Arduino 通过按钮击键,如何去抖动,何时使用矩阵?

Arduino keystrokes via push-buttons, how to debounce, when to use matrix?

我有一组简单的 8 个按钮,连接到 Teensy 3.2 板(通过 Teensyduino 插件使用 Arduino)。 8 个按钮位于引脚 1-8 上,它们的公共接地线(一根线焊接到每个按钮上)位于 GND 引脚上。我有代码可以让任何一个按钮正常工作。目前设置为按下第二个按钮类型 "A."

我想让按钮 1 到 8 在您按下它们时分别键入 A、B、C...等。有人告诉我我的设置有两个问题,第一个是复制每个按钮的代码是一种糟糕的方法,第二个是它会出现弹跳问题(每按 5 次左右就会创建一次击键。)我也想设置它,以便将来我可以编写一个第 3 方应用程序,根据用户的偏好配置密钥。

加上这些需求,我不确定下一步该去哪里。我是新手,所以我不确定如何正确地合并弹跳 class 或者这是否是满足需要的正确方法。

矩阵是可行的方法还是有一种优雅的方法来手动设置每个按钮并补偿弹跳?谢谢~目前代码如下:

#define CHECK_EVERY_MS 20
#define MIN_STABLE_VALS 5

unsigned long previousMillis;
char stableVals;
char buttonPressed;

void setup() {
  // make pin 2 an input and turn on the 
  // pullup resistor so it goes high unless
  // connected to ground:
  pinMode(2, INPUT_PULLUP);
  Keyboard.begin();
}

void  loop() {
    if ((millis() - previousMillis) > CHECK_EVERY_MS)
    {
        previousMillis += CHECK_EVERY_MS;
        if (digitalRead(2) != buttonPressed)
        {
            stableVals++;
            if (stableVals >= MIN_STABLE_VALS)
            {
                buttonPressed = !buttonPressed;
                stableVals = 0;

                if (buttonPressed)
                {
                    //Send an ASCII 'A', 
                    Keyboard.write(65);
                }
            }
        }
        else
            stableVals = 0;
    }
}

---------- 代码编辑 1

#include <Bounce2.h>

// Instantiate a Bounce object
Bounce debouncer[8];
bool prevValues[8];

// Keyboard values for btn   1    2    3    4    5    6    7    8
char keyboardValues[] =    {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H'};

void setup() {
// First setup all the pins as input with pullup
    pinMode(BUTTON_PIN_1,INPUT_PULLUP);
    pinMode(BUTTON_PIN_2,INPUT_PULLUP);
    pinMode(BUTTON_PIN_3,INPUT_PULLUP);
    pinMode(BUTTON_PIN_4,INPUT_PULLUP);
    pinMode(BUTTON_PIN_5,INPUT_PULLUP);
    pinMode(BUTTON_PIN_6,INPUT_PULLUP);
    pinMode(BUTTON_PIN_7,INPUT_PULLUP);
    pinMode(BUTTON_PIN_8,INPUT_PULLUP);

// Setup Bounce instance - First attach them to the debouncer
    debouncer[0].attach(BUTTON_PIN_1);
    debouncer[1].attach(BUTTON_PIN_2);
    debouncer[2].attach(BUTTON_PIN_3);
    debouncer[3].attach(BUTTON_PIN_4);
    debouncer[4].attach(BUTTON_PIN_5);
    debouncer[5].attach(BUTTON_PIN_6);
    debouncer[6].attach(BUTTON_PIN_7);
    debouncer[7].attach(BUTTON_PIN_8);

    Keyboard.begin();
    // Then set the interval (e.g. 10 ms)
    unsigned char i;
    for (i = 0; i < 8; i++)
        prevValues[i] = 0;
}

void loop() {
    // Update the Bounce instances
    unsigned char i;
    for (i = 0; i < 8; i++)
        debouncer[i].update();

    bool debounced_btn_1 = debouncer[0].read();
    bool debounced_btn_2 = debouncer[1].read();
    bool debounced_btn_3 = debouncer[2].read();
    bool debounced_btn_4 = debouncer[3].read();
    bool debounced_btn_5 = debouncer[4].read();
    bool debounced_btn_6 = debouncer[5].read();
    bool debounced_btn_7 = debouncer[6].read();
    bool debounced_btn_8 = debouncer[7].read();      


    for (i = 0; i < 8; i++)
    {
        bool currVal = debouncer[i].read();
        if ((!currVal) && (prevValues[i]))
        { // If now it is pressed (value = 0) and it wasn't before (prevvalue = 1)
            Keyboard.write(keyboardValues[i]);
        }
    }

}

正如我已经向您建议的那样,如果您只需要使用一个按钮,则此解决方案效果很好。如果您需要更多按钮,您应该为每个按钮复制此代码。

另一种方法是直接检查端口值(一次 8 位)。我认为这是性能的最佳解决方案,但它不是很可读。

在我看来,bounce2 解决方案是最好的。你只需要

  1. 下载 Bounce2 库并正确安装它
  2. 在你的素描中使用它。

例如,您可以使用数组来存储所有保镖。 8 针示例:

#include <Bounce2.h>

// Instantiate a Bounce object
Bounce debouncer[8];

void setup() {
    // First setup all the pins as input with pullup
    pinMode(BUTTON_PIN_1,INPUT_PULLUP);
    pinMode(BUTTON_PIN_2,INPUT_PULLUP);
    ...

    // After setting up the button, setup the Bounce instance
    // First attach them to the debouncer
    debouncer[0].attach(BUTTON_PIN_1);
    debouncer[1].attach(BUTTON_PIN_2);
    ...

    // Then set the interval (e.g. 10 ms)
    unsigned char i;
    for (i = 0; i < 8; i++)
        debouncer[i].interval(10);

    // other initializations
    ...
}

void loop() {
    // Update the Bounce instances
    unsigned char i;
    for (i = 0; i < 8; i++)
        debouncer[i].update();

    // From now on you can access the debounced
    // values directly from the array, for instance

    bool debounced_btn_1 = debouncer[0].read();

    bool debounced_btn_8 = debouncer[7].read();

    ...
}

在你的例子中,既然你想发送一个键盘命令,你可以将所有的值存储在一个数组中(当然可以修改),然后在需要的时候发送;您还应该记住在按下按钮时发送值的最后状态...

bool prevValues[8];

// Keyboard values for btn   1    2    3    4    5    6    7    8
char keyboardValues[] =    {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H'};

void setup() {
    // Pins initializations
    ...

    for (i = 0; i < 8; i++)
        prevValues[i] = 0;
}

void loop() {
    // Update the Bounce instances
    ...


    for (i = 0; i < 8; i++)
    {
        bool currVal = debouncer[i].read();
        if ((!currVal) && (prevValues[i]))
        { // If now it is pressed (value = 0) and it wasn't before (prevvalue = 1)
            Keyboard.write(keyboardValues[i]);
        }
    }

    ...
}