минимальный код для устранения дребезга нескольких кнопок

У меня есть 4 кнопки, подключенные к 4 контактам, настроенным как входы с активированным внутренним подтягивающим резистором...

достаточно ли этой функции для получения состояния устранения дребезга нажатой кнопки?

byte buttonPressed(){
  byte btn = 0;
  if (digitalRead(30)==LOW) btn = 1; else
  if (digitalRead(9)==LOW) btn = 2; else
  if (digitalRead(31)==LOW) btn = 3; else
  if (digitalRead(8)==LOW) btn = 4;
  delay(20);
  return btn;
}

любые строго необходимые улучшения приветствуются...

, 👍1

Обсуждение

я пишу код а-ля-ва-вите, спасибо Эдгар., @moyoumos

В настоящее время в вашем коде отсутствует debounceing. Задержка совершенно бесполезна., @Kwasmich

Упс! Я удалил свой предыдущий комментарий, который был неправильным: я не заметил ваши else из-за вашего очень нетрадиционного стиля отступов., @Edgar Bonet


4 ответа


Лучший ответ:

3

Да, ваш код должен работать как самое простое средство устранения дребезга, хотя Время отката может быть немного короче. Однако следует отметить, что во многих случаях хотелось бы иметь немного больше, чем самое основное. Один также может понадобиться:

  • отказ от работы: при нажатии кнопки ваша рука может сделать Контакты немного смещаются, создавая всплески показаний, которые не являются связано с реальным изменением положения кнопки; вы не хотите эти шипы следует читать как «отпущены и нажаты снова»
  • обнаружение края: во многих случаях вас больше интересует кнопка событие нажатия, чем знание того, нажата ли кнопка или поднята; это может обрабатываться другой функцией, но может быть удобно интегрировать это с отскоком
  • неблокирующая операция: у вашей программы могут быть дела поважнее чем тратить циклы ЦП внутри delay().

Вот почему большинство кодов устранения дребезга значительно более эффективны. сложно. Но часто оно того стоит.


Правка 1: В свете комментариев, некоторые разъяснения кажутся необходимыми. нужно. Есть два вида сбоев, которые может вызвать механическая кнопка опыт:

  1. когда кнопка механически меняет положение, т.е. она нажато или отпущено; это называется отскок
  2. когда кнопка удерживается нажатой, особенно если давление на кнопка расположена низко, а палец, оказывающий на нее давление, несколько шаткий.

Большинство библиотек устранения дребезга, которые вы можете найти, на самом деле решают оба типа глюки. Таким образом, они делают больше, чем просто устранение дребезга, они делают то, что я называется «deglitching». Предыдущие ответы неявно предполагают, что правильный код устранения дребезга должен учитывать оба типа.

Код, указанный в вопросе, относится только к первому типу глюки, т.е. отскоки в строгом смысле. Вот почему я написал что он делает «самое основное устранение дребезга». Однако он восприимчив к второй тип глюков. Так что да, с этим кодом глюки могут сохраняться даже после устранения дребезга.

Правка 2: В качестве примера рассмотрим библиотеку Bounce 2. Она обеспечивает обнаружение краев, неблокируемую работу и, по умолчанию, конфигурация, полное устранение сбоев. Однако, его можно настроить на использование альтернативный алгоритм устранения дребезга под названием «Блокировка интервал», который более чувствителен, но не защищает от Ошибки «типа 2», упомянутые выше: он «не устраняет шум», как документация гласит.

,

есть ли какая-то связь между устранением сбоев и устранением дребезга?..., @moyoumos

@moyoumos: Отскок — это просто определенный вид сбоя, который происходит, когда кнопка нажата или отпущена. Если вы делаете deglitching, например, ждете, пока уровень не стабилизируется, вы также устраняете дребезг. Обратное неверно: код, который вы опубликовали, удаляет отскоки, но он не очищает должным образом сбои, которые происходят, когда кнопка удерживается., @Edgar Bonet

согласно тому, что вы говорите, глюки могут существовать или сохраняться даже после устранения дребезга!!!, @moyoumos

@moyoumos: Да, см. измененный ответ., @Edgar Bonet

Я думаю, что любой алгоритм устранения дребезга, основанный на временном интервале, не может устранить сбои, поскольку сбои (или глюки) сохраняются по истечении этого временного интервала!!! Я не прав?, @moyoumos

@moyoumos: Устранение сбоев по времени основано на предположении, что если кнопка выдает постоянные показания в течение заданного интервала времени, то эти показания не являются сбоем (сбои кратковременны)., @Edgar Bonet


0

Нет. На самом деле он просто проверяет каждую кнопку по одной. Кроме того, проверяется только последняя кнопка, поскольку она перезаписывает переменную btn.

Самый простой способ использования кнопки устранения дребезга 1:

byte buttonPressed()
{
    byte btn = 0;

    byte btn1Before = digitalRead(30);
    delay(50); // Подождать 50 мс или 100 в зависимости от времени дребезга
    byte btn1After = digitalRead(30);

    if ((btn1Before == LOW) && (btn1After == LOW))
    {
        btn = 1;
    }
}

Вам нужно сделать то же самое, что и другим. Вы можете использовать только одну задержку (просто добавьте 4 переменные до и после и проверьте их.

byte buttonPressed()
{
    byte btn = 0;

    byte btn1Before = digitalRead(30);
    byte btn2Before = digitalRead( 9);
    byte btn3Before = digitalRead(31);
    byte btn4Before = digitalRead( 8);

    delay(50); // Подождать 50 мс или 100 в зависимости от времени дребезга

    byte btn1After = digitalRead(30);
    byte btn2After = digitalRead( 9);
    byte btn3After = digitalRead(31);
    byte btn4After = digitalRead( 8);

    if ((btn1Before == LOW) && (btn1After == LOW))
    {
       btn = 1;
    } 
    else if ((btn2Before == LOW) && (btn2After == LOW))
    {
       btn = 2;
    } 
    else if ((btn3Before == LOW) && (btn3After == LOW))
    {
       btn = 3;
    } 
    else if ((btn4Before == LOW) && (btn4After == LOW))
    {
       btn = 4;
    } 

    return btn;
}

Обратите внимание, что таким образом программа не будет отвечать в течение 50 мс. Если вы этого не хотите, вам придется использовать millis, но это усложнит задачу. Проверьте пример устранения дребезга на сайте Arduino.

,

зачем проверять состояние кнопки до и после?..., @moyoumos

Проверяя это состояние снова после времени дребезга (я выбрал 50 мс). Если дребезг завершен, он покажет дважды LOW., @Michel Keijzers

Я думаю, что если оборудование обнаруживает первый низкий уровень, то это происходит из-за нажатия кнопки, и задержки (20 или 50 мс) достаточно, чтобы игнорировать все отскоки!!..., @moyoumos

Я хотел придерживаться оригинальной программы. Если прерывания не используются, то таким образом приоритет может быть изменен программно., @Michel Keijzers


0

Нет - просто delay() после считывания кнопки не скажет вам, подпрыгивает ли кнопка или, что еще важнее, каково ее конечное состояние. Для устранения подпрыгивания требуется, чтобы вы знали, что кнопка

  • измененное состояние;
  • перестал менять состояние;
  • в каком состоянии он находится.

Вам нужно будет заметить, что текущее состояние не соответствует последнему состоянию с устраненным дребезгом, которое вы видели; затем либо часто проверяйте его до тех пор, пока оно не перестанет менять состояние в течение некоторого количества тестов, либо просто подождите известное максимальное время, необходимое для стабилизации; затем считайте, сохраните и верните конечное состояние.

,

0

Хотя ответ @MichelKeijzers — это хорошее решение для простых запросов в основном цикле. Это непрактично для прерываний. Прерывания могут заблокировать весь MCU, а прерывание процедуры прерывания может вызвать серьезные проблемы.

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

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

,