Освой Arduino играючи
/* Моя кошка замечательно разбирается в программировании. Стоит мне объяснить проблему ей - и все становится ясно. */
John Robbins, Debugging Applications, Microsoft Press, 2000
Разберём работу с матричной клавиатурой. В моём распоряжении клавиатура размером 4х4, поэтому код будет писаться под неё.
Также могут попадаться клавиатуры с матрицей 4х3 и 4х1 и другие.
Клавиатура состоит из кнопок в виде герметичной панельки из прорезиненного материала. Задняя сторона сделана на самоклеящейся основе, что позволяет легко закрепить панель. Причём, панель гнётся, поэтому её можно прилепить даже на кружку. Клавиатуры герметичны, гибки и долговечны. Они не боятся воды, жары и выдерживают миллион нажатий.
Клавиатура выполнена в виде матрицы 4х4, каждая кнопка является областью воздушного зазора между двумя диэлектрическими слоями с нанесёнными на них токопроводящими покрытиями. Дорожки токопроводящего покрытия одного слоя нанесены горизонтально (выводы 1-4), а другого вертикально (выводы 5-8). Нажатие на кнопку приводит к соединению дорожки одного слоя с дорожкой другого, и как следствие, к замыканию одного из выводов 1-4 с одним из выводов 5-8.
Для удобства установим готовую библиотеку Keypad. Устанавливайте через менеджер библиотек в Arduino IDE.
Исходники для просмотра кода библиотеки.
Само подключение не должно вызвать трудностей. У клавиатуры восемь выводов в виде шлейфа, который нужно подключить к цифровым выводам платы от 9 до 2. Шлейф имеет мама-разъём с шагом 2,54 мм - можно легко установить с помощью макетной платы и линейки штырьковых соединителей. Также можно использовать перемычки папа-папа.
Библиотека снабжена несколькими примерами. Немного видоизменённые примеры представлены ниже.
Пример рассчитан на клавиатуру 4х3, поэтому необходимо внести небольшие изменения в коде (выделено жирным).
#include <Keypad.h>
const byte ROWS = 4; //four rows
const byte COLS = 4; //four columns
char keys[ROWS][COLS] = {
{'1', '2', '3', 'A'},
{'4', '5', '6', 'B'},
{'7', '8', '9', 'C'},
{'*', '0', '#', 'D'}
};
byte rowPins[ROWS] = {9, 8, 7, 6}; //connect to the row pinouts of the keypad
byte colPins[COLS] = {5, 4, 3, 2}; //connect to the column pinouts of the keypad
Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );
void setup() {
Serial.begin(9600);
}
void loop() {
char key = keypad.getKey();
if (key) {
Serial.println(key);
}
}
Залейте прошивку, запустите Serial Monitor и нажимайте на клавиши. Символ нажатой клавиши должен отображаться на экране.
Пример позволяет обрабатывать одновременные нажатия клавиш. Он также предназначен для клавиатуры 4х3, поэтому внесём аналогичные изменения в код.
#include <Keypad.h>
const byte ROWS = 4; //four rows
const byte COLS = 4; //4 columns
char keys[ROWS][COLS] = {
{'1', '2', '3', 'A'},
{'4', '5', '6', 'B'},
{'7', '8', '9', 'C'},
{'*', '0', '#', 'D'}
};
byte rowPins[ROWS] = {9, 8, 7, 6}; //connect to the row pinouts of the keypad
byte colPins[COLS] = {5, 4, 3, 2}; //connect to the column pinouts of the keypad
Keypad kpd = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );
unsigned long loopCount;
unsigned long startTime;
String msg;
void setup() {
Serial.begin(9600);
loopCount = 0;
startTime = millis();
msg = "";
}
void loop() {
loopCount++;
if ( (millis() - startTime) > 5000 ) {
Serial.print("Average loops per second = ");
Serial.println(loopCount / 5);
startTime = millis();
loopCount = 0;
}
// Fills kpd.key[ ] array with up-to 10 active keys.
// Returns true if there are ANY active keys.
if (kpd.getKeys())
{
for (int i = 0; i < LIST_MAX; i++) // Scan the whole key list.
{
if ( kpd.key[i].stateChanged ) // Only find keys that have changed state.
{
switch (kpd.key[i].kstate) { // Report active key state : IDLE, PRESSED, HOLD, or RELEASED
case PRESSED:
msg = " PRESSED.";
break;
case HOLD:
msg = " HOLD.";
break;
case RELEASED:
msg = " RELEASED.";
break;
case IDLE:
msg = " IDLE.";
}
Serial.print("Key ");
Serial.print(kpd.key[i].kchar);
Serial.println(msg);
}
}
}
}
Для демонстрации сначала была нажата клавиша "А". Удерживая её, нажал на клавишу "2", которую затем отпустил.
Клавиатуру логично использовать в качестве ввода пароля для доступа к каким-то возможностям. Для удобной обработки вводимых символов можно использовать готовую библиотеку Password. К сожалению, её нельзя установить через менеджер библиотек, поэтому придётся скачать архив и разместить папку в папке libraries самостоятельно.
У библиотеки несколько функций.
Скетч для ввода пароля
#include <Keypad.h>
#include <Password.h>
String newPassword; //hold the new password
char passchars[6]; //charaters of newPassword
//initialize password to 1234
//you can use password.set(newPassword) to overwrite it
Password password = Password("1234");
byte maxPasswordLength = 6;
byte currentPasswordLength = 0;
const byte ROWS = 4; //four rows
const byte COLS = 4; //four columns
char keys[ROWS][COLS] = {
{'1', '2', '3', 'A'},
{'4', '5', '6', 'B'},
{'7', '8', '9', 'C'},
{'*', '0', '#', 'D'}
};
byte rowPins[ROWS] = {9, 8, 7, 6}; //connect to the row pinouts of the keypad
byte colPins[COLS] = {5, 4, 3, 2}; //connect to the column pinouts of the keypad
Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );
void setup() {
Serial.begin(9600);
}
void loop() {
char key = keypad.getKey();
if (key != NO_KEY) {
delay(60);
switch (key) {
case 'A': break;
case 'B': break;
case 'C': break;
case 'D': changePassword(); break;
case '#': checkPassword(); break;
case '*': resetPassword(); break;
default: processNumberKey(key);
}
}
}
void processNumberKey(char key) {
Serial.print(key);
currentPasswordLength++;
password.append(key);
if (currentPasswordLength == maxPasswordLength) {
checkPassword();
}
}
void checkPassword() {
if (password.evaluate()) {
Serial.println(" OK.\n");
} else {
Serial.println(" Wrong passwowrd!");
}
resetPassword();
}
void resetPassword() {
password.reset();
currentPasswordLength = 0;
}
void changePassword() {
newPassword = "123";
newPassword.toCharArray(passchars, newPassword.length() + 1); //convert string to char array
password.set(passchars);
resetPassword();
Serial.print("Password changed to ");
Serial.println(newPassword);
}
В скетче устанавливается пароль "1234". Максимальное число ввода символов - 6. Если это число будет превышено, то автоматически сравниваем введённый набор с паролем и выдаём результат, сбрасывая ввод. Это избавит нас от бесконечного ввода.
Клавиши "A", "B", "C" ничего не делают, их можно не трогать. Для проверки пароля нужно нажать набор чисел и затем кнопку # (решётку). В успешном случае выводится сообщение OK, в противном случае появится сообщение о неправильном пароле.
Остальные кнопки меняют пароль (на 123), сбрасывают введённый пароль для повторного набора (если заметил ошибку при наборе).
На основе этого скетча можно написать свою логику. Также можно добавить запоминание нового пароля в долговременную память и т.д.
Если вам нужные несколько паролей, то создавайте разные экземпляры.
Password password1 = Password("1234");
Password password2 = Password("4567");
Password password3 = Password("7890");
void checkPassword(){
if (password1.evaluate()){
Serial.println("Success 1");
}
else if (password2.evaluate()){
Serial.println("Success 2");
}
else if (password3.evaluate()){
Serial.println("Success 3");
}
else{
Serial.println("Wrong");
}
}