Что такое RFID? Принцип работы? Подключение модуля RC522 RFID к Arduino
Представьте, что вы заходите в продуктовый магазин, наполняете корзину всем необходимым, а затем просто выходите через главный вход, не останавливаясь у кассы. Больше никаких долгих очередей, пока кассир сканирует каждый товар по одному! Теперь это возможно благодаря технологии RFID.
RFID позволяет магазинам создавать системы автоматической оплаты. С помощью этой технологии крошечные RFID-метки прикрепляются к каждому товару в магазине. Когда вы заканчиваете покупки, вы можете пройти через специальную зону, где RFID-считыватели обнаруживают каждый товар в вашей корзине практически мгновенно. Система автоматически определяет, что вы покупаете, и может списать оплату без необходимости выкладывать товары или ждать, пока кто-то их отсканирует.
Если вы хотите создать свой собственный RFID-проект или систему (может быть, не целый продуктовый магазин, но что-то поменьше), модуль RFID-считыватель/записыватель RC522 — отличный выбор. Модуль RC522 может как считывать информацию с RFID-меток, так и записывать на них новую информацию, открывая множество возможностей для творческих проектов с вашим Arduino.
С помощью всего нескольких подключений к плате Arduino вы можете начать создавать всё: от пользовательских систем контроля доступа до трекера инвентаризации или чего-то совершенно уникального. Начнём!
Что такое технология RFID и как она работает?
Система RFID (Радиочастотная идентификация) состоит из двух основных компонентов: считывателя и метки.
RFID-считыватель содержит радиочастотный модуль и антенну, которая создаёт вокруг себя высокочастотное электромагнитное поле.
RFID-метка прикрепляется к любому объекту, который мы хотим идентифицировать или отслеживать. Большинство меток являются пассивными, то есть у них нет батарей или собственного источника питания. Вместо этого они ожидают в покое, пока не попадут в электромагнитное поле считывателя.
Когда метка попадает в это поле, радиоволны от считывателя создают крошечный электрический ток в антенне метки. Этот небольшой ток даёт метке ровно столько энергии, чтобы активировать её микрочип. Микрочип содержит важную информацию об объекте, к которому прикреплена метка. После включения метка отправляет эту информацию обратно считывателю. Этот процесс называется обратное рассеяние — метка не генерирует собственный радиосигнал, а вместо этого модифицирует (или «модулирует», если предпочитаете технический термин) сигнал считывателя.
Считыватель принимает этот модифицированный сигнал, декодирует информацию и отправляет её компьютеру или микроконтроллеру для дальнейшего использования.
Хотя большинство RFID-меток пассивны, существуют и активные метки, имеющие собственный источник питания, например маленькую батарейку. Эти активные метки могут обмениваться данными на гораздо большем расстоянии, поскольку им не нужно полагаться на сигнал считывателя для питания.
Частоты RFID
RFID-системы работают на разных радиочастотах, каждая из которых имеет свои преимущества:
Низкая частота (LF): Работают на коротких расстояниях и часто используются для отслеживания животных или пропускных карт.
Высокая частота (HF): Предлагают хороший баланс между дальностью и скоростью передачи данных, что делает их идеальными для библиотечных книг, платёжных карт и многих хобби-проектов.
Сверхвысокая частота (UHF): Могут считываться с большего расстояния и отлично подходят для отслеживания товаров на складах или быстро движущихся предметов на конвейерах.
RFID-считыватель RC522, с которым мы будем работать, работает в диапазоне высоких частот, а именно на 13.56 МГц. Это делает его идеальным для проектов, где нужно считывать метки с расстояния нескольких сантиметров, таких как электронные дверные замки, системы учёта посещений или интерактивные дисплеи.
Обзор оборудования
RFID-модуль RC522, основанный на микросхеме MFRC522 от NXP, является одним из самых доступных RFID-решений на сегодняшний день, часто стоящим менее четырёх долларов. Это делает его отличным выбором для хобби-проектов и экспериментов.
Модуль обычно поставляется с двумя типами RFID-меток:
Карта, похожая на кредитную карту
Брелок, который можно прикрепить к связке ключей
Обе метки содержат 1 килобайт (1КБ) памяти. Хотя это может показаться мало по сравнению с картами microSD, этого вполне достаточно для многих проектов. Что особенно интересно — RC522 может не только считывать информацию с этих меток, но и записывать на них новую информацию. Это означает, что вы можете хранить сообщения, коды или идентификаторы по вашему выбору на метках.
RFID-считыватель RC522 рассчитан на работу на частоте 13.56 МГц и взаимодействует с RFID-метками, соответствующими стандарту ISO 14443A (общий набор правил для работы RFID-устройств).
При подключении RC522 к микроконтроллеру, такому как Arduino, у вас есть несколько вариантов: SPI (самый быстрый из трёх), I2C или UART. Эта гибкость означает, что вы можете выбрать способ связи, который лучше всего подходит для вашего проекта или используемого микроконтроллера.
Особенно полезная функция RC522 — возможность генерации прерываний. Вместо того чтобы Arduino постоянно спрашивал: «Есть ли карта поблизости?» снова и снова, сам модуль может оповестить Arduino, когда обнаружит метку в зоне действия. Это делает ваши проекты более эффективными и отзывчивыми.
Сам модуль RC522 работает при напряжении от 2.5V до 3.3V, но хорошая новость в том, что его коммуникационные выводы «5V-толерантны», то есть вы можете легко подключить его напрямую к Arduino или любому другому 5V микроконтроллеру без преобразователя уровня логики.
Технические характеристики
Вот технические характеристики:
Диапазон частот |
13.56 МГц ISM Band |
|---|---|
Интерфейс хоста |
SPI / I2C / UART |
Напряжение питания |
2.5V — 3.3V |
Макс. рабочий ток |
13-26 мА |
Мин. ток (спящий режим) |
10 мкА |
Логические входы |
5V-толерантные |
Дальность считывания |
5 см |
Для получения подробностей обратитесь к техническому описанию ниже.
Распиновка модуля RC522 RFID
Модуль RC522 имеет 8 выводов для подключения к Arduino или другому микроконтроллеру. Каждый из этих выводов выполняет определённую функцию:
VCC обеспечивает питание модуля. Ему требуется от 2.5 до 3.3 вольт, поэтому вы можете безопасно подключить его к выходу 3.3V вашего Arduino. Будьте осторожны — если вы случайно подключите его к выводу 5V, вы можете навсегда повредить модуль!
RST — это вывод сброса/перехода в спящий режим. Когда этот вывод притянут к LOW (подключён к земле), модуль переходит в спящий режим. В этом режиме генератор отключается, и входные выводы отключаются. Когда сигнал меняется с LOW на HIGH (нарастающий фронт), модуль сбрасывается и становится активным.
GND — это вывод заземления, который должен быть подключён к выводу GND на вашем Arduino.
IRQ — это вывод прерывания, который сигнализирует Arduino, когда RFID-метка обнаружена поблизости.
MISO / SCL / Tx — это многофункциональный вывод, функция которого меняется в зависимости от способа связи с модулем:
В режиме SPI это вывод Master-In-Slave-Out (MISO), по которому данные передаются от модуля к Arduino
В режиме I2C это вывод тактирования (SCL)
В режиме UART это вывод передачи (Tx), через который модуль отправляет данные
MOSI — через этот вывод Arduino отправляет данные модулю RC522 при использовании связи SPI.
SCK (Serial Clock) — через этот вывод модуль получает тактовые импульсы от Arduino при использовании связи SPI.
SS / SDA / Rx — ещё один многофункциональный вывод:
В режиме SPI это вывод выбора ведомого (SS)
В режиме I2C это вывод данных (SDA)
В режиме UART это вывод приёма (Rx), через который модуль получает данные
Этот вывод часто имеет квадратную маркировку на печатной плате, что помогает идентифицировать и остальные выводы.
Схема подключения модуля RC522 RFID к Arduino
Теперь, когда мы хорошо разобрались в модуле RC522, перейдём к его подключению к Arduino!
Шаг 1: Подключение питания
Начните с подключения выводов питания:
Подключите вывод VCC модуля RC522 к выводу 3.3V на вашем Arduino.
Подключите вывод GND к земле (GND) на Arduino.
Шаг 2: Выводы сброса и прерывания
Вывод RST (Reset) можно подключить к любому цифровому выводу Arduino; в нашем случае мы используем цифровой вывод #9.
Вывод IRQ (Interrupt Request Output) останется неподключённым, так как библиотека Arduino, которую мы будем использовать, не поддерживает функцию прерываний.
Шаг 3: Подключение SPI
Далее мы подключим выводы, используемые для связи SPI. Поскольку модулю RC522 необходимо быстро передавать данные, он лучше всего работает при подключении к аппаратным выводам SPI на вашем Arduino. Для плат Arduino, таких как UNO или Nano V3.0, это выводы: цифровой 13 (SCK), 12 (MISO), 11 (MOSI) и 10 (CS).
Если вы используете другую плату Arduino, обязательно проверьте официальную документацию Arduino, чтобы найти правильные аппаратные выводы SPI для вашей конкретной платы.
Шаг 4: Краткая справка
Для удобства приведём таблицу подключений:
| RC522 Module | Arduino | |
| VCC | 3.3V | |
| GND | GND | |
| RST | 9 | |
| MISO / SCL / Tx | 12 | |
| MOSI | 11 | |
| SCK | 13 | |
| SS / SDA / Rx | 10 |
Ниже представлено изображение, показывающее, как подключить модуль RC522 к Arduino.
Когда всё подключено, вы готовы приступить к программированию!
Установка библиотеки
Общение с RFID-модулем RC522 может показаться сложным поначалу, но не волнуйтесь! Существует библиотека MFRC522, которая значительно упрощает чтение и запись RFID-меток.
Однако эта библиотека не поставляется предустановленной с Arduino IDE, поэтому вам нужно сначала установить её самостоятельно.
Для установки библиотеки:
Сначала откройте Arduino IDE. Затем нажмите на значок Менеджер библиотек на левой боковой панели.
Введите «mfrc522» в поле поиска для фильтрации результатов.
Найдите библиотеку от Github Community
Нажмите кнопку Install для добавления её в Arduino IDE.
Код Arduino — Чтение RFID-метки
Теперь, когда библиотека установлена, перейдём к чтению RFID-метки с помощью примера скетча.
В Arduino IDE откройте меню Examples, перейдите к MFRC522 и выберите скетч DumpInfo. Этот скетч считывает RFID-метку и отображает всю хранящуюся на ней информацию. Это отличный способ изучить содержимое ваших меток, когда вы только начинаете.
Теперь загрузите скетч в Arduino и откройте монитор последовательного порта. Когда вы поднесёте RFID-метку (карту или брелок) к модулю, на экране появится информация. Она включает уникальный идентификатор (UID) метки, объём памяти и даже содержимое всей 1КБ памяти. Убедитесь, что вы держите метку неподвижно рядом с модулем, пока вся информация не будет считана и отображена.
Структура памяти MIFARE Classic 1K
Для эффективного использования метки важно понимать организацию её памяти.
Память метки 1К организована очень определённым образом, аналогично тому, как жилой дом делится на этажи, квартиры и комнаты.
Вся память метки разделена на 16 секторов (пронумерованных от 0 до 15). Каждый сектор далее делится на 4 блока (блоки 0–3). И каждый блок может хранить 16 байт данных (от 0 до 15).
Если посчитать, становится понятно, откуда взялось название «1К»:
16 секторов × 4 блока × 16 байт данных = 1024 байта = 1К памяти
Вся 1К памяти со всеми её секторами, блоками и данными показана на изображении ниже.
Вот 3D-представление структуры карты памяти MIFARE Classic 1K.
Последний блок (Блок #3) каждого сектора называется Sector Trailer (концевой блок сектора). Он содержит специальные данные, известные как биты доступа, которые контролируют права чтения и записи для оставшихся трёх блоков сектора. Из-за этого для записи ваших данных доступны только 3 блока каждого сектора (Блоки #0, #1 и #2). Это означает, что для ваших данных доступно только 48 байт на сектор.
Кроме того, самый первый блок во всей памяти метки (Блок #0 Сектора #0) называется Блок производителя. Этот специальный блок содержит запрограммированную на заводе информацию, включая данные производителя IC и уникальный идентификатор (UID) метки. Блок производителя выделен красным на изображении ниже.
Внимание:
Никогда не пытайтесь перезаписать или изменить блок производителя! Это крайне рискованно и может навсегда заблокировать метку, сделав её непригодной для использования.
Код Arduino — Запись RFID-метки
Теперь, когда вы успешно считали RFID-метку, давайте пойдём дальше и попробуем записать на неё пользовательские данные. Этот эксперимент покажет, как хранить информацию на RFID-метке и затем считать её обратно.
Прежде чем мы перейдём к подробному объяснению, загрузите следующий скетч в ваш Arduino и посмотрите, как он работает:
#include <SPI.h> //include the SPI bus library
#include <MFRC522.h> //include the RFID reader library
#define SS_PIN 10 //slave select pin
#define RST_PIN 9 //reset pin
MFRC522 mfrc522(SS_PIN, RST_PIN); // instatiate a MFRC522 reader object.
MFRC522::MIFARE_Key key; //create a MIFARE_Key struct named 'key', which will hold the card information
//this is the block number we will write into and then read.
int block = 2;
byte blockcontent[16] = { "Last-Minute-Engg" }; //an array with 16 bytes to be written into one of the 64 card blocks is defined
//byte blockcontent[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; //all zeros. This can be used to delete a block.
//This array is used for reading out a block.
byte readbackblock[18];
void setup() {
Serial.begin(9600); // Initialize serial communications with the PC
SPI.begin(); // Init SPI bus
mfrc522.PCD_Init(); // Init MFRC522 card (in case you wonder what PCD means: proximity coupling device)
Serial.println("Scan a MIFARE Classic card");
// Prepare the security key for the read and write functions.
for (byte i = 0; i < 6; i++) {
key.keyByte[i] = 0xFF; //keyByte is defined in the "MIFARE_Key" 'struct' definition in the .h file of the library
}
}
void loop() {
// Look for new cards
if (!mfrc522.PICC_IsNewCardPresent()) {
return;
}
// Select one of the cards
if (!mfrc522.PICC_ReadCardSerial()) {
return;
}
Serial.println("card selected");
//the blockcontent array is written into the card block
writeBlock(block, blockcontent);
//read the block back
readBlock(block, readbackblock);
//uncomment below line if you want to see the entire 1k memory with the block written into it.
//mfrc522.PICC_DumpToSerial(&(mfrc522.uid));
//print the block contents
Serial.print("read block: ");
for (int j = 0; j < 16; j++) {
Serial.write(readbackblock[j]);
}
Serial.println("");
}
//Write specific block
int writeBlock(int blockNumber, byte arrayAddress[]) {
//this makes sure that we only write into data blocks. Every 4th block is a trailer block for the access/security info.
int largestModulo4Number = blockNumber / 4 * 4;
int trailerBlock = largestModulo4Number + 3; //determine trailer block for the sector
if (blockNumber > 2 && (blockNumber + 1) % 4 == 0) {
Serial.print(blockNumber);
Serial.println(" is a trailer block:");
return 2;
}
Serial.print(blockNumber);
Serial.println(" is a data block:");
//authentication of the desired block for access
byte 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 3; //return "3" as error message
}
//writing the block
status = mfrc522.MIFARE_Write(blockNumber, arrayAddress, 16);
//status = mfrc522.MIFARE_Write(9, value1Block, 16);
if (status != MFRC522::STATUS_OK) {
Serial.print("MIFARE_Write() failed: ");
Serial.println(mfrc522.GetStatusCodeName(status));
return 4; //return "4" as error message
}
Serial.println("block was written");
}
//Read specific block
int readBlock(int blockNumber, byte arrayAddress[]) {
int largestModulo4Number = blockNumber / 4 * 4;
int trailerBlock = largestModulo4Number + 3; //determine trailer block for the sector
//authentication of the desired block for access
byte 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 (read): ");
Serial.println(mfrc522.GetStatusCodeName(status));
return 3; //return "3" as error message
}
//reading a block
byte buffersize = 18; //we need to define a variable with the read buffer size, since the MIFARE_Read method below needs a pointer to the variable that contains the size...
status = mfrc522.MIFARE_Read(blockNumber, arrayAddress, &buffersize); //&buffersize is a pointer to the buffersize variable; MIFARE_Read requires a pointer instead of just a number
if (status != MFRC522::STATUS_OK) {
Serial.print("MIFARE_read() failed: ");
Serial.println(mfrc522.GetStatusCodeName(status));
return 4; //return "4" as error message
}
Serial.println("block was read");
}
Когда вы запустите код и отсканируете карту, вы должны увидеть вывод подобный этому в мониторе последовательного порта:
Объяснение кода:
Программа начинается с подключения двух важных библиотек: SPI.h, которая помогает Arduino общаться с RFID-модулем по протоколу SPI, и MFRC522.h, которая содержит функции для управления RFID-модулем.
#include <SPI.h>//include the SPI bus library
#include <MFRC522.h>//include the RFID reader library
Затем мы определяем выводы, которые подключают RFID-модуль к Arduino:
#define SS_PIN 10 //slave select pin
#define RST_PIN 9 //reset pin
После этого мы создаём экземпляр класса MFRC522, который позволяет нам взаимодействовать с RFID-модулем. Мы также определяем ключ безопасности, который позволит нам читать и записывать данные на карту.
MFRC522 mfrc522(SS_PIN, RST_PIN); // instatiate a MFRC522 reader object.
MFRC522::MIFARE_Key key;//create a MIFARE_Key struct named 'key', which will hold the card information
Далее мы выбираем Сектор#0 Блок#2 в качестве ячейки памяти, куда хотим сохранить наши данные. Помните, что RFID-карты разделены на секторы, и каждый сектор содержит четыре блока. Очень важно никогда не записывать в Блок #3 любого сектора, потому что это концевой блок сектора (Sector Trailer), в котором хранятся настройки безопасности. Случайная перезапись этого блока может сделать весь раздел карты непригодным для использования.
//this is the block number we will write into and then read.
int block=2;
Для хранения наших данных мы определяем массив из 16 байт под названием blockcontent и устанавливаем его в «Last-Minute-Engg». Если вы когда-нибудь захотите стереть содержимое блока, просто перезапишите его нулями.
byte blockcontent[16] = {"Last-Minute-Engg"}; //an array with 16 bytes to be written into one of the 64 card blocks is defined
//byte blockcontent[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; //all zeros. This can be used to delete a block.
Для проверки успешности записи мы также определяем другой массив readbackblock. Интересно, что этот массив имеет длину 18 байт вместо 16. Причина в том, что функция MIFARE_Read из библиотеки MFRC522 требует буфер не менее 18 байт, хотя каждый блок фактически содержит только 16 байт данных.
//This array is used for reading out a block.
byte readbackblock[18];
В функции setup() мы инициализируем три вещи: последовательную связь, чтобы отправлять сообщения в монитор последовательного порта, связь SPI для общения Arduino с RFID-модулем, и сам RFID-модуль с помощью mfrc522.PCD_Init().
Serial.begin(9600); // Initialize serial communications with the PC
SPI.begin(); // Init SPI bus
mfrc522.PCD_Init(); // Init MFRC522 card (in case you wonder what PCD means: proximity coupling device)
Помните, что ранее мы определили ключ безопасности с помощью структуры MIFARE_Key под названием key. Этот ключ представляет собой массив из шести байт, используемый для получения доступа к RFID-карте. Здесь мы инициализируем его, устанавливая все шесть байтов в 0xFF.
Имейте в виду, что все новые RFID-карты имеют ключ безопасности 0xFF по умолчанию. Однако если карта была запрограммирована ранее, ей мог быть назначен другой ключ. В таком случае вы должны знать правильный ключ для доступа к памяти карты.
// Prepare the security key for the read and write functions.
for (byte i = 0; i < 6; i++) {
key.keyByte[i] = 0xFF; //keyByte is defined in the "MIFARE_Key" 'struct' definition in the .h file of the library
}
Внутри loop() программа непрерывно проверяет наличие новой RFID-карты. Когда карта обнаружена, считывается её уникальный серийный номер. После идентификации карты мы записываем данные из blockcontent в Блок #2. После завершения записи мы сразу же считываем данные из того же блока, чтобы убедиться в успешности записи. Наконец, полученные данные выводятся в монитор последовательного порта.
void loop() {
// Look for new cards
if (!mfrc522.PICC_IsNewCardPresent()) {
return;
}
// Select one of the cards
if (!mfrc522.PICC_ReadCardSerial()) {
return;
}
Serial.println("card selected");
//the blockcontent array is written into the card block
writeBlock(block, blockcontent);
//read the block back
readBlock(block, readbackblock);
//uncomment below line if you want to see the entire 1k memory with the block written into it.
//mfrc522.PICC_DumpToSerial(&(mfrc522.uid));
//print the block contents
Serial.print("read block: ");
for (int j = 0; j < 16; j++) {
Serial.write(readbackblock[j]);
}
Serial.println("");
}
Для записи данных мы просто вызываем пользовательскую функцию writeBlock(), которая принимает два параметра: номер блока, куда мы хотим сохранить данные, и сами данные (хранящиеся в виде массива из 16 байт). Перед записью программа аутентифицирует блок с помощью ключа безопасности. Если аутентификация не удалась, в мониторе последовательного порта появляется сообщение об ошибке. В случае успеха данные записываются на RFID-метку, и отображается подтверждающее сообщение — «block was written».
//Write specific block
int writeBlock(int blockNumber, byte arrayAddress[]) {
//this makes sure that we only write into data blocks. Every 4th block is a trailer block for the access/security info.
int largestModulo4Number = blockNumber / 4 * 4;
int trailerBlock = largestModulo4Number + 3; //determine trailer block for the sector
if (blockNumber > 2 && (blockNumber + 1) % 4 == 0) {
Serial.print(blockNumber);
Serial.println(" is a trailer block:");
return 2;
}
Serial.print(blockNumber);
Serial.println(" is a data block:");
//authentication of the desired block for access
byte 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 3; //return "3" as error message
}
//writing the block
status = mfrc522.MIFARE_Write(blockNumber, arrayAddress, 16);
//status = mfrc522.MIFARE_Write(9, value1Block, 16);
if (status != MFRC522::STATUS_OK) {
Serial.print("MIFARE_Write() failed: ");
Serial.println(mfrc522.GetStatusCodeName(status));
return 4; //return "4" as error message
}
Serial.println("block was written");
}
Для проверки данных мы вызываем другую пользовательскую функцию readBlock(), которая также принимает два параметра: номер блока для чтения и массив, в который будут сохранены полученные данные. Как и при записи, функция сначала аутентифицирует блок. При успешной аутентификации она считывает данные и сохраняет их в массиве readbackblock. Затем программа выводит эти данные в монитор последовательного порта, чтобы мы могли убедиться, что всё записано правильно.
//Read specific block
int readBlock(int blockNumber, byte arrayAddress[]) {
int largestModulo4Number = blockNumber / 4 * 4;
int trailerBlock = largestModulo4Number + 3; //determine trailer block for the sector
//authentication of the desired block for access
byte 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 (read): ");
Serial.println(mfrc522.GetStatusCodeName(status));
return 3; //return "3" as error message
}
//reading a block
byte buffersize = 18; //we need to define a variable with the read buffer size, since the MIFARE_Read method below needs a pointer to the variable that contains the size...
status = mfrc522.MIFARE_Read(blockNumber, arrayAddress, &buffersize); //&buffersize is a pointer to the buffersize variable; MIFARE_Read requires a pointer instead of just a number
if (status != MFRC522::STATUS_OK) {
Serial.print("MIFARE_read() failed: ");
Serial.println(mfrc522.GetStatusCodeName(status));
return 4; //return "4" as error message
}
Serial.println("block was read");
}
Проект Arduino — Система контроля доступа на основе RFID
Давайте создадим простую систему контроля доступа на основе RFID с использованием Arduino и RFID-модуля RC522. Этот проект будет сканировать RFID-метки и сравнивать их уникальные идентификаторы с предопределённой мастер-меткой, хранящейся в памяти Arduino. Если отсканированная метка совпадает с мастер-меткой, доступ предоставляется. В противном случае доступ отклоняется. Довольно круто, правда?
При сканировании метки система отобразит на LCD-экране сообщение о том, предоставлен или отклонён доступ.
Хотя этот проект просто отображает сообщения на LCD, вы можете легко модифицировать его для открытия дверей, активации реле, включения светодиодов или любого другого действия на основе авторизации метки.
Схема подключения
Прежде чем загрузить код и начать сканировать метки, давайте быстро рассмотрим подключение. RFID-модуль подключается к Arduino через интерфейс SPI, а LCD-экран — через цифровые выводы I/O.
Если вы не знакомы с использованием символьного LCD 16×2, рекомендуем ознакомиться с руководством по его настройке.
Код Arduino
Давайте попробуем скетч ниже.
#include <SPI.h>
#include <MFRC522.h>
#include <LiquidCrystal.h>
#define RST_PIN 9
#define SS_PIN 10
byte readCard[4];
String MasterTag = "20C3935E"; // REPLACE this Tag ID with your Tag ID!!!
String tagID = "";
// Create instances
MFRC522 mfrc522(SS_PIN, RST_PIN);
LiquidCrystal lcd(7, 6, 5, 4, 3, 2); //Parameters: (rs, enable, d4, d5, d6, d7)
void setup() {
// Initiating
SPI.begin(); // SPI bus
mfrc522.PCD_Init(); // MFRC522
lcd.begin(16, 2); // LCD screen
lcd.clear();
lcd.print(" Access Control ");
lcd.setCursor(0, 1);
lcd.print("Scan Your Card>>");
}
void loop() {
//Wait until new tag is available
while (getID()) {
lcd.clear();
lcd.setCursor(0, 0);
if (tagID == MasterTag) {
lcd.print(" Access Granted!");
// You can write any code here like opening doors, switching on a relay, lighting up an LED, or anything else you can think of.
} else {
lcd.print(" Access Denied!");
}
lcd.setCursor(0, 1);
lcd.print(" ID : ");
lcd.print(tagID);
delay(2000);
lcd.clear();
lcd.print(" Access Control ");
lcd.setCursor(0, 1);
lcd.print("Scan Your Card>>");
}
}
//Read new tag if available
boolean getID() {
// Getting ready for Reading PICCs
if (!mfrc522.PICC_IsNewCardPresent()) { //If a new PICC placed to RFID reader continue
return false;
}
if (!mfrc522.PICC_ReadCardSerial()) { //Since a PICC placed get Serial and continue
return false;
}
tagID = "";
for (uint8_t i = 0; i < 4; i++) { // The MIFARE PICCs that we use have 4 byte UID
//readCard[i] = mfrc522.uid.uidByte[i];
tagID.concat(String(mfrc522.uid.uidByte[i], HEX)); // Adds the 4 bytes in a single String variable
}
tagID.toUpperCase();
mfrc522.PICC_HaltA(); // Stop reading
return true;
}
Объяснение кода:
Программа довольно проста. Сначала мы подключаем необходимые библиотеки: SPI.h для связи с RFID-модулем, MFRC522.h для управления RFID-модулем и LiquidCrystal.h для LCD-дисплея. Затем определяем выводы, используемые для подключения RFID-модуля, и создаём экземпляры объектов MFRC522 и LiquidCrystal.
#include <SPI.h>
#include <MFRC522.h>
#include <LiquidCrystal.h>
#define RST_PIN 9
#define SS_PIN 10
// Create instances
MFRC522 mfrc522(SS_PIN, RST_PIN);
LiquidCrystal lcd(7, 6, 5, 4, 3, 2); //Parameters: (rs, enable, d4, d5, d6, d7)
Мы также настраиваем мастер-метку — авторизованную RFID-карту, которая предоставляет доступ. Уникальный идентификатор этой метки хранится в виде строки. Каждый раз при сканировании карты её ID считывается и сравнивается с мастер-меткой. Если они совпадают, доступ предоставляется; в противном случае доступ отклоняется.
byte readCard[4];
String MasterTag = "20C3935E"; // REPLACE this Tag ID with your Tag ID!!!
String tagID = "";
В функции setup() мы инициализируем связь SPI, настраиваем RFID-считыватель и конфигурируем LCD-дисплей. LCD-экран начинает с отображения приветственного сообщения, предлагающего пользователям отсканировать свои карты.
void setup() {
// Initiating
SPI.begin(); // SPI bus
mfrc522.PCD_Init(); // MFRC522
lcd.begin(16, 2); // LCD screen
lcd.clear();
lcd.print(" Access Control ");
lcd.setCursor(0, 1);
lcd.print("Scan Your Card>>");
}
Основная функция loop() непрерывно ожидает сканирования новой RFID-карты. Когда метка обнаружена, считывается её уникальный ID, и программа проверяет, совпадает ли он с мастер-меткой. Если да, LCD-экран отображает «Access Granted!» (Доступ предоставлен!). Если метка не распознана, отображается «Access Denied!» (Доступ отклонён!). ID отсканированной метки также отображается на экране для справки. После небольшой задержки система сбрасывается и предлагает следующему пользователю отсканировать карту.
void loop() {
//Wait until new tag is available
while (getID()) {
lcd.clear();
lcd.setCursor(0, 0);
if (tagID == MasterTag) {
lcd.print(" Access Granted!");
// You can write any code here like opening doors, switching on a relay, lighting up an LED, or anything else you can think of.
} else {
lcd.print(" Access Denied!");
}
lcd.setCursor(0, 1);
lcd.print(" ID : ");
lcd.print(tagID);
delay(2000);
lcd.clear();
lcd.print(" Access Control ");
lcd.setCursor(0, 1);
lcd.print("Scan Your Card>>");
}
}
Самая важная часть этого кода — функция getID(), которая отвечает за чтение уникального ID RFID-метки. Она сначала проверяет, есть ли новая карта. Если карта обнаружена, считывается серийный номер карты и четырёхбайтный уникальный идентификатор (UID) преобразуется в строку. Эта строка затем сохраняется и используется для сравнения с мастер-меткой. Наконец, функция прекращает чтение карты до сканирования новой.
//Read new tag if available
boolean getID() {
// Getting ready for Reading PICCs
if (!mfrc522.PICC_IsNewCardPresent()) { //If a new PICC placed to RFID reader continue
return false;
}
if (!mfrc522.PICC_ReadCardSerial()) { //Since a PICC placed get Serial and continue
return false;
}
tagID = "";
for (uint8_t i = 0; i < 4; i++) { // The MIFARE PICCs that we use have 4 byte UID
//readCard[i] = mfrc522.uid.uidByte[i];
tagID.concat(String(mfrc522.uid.uidByte[i], HEX)); // Adds the 4 bytes in a single String variable
}
tagID.toUpperCase();
mfrc522.PICC_HaltA(); // Stop reading
return true;
}
Этот проект — отличная отправная точка для создания полноценной системы контроля доступа на основе RFID. Вы можете расширить его, подключив реле для управления дверным замком, добавив зуммер для звуковой обратной связи или даже сохранив несколько авторизованных ID в памяти. Попробуйте поэкспериментировать с кодом, чтобы настроить систему под ваши нужды!