Arduino + RFID Card reader / Keyboard = ?
Feb. 20th, 2016 10:32 am![[personal profile]](https://www.dreamwidth.org/img/silk/identity/user.png)
У меня в ЖЖ появился новый тэг - "говнокодинг". Сюда будет скидываться всякое, что я клепаю для разных наших игр.
Понимаю, какое количество тапок и вторпродукта прилетит в меня от профессиональных программистов (а я, как в том анекдоте, не настоящий сварщик, а маску на стройке нашёл).
Скажите это будет интересно кому-нибудь или вешать в режиме "только для себя"?
Итак. Первый пример.
Для одного проекта делаю некую игровую систему контроля доступа, с основным модулем на базе Raspberry Pi.
По задумке, устройство должно представлять собой "замок", открываемый с двух сторон карточкой или набором кода с клавиатуры. Кроме собственно функций замка - его варианты открытия могут сильно меняться от внешних условий (для чего первоначально и был выбран Raspberry).
В качестве клавиатуры был выбран вот такой вот считыватель: http://www.dx.com/ru/p/security-password-access-control-id-proximity-sensor-card-reader-white-143727
В дальнейшем выяснилось, что стандартные адаптеры для протокола Wiegand, который он выдаёт, или требуют подключения по USB, или двух последовательных портов, что, опять же, для Raspberry, означает дополнительный адаптер.
И вот играясь на днях с Ардуино (если кому будет интересно. о том проекте попозже), подумал, а не сгородить ли мне на нём универсальный контроллер для таких считывателей?
Полез в инет. Быстро нашел некоторое количество программ, но все они были рассчитаны на старшие модели Ардуино и использование прерываний. Мне же хотелось собрать изделие на Ардуино НАНО, или вообще Ардуино ПРО МИНИ.
В конце концов Wiegand не сильно замороченный протокол, и вот - сегодня за пару часов написалось.
Два считывателя, ардуино. Выяснилось, что при нажатии клавиши не выдаётся полный пакет в 26 бит (2 бита контрольных, в начале и конце), а тупо идёт полбайта с номером нажатой кнопки.
В результате это решилось анализом задержки по таймауту.
Как результат, на последовательный порт выдаётся строка в виде:
R1KB10
R1CD0А3456
Где R1 - идентификатор считывателя (R1 или R2), KB или CD - соответственно клавиатура или карта, и дальше либо цифра нажатой клавиши (10 - *, 11 - #), либо три байта в шестнадцатеричном виде с кодом карты.
Собственно код для ардуины:
Понимаю, какое количество тапок и вторпродукта прилетит в меня от профессиональных программистов (а я, как в том анекдоте, не настоящий сварщик, а маску на стройке нашёл).
Скажите это будет интересно кому-нибудь или вешать в режиме "только для себя"?
Итак. Первый пример.
Для одного проекта делаю некую игровую систему контроля доступа, с основным модулем на базе Raspberry Pi.
По задумке, устройство должно представлять собой "замок", открываемый с двух сторон карточкой или набором кода с клавиатуры. Кроме собственно функций замка - его варианты открытия могут сильно меняться от внешних условий (для чего первоначально и был выбран Raspberry).
В качестве клавиатуры был выбран вот такой вот считыватель: http://www.dx.com/ru/p/security-password-access-control-id-proximity-sensor-card-reader-white-143727
В дальнейшем выяснилось, что стандартные адаптеры для протокола Wiegand, который он выдаёт, или требуют подключения по USB, или двух последовательных портов, что, опять же, для Raspberry, означает дополнительный адаптер.
И вот играясь на днях с Ардуино (если кому будет интересно. о том проекте попозже), подумал, а не сгородить ли мне на нём универсальный контроллер для таких считывателей?
Полез в инет. Быстро нашел некоторое количество программ, но все они были рассчитаны на старшие модели Ардуино и использование прерываний. Мне же хотелось собрать изделие на Ардуино НАНО, или вообще Ардуино ПРО МИНИ.
В конце концов Wiegand не сильно замороченный протокол, и вот - сегодня за пару часов написалось.
Два считывателя, ардуино. Выяснилось, что при нажатии клавиши не выдаётся полный пакет в 26 бит (2 бита контрольных, в начале и конце), а тупо идёт полбайта с номером нажатой кнопки.
В результате это решилось анализом задержки по таймауту.
Как результат, на последовательный порт выдаётся строка в виде:
R1KB10
R1CD0А3456
Где R1 - идентификатор считывателя (R1 или R2), KB или CD - соответственно клавиатура или карта, и дальше либо цифра нажатой клавиши (10 - *, 11 - #), либо три байта в шестнадцатеричном виде с кодом карты.
Собственно код для ардуины:
#define R1_D0 4 #define R1_D1 5 #define R2_D0 6 #define R2_D1 7 #define DELAYKB 20 #include "pins_arduino.h" void setup() { Serial.begin(9600); Serial.println("Starting!"); pinMode(R1_D0,INPUT); digitalWrite(R1_D0,HIGH); pinMode(R1_D1,INPUT); digitalWrite(R1_D1,HIGH); pinMode(R2_D0,INPUT); digitalWrite(R2_D0,HIGH); pinMode(R2_D1,INPUT); digitalWrite(R2_D1,HIGH); Serial.println("Ready!"); } int r1_d0_s = HIGH, r1_d1_s = HIGH, r1_d0_f = 0, r1_d1_f = 0; int r2_d0_s = HIGH, r2_d1_s = HIGH, r2_d0_f = 0, r2_d1_f = 0; byte r1_b = 0, r1_cnt = 0, r1_card[26] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0} ; byte r2_b = 0, r2_cnt = 0, r2_card[26] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0} ; char r1_out[2], r2_out[2]; unsigned long int r1_timeout; unsigned long int r2_timeout; void loop() { r1_d0_s = digitalRead(R1_D0); r1_d1_s = digitalRead(R1_D1); r2_d0_s = digitalRead(R2_D0); r2_d1_s = digitalRead(R2_D1); if(r1_d0_s == HIGH) { r1_d0_f = 0; } if(r1_d1_s == HIGH) { r1_d1_f = 0; } if(r1_d0_s == LOW) { // Поймали ввод со считывателя 1 d0 if(r1_d0_f == 0) { // Статус не изменялся r1_timeout = millis(); r1_d0_f = 1; // Начали читать if(r1_d1_s == HIGH) { r1_card[r1_cnt] = 0 ; r1_d1_f = 0; r1_cnt += 1; r1_b = r1_b << 1; } } } if(r1_d1_s == LOW) { // Поймали ввод со считывателя 1 d1 if(r1_d1_f == 0) { // Статус не изменялся r1_timeout = millis(); r1_d1_f = 1; // Начали читать if(r1_d0_s == HIGH) { r1_card[r1_cnt] = 1 ; r1_d0_f = 0; r1_cnt += 1; r1_b = (r1_b << 1) | 0x01; } } } if(r2_d0_s == HIGH) { r2_d0_f = 0; } if(r2_d1_s == HIGH) { r2_d1_f = 0; } if(r2_d0_s == LOW) { // Поймали ввод со считывателя 2 d0 if(r2_d0_f == 0) { // Статус не изменялся r2_timeout = millis(); r2_d0_f = 1; // Начали читать if(r2_d1_s == HIGH) { r2_card[r2_cnt] = 0 ; r2_d1_f = 0; r2_cnt += 1; r2_b = r2_b << 1; } } } if(r2_d1_s == LOW) { // Поймали ввод со считывателя 2 d1 if(r2_d1_f == 0) { // Статус не изменялся r2_timeout = millis(); r2_d1_f = 1; // Начали читать if(r2_d0_s == HIGH) { r2_card[r2_cnt] = 1 ; r2_d0_f = 0; r2_cnt += 1; r2_b = (r2_b << 1) | 0x01; } } } if(r1_cnt == 4) { if((millis() - r1_timeout) >= DELAYKB) { // Нажата кнопка Serial.print("R1KB"); Serial.println(r1_b); r1_b = 0; r1_cnt = 0; r1_timeout=millis(); } } else if (r1_cnt == 26) { // Считываем карточку Serial.print("R1CD"); r1_b = 0; for(int i=1; i <= 24; i++) { r1_b = (r1_b << 1) | r1_card[i]; if(i%8 == 0) { sprintf(r1_out,"%02X",r1_b); Serial.print(r1_out); } } Serial.println(""); r1_b = 0; r1_cnt = 0; r1_timeout=millis(); } if(r2_cnt == 4) { if((millis() - r2_timeout) >= DELAYKB) { // Нажата кнопка Serial.print("R2KB"); Serial.println(r2_b); r2_b = 0; r2_cnt = 0; r2_timeout=millis(); } } else if (r2_cnt == 26) { // Считываем карточку Serial.print("R2CD"); for(int i=1; i <= 24; i++) { r2_b = (r2_b << 1) | r2_card[i]; if(i%8 == 0) { sprintf(r2_out,"%02X",r2_b); Serial.print(r2_out); } } Serial.println(""); r2_b = 0; r2_cnt = 0; r2_timeout=millis(); } }