跳到主要内容

Arduino 按键消抖

本文主要介绍在 Arduino 中消除按键抖动的几种方法,包括常见的延时判断,以及一些库的使用。

由于物理性质和机械特性等原因,矩阵按键经常在按下后的一小段时间产生不定状态,这很可能被程序误认为在短时间内进行了多次按键操作。因此,在使用矩阵按键时,如果没有硬件消抖的措施,软件消抖是必不可少的,否则可能会产生不可预期的效果!

延时判断

延时判断就是通过在一小段间隔时间后再次读取按键状态的方式,来确保按键确实是完全被按下了,简单来说就是屏蔽掉发生按键抖动的时间段。在 Arduino 中可以使用 millis() 函数来算得按键按下后经过的时间。

下面示例代码通过延时判断去除按键抖动,并控制 LED 灯翻转。你可能需要根据 Arduino 开发板的硬件情况,修改引脚和有效电平状态。

const int buttonPin = 2;    // 连接矩阵按键的引脚
const int ledPin = 13; // LED引脚

int ledState = HIGH; // 记录LED的状态
int buttonState; // 记录按键的状态
int lastButtonState = LOW; // 上一次按键的状态

// 以下代码以long类型声明,因为时间值以毫秒为单位(用整型会很快溢出)
long lastDebounceTime = 0; // 按键最后一次被触发
long debounceDelay = 50; // 为了滤去抖动暂停的时间,如果发现输出不正常增加这个值

void setup() {
pinMode(buttonPin, INPUT);
pinMode(ledPin, OUTPUT);

// 设置LED初始状态
digitalWrite(ledPin, ledState);
}

void loop() {
// 读取按键状态并存储到变量中
int reading = digitalRead(buttonPin);

// 检查下按键状态是否改变(换句话说,输入是否是从 LOW 到 HIGH)
// 检查是否距离上一次按下的时间已经足够滤去按键抖动

if (reading != lastButtonState) { // 如果按键状态和上次不同
lastDebounceTime = millis(); // 记录初始时间
}

// 离初始时间已经过了按键抖动出现的时间,因此当前的按键状态是稳定状态
if ((millis() - lastDebounceTime) > debounceDelay) {

if (reading != buttonState) { // 如果按键状态改变了
buttonState = reading;

if (buttonState == HIGH) { // 只有当按键状态稳定为 HIGH 时才打开 LED
ledState = !ledState;
}
}
}

digitalWrite(ledPin, ledState); // 设置LED
lastButtonState = reading; // 保存处理结果
}

Bounce2 库

Bounce2 库是 Thomas O Fredericks 编写的一个专用于机械按钮和开关消抖的软件库。

这个库包含三个类:

  • Debouncer:执行实际去抖动的代码。只有高级用户会关心这个类,一般用户不需要关心。
  • Bounce:这是通用库。它的底层由 Debouncer 实现。
  • Button:基于 Bounce 类,专用于按下(pressed)按钮。

使用该库需要预先安装,并载入头文件:

#include <Bounce2.h>

Bounce 示例

下面示例代码通过 Bounce 类实现按键消抖,当按下按钮(pin 2)时翻转 LED 灯(pin 13)状态。你可能需要根据 Arduino 开发板的硬件情况,修改引脚和有效电平状态。

#include <Bounce2.h>

#define BUTTON_PIN 2
#define LED_PIN 13

int ledState = LOW;


Bounce b = Bounce(); // Instantiate a Bounce object

void setup() {

b.attach(BUTTON_PIN,INPUT_PULLUP); // Attach the debouncer to a pin with INPUT_PULLUP mode
b.interval(25); // Use a debounce interval of 25 milliseconds


pinMode(LED_PIN,OUTPUT); // Setup the LED
digitalWrite(LED_PIN,ledState); // Turn off the LED

}

void loop() {

b.update(); // Update the Bounce instance

if ( b.fell() ) { // Call code if button transitions from HIGH to LOW
ledState = !ledState; // Toggle LED state
digitalWrite(LED_PIN,ledState); // Apply new LED state
}
}

Button 示例

下面示例代码通过 Button 类实现按键消抖,当按下按钮(pin 39)时翻转 LED 灯(pin 13)状态。你可能需要根据 Arduino 开发板的硬件情况,修改引脚和有效电平状态。

#include <Bounce2.h>

// INSTANTIATE A Button OBJECT
Bounce2::Button button = Bounce2::Button();

// WE WILL attach() THE BUTTON TO THE FOLLOWING PIN IN setup()
#define BUTTON_PIN 39

// DEFINE THE PIN FOR THE LED :
// 1) SOME BOARDS HAVE A DEFAULT LED (LED_BUILTIN)
//#define LED_PIN LED_BUILTIN
// 2) OTHERWISE SET YOUR OWN PIN
#define LED_PIN 13

// SET A VARIABLE TO STORE THE LED STATE
bool ledState = LOW;

void setup() {

// BUTTON SETUP

// SELECT ONE OF THE FOLLOWING :
// 1) IF YOUR BUTTON HAS AN INTERNAL PULL-UP
// button.attach( BUTTON_PIN , INPUT_PULLUP ); // USE INTERNAL PULL-UP
// 2) IF YOUR BUTTON USES AN EXTERNAL PULL-UP
button.attach( BUTTON_PIN, INPUT ); // USE EXTERNAL PULL-UP

// DEBOUNCE INTERVAL IN MILLISECONDS
button.interval(5);

// INDICATE THAT THE LOW STATE CORRESPONDS TO PHYSICALLY PRESSING THE BUTTON
button.setPressedState(LOW);

// LED SETUP
pinMode(LED_PIN,OUTPUT);
digitalWrite(LED_PIN,ledState);

}

void loop() {
// UPDATE THE BUTTON
// YOU MUST CALL THIS EVERY LOOP
button.update();

if ( button.pressed() ) {

// TOGGLE THE LED STATE :
ledState = !ledState; // SET ledState TO THE OPPOSITE OF ledState
digitalWrite(LED_PIN,ledState);

}
}