Дребезг кнопки на аналоговом входе
- Войдите на сайт для отправки комментариев
Втр, 03/06/2014 - 21:23
Подключаю несколько кнопок на аналоговый вход (не хватает пинов). Работает. Нужно, чтобы кнопка могла работать в нескольких режимах. Вроде работает, но дребезг замучал. Как в этой ситуации его победить
a = analogRead(0); delay(15); if (a>250 && a<350) { regim++; flag=1; if(regim > 3) regim=1; } if(regim == 1) { Serial.println("fffffffffff"); digitalWrite(led, LOW); } if(regim == 2) { Serial.println("nnnnnnnnnnn"); digitalWrite(led, HIGH); } if(regim ==3) { Serial.println("ccccccccccc"); unsigned long currentMillis = millis(); if(currentMillis - previousMillis > interval) { previousMillis = currentMillis; if (ledState == LOW) ledState = HIGH; else ledState = LOW; digitalWrite(led, ledState); } }
Вот обнуление флага
Опрашивать несколько раз с задержками, сравнивая с предидущим значением, как это делается с цифровыми кнопками...поищите что-то типа "программная защита от дребезга"
Вначале нужно научится бороться с дребезгом обычной кнопки. Если умеете - покажите как бы вы делали для обычной кнопки (на цифровом входе), если не умеете, то читайте прикрепленную тему Работа с кнопками. В помощь новичку.
Чаще всего через библу Bounce
Если одна кнопка, то так и всегда гуд( пример взял в теме Работа с кнопками)
Ну тогда у вас есть два варианта:
1. Искать библиотеку типа Bounce но с поддержкой аналоговых (сомневаюсь, хотя может быть и существует)
2. Все таки разобратся, как самому, без библиотеки давить дребезг цифровый кнопок. Благо ничего сверх-сложного в этом нет. Пара строчек, только "понять идею" (если не понятно в той теме, так в инете нагуглить можно статьи по этому поводу. Все - для новичков).
А понимая как давиться "цифровой" дребезг, несожно и "аналоговый" сделать аналогично. Либо сами сообразите, либо подскажу как свести "аналоговую задачу", к уже решенной "цифровой".
Самое интересное, что остальные кнопки на ан. входе работают без проблем, а вот которая с режимами - здесь дребезг дубасит.
>Если одна кнопка, то так и всегда гуд( пример взял в теме Работа с кнопками)
Честно говоря, я не вижу где-тут "защита от дребезга" (хотя в комментах это и написано. Но коменты - явно расходятся с кодом. Скажем написанно "обнуляем переменную knopka", в коде flag=0). Так что, скорее всего, это кнопка у вас "не дребезжит".
Вообщем-то сама идея "антидребезга", проста до безобразия: после того как поймали первое нажатие кнопки - перестаем ее читать какое-то небольшое время (милиссекунд 50-100). Как правило человек с такой скоростью нажимать не может, а все дребезги - успевают за это время закончится.
Самый тупой вариант это сделать: воткнуть, скажем delay(50) после того как детектировали что кнопка нажата.
Вообщем смотрите, вот как бы мы ловили нажатие цифровой кнопки, подтянутой к питанию (именно "нажатие", а не удержание)
Так же обратите внимание, что у меня разделены "котлеты и мухи". Чтение кнопки и логика определения что произошло с кнопкой. Только одно чтение digitalRead(). Сама "логика обработки" кнопки - ничерта не знает о том как мы ее читали. Она смотрит только на переменную buttonState. Которая имеет значения true если кнопка в данный момент удерживается.
Теперь, добавим "антидребезг". Вначале самым "тупым способом".
То есть после того как мы словили нажатие кнопки, мы просто останавливаем контроллер на 100ms. В результате все лишние нажатия - он просто "прощелкает клювом".
Спасибо, щщщщас попробую
Но delay() - в большинстве случаев не приемлим в боевых скетчей. Именно из-за того, что полностью останавливает скетч (мало ли что нам еще нужно в этот момент делать?)
Поэтому используем millis(). Идея, в чем-то родственна тому, что вы использовали в стартовом скетче для мигания светодиодом без delay()
1. Запоминаем момент когда кнопка была нажата.
2. Все "анализы нажатий" делаем только если с момента нажатия прошло достаточно времени (больше 100ms)
Пока ход рассуждений понятен?
Ну, вот... а теперь мы можем попробовать перейти на работу с аналоговыми. Так как у нас нет никаких digitalRead в if-фах. То всю логику "ловли нажатия" и "антидребезга" - мы не трогаем. Она не зависит от типа кнопки. Единстевенная строка которая потребует нашего внимания, это само чтение текущего состояни, кнопки
Нам нужно переделать ее таким образом, что-бы читался аналоговых вход. И buttonState, по прежнему принимал true, если кнопка сейчас нажата.
Или чуток короче (разница - в синтаксисе, сут - таже самая)
P.S. я поменял тип переменных buttonState и prevButtonState с byte, на boolean. Сточки зрения "работоспособности" - это без разницы, но так человеком легче читается. Более явно видно, что в переменных могут быть только true/false (1/0)
Да, спасибо
Ох, строка 5-ть, с ошибкой....
Написал "будем хранить", а по факту оно будет терятся сразу по оконачании loop().
Что-бы не терялось, ее нужно либо вынести за пределы loop() (в начало скетча).
Либо добавить ключевое слово static (как мы делали это для prevButtonState)
P.S. Писал все из "головы на ходу", в компиляторе не проверял. Сугубо для "объяснить идею".
Вот так работает, спасибо за помощь
Ну, вот... а теперь мы можем попробовать перейти на работу с аналоговыми. Так как у нас нет никаких digitalRead в if-фах. То всю логику "ловли нажатия" и "антидребезга" - мы не трогаем. Она не зависит от типа кнопки. Единстевенная строка которая потребует нашего внимания, это само чтение текущего состояни, кнопки
Нам нужно переделать ее таким образом, что-бы читался аналоговых вход. И buttonState, по прежнему принимал true, если кнопка сейчас нажата.
Или чуток короче (разница - в синтаксисе, сут - таже самая)
P.S. я поменял тип переменных buttonState и prevButtonState с byte, на boolean. Сточки зрения "работоспособности" - это без разницы, но так человеком легче читается. Более явно видно, что в переменных могут быть только true/false (1/0)
А можно полный вариант этого алгоритма выложить ? С цифровой кнопкой вроде все понятно, а с аналоговыми никак не могу понять.
Могу предложить готовую библиотеку. Вот пример ее использования.
AnalogKey5 это класс обработчика 5-ти кнопок на аналоговом входе. Числа при создании класса - это средние значения АЦП для каждой из кнопок. Последнее - половина ширины зоны для каждой кнопки. Для первой кнопки зона в данном примере 0...20, для второй 134...154.
Если значение АЦП находится в этой зоне в течение 50мс, то считается, что кнопка нажата. Выход из зоны так же снимает значение нажатия клавиши через 50мс. Времена антидребезга жестко зашиты в библиотеке. Меняются изменением ccp-файла. В методе void AnalogKey5::Refresh(int aValue) находите 50 и ставите нужное значение.
Библиотека здесь
https://github.com/X-Dron/X-Dron_lib/archive/master.zip
ошибся, пардон
проверил, все там есть
Это информация о только что скачанном архиве, с сервера. Время создание локальной копии на компе
https://yadi.sk/i/9TRd12o-fG4Gx
Вот содержимое архива
https://yadi.sk/i/3yMBssfvfG4Jg
Изменен 24-го февраля.
Могу предложить готовую библиотеку. Вот пример ее использования.
Вроде все понятно, кроме вот этой строки
Я так понимаю она должна подавать на выходной пин такой же потенциал, как берётся со входного пина и соответственно светодиод будет гореть ярче или тусклее? Что значит Key1?
Как мне прописать другое действие, например вывод в сериал порт определенных фраз в зависимости от того, какая кнопка нажата?
Извиняюсь за тупые вопросы, но мой уровень не очень высокий во всех этих классах и т.п.
У Вас что памяти для программы слишком много?
Повесьте ёмкость и не морочьтесь.
У Вас что памяти для программы слишком много?
Повесьте ёмкость и не морочьтесь.
Можно по-подробнее - куда и какую? Видимо Вы пытались вставить схему, но её не видно.
Пытался.
http://vrtp.ru/index.php?showtopic=20766
там... В середине первой простыни. Я делаю проще, 0.1мкФ от кнопки на землю , правда для цифровом входе. Однако зависит от Вашей работы на аналоговом порте. Куда и как подвешено, куда замыкается, одна кнопка , или несколько?
1. Аналоговые входы A0-A5 могут быть быть использованы как обыкновенные дискретные. Для их считывания используются адреса пинов 14-19. Например, pinMode(14, INPUT); digitalWrite(14, LOW); для A0
2. Класс AnalogKey5 писался как альтернатива "стандартному решению" для такого устройства
http://www.droboticsonline.com/media/catalog/product/cache/1/image/5e06319eda06f020e43594a9c230972d/a/r/arduinolcdkeypadforstore3.jpg
с такой схемой подключения
http://chingachgook.net/wp-content/uploads/2014/06/Keypad.jpg
Здесь на один аналоговый вход вешаются 5 кнопок. Нажатие каждой соответствует своему уровню напряжения на A0. Что соответствует первому посту темы
3. Относительно п2. AKeys.Key1() это метод, который возвращает булевое значение "клавиши". Нажата/отпущена. digitalWrite(LED_PIN, AKeys.Key1()); зажигает лампочку, если кнопка надата
4. Памяти для простейших "проектов" чаще всего за глаза.
1. Аналоговые входы A0-A5 могут быть быть использованы как обыкновенные дискретные. Для их считывания используются адреса пинов 14-19. Например, pinMode(14, INPUT); digitalWrite(14, LOW); для A0
2. Класс AnalogKey5 писался как альтернатива "стандартному решению" для такого устройства
http://www.droboticsonline.com/media/catalog/product/cache/1/image/5e06319eda06f020e43594a9c230972d/a/r/arduinolcdkeypadforstore3.jpg
с такой схемой подключения
http://chingachgook.net/wp-content/uploads/2014/06/Keypad.jpg
Здесь на один аналоговый вход вешаются 5 кнопок. Нажатие каждой соответствует своему уровню напряжения на A0. Что соответствует первому посту темы
Подключаю несколько кнопок на аналоговый вход (не хватает пинов). Работает.
3. Относительно п2. AKeys.Key1() это метод, который возвращает булевое значение "клавиши". Нажата/отпущена. digitalWrite(LED_PIN, AKeys.Key1()); зажигает лампочку, если кнопка нажата. Для клавиши 2 AKeys.Key2()... для пятой AKeys.Key5()
4. Памяти для простейших "проектов" чаще всего за глаза.
С изменением режима немного по позже
По нажатию второй клавиши на аналоговом вводе меняется режим от 0 до 2 и выводится на терминал.
там... В середине первой простыни. Я делаю проще, 0.1мкФ от кнопки на землю , правда для цифровом входе. Однако зависит от Вашей работы на аналоговом порте. Куда и как подвешено, куда замыкается, одна кнопка , или несколько?
Схема подключения по типу такой. 4 кнопки на один порт.
http://chingachgook.net/wp-content/uploads/2014/06/Keypad.jpg
Про аппаратное устранение дребезга на цифровом порту я в курсе. Как сделать тоже самое на аналоговом порту, если такое возможно?
3. Относительно п2. AKeys.Key1() это метод, который возвращает булевое значение "клавиши". Нажата/отпущена. digitalWrite(LED_PIN, AKeys.Key1()); зажигает лампочку, если кнопка надата
Как оно распознает какая именно кнопка из пяти нажата? Булево возвращает либо да, либо нет. А как распознать что именно нажато в этом примере?
Как оно распознает какая именно кнопка из пяти нажата? Булево возвращает либо да, либо нет. А как распознать что именно нажато в этом примере?
Читайте 18й пост.
сначала надо настроить уровни срабатывания созданием экземпляра класса
Потом делаем обновление внутренних переменных, делая расчет с новым входным значением входного аналогового сигнала
А потом запрашивать нажато/ненажато
Или Вам непонятно как из int значения получается boolean?
Элементарный пример - операторы сравнения. :)
digitalWrite(LED_PIN, AKeys.Key1());
эквивалентна такой записи
кто там боролся за краткость кода?
Да повесьте порт на землю кондеем. Впрос не в этом. Сотворите компаратор , чтобы ловил все кнопки формированием уровня ( например нуля). Повесьте на прерывание. Прерывание сделайте FALLING. Внутри прерывания добавьте задержку, сформируйте флаг и остальное обрабатывайте в основном цикле. ОНО будет ловить дребезг , фактически триггер.
Не забудьте. На входе в прерывание запрещайте прерывания , на выходе разрешайте.
сначала надо настроить уровни срабатывания созданием экземпляра класса
Сделал вот так, ничего не изменилось, дребезг остался. Что не так?
Интересно, как Вы по этому коду узнали что есть дребезг?
"Button 1 pressed" выводится все время, пока клавиша нажата.
Правильнее все-же так
А если все-таки нужен фронт нажатия клавиши, то так.
проверил библиотеку X-Dron - всё нормально работает, автор молодца
буду использовать
А если все-таки нужен фронт нажатия клавиши, то так.
Вот это заработало как надо. Сколько кнопку не держи, а все равно только один раз в порт печать идет.
Если кнопок несколько то для каждой нужна переменная boolean Key_Old как я понял.
Спасибо. Но если честно я все равно не понял как оно работает :) Буду использовать как есть.
почитай в его библе файл AnalogKey5.срр там всё расписано
Да я читал. Но это выше моего понимания :)
Alexus-12, а вот если бы вы не стали бы пользоваться библиотекой, то глядишь и научились бы самостоятельно решать этот вопрос, и получили бы самое ценное -опыт.
Извиняюсь за тупые вопросы, но мой уровень не очень высокий во всех этих классах и т.п.
Конечно лучше самому разобраться и понять механизм работы без библиотек - обратите внимание, как происходит борьба с дребезгом и погрешностью АЦП путем битового сдвига в статье - http://codius.ru/articles/221#a18
#define BUTTON A0 // Пин, к которому подключены кнопки (А0)
Подскажите пожалуйста, как прописать несколько пинов если групп кнопок больше одной.
С дребезгом на на аналоговом входе я борюсь так
Подскажите пожалуйста, как прописать несколько пинов если групп кнопок больше одной.
Настолько больше, что нельзя на один пин замкнуть?
Приветствую. Заинтересовался тоже темой подключения пяти кнопок к одному аналоговому порту. У меня возник вопрос как можно определить по аналоговому значению какая кнопка нажата и присвоить соответственное значение переменной?
Я решил написать код так, но уверен что это можно реализовать как нибудь по другому.
Буду очень признателен за советы опытных программистов.
Посмотрите статью http://codius.ru/articles/221 - там много конструкций кода.
Спасибо большое за ссылку, почитал стало не много ясней.
Вопрос назрел такой, как в ардуинке сделать подпрограмму для того чтобы присваивать переменной имя кнопки по коду выше, но что бы это происходило не в цикле основной программы а что б в основной программе прозванивался порт и если кнопка нажата, то обратится к той самой подпрограмме для устранения дребезга, определения нажатой кнопки и присвоения имени некой переменной и вот с ней то и вернуться в цикл основной программы для дальнейшего действия?
Так, а код из сотого абзаца вас чем не устраивает?
Так, а код из сотого абзаца вас чем не устраивает?
Что за сотый абзац?
http://codius.ru/articles/221#a100
Вы хотите такой подход?http://arduino.ru/forum/programmirovanie/rabota-s-knopkami-v-pomoshch-novichku?page=21#comment-269244
Читал я эту тему, там очень сложно пока для меня.
Чего там сложного. Подключили аналоговую клавиатуру . Залили скетч и посмотрели как он работает. убедились в работе, по отправке нужного сообщения в сериал, по нажатию кнопки. Ну а дальше уже прописали, что вам надо сделать по нажатию кнопки. Для чего я пишу эти библиотеки. Для того что бы если надо я банально вставлю в нужную программу и все.