適用於ROHM感測器評價工具組的簡易Arduino程式

arduino library

@CoreStaff

ROHM感測器評價工具組是一種相容Arduino的擴展板(Shield),搭配有以下8款感測器:加速度感測器、氣壓感測器、地磁感測器、近接照度感測器、色彩感測器、霍爾感測器、溫度感測器和紫外線感測器。該感測器擴展板的設置指南請參閱 ROHM感測器評價工具組概述。各別感測器的Arduino程式以及詳細資料可以從官網上下載: http://www.rohm.com/web/global/sensor-shield-support

針對您想要使用的任何感測器,官網所列的程式包含了另外一個在Arduino草圖中的程式。如果您只想使用一個或二個感測器,那麼這樣做行得通,但是如果您決定讓單一Arduino UNO擴展板同時處理多個感測器(比如6個感測器)呢?!

硬體

 

軟體

  • Arduino IDE
  • GitHub ROHMMultiSensor程式

上述連結是一個專門用於ROHMMultiSensor的GitHub程式庫,該單一Arduino程式能夠讓您控制ROHM感測器評價工具組中的所有感測器,不需要單獨包含每個感測器程式,因此可以節省您的時間。此外,該程式可讓您根據當下需求來設置感測器——這是原ROHM程式目前所缺乏的特性。該程式的另一個優點就是符合Arduino 1.5 IDE規範。它還包括自訂醒目語法、詳細的自述文件和大量實例!

與ROHM提供的程式相比較

我們假設您想用ROHM提供的程式來連接所有的感測器。這不僅會導致Arduino程式相當長,而且還會造成許多不必要的後台運算。比如,每個程式都有自己的I2C匯流排控制方法,但它們都相同。這些都會增加Arduino程式的整體大小和記憶體使用量。我們能不能只用一個I2C方法呢?下圖顯示了使用所需6個ROHM程式時的程式編譯器輸出:

arduino library

圖1.使用ROHM提供的程式來處理所有感測器時的編譯器輸出

 

9886位元組似乎不是很大,但是記住,該程式除了從感測器中提取資料並在序列埠上顯示之外,沒有做任何其他事情。這個數字告訴我們,儘管任務非常簡單,但是卻佔用了三分之一的儲存空間。這在添加更多功能時會造成儲存空間的問題。

現在,讓我們比較一下使用ROHMMultiSensor程式的編譯器輸出,其功能完全一樣:

 

arduino library

圖2.使用ROHMMultiSensor程式處理所有感測器時的編譯器輸出。 請注意快閃記憶體儲存空間和記憶體需求都減少了。

您可以看到,我們節省了超過2000位元組的快閃記憶體儲存空間以及100位元組的記憶體需求!

同時使用多個感測器的五個步驟

讓我們看一下上述文章中所提到的例子,在單個Arduin擴展板上運行6個ROHM感測器。所用感測器包括:加速度感測器(kx022 – 1020)、氣壓感測器(BM1383GLV)、近接照度感測器模組(RPR-0521RS)、色彩感測器(BH1745NUC)、溫度感測器(BD1020HFV)和紫外線感測器(ML8511A)。

arduino library

圖3.同時使用6個感測器

 

使用這些感測器的理由非常簡單:它們的工作電壓都是3V。由於我們只能在擴展板上為所有感測器設置一種電壓,因此我們必須使用大多數感測器能支援的電壓。使用ROHMMultiSensor程式時,代碼如下所示:

 

 

Arduino IDE串列繪圖器(Serial Plotter)的輸出如下圖所示。當然,這種輸出幾乎無法用在任何實務面需求。然而,它卻顯示了所有感測器都正在工作並測量資料中。

arduino library

圖4.所有6個感測器的串列繪圖器輸出

 

使用這個程式時,您必須按照以下五個步驟進行配置:定義、包含、產生實體、初始化和測量。這聽起來比較複雜,所以我們接下來詳細解釋每一步。

1.定義

 

第一步就是#define(定義)所有要使用的感測器。下面的步驟解釋了為什麼必須首先執行這些定義。

為了縮短代碼,您可以使用一個預程式設計的簡化定義。#define
INCLUDE_ALL_1V8_SENSORS#define
INCLUDE_ALL_3V0_SENSORS和#define
INCLUDE_ALL_3V0_SENSORS和#define
INCLUDE_ALL_1V8_SENSORS將會定義所有推薦供電電壓為1.8V的感測器。而電壓為3V和5V的定義語句分別為:#define
INCLUDE_ALL_3V0_SENSORS和#define
INCLUDE_ALL_5V0_SENSORS。

2.包含

 

這實際上就是您#include(包含)程式標頭檔案的地方。在此步驟之前必須完成所有感測器#define語句的原因很簡單:標頭檔案
(ROHMMultiSensor.h)中包含了其他的感測器特定檔,而這必須以定義適當感測器為基礎。這使得程式可以根據使用者需求動態改變其大小,從而節省Arduino快閃記憶體儲存空間和記憶體需求。

3. 產生實例

 

因為每個感測器都有自己的分類,因此存取其語言之前,您必須創建該類的一個實例。該過程被稱為產生實例,您所要做的就是輸入感測器分類名稱,然後緊跟實例名。比如:

BM1383GLV bar;

該語句會創建一個 BM1383GLV 類實例,而且您可以通過名稱bar存取該實例。

4. 初始化

每個感測器在使用前都必須初始化。您所要做的就是為每個感測器調用.init()方法。此方法在成功完成後返回0,如有任何問題,則返回1。您可以用以下代碼檢查所有感測器是否都已經成功初始化:

 

 

.init()方法還有一個額外功能:更改感測器設置。您可以通過傳遞各種參數來改變感測器的行為。

比如我們想要改變壓力感測器的工作模式。在預設模式下,感測器會測量200毫秒,然後返回平均值。如果我們想讓感測器運行得更快(可能會變得不那麼準確),我們可以使用以下參數調用.init()方法:

bar.init(BM1383GLV_CONTINUOUS_100_MS);

現在,測量只會在100 ms的工作模式下進行。每次重新開機感測器之後,所有設置都會被重置為預設值。這通常只與整個Arduino重置(即按重新開機按鈕)相關,所以這並不是一個問題。

 

請參閱 GitHub 程式參考 檔,以獲得每個感測器當前已經實現的完整設置列表。

注:這些設置都是可供選擇更改的;通常,初始設置就已足夠使用(即直接調用.init(),無需任何參數)。

5.測量

 

此時,一切準備就緒,可以開始測量資料了。您可以通過調整感測器的.measure()方法執行此操作。該方法無需參數,其返回資料類型取決於感測器種類。有些感測器會回應單一數值:一個浮點或者一個整數。

float pressValue = bar.measure();

上述語句示例會透過BM1383GLV感測器測量壓力,並回覆成單位為hPa的壓力數值。

然而,有些感測器需要回覆多個數值。比如,KX022-1020 加速度計會測量三個軸上的減速度:X、Y和Z。顯然,我們需要使用一個陣列,以回覆所有數值。陣列所用記憶體是動態分配的,所以當我們不需要陣列時,我們必須重新釋放記憶體。

在下面的例子中,我們定義、包含、產生實例並啟動KX022-1020加速度感測器。然後,我們創建一個名為accelValue的浮點動態陣列。如果我們後面不再需要陣列,我們可以通過delete[]釋放記憶體。這樣可以確保沒有記憶體洩漏。記憶體洩漏是指動態分配的記憶體無法正確釋放,並且只要Arduino未重置就不可存取的情況。在這個例子中,您會看到如何正確釋放動態分配的記憶體。

 

 

中斷和BM1422GMV地磁感測器

如果您用過Arduino,您很可能已經見過中斷功能了。即使沒有,也請不要擔心,如果設置正確,中斷用起來很簡單。

簡單來講,中斷就是讓Arduino“跳轉”至代碼特定部分的信號。這部分代碼是一種稱為中斷服務程式的特殊函數,通常簡稱為ISR。中斷的最常見用途就是進行精確時序控制,所以ISR函數應盡可能短。此外,中斷函數不帶任何參數,也不會返回任何值。

讓我們來看一下需要正確設置中斷的BM1422GMV地磁感測器。

 

 

我們需要記憶體釋放(因為與加速度感測器類似,BM1422GMV會回覆三個軸的數值)以及ISR。您可以看到,中斷只是在BM1422GMV類中形成一個標誌,表示有新資料需要收集。.setFlagDrdy()方法是該程式的一部分。請注意,您必須向.init()方法提供ISR名稱。

然而,只在代碼中設置中斷服務程式是不夠的。我們需要在擴展板上選擇正確設置。

Arduino UNO具有兩個外部中斷:INT0(引腳D2)和 INT1(引腳D3)。我們必須將適當的引腳連到感測器上的INT引腳。您可以在類別的產生實例中選擇使用哪個中斷。使用Arduino引腳D2中斷的預設值為INT_0,或者如果Arduino D2上的中斷已經用於其他設置,您可以將其改為INT_1。

arduino library

圖5.負責中斷設置的所有引腳

要將感測器中斷連至Arduino,我們應使用J3和J4排針。J3將中斷連至Arduino D2,而J4則將中斷連至D3。每個排針都有標記為INT1至INT5的引腳以及標記為INTR1至INTR5的引腳。這是因為感測器具有兩種不同的中斷輸出:

  1. CMOS類型輸出:KX022-1020和BM1422GMV屬於這種輸出。這些中斷信號可以直接連至 Arduino,並且使用引腳INTR1-5。
  2. 2. 需要外部上拉電阻的中斷:使用這種中斷的感測器為BH1745NUC和RPR-0521RS。它們會使用引腳INT1-5。注:在排針J16上,相應的引腳號必須短接,以使能外部上拉電阻。比如,如果要在J3上使用INT1引腳,您還必須將INT1短接至J16。

 

我們再看一下上述內容中的示例代碼。我們想要把Arduino的INT0連至BM1422GMV的INT引腳。假設感測器連到了I2C_1插槽。在這種情況下,我們應將INTR1引腳短接至J3。

arduino library

圖6.BM1422GMV連至I2C_1插槽時的中斷設置

 

如果任何其他感測器需要使用中斷,比如BH1745NUC色彩感測器,那麼中斷設置步驟如下所示:如果我們將感測器連至I2C_3並且要使用Arduino的中斷INT1,那麼我們應將引腳INT3短接到J4和J16上,因為該感測器需要一個外部上拉電阻。

arduino library

圖7.H1745NUC連至I2C_3插槽時的中斷設置

 

有關中斷的詳細資訊以及針對不同感測器的設置資訊,請參考該程式README中的 注釋 部分。

技巧和訣竅

1.地磁感測器(BM1422GMV)是唯一需要中斷才能工作的感測器。然而,所有其他I2C感測器也可以使用中斷。程式的運行不需要允許中斷,但是這在一些應用程式中可能非常有用。目前,除磁力計之外,程式中沒有實現其他感測器的中斷功能。

2.使用霍爾(BD7411G)感測器時,向Arduino上傳程式之前必須斷開感測器。否則,您將在上傳程式時收到以下錯誤資訊:avrdude: stk500_getsync() 錯誤。這是因為BD7411G上的OUT引腳直接連至 Arduino引腳D0,而D0還是串列RX引腳。如果沒有檢測到磁場,那麼BD7411G的輸出為(HIGH),這會阻斷所有從序列埠進入的訊息,包括草圖上傳。

 

arduino library

圖8.使用BD7411G時可能遇到的錯誤範例。請注意,如果您在Arduino IDE設置中關閉了詳細輸出,您將只會收到一條消息:“上傳程式時出現錯誤(An error occurred while uploading the sketch)”。要打開詳細輸出資訊,請轉到Arduino IDE ->檔(File)->首選項(Preferences),然後勾選“上傳時顯示詳細輸出(Show verbose output during upload)”。

3. .當使用其中一個類比感測器(BD1020HFV溫度感測器或ML8511A紫外線感測器)時,您必須提供感測器所連接的插槽名稱。擴展板上有兩個模擬插槽:ANALOG_1和ANALOG_2。為其中一個模擬感測器調用.init()方法時,您必須向.init()方法提供插槽名稱(即調用.init(ANALOG_1),以初始化連至插槽ANALOG_1的模擬感測器)。作為安全措施,如果您沒有提供任何內容,.init()的預設值將會是 ANALOG_1,然而,感測器必須連至插槽ANALOG_1。如果您從類比感測器獲取的資料很奇怪,那麼請首先確保您提供的插槽名稱與感測器相連的插槽一致。

本文的主要目的是為ROHM原始程式碼提供一種潛在的替代方案。顧名思義,如果您需要在ROHM感測器評價工具組中處理多個感測器,那麼ROHMMultiSensor程式將會非常有用,您的下一個大型專案可能會需要這個程式!

如果您有任何改進建議,請上GitHub進行分享:收集修改意見;或者在 問題(Issues)選項卡中建立GitHub問題。要建立一個GitHub問題非常簡單,您的回饋對我們來說非常有價值。另外,如果您喜歡這個程式,也讓您的代碼因此變得更漂亮,那麼請給ROHMMultiSensor檔案庫一顆星,然後盡情地開發吧!

 

Jan Gromes
Jan Gromes
Jan目前就讀於布爾諾理工大學電氣工程專業,擁有多年Arduino和其他微控制器專案經驗,尤其對於機器人系統的機械設計感興趣。

Check us out on Social Media