Arduino | 旋轉編碼器模組使用(2)---使用中斷
關鍵字:arduino旋轉編碼器模組、arduino中斷。繼上篇<Arduino | 旋轉編碼器模組使用(1)>的介紹後,此篇說明如何藉由Arduino開發板的中斷功能,計算旋轉編碼器的轉速與位置。
中斷服務(ISR)
黑修斯只有簡單節錄一些重點介紹中斷,關於中斷服務的詳細說明,請至本篇文章最下方的參考有更詳細的說明。註:呼叫的函數在官方文件為ISR,中文為中斷處理函數或中斷服務常式等。
什麼是中斷?
中斷就好像是燒開水的水壺鳴笛,當水還沒燒開時,我們能夠先去做自己的事情,當水燒開,水壺會發出鳴笛聲(中斷發生),告訴我們水已經燒開,這個時候我們先暫停手邊的工作將火熄滅。attachInterrupt(中斷編號, 呼叫的函數, 中斷模式)在Arduino開發板中,最基本的中斷呼叫方法如上,其中需要引入三個參數(中斷編號, 呼叫的函數, 中斷模式),下列會依序說明。
中斷編號
Arduino (Uno, Nano, Mini, other 328-based)開發板配備二個中斷編號,對應的腳位如下表中斷編號 | 對應之Arduino腳位 |
中斷0 | Pin 2 |
中斷1 | Pin 3 |
Arduino(Mega, Mega2560, MegaADK)開發板配備六個中斷編號,對應的腳位如下表
中斷編號 | 對應之Arduino腳位 |
中斷0 | Pin 2 |
中斷1 | Pin 3 |
中斷2 | Pin 21 |
中斷3 | Pin 20 |
中斷4 | Pin 19 |
中斷5 | Pin 18 |
呼叫函式
當中斷發生時,將執行的函式,一般中斷呼叫的函式,盡量都以簡單的運算為主,中斷時間太長將會影響Arduino晶片的運作。中斷模式
中斷模式有4+1種,其中中斷模式HIGH限用特定的開發板。中斷模式 | 觸發中斷方法 | 備註 |
LOW | 訊號低電位(LOW)時觸發中斷 | |
CHANGE | 訊號改變時觸發中斷 | |
RISING | 訊號由LOW變成HIGH時觸發中斷 | |
FALLING | 訊號由HIGH變成LOW時觸發中斷 | |
HIGH | 訊號高電位(HIGH)時觸發中斷 | 只限用於某些板子如 Due, Zero and MKR1000 .... |
中斷服務的使用範例
attachInterrupt(0, test,CHANGE )
- 啟用中斷0(Arduino 開發板Pin 2)
- 中斷模式為"CHANGE"
- 中斷發生時會呼叫test函式,test函式可以自己自訂名稱。
腳位說明
腳位 | 說明 |
CLK | 相當於A相 |
DT | 相當於B相 |
SW | 編碼器按鈕腳位(編碼器上有開關的功能,可以按壓) |
+ | 正電源 |
GND | 接地 |
腳位觸發變化
通電後,CLK、DT、SW都是高電位(HIGH),當觸發時會變低電位(LOW),而SW(按鈕)被按下時變為低電位(LOW)。
程式接腳
腳位
|
連接Arduino開發板腳位
| |
CLK
|
<--->
|
Arduino Pin2
|
DT
|
<--->
|
Arduino Pin7
|
SW
|
<--->
| 不使用 |
+
|
<--->
|
正電源 5V or 3.3V
|
GND
|
<--->
|
接地
|
程式碼
程式亦可到GitHub下載。程式原理和上一篇大同小異,請見<Arduino | 旋轉編碼器模組使用(1)>。
中斷模式CHANG說明
當讀者將黑修斯的範例程式燒錄到Arduino開發板上,就能夠動手理解"中斷模式CHANG"的實際運作方式。理論觸發狀況
CHANG模式[有改變就觸發],訊號由HIGH -> LOW 或 LOW -> HIGH。理論上會如下圖,當旋轉編碼器轉動一下,計數值應為+1或-1。
實際觸發狀況
實際上,計數值有可能為+2或-2,因為旋轉編碼器的初始狀態是"高電位",如下圖二說明,每轉一次的pluse狀態會觸發兩次中斷,所以計數2次。解決實際計數值不符
解決實際計數值不符的狀況,黑修斯故意埋伏筆,讓讀者們可以試著思考與解決,提示兩個解決問題的方向。1.CHANGE模式改LOW 模式
2018/06/24:黑修斯在撰寫系列文章第三篇< Arduino | 旋轉編碼器模組使用(3)---使用中斷並加入按鈕歸零>中,嘗試過LOW模式與FALLING模式,效果並不是很好,應該說準確性沒有CHANGE模式好,而且可以說是不如人意,所以建議讀者們參考方法2。機構上的小問題
這款旋轉編碼器只要輕轉半格,計數值還是可以顯示+1或-1,原因在於內部結構為光遮罩式的設計,輕轉半格就能遮光,進而產生LOW->HIGH的Pluse訊號。
2.程式中的計數值/2 再顯示
圖一 |
圖二 |
最後的結論
透過中斷的方式,可以準確地控制,只要轉速不超過Arduino開發板的處理速度即可。另外的小地雷(設計上的BUG)
另外的小實驗:使用中斷仍然會失步的狀況,通訊延遲造成的將原本程式碼中void loop()的區塊,如下圖移到test()函式中的位置,讓每次中斷發生才傳回計數值,如果旋轉編碼氣旋轉快一些,會出現計數錯誤,原因為通訊速度造成的延遲現象,可透過調高Serial Port的通訊速度減少這個現象。
亦或是使用原本的程式碼,不將void loop()的區塊移動。
Reference
轉貼本文時,需註明來自黑修斯隨手札記原創作者 hughes chen(黑修斯),及附上原文連結,同時 禁止修改,禁止商業使用 。
0 留言
不一定能即時回覆問題,有時間會盡量答覆。