Вступление
Доброго времени суток! Параллельно моей предыдущей статье я работал еще над одним «проектом». Собственно у меня завалялось пару китайских RFID читалок. Вот таких:
Фото RC522
До этого, перебирая ящик с инструментами, я нашел новенький, но никому не нужный замок.
Видео работы устройства
На видео есть еще одна Arduino — она нужна только для питания Arduino Pro Mini. В конечной схеме её конечно нет, просто блок питания на 5В я еще не приобрел. Под катом очень много фотографий!
Читать дальше
Как это работает?
Вся система состоит из 5-и элементов:
- Модуль RFID RC522 13,56 Mhz;
- Микроконтроллер Arduino Pro Mini;
- Транзистор;
- Стабилизатор напряжения 3.3В;
- Сервопривод TowerPro SG-90.
Пока метка не поднесена к RC522, микроконтроллер слушает состояние ножки, на которой «висит» кнопка. Если на входе высокое напряжение — программа инвертирует положение системы: замок открыт — закрыть, и наоборот. В зависимости от открыт/закрыт загораются светодиоды: красный — закрыт, зеленый — открыт. Наконец то подносим метку к RC522. Arduino считывает 16 байт данных и сверяет с имеющимся двухмерным массивом пользователей. При совпадении система инвертируется, иначе — ничего не происходит.
Для замочка нам понадобится:
Микроконтроллер Arduino.
Фото Arduino Pro Mini
Модуль считывания RFID меток RC522. Фото модуля вначале статьи.
Сервопривод TowerPro SG-90. Просто потому что был под рукой. На самом деле купить помощнее и надежнее не было бы лишним.
Фото TowerPro SG-90

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

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

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

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

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


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

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

Программная часть
Замок
/* ----------------------------------------------------------------------------- * 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("\r\n"); 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("\r\n"); byte piccType = mfrc522.PICC_GetType(mfrc522.uid.sak); //Serial.print(mfrc522.PICC_GetTypeName(piccType)); //Serial.print("\r\n"); 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; MFRC522::StatusCode 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("\r\n"); Serial.print(buffer[1]); Serial.print("\r\n"); Serial.print(buffer[2]); Serial.print("\r\n"); Serial.print(buffer[3]); Serial.print("\r\n"); Serial.print(buffer[4]); Serial.print("\r\n"); Serial.print(buffer[5]); Serial.print("\r\n"); Serial.print(buffer[6]); Serial.print("\r\n"); Serial.print(buffer[7]); Serial.print("\r\n"); Serial.print(buffer[8]); Serial.print("\r\n"); Serial.print(buffer[9]); Serial.print("\r\n"); Serial.print(buffer[10]); Serial.print("\r\n"); Serial.print(buffer[11]); Serial.print("\r\n"); Serial.print(buffer[12]); Serial.print("\r\n"); Serial.print(buffer[13]); Serial.print("\r\n"); Serial.print(buffer[14]); Serial.print("\r\n"); Serial.print(buffer[15]); Serial.print("\r\n"); 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 тогда было бы надежнее, но я пока не собирался его куда-нибудь ставить.
