2014年6月28日 星期六
[Arduino] 消除機械彈跳 – Debounce
我們在玩按鈕式的開完時,常會發生的就是按的時候手給他抖了一下。這時候 arduino 會在短時間內偵測到開關開關開關的機械彈跳訊號,造成判定上的問題。
這是按鈕開關機構上 (通常搭配一個小彈簧) 的問題,如果我們使用搖頭式的開關就不容易發生這種狀況了。幸好,如果我們需要用到按鈕開關這個元件,只要搭配 debounce 的語法就可以輕易消除機械彈跳了!
這邊我收集到幾種 debounce 的語法:
一、一定的時間內偵測兩次判定
偵測原理就是在第一次按下按鈕後的一段時間後再讀取按鈕狀態,如果與第一次按下的狀態相同,就判定按鈕狀態穩定,不會因為機械彈跳造成系統異常。
在 Sketch 中插入下列語法,就可以達到這個效果。
boolean previousState;
boolean state;
boolean swState; // 穩定後的按鈕狀態
previousState = digitalRead(2); // 讀取第一次按鈕狀態
delay(10); // 隔 10 毫秒後再讀取第二次狀態
state = digitalRead(2);
if(state == previousState) //如果兩次狀態相同,判定按鈕狀態穩定
{
swState = state; // 判定按鈕狀態
}
二、確認按鈕穩定度的判定
但第一種方法有一個小缺點,因為主要邏輯是一段時間 (10 毫秒) 後比對狀態,可能中間發生了多次的機械彈跳是無法確認的。
因此,另一種作法是當一個狀態持續超過一段時間後判定穩定。
我們可以寫成一個 function,當判定穩定的時候回傳 true。
int bounceDelay = 5; // 設定連續 5 毫秒狀態相同時,判定為穩定
boolean debounce(int pin)
{
boolean state;
boolean previousState;
previousState = digitalRead(pin); // 儲存按鈕狀態
for(int counter=0;counter<debounceDelay;counter++)
{
delay(1);
state = digitalRead(pin);// 再讀取一次按鈕狀態 // 如果兩次狀態不同,把 counter 設為零,重新確認狀態
if(state != previousState)
{
counter=0;
previousState = state;
}
}
// for 迴圈每次都會 delay 1 毫秒,當每次讀取狀態都與第一次相同時,整個 for 跑完 5 毫秒,與之前設定的 bounceDelay 時間相同,回傳穩定的按鈕狀態
return state;
}
這個做法還存在一個小缺點:因為用到了 delay 的功能,確認按鈕穩定前,整個 sketch 會暫停。其實也還好,並不會有甚麼太大影響。如果擔心 delay 的問題,也可以把 delay(1) 這行整個拿掉,這樣就變成連續 5 次相同即判定,而不是 5 毫秒。
其實在 Arduino IDE 有內建的 debounce code 的範本,方便直接拿來用,整體邏輯是類似第二種判定方式,連續時間內狀態相同才判定按鈕穩定,給大家參考參考!
訂閱:
張貼留言 (Atom)
沒有留言:
張貼留言
Anything That's Worth Chatting