2014年6月28日 星期六

[Arduino] 消除機械彈跳 – Debounce

Springs_L
我們在玩按鈕式的開完時,常會發生的就是按的時候手給他抖了一下。這時候 arduino 會在短時間內偵測到開關開關開關的機械彈跳訊號,造成判定上的問題。

這是按鈕開關機構上 (通常搭配一個小彈簧) 的問題,如果我們使用搖頭式的開關就不容易發生這種狀況了。幸好,如果我們需要用到按鈕開關這個元件,只要搭配 debounce 的語法就可以輕易消除機械彈跳了

這邊我收集到幾種 debounce 的語法:

一、一定的時間內偵測兩次判定

偵測原理就是在第一次按下按鈕後的一段時間後再讀取按鈕狀態,如果與第一次按下的狀態相同,就判定按鈕狀態穩定,不會因為機械彈跳造成系統異常。
image
在 Sketch 中插入下列語法,就可以達到這個效果

boolean previousState;
boolean state;
boolean swState;      // 穩定後的按鈕狀態

previousState = digitalRead(2);      // 讀取第一次按鈕狀態
delay(10);      // 隔 10 毫秒後再讀取第二次狀態
state = digitalRead(2);
if(state == previousState)     //如果兩次狀態相同,判定按鈕狀態穩定
{
   swState = state; // 判定按鈕狀態
}



二、確認按鈕穩定度的判定

但第一種方法有一個小缺點,因為主要邏輯是一段時間 (10 毫秒) 後比對狀態,可能中間發生了多次的機械彈跳是無法確認的。
image

因此,另一種作法是當一個狀態持續超過一段時間後判定穩定。
image

我們可以寫成一個 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 的範本,方便直接拿來用,整體邏輯是類似第二種判定方式,連續時間內狀態相同才判定按鈕穩定,給大家參考參考!
image





沒有留言:

張貼留言

Anything That's Worth Chatting

Related Posts Plugin for WordPress, Blogger...