Нажатия клавиш Arduino с помощью кнопок, как устранить дребезг, когда использовать матрицу?

У меня есть простой набор из 8 кнопок, подключенных к плате Teensy 3.2 (которая использует Arduino через плагин Teensyduino). 8 кнопок находятся на контактах 1-8, а их общая линия заземления (по одной линии, припаянной к каждой из них) находится на контакте GND. У меня есть код, чтобы заставить работать любую кнопку, которая работает. В настоящее время он настроен на нажатие второй кнопки типа «А».

Я хотел бы, чтобы кнопки с 1 по 8 печатали A, B, C... и т. д. соответственно, когда вы их нажимаете. Мне сказали о двух проблемах с моей настройкой, первая из которых заключается в том, что копирование кода для каждой кнопки - плохой способ сделать это, а во-вторых, это может привести к проблемам с отказом (создает нажатие клавиши один раз каждые 5 нажатий или около того). Я также хотел бы настроить это, чтобы в будущем я мог написать стороннее приложение, которое настраивает ключи в зависимости от предпочтений пользователя.

Добавляя эти потребности, я не уверен, куда идти дальше. Я достаточно новичок, поэтому не знаю, как правильно включить класс отказов или правильно ли это, учитывая потребности.

Подойдет ли матрица или есть элегантный способ вручную настроить каждую кнопку и компенсировать дребезг? Спасибо~ Текущий код:

#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]);
        }
    }

}

person sylcat    schedule 03.11.2015    source источник


Ответы (1)


Как я уже говорил вам, это решение хорошо работает, если вам нужно использовать только одну кнопку. Если вам нужно больше кнопок, вы должны продублировать этот код для каждой кнопки.

Альтернативой является проверка напрямую значения порта (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]);
        }
    }

    ...
}
person frarugi87    schedule 04.11.2015
comment
Я обновил код в Code Edit 1, насколько я понимаю принципы. Я знаю, что ваша информация великолепна, но я думаю, что неправильно ее перепутал или пропустил что-то, что вызывает ошибки объявления? - person sylcat; 04.11.2015
comment
В вашем коде вы 1) пропустили запись заданных интервальных функций for (i = 0; i < 8; i++) debouncer[i].interval(10); в настройках. 2) восемь вызовов bool debounced_btn_1 = debouncer[0].read(); бесполезны (вы их уже читаете в следующем цикле). 3) вы никогда не объявляли BUTTON_PIN_1 до BUTTON_PIN_8: какие у вас булавки? - person frarugi87; 05.11.2015
comment
В настоящее время мои кнопки находятся на 2-9, а общий провод на GND. - person sylcat; 07.11.2015
comment
Пишите #define BUTTON_PIN_1 2, #define BUTTON_PIN_2 3 и так далее, или const byte BUTTON_PIN_1 = 2;, const byte BUTTON_PIN_2 = 3; и так далее - person frarugi87; 07.11.2015