在 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 的调用以减慢速度。您将不得不稍微调整延迟量,但它可以工作。不过,您的解决方案看起来确实不错。