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