Button Keypad 4x4 module Assembled_RU - RobotDynOfficial/Documentation GitHub Wiki
Клавиатура Button Keypad 4x4 module (Assembled) очень похожа на очень распространенную клавиатуру Matrix Membrane Keypad 16 Key (4x4), но на самом деле работает совсем иначе. На клавиатуре Matrix Membrane Keypad 16 Key (4x4) кнопки образуют матрицу 4x4 и чтобы подключить данную клавиатуру к микроконтроллеру необходимо использовать 8 контактов, что для некоторых проектов очень расточительно. Клавиатура Button Keypad 4x4 module (Assembled) имеет всего 3 контакта (VCC, GND, Out) и для подключения к микроконтроллеру (например, Arduino) достаточно одного аналогового входа.
Как же такое возможно? Для этого посмотрим на электрическую схему данной клавиатуры.
Схема электрическая клавиатуры Button Keypad 4x4 module (Assembled):
Напряжение подается на контакты 3 (VCC) и 2 (GND). Нажатие одной из кнопок SW1-SW16 образует на выходе 1 (Out) делитель напряжения, причем для каждой кнопки получается свой уникальный делитель напряжения. Например для кнопки SW2 – 1/10, для кнопки SW10 – 11/10. Подключив данный контакт к аналоговому входу микроконтроллера при нажатии кнопок будем получать разные значения, по которым сможем идентифицировать нажатую кнопку.
Подключим клавиатуру Button Keypad 4x4 module (Assembled) к плате Arduino и напишем скетч определения нажатой клавиши.
Будем использовать следующие компоненты:
-
Плата Arduino UNO – 1;
-
Клавиатура Button Keypad 4x4 module (Assembled) – 1;
-
Провода FM – 3.
Схема подключения:
На обратной стороне клавиатуры приведены примерные аналоговые значения при нажатии кнопок клавиатуры.
Проверим на практике. Подключаем плату Arduino к компьютеру. В Arduino IDE создаем новый скетч и заносим в него следующий код:
void setup() {
// запуск последовательного порта
Serial.begin(9600);
}
void loop() {
// получение данных на аналоговом входе A1
int valueA1=analogRead(A1);
// вывод данных в последовательный порт
Serial.println(valueA1);
// пауза
delay(500);
}
Загружаем скетч на плату Arduino, открываем монитор последовательного порта и смотрим значения на аналоговом входе при нажатии клавиш клавиатуры:
Схема в сборе:
Результаты измерений (сравнение ожидаемых и реальных значений на аналоговом входе при нажатии клавиш) представлены в таблице:
Кнопка | Ожидаемое значение | Среднее реальное | Кнопка | Ожидаемое значение | Среднее реальное |
---|---|---|---|---|---|
SW1 | 1023 | 1023 | SW9 | 512 | 517 |
SW2 | 930 | 934 | SW10 | 487 | 492 |
SW3 | 850 | 859 | SW11 | 465 | 470 |
SW4 | 790 | 796 | SW12 | 445 | 450 |
SW5 | 680 | 686 | SW13 | 410 | 412 |
SW6 | 640 | 645 | SW14 | 330 | 333 |
SW7 | 600 | 607 | SW15 | 277 | 278 |
SW8 | 570 | 574 | SW16 | 238 | 240 |
Необходимо знать, что значение на аналоговом входе принимает значение 0-1023 относительно опорного напряжения. По умолчанию – это напряжение питания микроконтроллера. Опорное напряжение играет главную роль в измерении аналогового сигнала, потому что именно от него зависит максимальное измеряемое напряжение и вообще возможность и точность перевода полученного значения 0-1023 в Вольты. Изучим следующую функцию – analogReference(mode), где mode:
-
DEFAULT: опорное напряжение равно напряжению питания МК. Активно по умолчанию;
-
INTERNAL: встроенный источник опорного на 1.1V для ATmega168 или ATmega328P и 2.56V на ATmega8;
-
INTERNAL1V1: встроенный источник опорного на 1.1V (только для Arduino Mega);
-
INTERNAL2V56: встроенный источник опорного на 2.56V (только для Arduino Mega);
-
EXTERNAL: опорным будет считаться напряжение, поданное на пин AREF.
Значение 1023 функции analogRead() будет соответствовать выбранному опорному напряжению или напряжению выше его, но не выше 5.5V, что спалит плату. То есть при режиме DEFAULT мы можем оцифровать напряжение от 0 до напряжения питания. Если напряжение питания 4.5 Вольта, и мы подаём 4.5 В – получим оцифрованное значение 1023. Если подаём 5 Вольт – опять же получим 1023, т.к. выше опорного. Это правило работает и дальше, главное не превышать 5.5 Вольт.
Что касается точности: при питании от 5V и режиме DEFAULT мы получим точность измерения напряжения (5 / 1023 ~ 8 мВ) – 8 милливольт. Поставив INTERNAL мы можем измерять напряжение от 0V до 1.1V с точностью (1.1 / 1023 ~ 1.2 мВ) – 1.2 милливольта. Весьма неплохо, особенно если баловаться с делителем напряжения.
Что касается внешнего источника опорного напряжения. Нельзя использовать напряжение меньше 0 В или выше 5.5 В в качестве внешнего опорного в пин AREF. Также при использовании режима EXTERNAL нужно вызвать analogReference(EXTERNAL) до вызова функции analogRead(), иначе можно повредить микроконтроллер.
Теперь зная реальные значения на аналоговом входе, напишем скетч, определяющий нажатую клавишу. Содержимое скетча :
void setup() {
// запуск последовательного порта
Serial.begin(9600);
}
void loop() {
// нажата ли кнопка?
int valueA1=get_button();
if(valueA1>0) { // если нажатие
Serial.print("Click button ");
Serial.println(valueA1);
delay(500);
}
}
// функция определения нажатия кнопки
int get_button() {
// получение данных на аналоговом воде A1
int val=analogRead(A1);
if(val>1000)
return 1;
else if(val>900)
return 2;
else if(val>820)
return 3;
else if(val>750)
return 4;
else if(val>660)
return 5;
else if(val>620)
return 6;
else if(val>585)
return 7;
else if(val>540)
return 8;
else if(val>500)
return 9;
else if(val>475)
return 10;
else if(val>455)
return 11;
else if(val>425)
return 12;
else if(val>370)
return 13;
else if(val>300)
return 14;
else if(val>260)
return 15;
else if(val>200)
return 16;
else
return 0;
}
Загружаем скетч на плату Arduino, открываем монитор последовательного порта и смотрим значения на аналоговом входе при нажатии клавиш клавиатуры:
Заметим, что продолжительное нажатие на клавишу (>500 мсек) приводит к автоповтору.
В качестве примера использования клавиатуры, создадим проект мини-калькулятора для арифметических действий (сложение, вычитание, умножение, деление) с двумя числами на плате Arduino и дисплее WH1602 на контроллере HD77480.
Будем использовать следующие компоненты:
-
Плата Arduino UNO – 1;
-
Клавиатура Button Keypad 4x4 module (Assembled) – 1;
-
Дисплей WH1602 (в нашем случае LCD Keypad shield) – 1;
-
Провода MM – 3.
Схема соединений для мини-калькулятора на Arduino UNO, клавиатуре Button Keypad 4x4 module (Assembled) и LCD keypad shield:
Назначение клавиш клавиатуры в проекте согласно рисунку:
Приступим к написанию скетча.
Все нажатия цифр 0-9 и действий (+,-,/,*) заносим в буфер и выводим на дисплей. При этом вводим ограничения:
-
начинаем ввод с цифры;
-
после ввода арифметического действия ввод другого действия блокирован;
-
кнопку "=" (итого) можно ввести после цифры;
-
клавиша "забой" удаляет предыдущий символ.
Содержимое скетча:
// подключение библиотеки для дисплея
\#include <LiquidCrystal.h>
// создание экземпляра объекта
const int rs = 8, en = 9, d4 = 4, d5 = 5, d6 = 6, d7 = 7;
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
// переменные
int pos=0; // количество введенных символов
int buf[32]; // массив для введенных данных
int endkey=0; // 1 - цифра, 2 - действие 3 - результат
// массив преобразований клавиш
// 1,2,3,+
// 4,5,6,-
// 7,8,9,/
// зб,0,=,*
int trans[]={0,
1,2,3,10,
4,5,6,11,
7,8,9,12,
14,0,15,13,
};
// массив перевода клавиши в символ
char sw[]={'0','1','2','3','4','5','6','7','8','9','+','-','/','*',' ','='};
void setup() {
// запуск дисплея
lcd.begin(16,2);
lcd.clear();
// вывод заголовка
lcd.setCursor(3,0);
lcd.print("Calculator");
lcd.setCursor(2,1);
lcd.print("Robotdyn.com");
delay(3000);
// очистить дисплей
lcd.clear();
// показывать курсор
lcd.cursor();
}
void loop() {
// нажата ли кнопка?
int valueA1=get_button();
if(valueA1>0) { // если нажатие
// обработка нажатой клавиши
add_key(trans[valueA1]);
delay(500);
}
}
// функция определения нажатия кнопки
int get_button() {
// получение данных на аналоговом воде A1
int val=analogRead(A1);
if(val>1000)
return 1;
else if(val>900)
return 2;
else if(val>820)
return 3;
else if(val>750)
return 4;
else if(val>660)
return 5;
else if(val>620)
return 6;
else if(val>585)
return 7;
else if(val>540)
return 8;
else if(val>500)
return 9;
else if(val>475)
return 10;
else if(val>455)
return 11;
else if(val>425)
return 12;
else if(val>370)
return 13;
else if(val>300)
return 14;
else if(val>260)
return 15;
else if(val>200)
return 16;
else
return 0;
}
// добавление новой кнопки в массив buf[]
void add_key(int key) {
// 0-9
if(key<10) {
if(endkey==3) { // после вывода суммы
// очищение и начало
// новых действий
startover();pos=0;
}
buf[pos]=key;tolcd(key);endkey=1;
}
// + - / *
else if(key<14) {
if(endkey==1) {
buf[pos]=key;tolcd(key);endkey=2;
}
}
// забой
else if(key==14) {
pos=max(0,pos-1);tolcd(key);
pos=pos-1;lcd.setCursor(pos%15,pos/15);
if(pos==0)
endkey=0;
else if(buf[pos-1]>=0 && buf[pos-1]<=9)
endkey=1;
else
endkey=2;
}
// = (итог)
else {
if(endkey==1) {
buf[pos]=key;tolcd(key);
itogo();
endkey=3;
}
}
}
// вывод на дисплей
void tolcd(int s) {
// позиция курсора
lcd.setCursor(pos%15,pos/15);
lcd.print(sw[s]);
pos=pos+1;
}
// получить и вывести результат
void itogo() {
String number1="";
String number2="";
char d;
int i;
int summa;
// получить первое число
for(i=0;i<pos;i++) {
if(buf[i]>=0 && buf[i]<=9)
number1+=sw[buf[i]];
else
break;
}
// действие
d=buf[i];
// получить второе число
for(i=i+1;i<pos;i++) {
if(buf[i]>=0 && buf[i]<=9)
number2+=sw[buf[i]];
else
break;
}
switch(d) {
// +
case 10: summa=number1.toInt()+number2.toInt();
break;
// -
case 11: summa=number1.toInt()-number2.toInt();
break;
// /
case 12: summa=number1.toInt()/number2.toInt();
break;
// *
case 13: summa=number1.toInt()*number2.toInt();
break;
default:
break;
}
// вывести результат на экран
lcd.setCursor(pos%15,pos/15);
lcd.print(summa);
}
// очистка при начале нового набора
void startover() {
for(int i=0;i<=pos;i++) {
buf[i]=0;
}
lcd.clear();
}
Загружаем скетч на плату Arduino, и начинаем пользоваться мини-калькулятором.