Похоже ли это на хороший подход к декодированию тупой клавиатуры?

isr keypad demultiplex

Фон:


Я купил «тупую» 8-контактную клавиатуру 4х4 для использования в проекте. (Этот: https://www.sparkfun.com/products/14881 Он имеет провод, подключенный к каждой строке, и провод, подключенный к каждому столбцу. Когда вы нажимаете клавишу, она соединяет вывод строки и вывод столбца. Вы должны использовать выходы GPIO для подачи +5 В вниз по одной строке/столбцу за раз, а затем использовать входы для поиска HIGH на соответствующем наборе контактов из другого измерения, что указывает на соединение между конкретной парой строк/столбцов. .)

Я нашел фреймворк MultitapKeypad, который на первый взгляд показался идеальным. Это красивый чистый объект C++ с простым основным методом getKey(), который возвращает структуру с информацией о клавише, нажатой пользователем. Он распознает длинные и повторные нажатия, и я планирую это использовать.

Однако, когда я изучил это, я обнаружил, что внутри все не так хорошо. Метод getKey использует цикл while (без нажатия клавиши), который повторяется вечно. Решение автора, позволяющее не блокировать Arduino каждый раз, когда вы ожидаете нажатия клавиши, состоит в том, чтобы предоставить функцию обратного вызова, которую библиотека вызывает из цикла while.

Идея полностью перевернуть поток управления скетчом и выполнять всю обработку событий вашего приложения из обратного вызова класса клавиатуры кажется неправильной. Затем поток управления из основного цикла приложения должен пройти через обратный вызов клавиатуры, когда я жду клавиш, или через какой-либо другой поток в противном случае.

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

Поэтому я подумывал о написании собственного обработчика клавиатуры.

Мой текущий проект — контроллер питания освещения, зарядные устройства и сушилка с теплым воздухом с регулируемой влажностью — будет запускать все эти функции одновременно. Он оснащен ЖК-дисплеем с подсветкой и использует датчик движения и фоторезистор для включения света при обнаружении движения в условиях низкой освещенности.

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

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


Мой предлагаемый дизайн:

Я подумывал подключить клавиатуру так, чтобы все контакты ряда были подключены к 9-му контакту с помощью диодов, аноды были направлены в сторону 9-го контакта. Я бы установил этот 9-й вывод в режим INPUT_PULLUP и подключил его к прерыванию, настроенному на запуск по сигналу FALLING (или, возможно, CHANGE. См. ниже). Все выводы строк также будут настроены как INPUT_PULLUP. Все контакты столбца будут настроены как выходы и переведены в НИЗКИЙ уровень.

Когда пользователь нажимал клавишу, он соединял один из контактов столбца с контактом строки. Это приведет к переводу входа этого вывода строки в НИЗКИЙ уровень, а также переводит вывод прерывания в НИЗКИЙ уровень, запуская ISR (процедуру обслуживания прерываний).

В ISR я бы использовал регистры портов, чтобы переключить все выводы столбца на ВЫСОКИЙ уровень, а затем переключал один вывод столбца обратно на НИЗКИЙ, следя за тем, чтобы вывод строки также опускался на НИЗКИЙ уровень. Если один и только один столбец переходит в НИЗКИЙ уровень, то одна и только одна строка переходит в НИЗКИЙ уровень, я знаю, что нажата только одна кнопка, и знаю комбинацию строк/столбцов и, следовательно, нажатую клавишу. Если несколько столбцов запускают строку или несколько строк падают до уровня LOW, я знаю, что нажата более одной клавиши. (Я мог бы использовать эту информацию, чтобы сообщать о нажатиях нескольких клавиш, если мне нужно, хотя >2 клавиши одновременно быстро становятся беспорядочными.)

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

Остальная часть моего скетча затем могла бы запросить у моей клавиатуры статус «ключ готов» и прочитать одну или несколько клавиш по мере необходимости. Я бы предоставил служебные функции для очистки ключевого буфера, способ обнаружения переполнения буфера и т. д.

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

Мне также нужно было бы добавить ту или иную систему устранения дребезжания. Я мог бы использовать простой RC-фильтр на каждом входном контакте, но на макетной плате у меня осталось мало места, и для этого потребовалось бы 4 конденсатора и 8 резисторов.

Судя по тому, что я прочитал, функция millis() немного медленная, и ее лучше избегать в процедурах ISR. Есть ли быстрая альтернатива получению текущего значения часов непосредственно в ISR? Если да, то я мог бы использовать программное обеспечение для устранения дребезга клавиш.

Есть ли в моем плане очевидные недостатки? Разумно ли использовать такой ISR? Клавиатура на самом деле не замыкает контакты строки/столбца вместе. Я думаю, он использует переменные сопротивления между комбинациями строк и столбцов, чтобы вы могли использовать делитель напряжения и аналоговый вход, чтобы определить, какая клавиша была нажата, на основе измеренного напряжения. В документации к клавиатуре указано, что сопротивление пары строк-столбцов варьируется от 10 до 625 Ом. Я предполагаю, что сопротивление ключа достаточно низкое, поэтому даже при наличии сигнальных диодов в цепи сопротивление закрытого переключателя должно быть достаточным, чтобы перевести мой вывод прерывания и мои контакты строки в НИЗКОЕ положение.

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

В качестве альтернативы, существуют ли другие платформы клавиатуры, которые поддерживают клавиатуры 3x4 и 4x4 и предлагают такие функции, как повторные нажатия, длинные нажатия и позволяют запускать события при ЛЮБОМ нажатии клавиши (чтобы я мог держать свой ЖК-дисплей включенным).

>

, 👍-1

Обсуждение

Это предлагаемое комбинированное аппаратно-программное решение. Я еще ничего не создавал и не писал, поэтому у меня нет кода для публикации. Я надеюсь, что кто-нибудь, у кого больше опыта, чем у меня, расскажет мне об относительных достоинствах того, что я предлагаю., @Duncan C

Где вы прочитали, что функция миллис медленная? Это очень быстро. Что не так с остальной частью вашего эскиза? Функция цикла выполняется в 10 или более раз в секунду? тогда вам не нужны прерывания. Вы можете использовать таймер, который генерирует прерывание (возможно, 20 раз в секунду или чаще) и сканировать всю клавиатуру во время прерывания. Это также облегчает откат. Возможно, вместо такого количества диодов можно использовать транзистор, распознающий нажатие на клавиатуру. Вы раньше создавали кольцевой буфер? Я думаю, что код кольцевого буфера есть в библиотеках Arduino, но я не уверен., @Jot

Я использую 2 датчика температуры/влажности DHT22. Библиотека для их чтения останавливает цикл событий на ≈250 мс за каждое чтение, а я читаю оба события каждые 2 секунды, поэтому цикл событий останавливается в 1/4 времени, каждый раз на 1/4 секунды., @Duncan C

Похоже на проблему XY. Вы хотите читать клавиатуру с быстрой реакцией на ввод пользователя, но у вас есть функция блокировки, которая предотвращает запуск вашего кода, вынуждая вас без необходимости полагаться на прерывания или таймеры. Поиск в Интернете по запросу «DHT22 arduino неблокирующий» показывает, что существуют и другие решения, устраняющие блокировку при считывании показаний датчиков., @jose can u c

Спасибо за это предложение. Я действительно рассмотрю эти альтернативы. Я также хочу посмотреть на лучшие библиотеки для моей клавиатуры., @Duncan C

Я думаю, что волшебными ключевыми словами являются «неблокирующий» и/или «таймер». https://www.eevblog.com/forum/beginners/4x4-keypad-arduino-non-blocking/msg1236988/#msg1236988 Вот сообщение на форуме, в котором есть пример кода для функции клавиатуры, аналогичной вашей структуре, за исключением того, что этот человек устанавливает включить Таймер1 на Arduino для регулярного срабатывания, вызывая ISR, который сканирует ключи. Для этого не требуется внешнее прерывание или прерывание смены контакта, только прерывание по таймеру. Он сканирует достаточно быстро для взаимодействия с человеком (заявление о 160 мкс для сканирования клавиатуры?), @jose can u c


1 ответ


-1

Я сделал простой радиочастотный пульт дистанционного управления, используя очень похожий метод с кепьядом 4x4, с диодами, соединенными вместе для запуска прерывания. и прочитать нажатие клавиши. После любого нажатия клавиши прерывание пробуждало процессор (немодифицированный Promini 8 МГц с Atmega328P), он использовал библиотеку keypad.h для обнаружения нажатой клавиши и отправлял ее через короткий радиочастотный импульс (передатчик 433 МГц) с использованием библиотеки (8 лет назад). теперь, рисуя пробел в имени), которая стала библиотекой Radiohead (найдите ее на github), а затем снова заснула. Работает около месяца от LiPo аккумулятора емкостью 2000 мАч (или около того?), прикрепленного к нижней части платы.

Насколько я помню, перед переходом в спящий режим мне приходилось записывать выходы, противоположные их нормальному состоянию, чтобы прерывание работало корректно, а затем восстанавливать их перед чтением значения keypad.h. Затем верните их в противоположное состояние, прежде чем вернуться в спящий режим. Работает хорошо, но я передаю только один ключ за раз. Полной информации у меня здесь нет, могу опубликовать ее позже, когда вернусь домой. Вы можете увидеть изображение пульта внизу этого сайта — извините за прокрутку, мне удалось перезаписать файл index.html, в котором были ссылки/вкладки для перехода к различным областям, которые мой сын сделал для меня. http://www.crossroadsfencing.com/BobuinoRev17

,