
A kódzár építéséhez szükséges elemek:
1; arduino modul (Pro Mini, Nano, Uno)
2; billentyűzet (4x3 matrix)
3; oled kijelző (SSD1306, elhagyható)
4; 4 db led (WS2812B, APA106, elhagyható, de jó ha van)
5; passzív csipogó (zümmer) - ez mindenképp ajánlott
6; relé modul a nyitáshoz
7; nyomógomb - ezt rejtett helyre tesszük, a kódváltáshoz szükséges
The necessary components for building a code lock:
1; Arduino module (Pro Mini, Nano, Uno)
2; Keypad (4x3 matrix)
3; OLED display (SSD1306, optional)
4; 4 LEDs (WS2812B, APA106, optional but recommended)
5; Passive buzzer - recommended
6; Relay module for opening
7; Push button - this is hidden and used for changing the code.
Kód: Egész kijelölése
#include <Wire.h>
#include <EEPROM.h>
#include <Adafruit_NeoPixel.h>
#define LED_PIN 11 // A neopixel led adatvezeték csatlakozója az Arduino-n
#define LED_COUNT 4 // A használt LED-ek száma
Adafruit_NeoPixel leds(LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800);
int ledState = 0;
unsigned char addr = 0x3C; //0x78
// standard ascii 5x7 font - https://github.com/PaulStoffregen/LedDisplay/blob/master/font5x7.h
// 0x3E, 0x51, 0x49, 0x45, 0x3E, //crossed 0
static const unsigned char font[] = {
0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x5F, 0x00, 0x00,
0x00, 0x07, 0x00, 0x07, 0x00,
0x14, 0x7F, 0x14, 0x7F, 0x14,
0x24, 0x2A, 0x7F, 0x2A, 0x12,
0x23, 0x13, 0x08, 0x64, 0x62,
0x36, 0x49, 0x56, 0x20, 0x50,
0x00, 0x08, 0x07, 0x03, 0x00,
0x00, 0x1C, 0x22, 0x41, 0x00,
0x00, 0x41, 0x22, 0x1C, 0x00,
0x2A, 0x1C, 0x7F, 0x1C, 0x2A,
0x08, 0x08, 0x3E, 0x08, 0x08,
0x00, 0x80, 0x70, 0x30, 0x00,
0x08, 0x08, 0x08, 0x08, 0x08,
0x00, 0x00, 0x60, 0x60, 0x00,
0x20, 0x10, 0x08, 0x04, 0x02,
0x3E, 0x41, 0x41, 0x41, 0x3E, //un-crossed 0
0x00, 0x42, 0x7F, 0x40, 0x00,
0x72, 0x49, 0x49, 0x49, 0x46,
0x21, 0x41, 0x49, 0x4D, 0x33,
0x18, 0x14, 0x12, 0x7F, 0x10,
0x27, 0x45, 0x45, 0x45, 0x39,
0x3C, 0x4A, 0x49, 0x49, 0x31,
0x41, 0x21, 0x11, 0x09, 0x07,
0x36, 0x49, 0x49, 0x49, 0x36,
0x46, 0x49, 0x49, 0x29, 0x1E,
0x00, 0x00, 0x14, 0x00, 0x00,
0x00, 0x40, 0x34, 0x00, 0x00,
0x00, 0x08, 0x14, 0x22, 0x41,
0x14, 0x14, 0x14, 0x14, 0x14,
0x00, 0x41, 0x22, 0x14, 0x08,
0x02, 0x01, 0x59, 0x09, 0x06,
0x3E, 0x41, 0x5D, 0x59, 0x4E,
0x7C, 0x12, 0x11, 0x12, 0x7C, //A
0x7F, 0x49, 0x49, 0x49, 0x36,
0x3E, 0x41, 0x41, 0x41, 0x22,
0x7F, 0x41, 0x41, 0x41, 0x3E,
0x7F, 0x49, 0x49, 0x49, 0x41,
0x7F, 0x09, 0x09, 0x09, 0x01,
0x3E, 0x41, 0x41, 0x51, 0x73,
0x7F, 0x08, 0x08, 0x08, 0x7F, //H
0x00, 0x41, 0x7F, 0x41, 0x00,
0x20, 0x40, 0x41, 0x3F, 0x01,
0x7F, 0x08, 0x14, 0x22, 0x41,
0x7F, 0x40, 0x40, 0x40, 0x40,
0x7F, 0x02, 0x1C, 0x02, 0x7F,
0x7F, 0x04, 0x08, 0x10, 0x7F,
0x3E, 0x41, 0x41, 0x41, 0x3E,
0x7F, 0x09, 0x09, 0x09, 0x06,
0x3E, 0x41, 0x51, 0x21, 0x5E,
0x7F, 0x09, 0x19, 0x29, 0x46,
0x26, 0x49, 0x49, 0x49, 0x32, //S
0x03, 0x01, 0x7F, 0x01, 0x03,
0x3F, 0x40, 0x40, 0x40, 0x3F,
0x1F, 0x20, 0x40, 0x20, 0x1F,
0x3F, 0x40, 0x38, 0x40, 0x3F,
0x63, 0x14, 0x08, 0x14, 0x63,
0x03, 0x04, 0x78, 0x04, 0x03,
0x61, 0x59, 0x49, 0x4D, 0x43,
0x00, 0x7F, 0x41, 0x41, 0x41,
0x02, 0x04, 0x08, 0x10, 0x20,
0x00, 0x41, 0x41, 0x41, 0x7F,
0x04, 0x02, 0x01, 0x02, 0x04,
0x40, 0x40, 0x40, 0x40, 0x40,
0x00, 0x03, 0x07, 0x08, 0x00,
0x20, 0x54, 0x54, 0x78, 0x40,
0x7F, 0x28, 0x44, 0x44, 0x38,
0x38, 0x44, 0x44, 0x44, 0x28,
0x38, 0x44, 0x44, 0x28, 0x7F,
0x38, 0x54, 0x54, 0x54, 0x18,
0x00, 0x08, 0x7E, 0x09, 0x02,
0x18, 0xA4, 0xA4, 0x9C, 0x78,
0x7F, 0x08, 0x04, 0x04, 0x78,
0x00, 0x44, 0x7D, 0x40, 0x00,
0x20, 0x40, 0x40, 0x3D, 0x00,
0x7F, 0x10, 0x28, 0x44, 0x00,
0x00, 0x41, 0x7F, 0x40, 0x00,
0x7C, 0x04, 0x78, 0x04, 0x78,
0x7C, 0x08, 0x04, 0x04, 0x78, //n
0x38, 0x44, 0x44, 0x44, 0x38,
0xFC, 0x18, 0x24, 0x24, 0x18,
0x18, 0x24, 0x24, 0x18, 0xFC,
0x7C, 0x08, 0x04, 0x04, 0x08,
0x48, 0x54, 0x54, 0x54, 0x24,
0x04, 0x04, 0x3F, 0x44, 0x24,
0x3C, 0x40, 0x40, 0x20, 0x7C, //u
0x1C, 0x20, 0x40, 0x20, 0x1C,
0x3C, 0x40, 0x30, 0x40, 0x3C,
0x44, 0x28, 0x10, 0x28, 0x44,
0x4C, 0x90, 0x90, 0x90, 0x7C,
0x44, 0x64, 0x54, 0x4C, 0x44, //z
0x00, 0x08, 0x36, 0x41, 0x00,
};
unsigned char key, mem[4], num[4], ir = 0;
bool pMode = false;
void setup() {
pinMode(7, OUTPUT); //relé
pinMode(8, OUTPUT); // COL1
pinMode(9, OUTPUT); // COL2
pinMode(10, OUTPUT); // COL3
pinMode(13, OUTPUT); //ready LED
pinMode(12, OUTPUT); //buzzer
pinMode(2, INPUT_PULLUP); // ROW4
pinMode(3, INPUT_PULLUP); // ROW3
pinMode(4, INPUT_PULLUP); // ROW2
pinMode(5, INPUT_PULLUP); // ROW1
pinMode(6, INPUT_PULLUP); //nyomógomb pMode
leds.begin(); // LED-ek inicializálása
Wire.begin(); // init i2c bus
Wire.setClock(200000); //200khz
oled_init();
clrScreen();
digitalWrite(7, LOW);
digitalWrite(8, LOW);
digitalWrite(9, LOW);
digitalWrite(10, LOW);
readyL();
for (unsigned char i = 0; i < 4; ++i) {
num[i] = EEPROM.read(i);
}
for (unsigned char j = 0; j < 4; j++) {
drawChar2(0x5F, 5, j + 2);
}
}
void loop()
{
if (!digitalRead(6)) {
pMode = true;
drawChar2(0x20,1,1);
drawChar2(0x43,1,2); //code, programozó módhoz
drawChar2(0x4F,1,3);
drawChar2(0x44,1,4);
drawChar2(0x45,1,5);
drawChar2(0x20,1,6);
drawChar2(0x20,1,7);
drawChar2(0x20,1,8);
drawChar2(32, 1, 6);
digitalWrite(13, LOW);
}
if (!digitalRead(5) || !digitalRead(4) || !digitalRead(3) || !digitalRead(2)) {
get_key();
tone(12, 1000, 50);
drawChar2(key + 48, 5, ir + 2);
mem[ir] = key;
if (ir < LED_COUNT) { // Ha még nem világít az összes LED-ek
leds.setPixelColor(ledState, 0, 0, 255); // Az aktuális LED bekapcsolása kékre
leds.show(); // LED-ek frissítése
ledState++; // Az aktuális LED számának növelése
}
if (ir == 3 && pMode == false) {
if (mem[0] == num[0] && mem[1] == num[1] && mem[2] == num[2] && mem[3] == num[3]) {
digitalWrite(7, HIGH);
for (int i = 0; i < 4; i++) {
leds.setPixelColor(i, 0, 255, 0); // minden LED zöldre kapcsolása, ha helyes kód lett beírva
}
leds.show(); // a változtatások megjelenítése a LED-eken
tone(12, 1000, 150);
delay(150);
tone(12, 1500, 150);
delay(2000); // Relé ennyi ideig húz be
digitalWrite(7, LOW);
ledsclear();
}
if (mem[0] != num[0] || mem[1] != num[1] || mem[2] != num[2] || mem[3] != num[3]) {
for (int i = 0; i < 4; i++) {
leds.setPixelColor(i, 255, 0, 0); // minden LED pirosra kapcsolása, ha hibás kód lett beírva
}
leds.show(); // a változtatások megjelenítése a LED-eken
tone(12, 1000, 150);
delay(200);
tone(12, 1500, 150);
delay(200);
tone(12, 2000, 150);
delay(200);
tone(12, 1500, 150);
delay(200);
tone(12, 1000, 150);
delay(300);
ledsclear();
}
}
if (ir == 3 && pMode == true) {
for (unsigned char j = 0; j < 4; j++) {
EEPROM.write(j, mem[j]);
}
num[0] = mem[0];
num[1] = mem[1];
num[2] = mem[2];
num[3] = mem[3];
ledsclear();
pMode = false;
readyL();
}
ir++;
if (ir == 4) {
ir = 0;
for (unsigned char j = 0; j < 4; j++) {
drawChar2(0x5F, 5, j + 2);
}
}
while (!digitalRead(5) || !digitalRead(4) || !digitalRead(3) || !digitalRead(2)) {}
delay(100);
}
}
void readyL() {
drawChar2(0x4e, 1, 1); //NYITOKOD
drawChar2(0x59, 1, 2);
drawChar2(0x49, 1, 3);
drawChar2(0x54, 1, 4);
drawChar2(0x4f, 1, 5);
drawChar2(0x4b, 1, 6);
drawChar2(0x4f, 1, 7);
drawChar2(0x44, 1, 8);
digitalWrite(13, HIGH);
}
void get_key() {
digitalWrite(8, LOW);
digitalWrite(9, HIGH);
digitalWrite(10, HIGH);
if (!digitalRead(5)) {
key = 1;
}
if (!digitalRead(4)) {
key = 4;
}
if (!digitalRead(3)) {
key = 7;
}
digitalWrite(9, LOW);
digitalWrite(8, HIGH);
digitalWrite(10, HIGH);
if (!digitalRead(5)) {
key = 2;
}
if (!digitalRead(4)) {
key = 5;
}
if (!digitalRead(3)) {
key = 8;
}
if (!digitalRead(2)) {
key = 0;
}
digitalWrite(10, LOW);
digitalWrite(9, HIGH);
digitalWrite(8, HIGH);
if (!digitalRead(5)) {
key = 3;
}
if (!digitalRead(4)) {
key = 6;
}
if (!digitalRead(3)) {
key = 9;
}
digitalWrite(8, LOW);
digitalWrite(9, LOW);
}
void clrScreen() //fill screen with 0
{
unsigned char y, x;
for ( y = 0; y < 8; y++ ) {
for (x = 0; x < 17; x++) {
command(0x21); //col addr
command(8 * x); //col start
command(8 * x + 7); //col end
command(0x22); //0x22
command(y); // Page start
command(y); // Page end
Wire.beginTransmission(addr);
Wire.write(0x40);
for (unsigned char i = 0; i < 8; i++) {
Wire.write(0x00);
}
Wire.endTransmission();
}
}
}
void command( unsigned char comm) {
Wire.beginTransmission(addr);
Wire.write(0x00);
Wire.write(comm); // LSB
Wire.endTransmission();
}
void oled_init() { // https://www.micros.com.pl/mediaserver/OLED12864-0.96-W-2_0001.pdf
command(0xAE); // DISPLAYOFF
command(0x8D); // CHARGEPUMP *
command(0x14); //0x14-pump on
command(0x20); // MEMORYMODE
command(0x0); //0x0=horizontal, 0x01=vertical, 0x02=page
command(0xA1); //SEGREMAP * A0/A1=top/bottom
command(0xC8); //COMSCANDEC * C0/C8=left/right
command(0xDA); // SETCOMPINS *
command(0x12); //0x22=4rows, 0x12=8rows
command(0x81); // SETCONTRAST
command(0x9F); //0x8F
//following settings are set by default
// command(0xD5); // SETDISPLAYCLOCKDIV
// command(0x80);
// command(0xA8); // SETMULTIPLEX
// command(0x3F); // 0x1F
// command(0xD3); // SETDISPLAYOFFSET
// command(0x0);
// command(0x40); // SETSTARTLINE
// command(0xD9); // SETPRECHARGE
// command(0xF1);
// command(0xDB); // SETVCOMDETECT
// command(0x40);
// command(0xA4); // DISPLAYALLON_RESUME
// command(0xA6); // NORMALDISPLAY
command(0xAF); //DISPLAYON
}
//size x1 chars
void drawChar(char fig, unsigned char y, unsigned char x)
{
command(0x21); //col addr
command(7 * x); //col start
command(7 * x + 4); //col end
command(0x22); //0x22
command(y); // Page start
command(y); // Page end
Wire.beginTransmission(addr);
Wire.write(0x40);
for (unsigned char i = 0; i < 5; i++) {
Wire.write(font[5 * (fig - 32) + i]);
}
Wire.endTransmission();
}
//size x2 chars
void drawChar2(char fig, unsigned char y, unsigned char x)
{
unsigned char i, line, btm, top; //
command(0x20); // vert mode
command(0x01);
command(0x21); //col addr
command(13 * x); //col start
command(13 * x + 9); //col end
command(0x22); //0x22
command(y); // Page start
command(y + 1); // Page end
Wire.beginTransmission(addr);
Wire.write(0x40);
for (i = 0; i < 5; i++) {
line = font[5 * (fig - 32) + i]; //line=font[5*(fig-32)+i];
btm = 0; top = 0;
// expend char
if (line & 64) {
btm += 192;
}
if (line & 32) {
btm += 48;
}
if (line & 16) {
btm += 12;
}
if (line & 8) {
btm += 3;
}
if (line & 4) {
top += 192;
}
if (line & 2) {
top += 48;
}
if (line & 1) {
top += 12;
}
Wire.write(top); //top page
Wire.write(btm); //second page
Wire.write(top);
Wire.write(btm);
}
Wire.endTransmission();
command(0x20); // horizontal mode
command(0x00);
}
void ledsclear() {
leds.clear(); // Minden LED kikapcsolása
leds.show(); // LED-ek frissítése
ledState = 0; // Az aktuális LED számának nullázása
}
A programot itt tesztelheted: https://wokwi.com/projects/362424826523789313
Frissítés: 2025.08.26.
A használat során többször előfordult, hogy a beütött helyes kódot elutasította, így módosítottam a kódban, mivel a get_key() függvényben nem volt debounce kezelés.
Ha egy gomb mechanikailag "zizeg" (bounce-ol), akkor egyetlen lenyomás több értéket is adhat, vagy rosszul olvasódhat ki.
Update: 2025.08.26.
During use, it happened several times that the correct entered code was rejected, so I modified the code, since there was no debounce handling in the get_key() function.
If a button mechanically “bounces,” a single press can produce multiple values or be read incorrectly.
Kód: Egész kijelölése
#include <Wire.h>
#include <EEPROM.h>
#include <Adafruit_NeoPixel.h>
#define LED_PIN 11 // A neopixel led adatvezeték csatlakozója az Arduino-n
#define LED_COUNT 4 // A használt LED-ek száma
Adafruit_NeoPixel leds(LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800);
int ledState = 0;
unsigned char addr = 0x3C; //0x78
// standard ascii 5x7 font - https://github.com/PaulStoffregen/LedDisplay/blob/master/font5x7.h
// 0x3E, 0x51, 0x49, 0x45, 0x3E, //crossed 0
static const unsigned char font[] = {
0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x5F, 0x00, 0x00,
0x00, 0x07, 0x00, 0x07, 0x00,
0x14, 0x7F, 0x14, 0x7F, 0x14,
0x24, 0x2A, 0x7F, 0x2A, 0x12,
0x23, 0x13, 0x08, 0x64, 0x62,
0x36, 0x49, 0x56, 0x20, 0x50,
0x00, 0x08, 0x07, 0x03, 0x00,
0x00, 0x1C, 0x22, 0x41, 0x00,
0x00, 0x41, 0x22, 0x1C, 0x00,
0x2A, 0x1C, 0x7F, 0x1C, 0x2A,
0x08, 0x08, 0x3E, 0x08, 0x08,
0x00, 0x80, 0x70, 0x30, 0x00,
0x08, 0x08, 0x08, 0x08, 0x08,
0x00, 0x00, 0x60, 0x60, 0x00,
0x20, 0x10, 0x08, 0x04, 0x02,
0x3E, 0x41, 0x41, 0x41, 0x3E, //un-crossed 0
0x00, 0x42, 0x7F, 0x40, 0x00,
0x72, 0x49, 0x49, 0x49, 0x46,
0x21, 0x41, 0x49, 0x4D, 0x33,
0x18, 0x14, 0x12, 0x7F, 0x10,
0x27, 0x45, 0x45, 0x45, 0x39,
0x3C, 0x4A, 0x49, 0x49, 0x31,
0x41, 0x21, 0x11, 0x09, 0x07,
0x36, 0x49, 0x49, 0x49, 0x36,
0x46, 0x49, 0x49, 0x29, 0x1E,
0x00, 0x00, 0x14, 0x00, 0x00,
0x00, 0x40, 0x34, 0x00, 0x00,
0x00, 0x08, 0x14, 0x22, 0x41,
0x14, 0x14, 0x14, 0x14, 0x14,
0x00, 0x41, 0x22, 0x14, 0x08,
0x02, 0x01, 0x59, 0x09, 0x06,
0x3E, 0x41, 0x5D, 0x59, 0x4E,
0x7C, 0x12, 0x11, 0x12, 0x7C, //A
0x7F, 0x49, 0x49, 0x49, 0x36,
0x3E, 0x41, 0x41, 0x41, 0x22,
0x7F, 0x41, 0x41, 0x41, 0x3E,
0x7F, 0x49, 0x49, 0x49, 0x41,
0x7F, 0x09, 0x09, 0x09, 0x01,
0x3E, 0x41, 0x41, 0x51, 0x73,
0x7F, 0x08, 0x08, 0x08, 0x7F, //H
0x00, 0x41, 0x7F, 0x41, 0x00,
0x20, 0x40, 0x41, 0x3F, 0x01,
0x7F, 0x08, 0x14, 0x22, 0x41,
0x7F, 0x40, 0x40, 0x40, 0x40,
0x7F, 0x02, 0x1C, 0x02, 0x7F,
0x7F, 0x04, 0x08, 0x10, 0x7F,
0x3E, 0x41, 0x41, 0x41, 0x3E,
0x7F, 0x09, 0x09, 0x09, 0x06,
0x3E, 0x41, 0x51, 0x21, 0x5E,
0x7F, 0x09, 0x19, 0x29, 0x46,
0x26, 0x49, 0x49, 0x49, 0x32, //S
0x03, 0x01, 0x7F, 0x01, 0x03,
0x3F, 0x40, 0x40, 0x40, 0x3F,
0x1F, 0x20, 0x40, 0x20, 0x1F,
0x3F, 0x40, 0x38, 0x40, 0x3F,
0x63, 0x14, 0x08, 0x14, 0x63,
0x03, 0x04, 0x78, 0x04, 0x03,
0x61, 0x59, 0x49, 0x4D, 0x43,
0x00, 0x7F, 0x41, 0x41, 0x41,
0x02, 0x04, 0x08, 0x10, 0x20,
0x00, 0x41, 0x41, 0x41, 0x7F,
0x04, 0x02, 0x01, 0x02, 0x04,
0x40, 0x40, 0x40, 0x40, 0x40,
0x00, 0x03, 0x07, 0x08, 0x00,
0x20, 0x54, 0x54, 0x78, 0x40,
0x7F, 0x28, 0x44, 0x44, 0x38,
0x38, 0x44, 0x44, 0x44, 0x28,
0x38, 0x44, 0x44, 0x28, 0x7F,
0x38, 0x54, 0x54, 0x54, 0x18,
0x00, 0x08, 0x7E, 0x09, 0x02,
0x18, 0xA4, 0xA4, 0x9C, 0x78,
0x7F, 0x08, 0x04, 0x04, 0x78,
0x00, 0x44, 0x7D, 0x40, 0x00,
0x20, 0x40, 0x40, 0x3D, 0x00,
0x7F, 0x10, 0x28, 0x44, 0x00,
0x00, 0x41, 0x7F, 0x40, 0x00,
0x7C, 0x04, 0x78, 0x04, 0x78,
0x7C, 0x08, 0x04, 0x04, 0x78, //n
0x38, 0x44, 0x44, 0x44, 0x38,
0xFC, 0x18, 0x24, 0x24, 0x18,
0x18, 0x24, 0x24, 0x18, 0xFC,
0x7C, 0x08, 0x04, 0x04, 0x08,
0x48, 0x54, 0x54, 0x54, 0x24,
0x04, 0x04, 0x3F, 0x44, 0x24,
0x3C, 0x40, 0x40, 0x20, 0x7C, //u
0x1C, 0x20, 0x40, 0x20, 0x1C,
0x3C, 0x40, 0x30, 0x40, 0x3C,
0x44, 0x28, 0x10, 0x28, 0x44,
0x4C, 0x90, 0x90, 0x90, 0x7C,
0x44, 0x64, 0x54, 0x4C, 0x44, //z
0x00, 0x08, 0x36, 0x41, 0x00,
};
unsigned char key, mem[4], num[4], ir = 0;
bool pMode = false;
void setup() {
pinMode(7, OUTPUT); //relé
pinMode(8, OUTPUT); // COL1
pinMode(9, OUTPUT); // COL2
pinMode(10, OUTPUT); // COL3
pinMode(13, OUTPUT); //ready LED
pinMode(12, OUTPUT); //buzzer
pinMode(2, INPUT_PULLUP); // ROW4
pinMode(3, INPUT_PULLUP); // ROW3
pinMode(4, INPUT_PULLUP); // ROW2
pinMode(5, INPUT_PULLUP); // ROW1
pinMode(6, INPUT_PULLUP); //nyomógomb pMode
leds.begin(); // LED-ek inicializálása
Wire.begin(); // init i2c bus
Wire.setClock(200000); //200khz
oled_init();
clrScreen();
digitalWrite(7, LOW);
digitalWrite(8, LOW);
digitalWrite(9, LOW);
digitalWrite(10, LOW);
readyL();
for (unsigned char i = 0; i < 4; ++i) {
num[i] = EEPROM.read(i);
}
for (unsigned char j = 0; j < 4; j++) {
drawChar2(0x5F, 5, j + 2);
}
}
void loop()
{
if (!digitalRead(6)) {
pMode = true;
drawChar2(0x20,1,1);
drawChar2(0x43,1,2); //code, programozó módhoz
drawChar2(0x4F,1,3);
drawChar2(0x44,1,4);
drawChar2(0x45,1,5);
drawChar2(0x20,1,6);
drawChar2(0x20,1,7);
drawChar2(0x20,1,8);
drawChar2(32, 1, 6);
digitalWrite(13, LOW);
}
if (!digitalRead(5) || !digitalRead(4) || !digitalRead(3) || !digitalRead(2)) {
get_key();
tone(12, 1000, 50);
drawChar2(key + 48, 5, ir + 2);
mem[ir] = key;
if (ir < LED_COUNT) { // Ha még nem világít az összes LED-ek
leds.setPixelColor(ledState, 0, 0, 255); // Az aktuális LED bekapcsolása kékre
leds.show(); // LED-ek frissítése
ledState++; // Az aktuális LED számának növelése
}
if (ir == 3 && pMode == false) {
if (mem[0] == num[0] && mem[1] == num[1] && mem[2] == num[2] && mem[3] == num[3]) {
digitalWrite(7, HIGH);
for (int i = 0; i < 4; i++) {
leds.setPixelColor(i, 0, 255, 0); // minden LED zöldre kapcsolása, ha helyes kód lett beírva
}
leds.show(); // a változtatások megjelenítése a LED-eken
tone(12, 1000, 150);
delay(150);
tone(12, 1500, 150);
delay(2000); // Relé ennyi ideig húz be
digitalWrite(7, LOW);
ledsclear();
}
if (mem[0] != num[0] || mem[1] != num[1] || mem[2] != num[2] || mem[3] != num[3]) {
for (int i = 0; i < 4; i++) {
leds.setPixelColor(i, 255, 0, 0); // minden LED pirosra kapcsolása, ha hibás kód lett beírva
}
leds.show(); // a változtatások megjelenítése a LED-eken
tone(12, 1000, 150);
delay(200);
tone(12, 1500, 150);
delay(200);
tone(12, 2000, 150);
delay(200);
tone(12, 1500, 150);
delay(200);
tone(12, 1000, 150);
delay(300);
ledsclear();
}
}
if (ir == 3 && pMode == true) {
for (unsigned char j = 0; j < 4; j++) {
EEPROM.write(j, mem[j]);
}
num[0] = mem[0];
num[1] = mem[1];
num[2] = mem[2];
num[3] = mem[3];
ledsclear();
pMode = false;
readyL();
}
ir++;
if (ir == 4) {
ir = 0;
for (unsigned char j = 0; j < 4; j++) {
drawChar2(0x5F, 5, j + 2);
}
}
while (!digitalRead(5) || !digitalRead(4) || !digitalRead(3) || !digitalRead(2)) {}
delay(100);
}
}
void readyL() {
drawChar2(0x4e, 1, 1); //NYITOKOD
drawChar2(0x59, 1, 2);
drawChar2(0x49, 1, 3);
drawChar2(0x54, 1, 4);
drawChar2(0x4f, 1, 5);
drawChar2(0x4b, 1, 6);
drawChar2(0x4f, 1, 7);
drawChar2(0x44, 1, 8);
digitalWrite(13, HIGH);
}
void get_key() {
digitalWrite(8, LOW);
digitalWrite(9, HIGH);
digitalWrite(10, HIGH);
if (!digitalRead(5)) {
key = 1;
}
if (!digitalRead(4)) {
key = 4;
}
if (!digitalRead(3)) {
key = 7;
}
digitalWrite(9, LOW);
digitalWrite(8, HIGH);
digitalWrite(10, HIGH);
if (!digitalRead(5)) {
key = 2;
}
if (!digitalRead(4)) {
key = 5;
}
if (!digitalRead(3)) {
key = 8;
}
if (!digitalRead(2)) {
key = 0;
}
digitalWrite(10, LOW);
digitalWrite(9, HIGH);
digitalWrite(8, HIGH);
if (!digitalRead(5)) {
key = 3;
}
if (!digitalRead(4)) {
key = 6;
}
if (!digitalRead(3)) {
key = 9;
}
digitalWrite(8, LOW);
digitalWrite(9, LOW);
}
void clrScreen() //fill screen with 0
{
unsigned char y, x;
for ( y = 0; y < 8; y++ ) {
for (x = 0; x < 17; x++) {
command(0x21); //col addr
command(8 * x); //col start
command(8 * x + 7); //col end
command(0x22); //0x22
command(y); // Page start
command(y); // Page end
Wire.beginTransmission(addr);
Wire.write(0x40);
for (unsigned char i = 0; i < 8; i++) {
Wire.write(0x00);
}
Wire.endTransmission();
}
}
}
void command( unsigned char comm) {
Wire.beginTransmission(addr);
Wire.write(0x00);
Wire.write(comm); // LSB
Wire.endTransmission();
}
void oled_init() { // https://www.micros.com.pl/mediaserver/OLED12864-0.96-W-2_0001.pdf
command(0xAE); // DISPLAYOFF
command(0x8D); // CHARGEPUMP *
command(0x14); //0x14-pump on
command(0x20); // MEMORYMODE
command(0x0); //0x0=horizontal, 0x01=vertical, 0x02=page
command(0xA1); //SEGREMAP * A0/A1=top/bottom
command(0xC8); //COMSCANDEC * C0/C8=left/right
command(0xDA); // SETCOMPINS *
command(0x12); //0x22=4rows, 0x12=8rows
command(0x81); // SETCONTRAST
command(0x9F); //0x8F
//following settings are set by default
// command(0xD5); // SETDISPLAYCLOCKDIV
// command(0x80);
// command(0xA8); // SETMULTIPLEX
// command(0x3F); // 0x1F
// command(0xD3); // SETDISPLAYOFFSET
// command(0x0);
// command(0x40); // SETSTARTLINE
// command(0xD9); // SETPRECHARGE
// command(0xF1);
// command(0xDB); // SETVCOMDETECT
// command(0x40);
// command(0xA4); // DISPLAYALLON_RESUME
// command(0xA6); // NORMALDISPLAY
command(0xAF); //DISPLAYON
}
//size x1 chars
void drawChar(char fig, unsigned char y, unsigned char x)
{
command(0x21); //col addr
command(7 * x); //col start
command(7 * x + 4); //col end
command(0x22); //0x22
command(y); // Page start
command(y); // Page end
Wire.beginTransmission(addr);
Wire.write(0x40);
for (unsigned char i = 0; i < 5; i++) {
Wire.write(font[5 * (fig - 32) + i]);
}
Wire.endTransmission();
}
//size x2 chars
void drawChar2(char fig, unsigned char y, unsigned char x)
{
unsigned char i, line, btm, top; //
command(0x20); // vert mode
command(0x01);
command(0x21); //col addr
command(13 * x); //col start
command(13 * x + 9); //col end
command(0x22); //0x22
command(y); // Page start
command(y + 1); // Page end
Wire.beginTransmission(addr);
Wire.write(0x40);
for (i = 0; i < 5; i++) {
line = font[5 * (fig - 32) + i]; //line=font[5*(fig-32)+i];
btm = 0; top = 0;
// expend char
if (line & 64) {
btm += 192;
}
if (line & 32) {
btm += 48;
}
if (line & 16) {
btm += 12;
}
if (line & 8) {
btm += 3;
}
if (line & 4) {
top += 192;
}
if (line & 2) {
top += 48;
}
if (line & 1) {
top += 12;
}
Wire.write(top); //top page
Wire.write(btm); //second page
Wire.write(top);
Wire.write(btm);
}
Wire.endTransmission();
command(0x20); // horizontal mode
command(0x00);
}
void ledsclear() {
leds.clear(); // Minden LED kikapcsolása
leds.show(); // LED-ek frissítése
ledState = 0; // Az aktuális LED számának nullázása
}
Az OLED kijelzőt kivettem a kódból, mivel a Neopixel led kijelzés teljesen jónak bizonyul, nincs szükség az OLED-re.
A D13 lábon a led a programozó módot jelzi, így a rejtett gomb lenyomása után világít, ebből tudjuk, hogy a következő beütött kód lesz eltárolva az EPROM-ban.
I removed the OLED display from the code, since the Neopixel LED display proved to be completely sufficient, there is no need for the OLED.
The LED on pin D13 indicates programming mode, so after pressing the hidden button it lights up, letting us know that the next entered code will be stored in the EPROM.
Kód: Egész kijelölése
/*
Kódos ajtónyitó rendszer
Verzió: v1.0
Dátum: 2025-08-26
Hardver: Arduino Pro Mini, 4x3 mátrix billentyűzet, relé, NeoPixel LED-ek
Leírás:
- 4 jegyű kód alapján vezérli a relét
- Programozó módban új kód menthető EEPROM-ba
- LED-ek és buzzer adnak visszajelzést
- D13 LED világít programozó módban, normál módban sötét
*/
#include <EEPROM.h>
#include <Adafruit_NeoPixel.h>
#define LED_PIN 11 // A neopixel LED adatvezeték csatlakozója az Arduino-n
#define LED_COUNT 4 // A használt LED-ek száma
Adafruit_NeoPixel leds(LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800);
int ledState = 0;
unsigned char key, mem[4], num[4], ir = 0;
bool pMode = false;
void setup() {
pinMode(7, OUTPUT); // relé
pinMode(8, OUTPUT); // COL1
pinMode(9, OUTPUT); // COL2
pinMode(10, OUTPUT); // COL3
pinMode(13, OUTPUT); // programozó LED
pinMode(12, OUTPUT); // buzzer
pinMode(2, INPUT_PULLUP); // ROW4
pinMode(3, INPUT_PULLUP); // ROW3
pinMode(4, INPUT_PULLUP); // ROW2
pinMode(5, INPUT_PULLUP); // ROW1
pinMode(6, INPUT_PULLUP); // nyomógomb pMode
leds.begin();
digitalWrite(7, LOW);
digitalWrite(8, LOW);
digitalWrite(9, LOW);
digitalWrite(10, LOW);
// EEPROM-ból beolvassuk a tárolt kódot
for (unsigned char i = 0; i < 4; ++i) {
num[i] = EEPROM.read(i);
}
digitalWrite(13, LOW); // alapból nem világít (nem programozó módban)
}
void loop() {
// Programozó mód kapcsoló
if (!digitalRead(6)) {
pMode = true;
digitalWrite(13, HIGH); // programozó LED bekapcsol
}
// Ha bármelyik gomb lenyomva
if (!digitalRead(5) || !digitalRead(4) || !digitalRead(3) || !digitalRead(2)) {
int pressed = get_key();
if (pressed != -1) {
tone(12, 1000, 50);
mem[ir] = pressed;
// LED visszajelzés kék
if (ir < LED_COUNT) {
leds.setPixelColor(ledState, 0, 0, 255);
leds.show();
ledState++;
}
// Ha megvan a 4 szám
if (ir == 3 && pMode == false) {
if (mem[0] == num[0] && mem[1] == num[1] && mem[2] == num[2] && mem[3] == num[3]) {
// Helyes kód
digitalWrite(7, HIGH);
for (int i = 0; i < 4; i++) {
leds.setPixelColor(i, 0, 255, 0); // zöld
}
leds.show();
tone(12, 1000, 150);
delay(150);
tone(12, 1500, 150);
delay(2500); // relé ennyi ideig húz be
digitalWrite(7, LOW);
ledsclear();
} else {
// Hibás kód
for (int i = 0; i < 4; i++) {
leds.setPixelColor(i, 255, 0, 0); // piros
}
leds.show();
tone(12, 1000, 150); delay(200);
tone(12, 1500, 150); delay(200);
tone(12, 2000, 150); delay(200);
tone(12, 1500, 150); delay(200);
tone(12, 1000, 150); delay(300);
ledsclear();
}
}
// Programozó mód: új kód mentése EEPROM-ba
if (ir == 3 && pMode == true) {
for (unsigned char j = 0; j < 4; j++) {
EEPROM.write(j, mem[j]);
num[j] = mem[j];
}
ledsclear();
pMode = false;
digitalWrite(13, LOW); // kilépés programozó módból
}
ir++;
if (ir == 4) {
ir = 0;
}
// várunk, amíg felengedik a gombot
while (!digitalRead(5) || !digitalRead(4) || !digitalRead(3) || !digitalRead(2)) {}
delay(100);
}
}
}
int get_key() {
int detectedKey = -1;
int lastKey = -1;
unsigned long startTime = millis();
// max 50 ms-ig figyelünk, stabil érték kell
while (millis() - startTime < 50) {
int currentKey = -1;
// Oszlop 1
digitalWrite(8, LOW);
digitalWrite(9, HIGH);
digitalWrite(10, HIGH);
if (!digitalRead(5)) currentKey = 1;
if (!digitalRead(4)) currentKey = 4;
if (!digitalRead(3)) currentKey = 7;
// Oszlop 2
digitalWrite(9, LOW);
digitalWrite(8, HIGH);
digitalWrite(10, HIGH);
if (!digitalRead(5)) currentKey = 2;
if (!digitalRead(4)) currentKey = 5;
if (!digitalRead(3)) currentKey = 8;
if (!digitalRead(2)) currentKey = 0;
// Oszlop 3
digitalWrite(10, LOW);
digitalWrite(9, HIGH);
digitalWrite(8, HIGH);
if (!digitalRead(5)) currentKey = 3;
if (!digitalRead(4)) currentKey = 6;
if (!digitalRead(3)) currentKey = 9;
// Ha kétszer egymás után ugyanaz jött -> stabil
if (currentKey == lastKey && currentKey != -1) {
detectedKey = currentKey;
break;
}
lastKey = currentKey;
delay(5);
}
// reseteljük az oszlopokat
digitalWrite(8, LOW);
digitalWrite(9, LOW);
digitalWrite(10, LOW);
if (detectedKey != -1) {
key = detectedKey;
}
return detectedKey;
}
void ledsclear() {
leds.clear();
leds.show();
ledState = 0;
}