按鈕與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

}