Что нам понадобится?
Плата Wemos D1 R1 (Lolin WEMOS D1 mini lite), макетная плата Breadboard, две кнопки, дисплей 128х64 12С SSD1306, один резистор на 2.2 кОм, горизонтальный держатель для CR2032 и конечно пустые "болванки" ключей RW1990 для их записи.Схема
Подробная схема подключения устройств и компонентов к плате Wemos D1 R1Сборка
Для начала разведем питание на макетной плате. Выведем пины 5V и GND на макетную плату.Подключим дисплей. Подсоединим пин SCL к пину D1 на плате, а пин SDA к пину D2.
Добавим кнопки. Соединим их с пинами D5 (считывание) и D6 (запись) на плате
Добавим горизонтальный держатель для батарейки CR2032. Шину OneWire подтягиваем через резистор 2.2 кОм и подсоединяем к нижней части держателя для батарейки CR2032, GND к его боковой части.
Подаем питание на плату. Подключаем библиотеки OneWire, ESP8266 and ESP32 Oled Driver for SSD1306 displays (Версия 4.1.0) и прошиваем плату скетчем представленным ниже.
Примечание. Мы добавили поддержку русского языка, поэтому необходимо добавить файл со шрифтом в папку со скетчем. Скачать шрифт.
Нажимаем кнопку Scan и прикладываем ключ.
Примечание. Горизонтальный держатель больше ключа RW1990 (болванки), поэтому важно, чтобы боковая часть ключа соприкасалась с боковым контактом держателя.
Нажимаем кнопку Copу, аналогично прикладывая ключ
Теперь мы можем быстро копировать ключи RW1990, имеющие возможность записи/перезаписи.
Показать / Cкрыть скетч
#include <SSD1306Wire.h>
#include <OneWire.h>
#include "fontsRus.h"
#define pin 2
#define PIN_BUTTON_SCAN 12 // D6 пин кнопки сканирования
#define PIN_BUTTON_COPY 14 // D5 пин кнопки копирования
SSD1306Wire display(0x3c, 5, 4);
OneWire myWire (pin);
bool button_state_scan = true;
uint32_t ms_button_scan = 0;
bool button_state_copy = true;
uint32_t ms_button_copy = 0;
String keycode_info;
String keycode;
byte addrkeyCodeInPlatform[8]; // массив для ключа, просто вывод кода на экране
byte addrScanKey[8]; // массив для сканируемого ключа
byte addrCopyKey[8]; // массив для копиремого ключа
void setup() {
Wire.begin();
Serial.begin(115200);
pinMode(PIN_BUTTON_SCAN, INPUT);
pinMode(PIN_BUTTON_COPY, INPUT);
display.init();
display.flipScreenVertically();
display.setFontTableLookupFunction(FontUtf8Rus);
display.setFont(ArialRus_Plain_10);
display.setContrast(255);
}
void loop() {
uint32_t ms = millis();
if ( button_state_scan && button_state_copy && myWire.search(addrkeyCodeInPlatform) ) {
display.clear();
display.drawString(35, 0, "КОД КЛЮЧА");
keycode_info = String(addrkeyCodeInPlatform[0], HEX)+' '+String(addrkeyCodeInPlatform[1], HEX)+' '+
String(addrkeyCodeInPlatform[2], HEX)+' '+String(addrkeyCodeInPlatform[3], HEX)+' '+
String(addrkeyCodeInPlatform[4], HEX)+' '+String(addrkeyCodeInPlatform[5], HEX)+' '+
String(addrkeyCodeInPlatform[6], HEX)+' '+String(addrkeyCodeInPlatform[7], HEX);
keycode_info.toUpperCase();
display.drawString(15, 25, keycode_info);
display.display();
myWire.reset_search();
return;
}
display.clear();
display.drawString(6, 0, "ВЫБЕРИТЕ ДЕЙСТВИЕ");
display.drawString(4, 14, "scan - считывание ключа");
display.drawHorizontalLine(0, 30, 128);
display.drawString(0, 30, "copy - копирование ключа");
display.drawRect (0, 48, 128, 16);
display.drawString(4, 48, "key - ");
if ( addrScanKey[0] == 0 ) {
display.drawString(26, 48, "empty");
} else {
keycode = String(addrScanKey[0], HEX)+' '+String(addrScanKey[1], HEX)+' '+
String(addrScanKey[2], HEX)+' '+String(addrScanKey[3], HEX)+' '+
String(addrScanKey[4], HEX)+' '+String(addrScanKey[5], HEX)+' '+
String(addrScanKey[6], HEX)+' '+String(addrScanKey[7], HEX);
keycode.toUpperCase();
display.drawString(26, 48, keycode);
}
display.display();
// Фиксируем нажатие кнопки сканирования
if ( digitalRead(PIN_BUTTON_SCAN) == LOW && !button_state_scan && ( ms - ms_button_scan ) > 50 ) {
button_state_scan = true;
ms_button_scan = ms;
for (byte y = 0; y < 10; y++) {
String timer;
timer = String(10 - y);
display.clear();
display.drawString(0, 0, "РЕЖИМ СКАНИРОВАНИЕ");
display.drawString(0, 15, "приложите ключ");
display.drawString(0, 25, "к платформе");
display.drawString(60, 45, timer);
display.display();
if (myWire.search (addrScanKey)) {
display.clear();
display.drawString(0, 20, "Сканирование завершено");
display.display();
delay(3000);
break;
}
delay(1000);
}
}
// Фиксируем отпускание кнопки сканирования
if ( digitalRead(PIN_BUTTON_SCAN) == HIGH && button_state_scan && ( ms - ms_button_scan ) > 50 ) {
button_state_scan = false;
ms_button_scan = ms;
}
// Фиксируем нажатие кнопки копирования
if ( digitalRead(PIN_BUTTON_COPY) == LOW && !button_state_copy && ( ms - ms_button_copy ) > 50 ) {
//compute crc scan key//
byte crcScanKeyFirst;
crcScanKeyFirst = myWire.crc8(addrScanKey, 7);
if ( crcScanKeyFirst == 0 ) {
display.clear();
display.drawString(2, 0, "ОШИБКА КОПИРОВАНИЯ");
display.drawString(33, 22, "В памяти нет");
display.drawString(2, 35, "отсканированного ключа");
display.display();
delay(3000);
button_state_copy = true;
ms_button_copy = ms;
return;
}
button_state_copy = true;
ms_button_copy = ms;
for (byte z = 0; z < 10; z++) {
String timer2;
timer2 = String(10 - z);
display.clear();
display.drawString(0, 0, "РЕЖИМ КОПИРОВАНИЕ");
display.drawString(0, 15, "приложите ключ");
display.drawString(0, 25, "к платформе");
display.drawString(60, 45, timer2);
display.display();
int u = 0;
if ( !myWire.search(addrCopyKey) ) {
} else {
myWire.skip();myWire.reset();myWire.write(0x33);
display.clear();
display.drawRect ( 1, 22, 100, 12);
display.display();
myWire.skip();myWire.reset();myWire.write(0xD1);
digitalWrite(2, LOW); pinMode(2, OUTPUT); delayMicroseconds(60);
pinMode(2, INPUT); digitalWrite(2, HIGH); delay(10);
myWire.skip();myWire.reset();myWire.write(0xD5);
for (byte v = 0; v < 8; v++) {
writeByte(addrScanKey[v]);
u = u + 12;
display.fillRect ( 3, 24, u, 8);
display.drawString(0, 0, "ИДЁТ ЗАПИСЬ!");
display.drawString(0, 40, "держите ключ");
display.drawString(0, 50, "до окончания записи!");
display.display();
delay(100);
}
myWire.reset();
myWire.write(0xD1);
digitalWrite(2, LOW); pinMode(2, OUTPUT); delayMicroseconds(10);
pinMode(2, INPUT); digitalWrite(2, HIGH); delay(10);
myWire.reset_search();
if ( myWire.search (addrCopyKey) ) {
//compute crc scan key//
byte crcScanKey;
crcScanKey = myWire.crc8(addrScanKey, 7);
//compute crc copy key//
byte crcCopyKey;
crcCopyKey = myWire.crc8(addrCopyKey, 7);
if ( crcScanKey == crcCopyKey ) {
display.clear();
display.drawString(0, 20, "Копирование завершено");
display.display();
delay(3000);
break;
} else {
display.clear();
display.drawString(0, 20, "Копирование неудачно!");
display.display();
delay(3000);
break;
}
} else {
display.clear();
display.drawString(45, 0, "ОШИБКА");
display.drawString(20, 30, "Рано убрали ключ!");
display.display();
delay(3000);
break;
}
}
delay(1000);
}
}
// Фиксируем отпускание кнопки копирования
if ( digitalRead(PIN_BUTTON_COPY) == HIGH && button_state_copy && ( ms - ms_button_copy ) > 50 ) {
button_state_copy = false;
ms_button_copy = ms;
}
}
int writeByte(byte data) {
int data_bit;
for (data_bit = 0; data_bit < 8; data_bit++) {
if (data & 1) {
digitalWrite(pin, LOW); pinMode(pin, OUTPUT);
delayMicroseconds(60);
pinMode(pin, INPUT); digitalWrite(pin, HIGH);
delay(10);
} else {
digitalWrite(pin, LOW); pinMode(pin, OUTPUT);
pinMode(pin, INPUT); digitalWrite(pin, HIGH);
delay(10);
}
data = data >> 1;
}
return 0;
}
char FontUtf8Rus(const byte ch) {
static uint8_t LASTCHAR;
if ((LASTCHAR == 0) && (ch < 0xC0)) {
return ch;
}
if (LASTCHAR == 0) {
LASTCHAR = ch;
return 0;
}
uint8_t last = LASTCHAR;
LASTCHAR = 0;
switch (last) {
case 0xD0:
if (ch == 0x81) return 0xA8;
if (ch >= 0x90 && ch <= 0xBF) return ch + 0x30;
break;
case 0xD1:
if (ch == 0x91) return 0xB8;
if (ch >= 0x80 && ch <= 0x8F) return ch + 0x70;
break;
}
return (uint8_t) 0;
}
Комментарии