Матричная клавиатура 4х4

image 2019-07-17 в 12:43, , рубрики: arduino, гайд, клавиатуры, микроконтроллеры, программирование микроконтроллеров, Разработка под Arduino, Разработка робототехники, разработка электроники, Электроника для начинающих

Привет! Сегодня я решил сделать полный гайд по клавиатурам для Arduino. Внимание! Статья ориентирована преимущественно на новичков!

Во многих проектах появляется необходимость создания возможности ввода данных пользователем. Если вам нужно реализовать большое количество кнопок(относительно), то подключать их по-отдельности становится и долго, и нерационально. Для этой цели лучше выбрать какую-нибудь клавиатуру, но как и к любому выбору, к нему нужно подходить осознано. Какие же бывают виды клавиатур и как с ними взаимодействовать? Глобально, все модули данного типа можно поделить на две большие категории: матричные и аналоговые.

Матричные клавиатуры

Самый простой, дешёвый и популярный вид клавиатур. Он относительно прост в изготовлении и заполняет собой большую часть рынка модулей ардуино. Выглядит чаще всего следующим образом:

image

Принцип работы

Понять как устроенная данная клавиатура можно изучив следующую схему:

Чтобы понять какая кнопка была нажата, нужно подавать сигнал на первые четыре контакта модуля и смотреть какой сигнал возвращается со второй. Но не стоит пугаться того, что вам придется писать алгоритмы обработки для восьми пинов вручную — в этом нам поможет готовая библиотека «keypad.h», благодаря которой нам не придется изобретать велосипед.

Подключение к плате

Подключение собственно модуля

В этой статье я воспользуюсь следующей схемой подключения:

У Вас наверное возникает вопрос: «Почему я решил использовать пины со второго по девятый, пропустив нулевой и первый?» — дело в том, что некоторые модули, используют их в качестве каналов RX и TX для получение и передачи данных соответственно. К примеру, блютуз модуль. По-этому с учётом возможного дополнения проекта другими модулями, было решено оставить данные пины подключения свободными.

Написание скетча

Для начала, для того, чтобы получить возможность использовать библиотеку для подключения клавиатур в коде, нужно установить её на ваше устройство. Это можно сделать следующим образом: в самой Arduino IDE нажимаем Скетч -> Подключить библиотеку -> Управлять библиотеками… либо используем комбинацию гарячих клавиш «Ctrl + Shift + I». В поиске вбиваем «keypad.h»(без скобочек) и нажимаем «Установка».

После установки приступаем к написанию скетча:

#include  // подключаем библиотеку для управление клавиатурой  const byte ROWS = 4; //число строк у нашей клавиатуры const byte COLS = 4; //число столбцов у нашей клавиатуры char hexaKeys[ROWS][COLS] = {// здесь мы располагаем названия наших клавиш, как на клавиатуре,для удобства пользования {'1','4','7','*'},  {'2','5','8','0'}, {'3','6','9','#'}, {'A','B','C','D'} };  byte rowPins[ROWS] = {5, 4, 3, 2}; //к каким выводам подключаем управление строками byte colPins[COLS] = {9, 8, 7, 6}; //к каким выводам подключаем управление столбцами  //передаем все эти данные библиотеке: Keypad customKeypad = Keypad( makeKeymap(hexaKeys), rowPins, colPins, ROWS, COLS);  void setup(){   Serial.begin(9600);//запускаем отладочный вывод в монитор порта }  void loop(){ char customKey = customKeypad.getKey();//записывем нажатый символ  if (customKey){//если что-то нажато   Serial.println(customKey);//выводим нажатый символ в монитор порта }  }

Плюсы и минусы

Минусы

  • Слишком много пинов нужно подключить для работы. Это довольна крупная проблема, если вы создаёте не калькулятор или кодовый замок, а более масштабный проект, в котором еще нужно задействовать огромное количество различных модулей — возможно им просто не хватит пинов.
  • Слишком низкое качество выполнения модуля: никто вам не гарантирует постоянный стабильный сигнал. Оригинальные клавитуры выполнены не на очень высоком уровне, а если вы вообще сделали заказ на Aliexpress, то скорее всего, вам предстоит исправлять косяки китайских инженеров паяльником, чтобы добится стабильной работы.
  • Используется дополнительная библиотека, которая также будет занимать память микроконтроллера, которой у него и так не очень много. Если вы пишите большой проект с множеством функций и вычислений и вам каждый байт на счету нужно считывать данные с клавиатуры вручную либо использовать аналоговую клавиатуру.

Плюсы

  • Низкая цена
  • Легко найти в продаже

Аналоговые клавиатуры

Принцип работы

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

Подключение к плате

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

Итак: аналоговый выход клавиатуры соединяем с любым аналоговым пином на плате, контакт VCC на плате соединяем с 3.3V(не смотрите на надпись на самой клавиатуре, которая гласит о 5V — это ошибка), а GND на плате с GND на модуле. Вы можете воспользоватся следующей схемой:

Написания скетча

Здесь не нужно использовать сторонние библиотеки, т.к. всё предельно просто и понятно. Вот собственно и сам код, который считывает нажатую кнопку и выводит её номер, от 1 до 16(слева на право, с верху в низ) либо 0 если ничего не нажато, в монитор порта.

unsigned const short int KEYPAD_PIN = 0;//аналоговый порт для клавиатуры  void setup() {   Serial.begin(9600);   analogReadResolution(10);//все аналоговые значение будут в диапазоне 0...1023 }  void loop() {   Serial.println(getPressedKeypadButton());//выводим номер нажатой кнопки в монитор порта }  short int getPressedKeypadButton(){//считывает нажатия keypad`a //возвращает значение от 1 до 16 в зависимости нажатой кнопки или 0 если ничего не нажато   const int OCCURACY = 5;//ошибка в точности определения значений   int sensorValue = analogRead(KEYPAD_PIN);//читаем значение с датчика   int keys[] = {1016, 937, 860, 794, 683, 641, 604, 571, 509, 485, 464, 444, 407, 328, 275, 236};//массив примерных значений для клавиш(0-15, где 0=1, 1=2 и т.д.)   if(sensorValue > -OCCURACY && sensorValue < OCCURACY){return 0;}//если ничего не нажато, то сразу возвращаем 0   for(short int i = 0; i < 16; i++){//проверяем в цыкле с каким по номеру элементом массива совпадает значение с датчика     if(sensorValue > (keys[i] - OCCURACY) && sensorValue < (keys[i] + OCCURACY)){       return i+1;//возвращаем на один больше, т.к. при проверке у нас 0 считается первой кнопкой, но для удобства 0 будет отсутсвием сигнала     }   } }

Плюсы и минусы

Плюсы

  • Очень простое подключение
  • Занимает лишь один пин
  • Экономит память, которую вы не тратите под библиотеку
  • Обеспечивает стабильную работу(при условии, если вы не будете нажимать более одной кнопки одновременно)

Минусы

  • Стоит дороже матричных клавиатур
  • Скорее всего единственным способом покупки будет заказывать с Китая и доставка займёт какое-то время

Итоги

Лично я рекомендую использовать именно аналоговые клавиатуры, так как они чаще-всего более качественные и подключать их проще-простого. Главное обращать внимание на таблицу значений нажатых кнопок, которую предоставляет производитель или же, если таковой нет, можно сделать эти замеры самостоятельно, выводя значения из аналогового порта в монитор порта, чтобы потом использовать их в коде. Но выбор, всегда остается за Вами: использовать стандартный дешёвый вариант либо переплатить ради значительных плюсов в некоторых ситуациях.

На этом у меня всё. Оставляйте свои вопросы в комментариях, пишите своё мнение и встретимся на просторах !

Автор: IcticStep

Источник

–>

Когда писал об организации меню в МК использовал клавиатуру 2х2 и не описал какой принцип сканирования клавиатуры. Сейчас хочу исправить это упущение.

Давайте подключим к МК клавиатуру 4х4. Каков же принцип работы такой клавиатуры? На самом деле все довольно просто:

  1. У нас есть биты порта настроенные на выход (в нашем случае будут биты 0-3 PORTD) и есть биты настроенные на вход (биты 4-7 PORTD).
  2. На выходах единица. На входах включен подтягивающие резисторы.
  3. Устанавливаем один из битов выхода в нуль и проверяем все входы порта на нуль. Если на входе везде единица, тогда устанавливаем следующий бит в нуль и снова проверяем входы на нуль и т.д. до последнего бита выхода, а затем начинаем заново. Если, например, мы установили бит 0 в нуль и при проверке входов на бите 4 обнаружен нуль, тогда мы считаем что была нажата кнопка и функция возвращает код кнопки. С которым мы дальше и работаем в основной программе.

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

Нарисуем схему подключения клавиатуры.

Подключение питания микроконтроллера не показано.

CLM1-CLM4 и есть выходы нашего порта, состояние которых мы будем менять.

ROW1-ROW4 это входы порта, состояние которых будем смотреть.

Приведу здесь код функции сканирования клавиатуры с комментариями. Простой пример использования клавиатуры с проектом в Proteus можно скачать в конце статьи.

//функция сканирования клавиатурыunsigned char fScanButtons(){unsigned char portd, clm, row;//объявляю переменныеfor(unsigned int i= ; i<<span>4; i++)//запускаю цикл для установки выходов в нуль{clm=(1<<i>//устанавливаем нужный выходportd = PORTD;portd = (clm ^ 0xFF);//исключающее или, т.е. там где соответствующие биты равны 1 будет 0.                 //Например, clm = 0b00000001, тогда portd = 0b11111110;PORTD = portd;//записываем в PORTD полученное значениеfor(unsigned int j=4; j<<span>8; j++)//цикл проверки входов {row=(1<<j>//устанавливаем вход, который будем смотретьportd = (clm | row)^0xFF;//получаем код конкретной кнопкиif(portd == PIND)//проверяем наличие этого кода return portd;//если код присутствует, возвращаем его значение}}return 0;//если ничего не совпало, возвращаем 0}

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

Главное понять принцип работы, а потом можно обобщить на любое количество кнопок. Например, используя два порта — один на выход, другой на вход, можно подключить 64 кнопки (не знаю, пока, зачем это может понадобиться) и код нажатой кнопки передавать по SPI на другое устройство, которое будет заниматься обработкой.

Как вам статья? Ваша реакция: +1 1 +1 +1 +1 +1 +1 Оцените статью: ★ ★ ★ ★ ★ Матричная клавиатура 4х4, / 5 ( голосов) Все видеоНовые видеоПопулярные видеоКатегории видео

Авто Видео-блоги ДТП, аварии Для маленьких Еда, напитки
Животные Закон и право Знаменитости Игры Искусство
Комедии Красота, мода Кулинария, рецепты Люди Мото
Музыка Мультфильмы Наука, технологии Новости Образование
Политика Праздники Приколы Природа Происшествия
Путешествия Развлечения Ржач Семья Сериалы
Спорт Стиль жизни ТВ передачи Танцы Технологии
Товары Ужасы Фильмы Шоу-бизнес Юмор

Главные новости С 6 по 9 августа 2021 года планируется проведение профилактического мероприятия «Трасса»”>Сотрудники ГИБДД устанавливают обстоятельства ДТП, в результате которого пострадал несовершеннолетний пешеход”>Житель Нижней Салды задержан по подозрению в том, что он до смерти избил свою 85-летнюю бабушку”>Полицейские в режиме «прямой линии» ведут общение с салдинцами по вопросам мошенничества”>Итоги «Безопасной дороги»”>Приемка образовательных учреждений к новому учебному году”>Профилактическое мероприятие «Безопасная дорога» с 23 по 26 июля 2021 года”>Госавтоинспекция ищет очевидцев!”>Сотрудники ГИБДД выясняют обстоятельства ДТП, в результате которого пострадал человек”>В Верхней Салде сотрудники ГИБДД устанавливают обстоятельства ДТП, в результате которого пострадали два человека”> Дикая лещина и фундук”>Разработка дизайна машинной вышивки”>Прохождение Grime: Часть – 1: Сфероголовый И Босс Амальгама”>В Белгороде перед судом предстанет житель Курской области за кражу на вокзале”>Как сетевику вести блог? Как сетевику упаковать личность и вести блог, чтобы добиться успеха в МЛМ?”>Ты должен знать этот узел. Как привязать крючок к леске. Рыболовные узлы для рыбалки. Рыбалка 2021″>Ролики для душевой кабины – практичная фурнитура для раздвижных стеклянных дверей”>На территории Саратовского региона приостановлено оказание дополнительных услуг в домах престарелых”>Автоматические шлагбаумы и устройства безопасности CAME”>Жизнь и карьера Вартана Саркисова”> Сдается 1-комнатная квартира”>Срочно сдам”>Куплю кабель, провод разных сечений, дорого!”>Куплю кабель, провод оптом с хранения”>Куплю кабель алюминиевый АВВГ, АПВБШВ, АПВПУ, АПвВнг LS,АПВБП с хранения, остатки с монтажа, любой объем, любой город. Дорого. Самовывоз”>Закупаем кабель Транскаб НППнг HF, ПВ1, ПВ3, ВВГ,КВВГ, ВБШВ, КГ-хл, АС, ААБл, ААШВ, АСБл, АСБ2л и другие, не в лом. Остатки с монтажа, невостребованный в производстве. Дорого.”>На постоянной основе закупаю кабель КВВГнг LS, КГ, Кг-хл, КУИН, КВИП, МКЭШ,МКЭКШВ, остатки с монтажа. Оптом. Любой регион. Дорого Самовывоз Расчет при”>Покупка акций ВСМПО-АВИСМА”>Вывод из запоя, кодирование, стационар, реабилитация зависимых.”>Ковромоечное оборудование CLEANVAC – FJB GROUP LLC”> Фото Doctor tooth”>Фото Mahir Azizov”>Фото Зоя шульжицкая (Кохановская)”>Фото Ирена Нестерова ( Вдовкина )”>Фото freefireyoutubu”>Фото Сергей Бикулов”>Фото tatanazurikova1@gmail.com”>Фото тамара колосенцева”>Фото Татьяна Воронова”>Фото Долгожитель”> Врач-флеболог 2 мин. назад Специалист по венам 10 мин. назад Сосудистый хирург 16 мин. назад Специалист-флеболог 23 мин. назад Варикозное расширение вен на ногах 27 мин. назад Лечение варикозного расширения вен 34 мин. назад Эндоваскулярная лазерная коагуляция 38 мин. назад Флебология 46 мин. назад Лечение варикоза 53 мин. назад Отрезные круги 2 ч. 50 мин. назад Последние комментарии Жанна Раевская Здравствуйте. Вы знаете, мой кот по весне загулял, да так что спать невыносимо было от его завываний. Живем в квартире, гулять о… 10 ч. 51 мин. назад Маргарита Пронько – очень удобный и выгодный способ доставки. Обычно заказывали перевозку по морю в контейнерах, довольно быстро и по цене устраи… 5 августа 2021 г. 17:07:20 Лилия Разумовская Ну, честно говоря, сомневаюсь… Мне больше по душе фитнес вот. Сама еще совсем недавно узнала о Скакалка оказывается очень м… 3 августа 2021 г. 8:55:37 Фролов Олег спасибо, был на этом мероприятии в этом году 30 июля 2021 г. 18:46:22 Настя Василенко Оформила ОСАГО на этом сайте из статьи, Юкаско. Полис быстро пришел. Так довольна, что никуда не надо ехать или забирать его на … 28 июля 2021 г. 16:28:49 rom kov Если нужны срочно деньги, то проще обратиться в мфо. Я беру деньги в долг до зарплаты в Мосзайме https://mos-zaim.ru/. Условия б… 20 июля 2021 г. 14:35:20 pochta19283@e1.ru Всегда хотела быть воспитателем, но потом решила быть педагогом. Довольна своей профессией полностью. Вот недавно узнавала … 20 июля 2021 г. 10:49:11 Лилия Разумовская Кредиты, кредиты, рассрочка, ипотека… ДА потому что зарплаты крошечные. Ни на что не хватает. Если работать средним специалист… 19 июля 2021 г. 9:27:14 Анна Волкова Как оказалось далеко непростая стала задача: в кратчайшие сроки отремонтировать стиральную машину в Минске. Гдето стоимость прос… 17 июля 2021 г. 10:36:40 Анна Волкова Как выяснилось стала задача не такая уж и простая: в кратчайшие сроки осуществить Ремонт стиральных машин в Минске. Гдето стоимо… 17 июля 2021 г. 10:29:34

Подумал, что интересно будет не только делать уроки, а сразу делать реальное изделие, которое можно применить в жизни. По основной работе я занимаюсь системами безопасности, и очень часто работаю с системами контроля доступа. Я работал с Болид, z5r, z5r web, и т.д. Какие-то системы невероятно сложные в установке и настройке (Болид привет), каким-то не хватает стабильности и функционала.

Решил попробовать сделать открытую систему прохода, с возможностью настройки и контроля по телефону. Начнём с ардуино, потом возможно перейдём на более мощный кристалл, а затем перенесём всё на свою плату, сделаем дизайн корпусов, напечатаем на 3д принтере. В первых уроках реализуем следующий функционал:

  • Управление замком – нужна поддержка электромагнитного замка и электромеханического
  • Управление временем открытия замка – в случае применения электромагнитного замка, пользователь не успеет выйти за 1 секунду, а где-то нужно и 5 секунд
  • Доступ с внешней стороны по 4-значному коду, изменение кода доступа также производится с клавиатуры
  • С внутренней стороны – выход по кнопке
  • Buzzer – небольшой динамик, который сигнализирует, и понятен на слух, разрешён ли проход или нет
  • Джампер аппаратного сброса

Нарисуем схему в Proteus, на которой будем проверять код, перед тем как собирать в реальном железе.

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

Принцип работы похож на динамическую индикацию светодиодных сегментных индикаторов, только делаем всё наоборот – не выводим информацию, а поочерёдно читаем. Рассмотрим схему матричной клавиатуры

У кнопки мгновенного действия минимум два контакта, которые замыкаются при нажатии. Следовательно ряды кнопок объединяем в массив одним контактом, и подписываем каждый ряд, а оставшийся контакт кнопок объединяем в ряды. Например, при нажатии кнопки 3, мы замкнём контакт ряда “A” и контакт столбца “3”

Выберем какие пины мы будем использовать у контроллера и дадим им для удобства осмысленные имена, будем использовать имя row – для строки, и column – для столбца.

 #define row1  12                          // Строки клавиатуры #define row2  2 #define row3  3 #define row4  4 #define column1 5                        // Колонки клавиатуры #define column2 6 #define column3 7 

Директива #define просто заменяет при трансляции одну последовательность символов на другую, т.е. строка #define row1 12 означает, что везде где в тексте программы встретится имя row1 компилятор заменит его на символы 12.

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

 byte keypadOut[4] {row1, row2, row3, row4};    // пины строк - на них будем подавать напряжение byte keypadIn[3] {column1, column2, column3};  // пины колонок - отсюда будем считывать напряжение 

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

 const char keyboardValue[4][3]          //Создаём двумерный массив { {'1', '2', '3'},                      //структура клавиатуры   {'4', '5', '6'},   {'7', '8', '9'},   {'*', '0', '#'} }; 

Двумерный массив даёт понятное представление данных в нём, визуально это полная копия клавиатуры. Перейдём непосредственно, к самому коду и алгоритму считывания данных, но сначала разберёмся, как мы будем определять нажатую клавишу. На ряды мы будем поочерёдно подавать низкий логический уровень, а во вложенном цикле на столбцах будем пытаться по очереди считать этот низкий уровень. Если в момент опроса увидим низкий уровень, то в алгоритме цикла будет легко понять, какой ряд и столбец мы сейчас опрашиваем. Поэтому не забудем задать режим работы i/o пинов микроконтроллера. Ряды – на выход, столбцы – на вход.

 // инициализируем порты на выход (подают нули на столбцы)     pinMode(row1, OUTPUT);                     pinMode(row2, OUTPUT);   pinMode(row3, OUTPUT);   pinMode(row4, OUTPUT); // входные порты колонок клавиатуры настроены на вход   pinMode (column1, INPUT);                  pinMode (column2, INPUT);   pinMode (column3, INPUT); 

Я не задаю программную Pull-up подтяжку для входных строк, потому-что в данном случае, использую резисторы на самой плате микроконтроллера. Выходы же можно не назначать в логическую 1, потому-что при старте контроллера, в первом цикле for, они и так примут нужные значения. Алгоритм считывания состоит из двух циклов for, один у нас перебирает строки по очереди, а второй цикл for перебирает ряды внутри каждой строки. Рассмотрим цикл for Для перебора строк.

 for (int r = 1; r <= 4; r++) // цикл, передающий 0 по всем столбцам {   digitalWrite(keypadOut[r - 1], LOW); // Подаём низкий уровень     {     здесь будем перебирать столбцы     }   digitalWrite(keypadOut[r - 1], HIGH); // подаём обратно высокий уровень } </pre> В первом цикле for мы указываем переменную r, которую будем использовать в самом теле цикла. Помним, что выводы контроллера, которые подсоединены к рядам, настроены на выход, причём в логической “1”. Чтобы сделать опрос конкретного ряда, нам нужно понизить логический уровень до “0”, что мы и сделаем командой   digitalWrite(keypadOut[r - 1], LOW); // Подаём низкий уровень 

В первом цикле, когда r=1, у нас будет keypadOut[0], что равно row1. Так получилось, потому-что 1 – 1 = 0 . Тут нужно не забывать, что ардуино это с++, а значит нумерация массива начинается с 0. Понятнее будет на картинке.

Смотрите также:  dc-dc

Если мы не будем использовать формулу [r – 1], то дойдя до 4 цикла, значение массива станет keypadOut = 4, что приведёт к ошибке, потому-что это будет уже 5 элемент массива, а размерность его мы задали [4].

Затем нам нужно будет сделать 3 опроса столбцов в следующем цикле, разберём этот кусок кода чуть дальше. После опросов столбцов, чтобы перейти к следующему ряду, нам нужно будет обратно вернуть логическую “1” на ряде, который мы сканировали, командой

 digitalWrite(keypadOut[r - 1], HIGH); 

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

     for (int c = 1; c <= 3; c++) //      {       if (digitalRead(keypadIn) == LOW) //        {              Serial.print(keyboardValue[r-1][c-1]);        }     } </pre> Здесь мы наоборот, ничего не подаём на выход, а считываем значения из массива keypadIn[3], который может принимать значения column1, column2 или column3. Если вдруг в какой-то момент мы замечаем низкий уровень на входе столбца, то в этот момент мы можем определить нажатую кнопку, так как мы знаем в какой итерации циклов FOR мы находимся, и знаем переменные r и c. Определить это можно следующей конструкцией   keyboardValue[r-1][c-1] 

Помним про свойство массивов, что нумерация начинается с 0, и в итоге считываем нажатую клавишу из этого массива

 const char keyboardValue[4][3]          //Создаём двумерный массив { {'1', '2', '3'},                      //структура клавиатуры   {'4', '5', '6'},   {'7', '8', '9'},   {'*', '0', '#'} }; 

Например, если сработка произошла при r=3 и c=2, то keyboardValue будет со значением [2][1], т.е. пример значение “8”. Для наглядности работы цикла я сделал небольшое видео, которое точно даст понимание, как действует алгоритм.

Смотрите также:  WG12864B

Попробуем запустить всё это в proteus, и нажмём кнопку 3. Для начала посмотрим на графики осциллографа, и увидим, что наш код выполняется правильно. row1 падает до низкого уровня, затем row2, затем row3. На 4 дорожку я подключил столбец 1, и тут мы замечаем первую проблему – дребезг контактов и длительность нажатия кнопки, приводит к нескольким срабатываниям

Один раз нажав на “1” мы получаем 7-8 сообщений в терминале, значит нужно эту проблему решить. В реальной жизни, мы ещё столкнёмся с диким дребезгом контактов, что можно поймать и 100 сработок в момент нажатия кнопки. В целом, сейчас мы опрашиваем кнопки в цикле Loop, и другого кода у нас нет, следовательно опрос идёт слишком часто. Попробуем добавить самую простую задержку delay, если мы заметили срабатывание кнопки, а затем повторно проверить состояние кнопки

       if (digitalRead(keypadIn) == LOW) { //         delay(50); // вводим дополнительную задержку, перед повторной проверкой         if (digitalRead(keypadIn) == LOW) {           {             Serial.print(keyboardValue[r-1][c-1]);            }         }       } 

Результат уже намного лучше – но всё равно присутствуют повторные нажатия

Смотрите также:  Стедикам своими руками

В какой-то момент, удаётся поймать однократное нажатие, и легко понять по виртуальному осциллографу почему. Длительности импульса от нажатия хватило, чтобы код сработал, он был более 60ms, оставшийся всплеск составил чуть менее 40ms, и программа не сделала условие if.

В разных устройствах работа с кнопками нуждается в разных алгоритмах, где-то нужно фиксировать двойные нажатия, где-то удерживание, а где-то и вовсе следить за комбинированным нажатием кнопок. В кодовой клавиатуре повторные срабатывания нам вообще ни к чему, и мы можем после игнорирования дребезга контактов, просто следить отпустили клавишу или нет. Представьте, человек вводит пароль, кто-то быстрее, кто-то медленнее, каждое двойное срабатывание заставит человека ошибаться в коде, поэтому всё, что нам нужно мониторить – это состояние клавиши, пока она ещё нажата, не будем переходить к действию, например так.

 while (digitalRead(keypadIn) == LOW) {} //пустой цикл, пока клавиша будет нажата 

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

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

В момент опроса, у нас низкий уровень поочередно меняется с первого ряда на 4-ый, но остальные при этом имеют выход 5В. Произойдёт КЗ, что очень плохо для МК. Чтобы этого не произошло нужно добавить диоды, и даже при нажатии двух таких кнопок, отрицательный потенциал не сможет пройти через анод.

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

Ссылки на скетч и проект протеуса здесь

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

Резистивная клавиатура для arduino

image

Резистивная клавиатура для arduino

В общем как это все устроено.

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

image

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

image

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

image

Это даже можно продемонстрировать. Ниже пример, который отправляет значение в serial которое считывает функцией analogread на выходе А0 к которому подключена клавиатура. Когда ничего не нажато в мониторе порта будет 1023, если надавить на кнопку это значение будет отличаться и зависеть от нажатой кнопки.

Осталось только различать эти значения в коде без условия if здесь не обойтись, а лучше вообще это вынести в отдельную функцию. К примеру эта функция будет key() и возвращает она байт

byte key(){     int val = analogRead(0); // считываем значение с аналогового входа в переменную val     if (val < 50) return 1; // сверяем переменную, если val меньше 50 возвращаем 1 (первая кнопка)     else if (val < 150) return 2; // если val меньше 150 вторая кнопка и т.д.       else if (val < 350) return 5;     else if (val < 500) return 4;     else if (val < 800) return 3;     else return 0;  // если ничего не подошло возвращаем 0 }

Дальше в цикле отправляем в serial, то что возвращает функция key

void loop() {  int sensorValue = analogRead(A0); // считываем значения с А0. Пригодится для отладки  Serial.print(key()); // выводим номер кнопки в serial     Serial.print(" ");  Serial.println(sensorValue); // выводим значения с А0. Пригодится для отладки  delay(1);        // задержка между считываниями для стабильности }

 Весь код

byte key(){    int val = analogRead(0);    if (val < 50) return 1;    else if (val < 150) return 2;    else if (val < 350) return 5;    else if (val < 500) return 4;    else if (val < 800) return 3;    else return 0;   }   // the setup routine runs once when you press reset: void setup() {  // initialize serial communication at 9600 bits per second:  Serial.begin(9600); }   // the loop routine runs over and over again forever: void loop() {  // read the input on analog pin 0:  int sensorValue = analogRead(A0);  // print out the value you read:  Serial.print(key());  Serial.print(" ");  Serial.println(sensorValue);  delay(1);        // delay in between reads for stability } 

Оцените статью
Рейтинг автора
4,8
Материал подготовил
Максим Коновалов
Наш эксперт
Написано статей
127
А как считаете Вы?
Напишите в комментариях, что вы думаете – согласны
ли со статьей или есть что добавить?
Добавить комментарий