機械式的接點,在接合或斷開的瞬間,會有一段不穩定的時期,我們稱其為彈跳現象(Bounce)。

2021K1

2021K2

記得在大學時,教授告訴我們彈跳現象持續的最長時間約為 13mS(對於這個數字我覺得僅供參考吧,反正大概落在 10mS這個數量級),當時學到的克服彈跳現象的方法是在偵測到電位改變時,先將目前的電位記憶起來,延遲 13mS後,再判斷一次電位,如果兩次讀到的電位相同,就判定為有效觸發,去執行對應的動作。

於是我就劈哩啪啦的寫了一段程式碼,相關的內容如下:

2021K3

實際測試時,發現根本不能用,不是1次跳2格,就是加、減錯誤,為什麼勒?讓我用示波器來看個究竟。

1. 有時後彈跳現象發生在 DT 已經變化之後,我想這應該是計數方向錯誤的原因吧。(而這也延伸出第2點)

2021K4

 

2. 旋轉越快,CLK跟DT的相差時間越短。導致我們無法使用較長(較合適)的延長時間,以避開彈跳期間去判斷第二次的電位,這推翻了我們想使用這方法的基本構想。而且可能是機構精密度的問題,轉動每一格的相差時間長短不一。

 

3. 中斷程序處理中,再一次產生中斷。圖中綠色的訊號,是我為了觀察程序進入中斷服務程式的狀況,在一進入中斷服務程序時,便將這個接腳拉HIGH;退出中斷服務程序前,將此腳置LOW。之後雖然在程式碼中加入"在一進入中斷程序時,立即使中斷失能"。但這並沒有使此問題解決,仍然出現兩次中斷,我想應該是來不及使中斷失能,又立刻產生中斷(INTF0被置1),於是處理完目前的中斷服務程序後,因旗標為1 而再進入中斷程序一次。為解決此問題,於是在要退出中斷服務程序時,清除了 INTF0 (對INTF0寫1即可清除此旗標)。如此的確克服了2次中斷的問題,但又產生了下一個問題。

2021K5

 

4. 當彈跳現象出現在變化之前,若進入服務程序期間的中斷旗標都被乎視,可能連同正確的中斷請求都被清除了,如此便會遺漏掉此次的CLK導致少數了一格。

2021K6

 

期間我也試過連續讀電位狀態10次,若皆相同即執行對應工作,否則立即退出中斷程序,但都沒有很好的效果。或許這個方法根本不對,或是不適用在旋轉編碼器這樣的應用。

不過別灰心,其實我已經有另一個可用的版本 (未完待續 ...)

 

(以下是 2021.04.22 補充)

先貼上程式碼。(其中"LED"是為了觀察中斷訊號而加入的)

2021K7-1

 

2021K7-2A

這與上一版本的差異只有將最後一次處理的狀態記憶起來,而且無須延遲。想法是只要處理過的狀態,不管來幾次因彈跳產生的中斷,都不予理會。

2021K8_1

2021K9_1

圖中紅色圈起來的部份即是進入中斷後,判斷為已處理過的狀態,所以沒有進行相對應的處置而立即離開中斷程序,所以時間較短。

因為進入中斷程序會對 LED 腳位進行寫入的動作兩次(進入時寫HIGH,離開前寫LOW),而且處理中也多了一個經由UART傳送目前數值的動作,這都會耗時,所以我們可以看到真正有處理時,中斷訊號會停留在HIGH較長的時間。這會讓我產生疑問,"會不會因為有這樣的耗時,等同於加了延遲?",所以我嘗試將 LED 顯示及 UART 即時傳送目前數值的程式碼拿掉,只在按下 SW 時才將目前的數值透過 UART 傳送到 Monitor。而實驗的結果依然沒有問題,確認了不需要延遲。

 

附上實驗短片

 

上一篇:旋轉編碼器(Rotary encoder)

arrow
arrow
    創作者介紹
    創作者 肯特王 的頭像
    肯特王

    肯特王的簿

    肯特王 發表在 痞客邦 留言(0) 人氣()