Arduino | 旋轉編碼器模組使用(2)---使用中斷


  Arduino | 旋轉編碼器模組使用(2)---使用中斷

關鍵字:arduino旋轉編碼器模組、arduino中斷。
繼上篇<Arduino | 旋轉編碼器模組使用(1)>的介紹後,此篇說明如何藉由Arduino開發板的中斷功能,計算旋轉編碼器的轉速與位置。

中斷服務(ISR)

黑修斯只有簡單節錄一些重點介紹中斷,關於中斷服務的詳細說明,請至本篇文章最下方的參考有更詳細的說明。
註:呼叫的函數在官方文件為ISR,中文為中斷處理函數或中斷服務常式等。

什麼是中斷?

中斷就好像是燒開水的水壺鳴笛,當水還沒燒開時,我們能夠先去做自己的事情,當水燒開,水壺會發出鳴笛聲(中斷發生),告訴我們水已經燒開,這個時候我們先暫停手邊的工作將火熄滅。

attachInterrupt(中斷編號, 呼叫的函數, 中斷模式)
在Arduino開發板中,最基本的中斷呼叫方法如上,其中需要引入三個參數(中斷編號, 呼叫的函數, 中斷模式),下列會依序說明。

中斷編號

Arduino (Uno, Nano, Mini, other 328-based)開發板配備二個中斷編號,對應的腳位如下表
中斷編號對應之Arduino腳位
中斷0Pin 2
中斷1Pin 3


Arduino(Mega, Mega2560, MegaADK)開發板配備六個中斷編號,對應的腳位如下表
中斷編號對應之Arduino腳位
中斷0Pin 2
中斷1Pin 3
中斷2Pin 21
中斷3Pin 20
中斷4Pin 19
中斷5Pin 18
其他型號的說明請參見arduino官方說明 。

呼叫函式

當中斷發生時,將執行的函式,一般中斷呼叫的函式,盡量都以簡單的運算為主,中斷時間太長將會影響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函式可以自己自訂名稱。
由於中斷模式為CHANGE,當訊號由HIGH -> LOW 或 LOW -> HIGH 會發生中斷,中斷期間會去執行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()的區塊移動。




轉貼本文時,需註明來自黑修斯隨手札記原創作者 hughes chen(黑修斯),及附上原文連結,同時 禁止修改,禁止商業使用 。

張貼留言

0 留言