這篇文章來源于DevicePlus.com英語網(wǎng)站的翻譯稿。
@CoreStaff
羅姆傳感器評(píng)估套件是一種兼容 Arduino 的擴(kuò)展板 (Shield),配有以下8鐘傳感器:加速度計(jì)、壓力傳感器、地磁傳感器、照度/接近傳感器、顏色傳感器、霍爾傳感器、溫度傳感器和紫外線傳感器。該傳感器擴(kuò)展板的設(shè)置指南請(qǐng)參閱Arduino傳感器 – ROHM傳感器評(píng)估套件概覽。單個(gè)傳感器的 Arduino 庫以及詳細(xì)文檔可以從官網(wǎng)上下載:https://www.rohm.com/web/global/sensor-shield-support
對(duì)于要用的每個(gè)傳感器,官網(wǎng)所列的庫都要求您在 Arduino 程序中包含另外一個(gè)庫。如果您計(jì)劃只使用一個(gè)或兩個(gè)傳感器,那么這樣做行得通,但是如果您決定讓單個(gè) Arduino UNO 開發(fā)板同時(shí)處理多個(gè)傳感器(比如6個(gè)傳感器)呢?!
Arduino UNO或Mega
羅姆傳感器評(píng)估套件
軟件
Arduino IDE
GitHub – 羅姆MultiSensor庫
上述鏈接是一個(gè)專門用于羅姆 MultiSensor 的GitHub程序庫——該單個(gè) Arduino 庫能夠讓您控制羅姆傳感器評(píng)估套件中的所有傳感器,不需要單獨(dú)包含每個(gè)傳感器庫,因此可以節(jié)省時(shí)間。此外,這個(gè)庫允許您根據(jù)當(dāng)前要求設(shè)置傳感器——這是原羅姆庫目前所缺乏的特性。該庫的另一個(gè)優(yōu)點(diǎn)就是符合 Arduino 1.5 IDE 規(guī)范。它還包括自定義語法高亮顯示功能、詳細(xì)的自述 (readme) 文件和大量實(shí)例!
與羅姆提供的庫比較
我們假設(shè)您想用羅姆提供的庫連接所有傳感器。這不僅會(huì)導(dǎo)致 Arduino 程序相當(dāng)長,而且還會(huì)造成后臺(tái)運(yùn)行許多不必要的運(yùn)算。比如,每個(gè)庫都有自己的I2C總線控制方法,但它們都相同。所有這些都會(huì)增加 Arduino 程序的整體大小和內(nèi)存使用量。我們能不能只用一個(gè)I2C方法呢?下圖顯示了使用所需6個(gè)羅姆庫時(shí)的程序編譯器輸出:
圖 1. 使用羅姆提供的庫處理所有傳感器時(shí)的編譯器輸出
9886 字節(jié)似乎不是很大,但是記住,該程序除了從傳感器中提取數(shù)據(jù)并在串口上顯示之外,沒有做任何其他事情。這個(gè)數(shù)字告訴我們,盡管任務(wù)非常簡單,但是卻占用了三分之一的存儲(chǔ)空間。這在添加更多功能時(shí)會(huì)造成空間問題。
現(xiàn)在,讓我們比較一下使用羅姆 MultiSensor 庫的程序的編譯器輸出,其功能完全一樣:
圖 2. 使用羅姆 MultiSensor 庫處理所有傳感器時(shí)的編譯器輸出。
請(qǐng)注意閃存存儲(chǔ)空間和內(nèi)存需求都減少了。
您可以看到,我們節(jié)省了超過 2000 字節(jié)的閃存存儲(chǔ)空間以及100字節(jié)的內(nèi)存需求 !
同時(shí)使用多個(gè)傳感器的5個(gè)步驟
讓我們看一下上文提到的例子——在單個(gè)Arduino開發(fā)板上運(yùn)行6個(gè)羅姆傳感器。所用傳感器包括:加速度計(jì)(kx022 – 1020)、壓力傳感器(BM1383GLV)、照度/接近傳感器(RPR-0521RS)、顏色傳感器(BH1745NUC)、溫度傳感器(BD1020HFV) 和紫外線傳感器 (ML8511A)。
圖 3.同時(shí)使用6個(gè)傳感器
使用這些傳感器的理由非常簡單:它們的工作電壓都是3V。由于我們只能在擴(kuò)展板上為所有傳感器設(shè)置一種電壓電平,因此我們必須使用大多數(shù)傳感器支持的電壓。使用羅姆MultiSensor庫時(shí),代碼如下所示:
// definition #define INCLUDE_KX022_1020 #define INCLUDE_BM1383GLV #define INCLUDE_RPR_0521RS #define INCLUDE_BH1745NUC #define INCLUDE_BD1020HFV #define INCLUDE_ML8511A // inclusion #include // instantiation KX022_1020 acc; BM1383GLV bar; RPR_0521RS als; BH1745NUC rgbc; BD1020HFV temp; ML8511A uv; void setup() { Serial.begin(9600); Wire.begin(); // initialization acc.init(); bar.init(); als.init(); rgbc.init(); temp.init(ANALOG_1); uv.init(ANALOG_2); Serial.println("X[g]tY[g]tZ[g]tp[hPa]tPS[cnt]tALS[lx]tR[-]tG[-]tB[-]tC[-]tt[dg C]tUV[mW/cm^2]"); void loop() { //measurement float* accelValue = acc.measure(); float pressValue = bar.measure(); float psValue = als.measure(PS); float alsValue = als.measure(ALS); unsigned int* rgbcValue = rgbc.measure(); float tempValue = temp.measure(); float uvValue = uv.measure(); Serial.print(accelValue[0]); Serial.print('t'); Serial.print(accelValue[1]); Serial.print('t'); Serial.print(accelValue[2]); Serial.print('t'); Serial.print(pressValue); Serial.print('t'); Serial.print(psValue); Serial.print('t'); Serial.print(alsValue); Serial.print('t'); Serial.print(rgbcValue[0]); Serial.print('t'); Serial.print(rgbcValue[1]); Serial.print('t'); Serial.print(rgbcValue[2]); Serial.print('t'); Serial.print(rgbcValue[3]); Serial.print('t'); Serial.print(tempValue); Serial.print('t'); Serial.println(uvValue); delete[] accelValue; delete[] rgbcValue; delay(100); }
Arduino IDE串行繪圖儀(Serial Plotter)的輸出如下圖所示。當(dāng)然,這種輸出幾乎無法用于任何實(shí)際用途。然而,它表明所有傳感器都在工作并測量數(shù)據(jù)。
圖 4. 所有6個(gè)傳感器的串行繪圖儀輸出
使用這個(gè)庫時(shí),您必須按照以下五個(gè)步驟進(jìn)行配置:定義、包含、實(shí)例化、初始化和測量。這聽起來比較復(fù)雜,所以我們接下來詳細(xì)解釋每一步。
1.定義
第一步就#define(定義)所有要使用的傳感器。下面的步驟解釋了為什么必須首先執(zhí)行這些定義。
為了縮短代碼,您可以使用一個(gè)預(yù)編程的簡化定義。#define INCLUDE_ALL_1V8_SENSORS#define INCLUDE_ALL_3V0_SENSORS和#define INCLUDE_ALL_5V0_SENSORS。比如,#define INCLUDE_ALL_1V8_SENSORS將會(huì)定義所有推薦供電電壓為1.8V的傳感器。而電壓為3V和5V的定義語句分別為:#define INCLUDE_ALL_3V0_SENSORS和#define INCLUDE_ALL_5V0_SENSORS。
2.包含
這實(shí)際上就是您#include(包含)庫頭文件的地方。在此步驟之前必須完成所有傳感器#define語句的原因很簡單:頭文件(羅姆MultiSensor.h)中包含了其他的傳感器特定文件,而這必須以定義適當(dāng)傳感器為基礎(chǔ)。這使得庫可以根據(jù)用戶需求動(dòng)態(tài)改變其大小,從而節(jié)省Arduino閃存存儲(chǔ)空間和內(nèi)存需求。
3.實(shí)例化
因?yàn)槊總€(gè)傳感器都有自己的類,因此訪問其方法之前,您必須創(chuàng)建該類的一個(gè)實(shí)例。該過程被稱為實(shí)例化,您所要做的就是輸入傳感器類名,然后緊跟實(shí)例名。比如:
BM1383GLV bar;
該語句會(huì)創(chuàng)建一個(gè)BM1383GLV類實(shí)例,而且您可以通過名稱bar訪問該實(shí)例。
4.初始化
每個(gè)傳感器在使用前都必須初始化。您所要做的就是為每個(gè)傳感器調(diào)用.init()方法。此方法在成功完成后返回0,如有任何問題,則返回1。您可以用以下代碼檢查所有傳感器是否都已經(jīng)成功初始化:
void setup() { if(bar.init() == 1) { // there was an error, you have to fix it! } // everything went fine, you can start measuring!
.init()方法還有一個(gè)額外功能:更改傳感器設(shè)置。您可以通過傳遞各種參數(shù)來改變傳感器的行為。
比如我們想要改變壓力傳感器的工作模式。在默認(rèn)模式下,傳感器會(huì)測量200毫秒,然后返回平均值。如果我們想讓傳感器運(yùn)行得更快(可能會(huì)變得不那么準(zhǔn)確),我們可以使用以下參數(shù)調(diào)用.init()方法:
bar.init(BM1383GLV_CONTINUOUS_100_MS);
現(xiàn)在,測量只會(huì)在100 ms的工作模式下進(jìn)行。每次重新啟動(dòng)傳感器之后,所有設(shè)置都會(huì)被重置為默認(rèn)值。這通常只與整個(gè)Arduino重置(即按重置按鈕)相關(guān),所以這并不是一個(gè)問題。
請(qǐng)參閱GitHub庫參考文件,以獲得每個(gè)傳感器當(dāng)前已經(jīng)實(shí)現(xiàn)的完整設(shè)置列表。
注:這些設(shè)置都是可選設(shè)置;通常,默認(rèn)設(shè)置就已足夠(即直接調(diào)用.init(),無需任何參數(shù))。
5.測量
此時(shí),一切準(zhǔn)備就緒,可以開始測量數(shù)據(jù)了。您可以通過調(diào)用所用傳感器的.measure()方法執(zhí)行此操作。該方法無需參數(shù),其返回?cái)?shù)據(jù)類型取決于傳感器種類。有些傳感器會(huì)返回單個(gè)數(shù)值——一個(gè)浮點(diǎn)數(shù)或者一個(gè)整數(shù)。
float pressValue = bar.measure();
上述語句示例會(huì)通過BM1383GLV傳感器測量壓力,并返回單位為hPa的壓力數(shù)值。
然而,有些傳感器需要返回多個(gè)數(shù)值。比如,KX022-1020 加速度計(jì)會(huì)測量三個(gè)軸上的減速度:X、Y和Z。顯然,我們需要使用一個(gè)數(shù)組,以返回所有數(shù)值。數(shù)組所用內(nèi)存是動(dòng)態(tài)分配的,所以當(dāng)我們不需要數(shù)組時(shí),我們必須重新釋放內(nèi)存。
在下面的例子中,我們定義、包含、實(shí)例化并啟動(dòng)KX022-1020加速度計(jì)。然后,我們創(chuàng)建一個(gè)名為accelValue的浮點(diǎn)數(shù)動(dòng)態(tài)數(shù)組。如果我們后面不再需要數(shù)組,我們可以通過delete[]釋放內(nèi)存。這樣可以確保沒有內(nèi)存泄漏。內(nèi)存泄漏是指動(dòng)態(tài)分配的內(nèi)存無法正確釋放,并且只要Arduino未重置就不可訪問的情況。在這個(gè)例子中,您會(huì)看到如何正確釋放動(dòng)態(tài)分配的內(nèi)存。
#define INCLUDE_KX022_1020 #include KX022_1020 acc; void setup() { Serial.begin(9600); Wire.begin(); acc.init(); Serial.println("X[g]tY[g]tZ[g]”); } void loop() { // dynamically create an array float* accelValue = acc.measure(); // now we can access the elements in accelValue array Serial.print(accelValue[0]); Serial.print('t'); Serial.print(accelValue[1]); Serial.print('t'); Serial.println(accelValue[2]); //safely deallocate the memory delete[] accelValue; delay(100); }
中斷和BM1422GMV地磁傳感器
如果您用過Arduino,您很可能已經(jīng)見過中斷功能了。即使沒有,也請(qǐng)不要擔(dān)心,如果設(shè)置正確,中斷用起來很簡單。
簡單來講,中斷就是讓Arduino“跳轉(zhuǎn)”至代碼特定部分的信號(hào)。這部分代碼是一種稱為中斷服務(wù)程序的特殊函數(shù),通常簡稱為ISR。中斷的最常見用途就是進(jìn)行精確時(shí)序控制,所以ISR函數(shù)應(yīng)盡可能短。此外,中斷函數(shù)不帶任何參數(shù),也不會(huì)返回任何值。
讓我們來看一下需要正確設(shè)置中斷的BM1422GMV地磁傳感器。
#define INCLUDE_BM1422GMV #include BM1422GMV mag; void isr(void) { mag.setFlagDrdy(); } void setup() { Serial.begin(9600); Wire.begin(); mag.init(isr); Serial.println("X[uT]tY[uT]tZ[uT]"); } void loop() { float* magValue = mag.measure(); Serial.print(magValue[0]); Serial.print('t'); Serial.print(magValue[1]); Serial.print('t'); Serial.println(magValue[2]); delete[] magValue; delay(100); }
我們需要內(nèi)存釋放(因?yàn)榕c加速度計(jì)類似,BM1422GMV會(huì)返回三個(gè)軸的數(shù)值)以及ISR。您可以看到,中斷只是在BM1422GMV類中形成一個(gè)標(biāo)志,表示有新數(shù)據(jù)需要收集。.setFlagDrdy()方法是該庫的一部分。請(qǐng)注意,您必須向.init()方法提供ISR名稱。
然而,只在代碼中設(shè)置中斷服務(wù)程序是不夠的。我們需要在擴(kuò)展板上選擇正確設(shè)置。
Arduino UNO具有兩個(gè)外部中斷:INT0(引腳D2)和 INT1(引腳D3)。我們必須將適當(dāng)?shù)囊_連到傳感器上的INT引腳。您可以在類的實(shí)例化中選擇使用哪個(gè)中斷。使用Arduino引腳D2中斷的默認(rèn)值為INT_0,或者如果Arduino D2上的中斷已經(jīng)用于其他設(shè)置,您可以將其改為INT_1。
圖 5. 負(fù)責(zé)中斷設(shè)置的所有引腳概覽
要將傳感器中斷連至Arduino,我們應(yīng)使用J3和J4排針。J3將中斷連至Arduino D2,而J4則將中斷連至D3。每個(gè)排針都有標(biāo)記為INT1至INT5的引腳以及標(biāo)記為INTR1至INTR5的引腳。這是因?yàn)閭鞲衅骶哂袃煞N不同的中斷輸出:
CMOS類型輸出:KX022-1020和BM1422GMV屬于這種輸出。這些中斷信號(hào)可以直接連至 Arduino,并且使用引腳INTR1-5。
需要外部上拉電阻的中斷:使用這種中斷的傳感器為BH1745NUC和RPR-0521RS。它們會(huì)使用引腳INT1-5。注:在排針J16上,相應(yīng)的引腳號(hào)必須短接,以使能外部上拉電阻。比如,如果要在J3上使用INT1引腳,您還必須將INT1短接至J16。
我們?cè)倏匆幌律衔慕o出的示例代碼。我們想要把Arduino的INT0連至BM1422GMV的INT引腳。假設(shè)傳感器連到了I2C_1插槽。在這種情況下,我們應(yīng)將INTR1引腳短接至J3。
圖 6. BM1422GMV連至I2C_1插槽時(shí)的中斷設(shè)置
如果任何其他傳感器需要使用中斷——比如BH1745NUC顏色傳感器,那么中斷設(shè)置步驟如下所示:如果我們將傳感器連至I2C_3并且要使用Arduino的中斷INT1,那么我們應(yīng)將引腳INT3短接到J4和J16上,因?yàn)樵搨鞲衅餍枰粋€(gè)外部上拉電阻。
圖 7. H1745NUC連至I2C_3插槽時(shí)的中斷設(shè)置
有關(guān)中斷的詳細(xì)信息以及針對(duì)不同傳感器的設(shè)置信息,請(qǐng)參考該庫README中的注釋部分。
技巧和決竅
1.地磁傳感器(BM1422GMV)是唯一需要中斷才能工作的傳感器。然而,所有其他I2C傳感器也可以使用中斷。庫的運(yùn)行不需要使能中斷,但是這在一些應(yīng)用程序中可能非常有用。目前,除磁力計(jì)之外,庫中沒有實(shí)現(xiàn)其他傳感器的中斷功能。
2.使用霍爾(BD7411G)傳感器時(shí),向Arduino上傳程序之前必須斷開傳感器。否則,您將在上傳程序時(shí)收到以下錯(cuò)誤信息:avrdude: stk500_getsync()錯(cuò)誤。這是因?yàn)锽D7411G上的OUT引腳直接連至Arduino引腳D0,而D0還是串行RX引腳。如果沒有檢測到磁場,那么BD7411G的輸出為高電平(HIGH),這會(huì)阻止串行端口的任何傳入通信——包括程序上傳。
圖8.使用BD7411G時(shí)可能遇到的錯(cuò)誤示例。請(qǐng)注意,如果您在Arduino IDE設(shè)置中關(guān)閉了詳細(xì)輸出,您將只會(huì)收到一條消息:“上傳程序時(shí)出現(xiàn)錯(cuò)誤(An error occurred while uploading the sketch)”。要打開詳細(xì)輸出信息,請(qǐng)轉(zhuǎn)到Arduino IDE ->文件(File)->首選項(xiàng)(Preferences),然后勾選“上傳時(shí)顯示詳細(xì)輸出(Show verbose output during upload)”。
3.當(dāng)使用其中一個(gè)模擬傳感器(BD1020HFV溫度傳感器或ML8511A UV傳感器)時(shí),您必須提供傳感器所連接的插槽名稱。擴(kuò)展板上有兩個(gè)模擬插槽:ANALOG_1和ANALOG_2。為其中一個(gè)模擬傳感器調(diào)用.init()方法時(shí),您必須向.init()方法提供插槽名稱(即調(diào)用.init(ANALOG_1),以初始化連至插槽ANALOG_1的模擬傳感器)。作為安全措施,如果您沒有提供任何內(nèi)容,.init()的默認(rèn)值將會(huì)是ANALOG_1,然而,傳感器必須連至插槽ANALOG_1。如果您從模擬傳感器獲取的數(shù)據(jù)很奇怪,那么請(qǐng)首先確保您提供的插槽名稱與傳感器相連的插槽一致。
本文的主要目的是為羅姆源代碼提供一種潛在的替代方案。顧名思義,如果您需要在羅姆傳感器評(píng)估套件中處理多個(gè)傳感器,那么羅姆MultiSensor庫將會(huì)非常有用——您的下一個(gè)大型項(xiàng)目可能會(huì)需要這個(gè)庫!
如果您有任何改進(jìn)建議,請(qǐng)GitHub上進(jìn)行分享:創(chuàng)建修改意見;或者在問題(Issues) 選項(xiàng)卡中建立GitHub問題。創(chuàng)建GitHub問題非常簡單,您的反饋對(duì)我們來說非常有價(jià)值。另外,如果您喜歡這個(gè)庫,如果您的代碼由此變得更漂亮,那么請(qǐng)考慮賞給羅姆MultiSensor程序庫一顆星。盡情開發(fā)吧!
Jan Gromes
Jan目前在布爾諾理工大學(xué)學(xué)習(xí)電氣工程。他擁有多年使用Arduino和其他微控制器構(gòu)建項(xiàng)目的經(jīng)驗(yàn)。他的特殊興趣在于機(jī)器人系統(tǒng)的機(jī)械設(shè)計(jì)。
審核編輯黃宇
-
傳感器
+關(guān)注
關(guān)注
2550文章
51035瀏覽量
753072 -
Arduino
+關(guān)注
關(guān)注
188文章
6468瀏覽量
186952
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論