我正在尝试使用简单的Arduino电路,该电路在按下电路中的按钮(连接为INPUT到PIN 8)时递增计数器变量。我的代码简单如下:
#include <LiquidCrystal.h>
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
int c = 0, btnPIN, btnVal;
void setup ()
{
btnPIN = 8;
pinMode(btnPIN, INPUT);
lcd.begin(16,2);
lcd.clear();
}
void void loop()
{
btnVal = digitalRead(btnPIN);
if (btnVal == LOW)
{
c++;
lcd.clear();
lcd.print(c);
}
}
问题是,每次按下按钮,计数器都会增加1以上。串行监视器上的一点点打印表示每次按下按钮且电压为低电平时,条件代码会多次执行,计数器会增加多次而不是1.
也许,我需要编写一些逻辑来检查按钮最初是否未按下,然后按下然后再次释放,然后这些步骤将触发所需的操作。
我目前正在使用的解决方案如下(工作正常):
int btnStatus = 0;
void loop()
{
btnVal = digitalRead(btnPIN);
if (btnVal == LOW)
btnStatus = 1;
if(btnStatus == 1 && btnVal == HIGH)
{
c++;
lcd.clear();
lcd.print(c);
btnStatus = 0;
}
}
我不确定是否有更简单的解决方案,或者这种方法是否因其他原因而出错?任何建议都是最受欢迎的!
答案 0 :(得分:2)
您可能遇到的另一个问题是机械按钮bounce。也就是说,他们在两个位置之间快速跳跃几次,然后才能进入最终位置。这是标准操作,因此必须“去抖动”按钮。
有很多方法可以做到这一点,但Here是一个使用Arduino的教程。
正如您可能已经发现的那样,主要问题是按钮关闭时多次调用loop
函数。这是你的代码修复的,你的代码看起来是一个很好的解决方案,我真的没有看到更简单的方法。但是,换句话说,也许您可以尝试在delay
的末尾添加对loop
的调用,以减慢它的速度。你必须稍微玩一下延迟量,但它可以工作。实际上,你的解决方案看起来很不错。
答案 1 :(得分:1)
您的想法是正确的,您需要跟踪按钮的先前状态,以确定它是新按或是否只是被按下。但是,您的代码可能会被重写为更像状态机:
typedef enum {
BTN_STATE_RELEASED,
BTN_STATE_PRESSED
} ButtonState;
ButtonState btnStatus = BTN_STATE_RELEASED;
void increment_counter()
{
c++;
lcd.clear();
lcd.print(c);
}
void loop()
{
btnVal = digitalRead(btnPIN);
switch(btnStatus)
{
case BTN_STATE_PRESSED:
// Handle button release
if(btnVal == HIGH)
{
btnStatus = BTN_STATE_RELEASED;
}
break;
case BTN_STATE_RELEASED:
// Handle button press
if(btnVal == LOW)
{
increment_counter();
btnStatus = BTN_STATE_PRESSED;
}
break;
}
}
这被重写为使用枚举来跟踪系统的状态(对于一个简单的按钮来说有点矫枉过正,但是如果你的系统变得越来越复杂,这是一个重要的概念)。
更新显示的代码也被移动到它自己的功能中,以便在显示更改和状态的实际更新之间更好地分开。