Дверной замок. RFID

в 14:47, , рубрики: arduino, diy или сделай сам, NFC, rc522, Беспроводные технологии

Вступление

Доброго времени суток! Параллельно моей предыдущей статье я работал еще над одним «проектом». Собственно у меня завалялось пару китайских RFID читалок. Вот таких:

Фото RC522

Дверной замок. RFID

До этого, перебирая ящик с инструментами, я нашел новенький, но никому не нужный замок.

Видео работы устройства

На видео есть еще одна Arduino — она нужна только для питания Arduino Pro Mini. В конечной схеме её конечно нет, просто блок питания на 5В я еще не приобрел. Под катом очень много фотографий!

Читать дальше

Для замочка нам понадобится:

Микроконтроллер Arduino.

Фото Arduino Pro Mini

Дверной замок. RFID

Модуль считывания RFID меток RC522. Фото модуля вначале статьи.

Сервопривод TowerPro SG-90. Просто потому что был под рукой. На самом деле купить помощнее и надежнее не было бы лишним.

Фото TowerPro SG-90

Дверной замок. RFID

Любой подходящий транзистор. У меня был 2N2222.

Фото 2N2222

Дверной замок. RFID

Любой стабилизатор напряжения 3.3В. В наличии был LF33CV.

Фото LF33CV

Дверной замок. RFID

Ну и конечно ключи. Пока был в Киеве, я приобрел вот такой силиконовый RFID-браслет:

Фото RFID-браслета

Дверной замок. RFID

Сборка устройства

Замок

Пошагово снять процесс переделывания замка не вышло. Но думаю будет и так все ясно.
Дверной замок. RFID

Дверной замок. RFID

Аккуратно вырезано отверстие для сервопривода и просверлены отверстия для крепления болтами. Рычаг привода сделан из двух деталей, которые шли в комплекте с ним, и обычной скрепки. На конце привинчен шурупчик.

Дверной замок. RFID

Запирающая часть замка была усилена у основания штырей, а так же утолщена, чтобы не болталась.

Дверной замок. RFID

Дверной замок. RFID

Схема

Дверной замок. RFID

Дверной замок. RFID

На самой печатной плате присутствует разъем ИК-приемника, но реализовывать не стал.

Устройство

Дверной замок. RFID

Дверной замок. RFID

В итоговом устройстве я совсем забыл про резистор для кнопки, но в схеме я его добавил.

Дверной замок. RFID

Для питания Arduino Pro Mini был взят штекер от старого ПК.

Дверной замок. RFID

Программная часть

Замок

/*
 -----------------------------------------------------------------------------
 * Pin layout should be as follows:
 * Signal     Pin              Pin               Pin
 *            Arduino Uno      Arduino Mega      MFRC522 board
 * ------------------------------------------------------------
 * Reset      9                5                 RST
 * SPI SS     10               53                SDA
 * SPI MOSI   11               51                MOSI
 * SPI MISO   12               50                MISO
 * SPI SCK    13               52                SCK
 *
 *  
 */

#include <SPI.h>
#include <MFRC522.h>
#include <Servo.h> 

#define SS_PIN 10
#define RST_PIN 9
MFRC522 mfrc522(SS_PIN, RST_PIN);        // Create MFRC522 instance.
Servo myservo;
boolean doorOpen;

/*
Users
*/

int countUsers = 2;
byte Users[2][16] = {{1,2,3,4, 5,6,7,8, 9,10,255,12, 13,14,15,16},
                              {0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,1}};

void setup() {
        Serial.begin(9600);
        pinMode(8, INPUT); //button open/close door
        pinMode(7, OUTPUT); //load transistor
        digitalWrite(7, LOW);
        pinMode(5, OUTPUT); //LED open/close door
        myservo.attach(6);
        SPI.begin(); 
        mfrc522.PCD_Init();
}

void loop() {
        
        MFRC522::MIFARE_Key key;
        for (byte i = 0; i < 6; i++) {
                key.keyByte[i] = 0xFF;
        }

        if ( ! mfrc522.PICC_IsNewCardPresent()) {
           if (digitalRead(8) == HIGH) {
            digitalWrite(7, HIGH);
            delay(500);
            if (doorOpen) 
            {
              myservo.write(80);
              doorOpen = false;
              Serial.println("CLOSED!");
              digitalWrite(5, HIGH);
            } 
            else 
            {
              myservo.write(2);
              doorOpen = true;
              Serial.println("OPENED!");
              digitalWrite(5, LOW);
            }
            delay(500);
            digitalWrite(7, LOW);
          }
            return;
        }


        if ( ! mfrc522.PICC_ReadCardSerial()) {
                return;
        }

        Serial.print("!");
        Serial.print("rn");

        for (byte i = 0; i < mfrc522.uid.size; i++) {
                Serial.print(mfrc522.uid.uidByte[i] < 0x10 ? " 0" : " ");
                Serial.print(mfrc522.uid.uidByte[i], HEX);
        } 
        Serial.print("rn");

        byte piccType = mfrc522.PICC_GetType(mfrc522.uid.sak);
        Serial.print(mfrc522.PICC_GetTypeName(piccType));
        Serial.print("rn");
        if (        piccType != MFRC522::PICC_TYPE_MIFARE_MINI 
                &&        piccType != MFRC522::PICC_TYPE_MIFARE_1K
                &&        piccType != MFRC522::PICC_TYPE_MIFARE_4K) {
                return;
        }

        byte sector         = 1;
        byte valueBlockA    = 4;
        byte valueBlockB    = 5;
        byte valueBlockC    = 6;
        byte trailerBlock   = 7;
        byte status;

        status = mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, trailerBlock, &key, &(mfrc522.uid));
        if (status != MFRC522::STATUS_OK) {
                Serial.print("PCD_Authenticate() failed: ");
                Serial.println(mfrc522.GetStatusCodeName(status));
                return;
        }

        status = mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_B, trailerBlock, &key, &(mfrc522.uid));
        if (status != MFRC522::STATUS_OK) {
                Serial.print("PCD_Authenticate() failed: ");
                Serial.println(mfrc522.GetStatusCodeName(status));
                return;
        }
  
        byte buffer[18];
        byte size = sizeof(buffer);

        status = mfrc522.MIFARE_Read(valueBlockA, buffer, &size);
        Serial.print(buffer[0]);
        Serial.print("rn");
        Serial.print(buffer[1]);
        Serial.print("rn");
        Serial.print(buffer[2]);
        Serial.print("rn");
        Serial.print(buffer[3]);
        Serial.print("rn");
        Serial.print(buffer[4]);
        Serial.print("rn");
        Serial.print(buffer[5]);
        Serial.print("rn");
        Serial.print(buffer[6]);
        Serial.print("rn");
        Serial.print(buffer[7]);
        Serial.print("rn");
        Serial.print(buffer[8]);
        Serial.print("rn");
        Serial.print(buffer[9]);
        Serial.print("rn");
        Serial.print(buffer[10]);
        Serial.print("rn");
        Serial.print(buffer[11]);
        Serial.print("rn");
        Serial.print(buffer[12]);
        Serial.print("rn");
        Serial.print(buffer[13]);
        Serial.print("rn");
        Serial.print(buffer[14]);
        Serial.print("rn");
        Serial.print(buffer[15]);
        Serial.print("rn");

        byte trueBytes = 0;
        boolean acceptUser = false;
        for (int i = 0; i < countUsers; i++) {
          if (!acceptUser) {
            for (int j = 0; j < 16; j++) {
              if (buffer[j] == Users[i][j]) {
                trueBytes++; 
              }
            }
          }
          if (trueBytes == 16) {
            digitalWrite(7, HIGH);
            delay(500);
            if (doorOpen) 
            {
              myservo.write(80);
              doorOpen = false;
              Serial.println("CLOSED!");
              digitalWrite(5, HIGH);
            } 
            else 
            {
              myservo.write(2);
              doorOpen = true;
              Serial.println("OPENED!");
              digitalWrite(5, LOW);
            }
            delay(500);
            digitalWrite(7, LOW);
            acceptUser = true;
            trueBytes = 0;
          } else trueBytes = 0;
        }
        
        mfrc522.PICC_HaltA();

        mfrc522.PCD_StopCrypto1();
        
        
}

Вывод

«boolean yes = false;» уже не будет, но все может быть :)
Используемые библиотеки: MFRC522.h и Servo.h. Пример был взят из RFID библиотеки и дописан под себя.
В примерах так же есть функция записи первого блока(по факту второго, первый блок read-only). Мне было достаточно 16 байт данных. Конечно лучше было использовать еще UID тогда было бы надежнее, но я пока не собирался его куда-нибудь ставить.

Автор: Im_Alive

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js