← До всіх проєктів
Автоматизація Початковий

Кодовий замок: клавіатура 4×4, LCD і PIN-код

Мембранна клавіатура 4×4 займає лише 8 виводів завдяки матричному скануванню. Збираємо кодовий замок: введення PIN зі зірочками на LCD, «#» — підтвердити, «*» — стерти, світлодіод замість електромагнітного замка.

Складність
Початковий
Час
45 min
Категорія
Автоматизація
Оновлено

Про проєкт

16 кнопок — 16 виводів? Ні, достатньо восьми: кнопки мембранної клавіатури з'єднані в матрицю 4 рядки × 4 стовпці. Збираємо кодовий замок із виводом на LCD 1602 і «замком», який відкривається на 2 секунди після правильного PIN.

Що знадобиться

  • ESP32 DevKit
  • Мембранна клавіатура 4×4
  • LCD 1602 з I2C-перехідником
  • Світлодіод + резистор 220 Ом (у реальному проєкті — реле або MOSFET і електромагнітний замок)
  • Бібліотеки Keypad і LiquidCrystal_I2C

Схема

Клавіатура R1 R2 R3 R4 C1 C2 C3 C4
ESP32 GPIO19 GPIO18 GPIO5 GPIO17 GPIO16 GPIO4 GPIO13 GPIO14
  • LCD: VCC → 3V3, GND → GND, SDA → GPIO21, SCL → GPIO22.
  • «Замок»: GPIO26 → 220 Ом → світлодіод → GND.

Шлейф клавіатури має 8 контактів: зліва направо (кнопками до себе) спершу чотири рядки, потім чотири стовпці.

Як сканується матриця

Бібліотека по черзі опускає в LOW один стовпець, а рядки читає з підтяжкою INPUT_PULLUP. Якщо рядок R2 прочитався як LOW, поки активний стовпець C3, натиснуто клавішу на перетині — «6». Весь цикл займає мікросекунди, тож для користувача це непомітно.

keypad.getKey() повертає символ один раз на натискання (антидребезг усередині) або 0, якщо нічого не натиснуто.

Код

// Кодовий замок: клавіатура 4×4 + LCD 1602, PIN 1234
#include <Keypad.h>
#include <LiquidCrystal_I2C.h>

const byte ROWS = 4, COLS = 4;
char keys[ROWS][COLS] = {
  {'1', '2', '3', 'A'},
  {'4', '5', '6', 'B'},
  {'7', '8', '9', 'C'},
  {'*', '0', '#', 'D'},
};
byte rowPins[ROWS] = {19, 18, 5, 17};
byte colPins[COLS] = {16, 4, 13, 14};
Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);
LiquidCrystal_I2C lcd(0x27, 16, 2);

const int LOCK = 26;
const String PIN_CODE = "1234";
String entered;

void show() {
  lcd.clear();
  lcd.print("PIN: ");
  for (unsigned int i = 0; i < entered.length(); i++) lcd.print('*');   // цифри не показуємо
}

void setup() {
  lcd.init();
  lcd.backlight();
  pinMode(LOCK, OUTPUT);
  show();
}

void loop() {
  char k = keypad.getKey();
  if (!k) return;
  if (k == '#') {             // підтвердити
    lcd.clear();
    if (entered == PIN_CODE) {
      lcd.print("Access granted");
      digitalWrite(LOCK, HIGH);   // відкрити замок на 2 с
      delay(2000);
      digitalWrite(LOCK, LOW);
    } else {
      lcd.print("Wrong PIN");
      delay(1500);
    }
    entered = "";
    show();
  } else if (k == '*') {      // стерти
    entered = "";
    show();
  } else if (entered.length() < 8) {
    entered += k;
    show();
  }
}

Як зробити по-справжньому

  • Замок. Електромагнітна засувка на 12 В бере 0.3–1 А: вмикайте її через MOSFET або реле, з діодом паралельно котушці.
  • Захист від перебору. Після трьох помилок блокуйте введення на хвилину, а далі збільшуйте паузу вдвічі.
  • PIN не в коді. Зберігайте його в Preferences (флеш ESP32) і дайте можливість змінити: наприклад, «A» + старий PIN + новий PIN.
  • Живлення. Замок, що відкривається від будь-якого збою, — погана ідея. Подумайте, що станеться, якщо ESP32 перезавантажиться, коли вихід у HIGH.