Я, как и было сказано в описании к странице, довольно давно написал данный модуль и поэтому предлагаю его вам как альтернативу с отслеживанием нажатии кнопок на Ардуино. История создания такова.
Как и все радиолюбители я давно заинтересовался Ардуиной из за её гибкости и удобства. Действительно, зачем паять реле времени на куче микросхем и индикаторов и заниматься несколько дней отладкой когда одна плата, индикатор и кнопки могут решить такую проблему буквально на коленке за полчаса. Как и у большинства ардуинцев у меня постоянно возникали проблемы с отслеживанием нажатий кнопок. Приходилось собирать схему на кнопках, заливать скетч с отслеживанием состояния порта и потом в Arduino IDE в мониторе порта отслеживать значения нажимаемых кнопок… Долго, муторно и занимало кучу времени, нервов и сил. Я думаю очень много любителей так и идут этим путем. У меня возникла идея автоматизировать данный процесс после ознакомления с библиотекой ЕЕПРОМ. Почему бы не заносить данные кнопок в ЕЕПРОМ, значения сохраняются, и уже затем использовать эти значения в программе. Конечно размер подключаемой библиотеки играет немалую роль, поэтому для больших приложений может все таки будет удобнее ввести значения напрямую. Но это решать уже Вам. Удобство данного модуля вы оцените после его первого использования. Скачать можете ЗДЕСЬ.
Опишу принцип действия. Подключаем библиотеки, в данном случае я писал обработчик кнопок для радио на RDA5807. Поэтому все переменные прошу воспринимать с точки зрения разработки именно проекта радио.
#include <EEPROM.h>
#include <LiquidCrystal.h>
LiquidCrystal lcd(7, 6, 5, 4, 3, 2);
long lastKeyPress;
byte bButt = 4; // количество кнопок
byte bn = 0; // счетчик для присваивания кнопок
int iVolUp, iVolDn, iFreqUp, iFreqDn; // значения кнопок
int iDelta = 20; // отклонение при нажатий кнопок
void(* resetFunc) (void) = 0; // объявляем функцию reset для сброса кнопок
Ничего такого особенного в объявлении нет кроме последней строки функции void. Данная функция принудительно перезагружает Ардуино. Ддя чего она нужна будет видно ниже.
Переходим к секции Setup.
void setup()
{
pinMode(10, INPUT); // вход для сброса ЕЕПРОМ
if (EEPROM.read(0) == 0 && EEPROM.read(1) == 0 && EEPROM.read(2) == 0 && EEPROM.read(3) == 0 )
{
// присваиваем значения кнопкам
#include «butt.h«;
valButt();
}
else
{
valButt();
}
}
Здесь мы объявляем 10 цифровой пин как вход. В дальнейшем программа отслеживает его состояние и, если на него поступит высокий уровень, производит процедуру перенастройки кнопок через очищение ЕЕПРОМ и переприсваивания значений кнопкам. Затем проверяем состояние первых 4 ячеек с 0 до 3 и, если в них находится по нолю (т.е. значения кнопкам еще не присвоены) подключаем страницу через include с процедурой присваивания значений кнопкам. По завершению записи значений кнопок происходит присваивание значений кнопок функцией valButt(). Если же во всех 4 ячейках есть какие то значения отличные от ноля то сразу переходим к valButt(). В принципе ничего сложного. Единственно на что следует обратить внимание в include файле- количество кнопок и операторов case должно совпадать и еще обратите внимание что ячейка ЕЕПРОМ может принимать значения от 0 до 255 (8 бит) а значения аналогового входа А0 с которого мы будем принимать данные нажатий кнопок — от 0 до 1023 (10 бит). Можно использовать множество вариантов для хранения 10 битных значений в формате 8 битных. Например:
- Использовать map преобразование.
- Использовать функцию word и хранить точное значение в двух ячейках
- Просто поделить полученное значение с порта А0 на 4 и записать полученное значение в ЕЕПРОМ.
В принципе 1 и 3 пункты ничем не отличаются, значения получатся одинаковые. Конечно значения с порта будут округляться в меньшую сторону. Например: с порта А0 пришло значение 777, и операция map(analogRead(A0), 0, 1023, 0, 255) и деление на 4 дадут одно и тоже число- 194, вместо 194,25. Вы скажете что при нажатии на данную кнопку данные не совпадут и кнопка при нажатии не сработает. Тут вы будете правы но я сделал немного иначе по двум причинам. Первая- десятичное число нельзя записать в ЕЕПРОМ, нужно обязательно целое число в пределах от 0 до 255. Поэтому контроллер при записи отбросит десятичную часть и запишет просто 194 в нужную ячейку. Вторая причина- не всегда происходит идеальное нажатие на кнопку, опять же кнопка со временем снашивается, окисляется и её передаваемое значение со временем может изменится. Получается что, например, после 500 нажатий кнопка перестанет отвечать. Поэтому я ввел еще одно значение iDelta. Оно отвечает за отклонение при нажатий кнопок. Т.е., в нашем случае, при iDelta =20 кнопка сработает в пределах от 194*4-20=756 до 194*4+20=796 (значения ЕЕПРОМ перемножаются в функции valButt() для каждой кнопки). Отсюда получается что нет никакой разницы в каком пределе срабатывать- 776 или 777 т.к. и то и это значения вписываются в поставленное условие! Согласитесь попасть в такой предел гораздо легче чем в единичное точное значение. iDelta можно как увеличить так и уменьшить, главное чтобы края значений кнопок не пересекались т.к. это может вызвать ложное срабатывание соседних по значению кнопок.
void loop()
{
if (digitalRead(10) == true) // если перемычка замкнута
{
// здесь можно вставить цикл for и по циклу обнулять ячейки
EEPROM.update(0, 0);
EEPROM.update(1, 0);
EEPROM.update(2, 0);
EEPROM.update(3, 0);
lcd.clear();
lcd.setCursor(1, 0);
lcd.print(«Reset Complete«);
delay(3000);
resetFunc(); //вызываем reset
}
handleKeys();
delay(10);
}
В секции loop сначала проверяем состояние 10 цифрового пина , если на нем высокий уровень то затираем значения первых ячеек. В принципе здесь можно написать цикл и стирать вообще весь ЕЕПРОМ. Просто не захотелось вводить еще одну вспомогательную переменную, всего 4 ячейки обнулить. Затем выводим сообщение на LCD о том что сброс произведен и перезапускает контроллер. Ну а при старте секция setup проверяет первые 4 ячейки на ноль и выйдет в меню присваивания. Все просто! Функция handleKeys() собственно производит опрос кнопок и в зависимости от нажатой кнопки будет обрабатывать программу. В этой секции я как раз и описал работу кнопки в iDelta. После delay(10) вы можете писать саму часть работающей программы.
Достоинством данного модуля является то что при монтаже не нужно соединять именно один провод с нужным выводом кнопки. Собираете и отлаживаете устройство. Оно отлично работает. Собираете все в корпус и тут вы перепутали несколько кнопок… Нужно разбираться, перепаивать или перетыкать нужные провода. Делаете проще- сбрасываете память контроллера перемычкой на 10 пине и заново переприсваиваете кнопкам нужные значения. Все просто и довольно быстро. Да, используется 3024 байта памяти (вместе с библиотекой LCD) но данное удобство бывает перевешивает все недостатки объема занимаемой памяти.