按鈕與Debounce問題

一、我們都一樣

剛開始接觸物聯網時,都會遇到按照老師的操作,做得一模一樣,但是....怎麼動作與預期中的不一樣

尤其是按鈕:明明按下要亮,卻按了一兩次才做動一次正常...

其實是這樣的,這就是按鈕的bounce,當我們按鈕按下的時候,其實是數位訊號讀取了幾十次,會建議在序列埠當中加一個counter,然後把它列印出來....

您會發現counter列印出來的數字,每次您按下按鍵時候,不是每次都加一,可能是加了十或加了幾百...

您看照片,當按鈕按下的時候其實一直在跑...

資料來源:https://iscixin.github.io/freakhq/push-button/

const byte swPin = 2;

const byte ledPin = 13;

boolean ledState = LOW;

int counter = 0;


void setup() {

 Serial.begin(9600);

 pinMode(ledPin, OUTPUT);

 pinMode(swPin, INPUT_PULLUP);

 digitalWrite(ledPin, ledState);

}


void loop() {

 boolean swState = digitalRead(swPin);

 if (swState == LOW) {

   ledState = !ledState;

   digitalWrite(ledPin, ledState);


   Serial.print("LOW count:");

   Serial.println(counter);

   counter++;

 }

} 

二、以polling方式來解決bounce

所以先講解決之道吧

設定一個狀態的flagdelay秒數約50毫秒或100毫秒...

曾希哲老師的大作上是這樣建議的

延遲100毫秒

按鈕接的時候,會建議於按鈕迴路加上10K歐姆的電阻,不然有很多雜訊讓電路訊號不穩定


Arduino電路中,電阻通常接在正訊號端


這是Arduino的程式,在7697上的應用也是一樣的

資料來源:https://i0.wp.com/www.lazytomatolab.com/wp-content/uploads/Arduino-SpeedUp-Class-8.138.jpeg?resize=1024%2C576&ssl=1

三、主動式外部中斷方式

山姆老師教得蠻清楚的...

完整程式碼:

#include "Arduino.h"

int  ledPin = 13;   // assign LED pin to number 13

int  digitalPin = 2;   // assign digital pin to number 2

bool bLedState = LOW; // initial LED state to LOW level

bool bBottonUP = true; // initial bottonUP flag

bool bHasINT0 = false; // initial INT0 flag


void setup()

{

    pinMode(ledPin, OUTPUT);     // initial LED pin to OUTPUT mode

    pinMode(digitalPin, INPUT);    // initial digital pin to INPUT mode

    digitalWrite(ledPin, bLedState); // setup LED state according to ledState


    Serial.begin(9600);

     while (!Serial){

      ; // wait for serial port to connect

     }

    Serial.println("Hello INT0");


    // config INT0 falling edge trigger (10) to generate interrupt by set EICRA

    EICRA |= _BV(ISC01);

    EICRA &= ~_BV(ISC00);

    // Enable INT0 interrupt by set EIMSK

    EIMSK |= _BV(INT0);

}


void loop()

{

 // read digital pin2 state and check bBottonUP

//  if ( digitalRead(digitalPin) == LOW && bBottonUP == true )

    if ( bHasINT0 && bBottonUP == true )

    {

     bLedState = ! bLedState;     // reverse LED state

     digitalWrite(ledPin, bLedState); // setup LED state according to ledState

     bBottonUP = false;

     delay(50);

    }

//  else if (digitalRead(digitalPin)== HIGH && bBottonUP == false)

    else if (bHasINT0 && bBottonUP == false)

    {

//   Serial.println("re-enable INT0");

     bBottonUP = true;

    bHasINT0 = false;

       // Re-enable INT0 interrupt by set EIMSK

       EIMSK |= _BV(INT0);

    }

}


ISR(INT0_vect)

{

 EIMSK &= ~_BV(INT0); // disable INT0

 bHasINT0 = true;  // Set flag

}