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