实现按钮的有限状态机(FSM)
本帖最后由 topdog 于 2021-3-24 06:32 编辑Arduino用按键来控制LED,一个按键的正确姿势如下图:
当你按下按钮时,按钮将电路中的两个点连接起来,UNO读取管脚3电平变化控制板载管脚13的LED亮或者灭。
const int buttonPin = 3;
const int ledPin =13;
int buttonState = 0;
void setup() {
pinMode(ledPin, OUTPUT);
pinMode(buttonPin, INPUT);
}
void loop() {
buttonState = digitalRead(buttonPin);
if (buttonState == HIGH) {
digitalWrite(ledPin, HIGH);
} else {
digitalWrite(ledPin, LOW);
}
}
但是按钮是机械装置,通常会出现虚假甚至是欺骗的状态转变,不去除抖动(Debounce),按一次按钮可能会导致不可预知的结果。必须在短时间内检查两次以确保按钮确实被按下了。下面的示例是使用millis()函数来记录按钮被按下后所经过的时间,称之为非阻塞的方式,区别于delay(),后者称为阻塞方式。
const int buttonPin = 3;
const int ledPin = 13;
int ledState = HIGH;
int buttonState;
int lastButtonState = LOW;
unsigned long lastDebounceTime = 0;
unsigned long debounceDelay = 50;
void setup() {
pinMode(buttonPin, INPUT);
pinMode(ledPin, OUTPUT);
digitalWrite(ledPin, ledState);
}
void loop() {
int reading = digitalRead(buttonPin);
if (reading != lastButtonState) {
lastDebounceTime = millis();
}
if ((millis() - lastDebounceTime) > debounceDelay) {
if (reading != buttonState) {
buttonState = reading;
if (buttonState == HIGH) {
ledState = !ledState;
}
}
}
digitalWrite(ledPin, ledState);
lastButtonState = reading;
}
即要考虑防抖动的基本需求,还要在控制过程中用一个按钮实现有限状态机(finite state machine,简称:FSM),推荐使用onebutton库。下面的示例是双击触发事件。
#include "OneButton.h"
//简略写法
//OneButton button(3);
#define BUTTON_PIN 3
//初始化为高电平
OneButton button = OneButton(
BUTTON_PIN,
false,
false
);
void setup() {
pinMode(13, OUTPUT);
button.attachDoubleClick(doubleclick);
}
void loop() {
button.tick();
delay(10);
}
void doubleclick() {
static int m = LOW;
m = !m;
digitalWrite(13, m);
}
实现细节:
如果你想了解这个库是如何工作的,这里有一些解释:
在OneButton库的tick()函数内,您可以找到检查输入引脚检测单点击,双击或长按情况的实现。这种实现被称为有限状态机(FSM),它实现了以下状态图:
每当tick()函数被调用时,就会显示当前情况,分析当前状态和输入值,并在适用时调用外部函数或者改变当前状态。特别是OneButton库的实现从来不会调用delay()或类似的函数,因此在大多数情况下都会很快返回。总之,OneButton库可以非常便捷地实现有限状态机(FSM),它有助于降低实现的复杂性。
页:
[1]