Освой Arduino играючи

Сайт Александра Климова

Шкодим

/* Моя кошка замечательно разбирается в программировании. Стоит мне объяснить проблему ей - и все становится ясно. */
John Robbins, Debugging Applications, Microsoft Press, 2000

Матричная мембранная клавиатура

Keypad

Библиотека Password

Разберём работу с матричной клавиатурой. В моём распоряжении клавиатура размером 4х4, поэтому код будет писаться под неё.

Также могут попадаться клавиатуры с матрицей 4х3 и 4х1 и другие.

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

Клавиатура выполнена в виде матрицы 4х4, каждая кнопка является областью воздушного зазора между двумя диэлектрическими слоями с нанесёнными на них токопроводящими покрытиями. Дорожки токопроводящего покрытия одного слоя нанесены горизонтально (выводы 1-4), а другого вертикально (выводы 5-8). Нажатие на кнопку приводит к соединению дорожки одного слоя с дорожкой другого, и как следствие, к замыканию одного из выводов 1-4 с одним из выводов 5-8.

Заказать на AliExpress

Технические характеристики

  • Размеры: 68×77×0,8 мм
  • Рабочее напряжение: до 12 В
  • Максимальный ток: 100 мА
  • Сопротивление изоляции: >100 МОм
  • Сопротивление контактов: <200 Ом
  • Дребезг контактов: <5мсек
  • Ресурс: 1 миллион нажатий
  • Рабочая температура: от 0 до +70 градусов Цельсия
  • Допустимая влажность: 90%-95%, 240 часов
  • Вес: 10 г

Для удобства установим готовую библиотеку Keypad. Устанавливайте через менеджер библиотек в Arduino IDE.

Исходники для просмотра кода библиотеки.

Keypad

Само подключение не должно вызвать трудностей. У клавиатуры восемь выводов в виде шлейфа, который нужно подключить к цифровым выводам платы от 9 до 2. Шлейф имеет мама-разъём с шагом 2,54 мм - можно легко установить с помощью макетной платы и линейки штырьковых соединителей. Также можно использовать перемычки папа-папа.

Keypad

Примеры

Библиотека снабжена несколькими примерами. Немного видоизменённые примеры представлены ниже.

HelloKeypad

Пример рассчитан на клавиатуру 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 и нажимайте на клавиши. Символ нажатой клавиши должен отображаться на экране.

MultiKey

Пример позволяет обрабатывать одновременные нажатия клавиш. Он также предназначен для клавиатуры 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", которую затем отпустил.

Keypad

Библиотека Password

Клавиатуру логично использовать в качестве ввода пароля для доступа к каким-то возможностям. Для удобной обработки вводимых символов можно использовать готовую библиотеку Password. К сожалению, её нельзя установить через менеджер библиотек, поэтому придётся скачать архив и разместить папку в папке libraries самостоятельно.

У библиотеки несколько функций.

set(password)
Устанавливает пароль
is(password)
Совпадает ли текущий набор пароля с установленным паролем
append(character)
Добавляет символ к текущему вводу пароля
reset()
Сбрасывает набранный ввод пароля
evaluate()
Совпадает ли текущий набор пароля с установленным паролем

Скетч для ввода пароля


#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");
  }
} 

Дополнительные материалы

Клавиатура 4х4 для Fritzing

Клавиатура 4х3 для Fritzing

Реклама