Почему скетч сообщает о слишком большом количестве нажатий кнопок?
Я использую кнопку для взаимодействия с эскизом (на моем Uno), и в основном она работает нормально. Однако иногда кажется, что он обнаруживает несколько нажатий, хотя нажата только один раз.
Это небольшая кнопка мгновенного действия, установленная на цепи, которая обычно открыта. Он подключен к +5 В напрямую к входному контакту. Я также добавил на вывод резистор сопротивления 10 кОм, чтобы вход не оставался плавающим.
Вот тестовый эскиз, который я использовал, который сообщает о количестве нажатий на последовательный монитор:
int oldState = LOW;
int numPresses = 0;
void setup()
{
pinMode(5, INPUT);
Serial.begin(9600);
}
void loop()
{
const int newState = digitalRead(5);
if (newState != oldState) {
if (newState == HIGH) Serial.println(++numPresses);
oldState = newState;
}
}
Иногда, когда я нажимаю кнопку один раз, монитор последовательного порта показывает два нажатия подряд. Иногда он даже сообщает о нажатии, когда я отпускаю кнопку.
Можно ли это исправить? Или у меня просто неисправна кнопка, булавка или что-то в этом роде?
3 ответа
Лучший ответ:
Отказ от контакта
Это называется отскоком контактов и происходит, когда металлические контакты кнопки или переключателя отскакивают друг от друга при нажатии. Микроконтроллер достаточно быстр, чтобы уловить эти скачки, и, что касается его, вы переключаете переключатель много раз за 10 миллисекунд.
Разные переключатели и кнопки будут иметь разную степень отскока контактов, и даже один переключатель будет вести себя по-разному при двух нажатиях.
Вот нажатие кнопки, зафиксированное на осциллографе (изображение взято с сайта Maxim):< /п>
При скорости 2 мс/дел мы не видим стабильного сигнала до тех пор, пока не пройдет 6 мс после первого контакта!
Решения
Добавить задержку
Самое простое решение — ввести небольшую задержку после прочтения ввода кнопки. Это не позволит коду обнаружить какие-либо отскоки, и когда он возобновится, сигнал должен быть стабильным.
if (digitalRead(A3) == 0) {
// делаем что-то здесь
delay(500);
}
В приведенном выше примере я задерживаю 500 мс после считывания состояния вывода. Обычно кнопка находится в высоком положении, поэтому, когда я нажимаю ее, состояние контакта переходит в логический 0. Я улавливаю это в коде и делаю что-то, а затем жду не менее 500 мс, прежде чем продолжить.
Очевидно, что этот код просто останавливается на полсекунды каждый раз, когда вы нажимаете кнопку, что может быть приемлемо или неприемлемо для вашего приложения. Вы также можете уменьшить величину задержки в зависимости от времени дребезга контактов вашего переключателя, но здесь я перестраховываюсь.
Игнорировать нажатия кнопок слишком близко друг к другу
Аналогично приведенному выше решению, но вместо добавления жесткой задержки вы используете функцию millis()
, чтобы отслеживать, когда в последний раз срабатывал переключатель. Каждый раз, когда вы видите триггер переключения, вы сравниваете его со временем и, если прошло недостаточно времени (скажем, 500 мс в моем предыдущем примере), вы его игнорируете.
Это решает проблему использования delay()
в вашем коде.
Переключение микросхемы дебаунсера
Есть такие вещи, как MAX6816, который представляет собой микросхему, которую вы вставляете между коммутатором. и вход микроконтроллера. Это осудит сигнал для вас. При цене 1,62 доллара США за 1 тысячу долларов вы, вероятно, никогда этим не воспользуетесь.
Другое
Есть много решений этой проблемы... Я всегда делаю это программно, но некоторые другие включают использование защелки или конденсатор.
Код Debounce — один пост, чтобы управлять всеми
спасибо, я учусь, и это сводило меня с ума!, @Gothburz
Сами контакты кнопки, вероятно, подпрыгивают, входя и выходя из контакта, что приводит к многократному размыканию и замыканию цепи, даже если положение кнопки не меняется.
Это распространенная проблема с кнопками, и я бы проверил ее в первую очередь. Чтобы это исправить, вам нужно убрать дребезг кнопки. Это можно сделать разными способами, некоторые из которых можно реализовать в самом эскизе.
Хорошим решением является код, который измеряет продолжительность каждого состояния кнопки и регистрирует изменение состояния только в том случае, если текущая продолжительность превышает желаемую. Эту опцию следует использовать для более сложных проектов. Код для него будет зависеть от проекта и, вероятно, будет использовать переменные, определенные в эскизе, но пример того, что необходимо сделать, можно найти здесь.
Если эскиз очень простой или вы просто хотите убедиться, что проблема в отскоке, вы можете добавить небольшую задержку после изменения состояния кнопки. Например:
void loop()
{
const int newState = digitalRead(5);
if (newState != oldState) {
if (newState == HIGH) Serial.println(++numPresses);
oldState = newState;
delay(10) //Отрегулируйте длину задержки так, чтобы она была как можно короче, не вызывая ошибок
}
}
Это ваша кнопка подпрыгивает, что вполне обычное поведение; это не имеет никакого отношения к качеству кнопок.
Есть два способа «устранить дребезг» кнопки: аппаратно или программно.
Лично я предпочитаю аппаратное обеспечение; просто поищите в Google схему устранения дребезга кнопок
, и вы найдете множество примеров.
Если у вас нет необходимых компонентов, вы можете использовать программное устранение дребезжания.
Что касается программного обеспечения, у вас есть пример здесь на веб-сайте Arduino.
Некоторые кнопки подпрыгивают гораздо сильнее, чем другие, так что это как-то связано с качеством кнопок., @sachleen
@sachleen Не уверена, что сказала бы так; это существенно зависит от металла, из которого изготовлены контакты кнопки. Я не думаю, что можно найти непрыгающую кнопку на все случаи жизни. Ожидается дребезг переключения, и он особенно укусит вас, если ваш скетч выполняется быстро между двумя вызовами digitalRead()
., @jfpoilpret
Также подпрыгивание будет зависеть от того, как нажимается кнопка (например, какая сила к ней приложена и как)., @jfpoilpret
Хотя это явление называется дребезгом контакта, с электрической точки зрения оно «выглядит» как «подпрыгивание» (и на самом деле может включать в себя некоторое фактическое «подпрыгивание»), в механическом переключателе контакты никогда не приближаются и не отходят друг от друга полностью под прямым углом; неизбежна некоторая степень скольжения друг по другу. Скольжение шероховатых поверхностей - это то, что вызывает явление замыкания-разрыва-сделания..., даже если контакты на самом деле не «отскакивают». (Представьте себе, что один гладкий камень скользит по другому). Обратите внимание, что это также означает, что разрыв контакта также будет включать в себя разрыв-размыкание-разрыв...., @JRobert
- Несколько кнопок на одном прерывании, как устранить дребезг?
- 4:1: ошибка: expected initializer before 'void'
- Как подключить выход к входу Pullup другого arduino
- NodeMCU - Vin контакт как выход 5V?
- Использовать все контакты как цифровые входы/выходы
- Как переключить светодиод при нажатии кнопки?
- Что такое ICSP pin (разъём)?
- Сколько датчиков может поддерживать один модуль Arduino?
Таким образом, может показаться, что при нажатии кнопки напряжение становится странным... не могли бы вы проверить напряжение с помощью измерителя и посмотреть, что произойдет? Возможно, кнопка просто создает странный контакт и, следовательно, контактирует там, где этого не должно быть..., @hichris123
Измеритель работает стабильно, если он подключен между +5 В и землей (хотя обычно он не показывает коротких всплесков)., @Peter Bloomfield
@ hichris123 Мультиметры обновляют дисплей только несколько раз в секунду. То, что мы ищем, длится максимум пару сотых секунды. Чтобы это увидеть, действительно нужен осциллограф. Смотрите мой ответ на картинке., @sachleen
@sachleen Да, не был уверен в этом. Мне сейчас нужен осциллограф (у меня есть только мультиметр и еще кое-что)., @hichris123
Хе-хе, может быть, вам следовало перефразировать заголовок вопроса примерно так: «Каковы веские основания покупать осциллограф?» :-), @jfpoilpret