在 Arduino 中使用按钮作为触发器
Using a PushButton as a trigger in Arduino
我正在尝试使用一个简单的 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;
}
}
我不确定是否有更简单的解决方案可用,或者这种方法是否由于其他原因是错误的?欢迎任何建议!
您的想法是正确的,您需要跟踪按钮之前的状态以了解它是新按下还是只是被按住。您的代码可以重写为看起来更像状态机,但是:
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;
}
}
这被重写为使用枚举来跟踪系统状态(对于一个简单的按钮来说有点矫枉过正,但这是一个重要的概念,以防您的系统变得更复杂)。
更新显示的代码也被移到了它自己的函数中,以使其更好地区分显示更改和实际状态更新。
您可能遇到的另一个问题是机械按钮 bounce。也就是说,它们会在两个位置之间快速跳跃几次,然后才能稳定到最终位置。这是标准操作,因此有必要 "debounce" 按钮。
有很多方法可以做到这一点,但是Here是一个使用 Arduino 的教程。
您可能已经发现,主要问题是 loop
函数在按下按钮时被多次调用。这是由您的代码修复的问题,您的代码看起来是一个很好的解决方案,但我真的没有看到更简单的方法。但是,对于另一种方式,也许您可以尝试在 loop
末尾添加对 delay
的调用以减慢速度。您将不得不稍微调整延迟量,但它可以工作。不过,您的解决方案看起来确实不错。
我正在尝试使用一个简单的 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;
}
}
我不确定是否有更简单的解决方案可用,或者这种方法是否由于其他原因是错误的?欢迎任何建议!
您的想法是正确的,您需要跟踪按钮之前的状态以了解它是新按下还是只是被按住。您的代码可以重写为看起来更像状态机,但是:
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;
}
}
这被重写为使用枚举来跟踪系统状态(对于一个简单的按钮来说有点矫枉过正,但这是一个重要的概念,以防您的系统变得更复杂)。
更新显示的代码也被移到了它自己的函数中,以使其更好地区分显示更改和实际状态更新。
您可能遇到的另一个问题是机械按钮 bounce。也就是说,它们会在两个位置之间快速跳跃几次,然后才能稳定到最终位置。这是标准操作,因此有必要 "debounce" 按钮。
有很多方法可以做到这一点,但是Here是一个使用 Arduino 的教程。
您可能已经发现,主要问题是 loop
函数在按下按钮时被多次调用。这是由您的代码修复的问题,您的代码看起来是一个很好的解决方案,但我真的没有看到更简单的方法。但是,对于另一种方式,也许您可以尝试在 loop
末尾添加对 delay
的调用以减慢速度。您将不得不稍微调整延迟量,但它可以工作。不过,您的解决方案看起来确实不错。