Создание системы ограничения доступа в программе FLProg с применением RFID-RC522

Добрый день. Я — разработчик программы FLProg, и сегодня я расскажу Вам как с помощью программы FLProg создать устройство контроля доступа с применением сканера бесконтактных меток RFID RC522. Поскольку данный пост – обучающий, то рассматриваться будет не законченное изделие, а только тестовый макет.
Рассмотрим данный сканер бесконтактных меток RFID RC522.
Сканер бесконтактных меток RFID-RC522 без меток позволяет обнаружить и считать идентификаторы бесконтактных карт, меток, пропусков стандарта 13,56 МГц на расстоянии до 10 см. Благодаря данному сканеру можно сделать ряд интересных проектов: пропускные системы, электронные замки, складской учету и много другое.
Технические характеристики сканера.
| Параметр | Значение |
|---|---|
| Потребляемый ток в активном состоянии | 13-26mA/DC 3.3V |
| Потребляемый ток в состоянии ожидания | 10-13mA/DC 3.3V |
| Ток в режиме сна | |
| Рабочая частота | 13.56MHz |
| Поддержвиаемые типы карт | MIFARE S50, MIFARE S70, MIFARE UltraLight, MIFARE Pro, MIFARE DESfire |
| Размер | 40mm х 60mm |
| Температура, при которой работает модуль | -20 до +80 С |
| Относительная влажность воздуха | от 5% до 95% |
Базовый принцип действия довольно прост для понимания. В карточке и в считывателе есть антенны, при этом сигнал считывающего устройства (суть электромагнитное поле) одновременно служит источником питания для карточки. Т.е. и в части энергетики, и в части передачи данных это очень похоже на ставшие сверхпопулярными беспроводные зарядки.
Сами же карточки, в зависимости от модификации, могут нести в себе от нескольких десятков байт до нескольких килобайт данных (в том числе — уникальный серийный номер). Также, в зависимости от модификации, карточка может быть укомплектована криптографической защитой информации.
В Китае подобные сканеры стоят от 200 рублей в комплекте с картой и брелком. Это очень привлекательно. Но всё-таки при заказе данного сканера советую брать, как говорится «с запасом». В моём случае из трёх имеющихся у меня сканеров, купленных в разное время у разных продавцов, нормально заработал только один. Второй видел карту, только поднесённую точно на определённое расстояние. Ближе или дальше – он её терял. Ну и третий вообще не видел поднесённых карт, хотя на запросы и тестирование по SPI отвечал нормально.
В программе FLProg реализовано два вида функциональных блоков для работы со сканером.
- «Наличие новой карты»
- «Информация о карте»
- «Чтения бока данных на карту»
- «Запись блока данных на карту»
В программе реализовано хранилище UUID карт, представляющее собой набор ячеек каждая из которых хранит непосредственно UUID карты, и статус ячейки. Три статуса зарезервировано программой.
0х00 – ячейка свободна
0Х01 – в ячейке хранится UUID но она заблокирована.
0х02 — в ячейке хранится UUID и она активна
Остальные коды статуса (3 … 255) пользователь может использовать по своему усмотрению.
Хранилище может располагаться в оперативной памяти контроллера (при снятии питания или перезагрузке оно очистится), или в EEPROM. Хранилищ может быть несколько, и они могут быть разных типов. При расположении хранилища в EEPROM размеры его ограниченны. Для Arduino Uno –это максимум 85 ячеек (во всех хранилищах EEPROM в сумме), для Arduino Mega – 341 ячейка.
- «Сохранить UUID карты в хранилище»
- «Прочитать UUID карты из хранилища»
- «Статус ячейки в хранилище»
- «Записать статус ячейки в хранилище»
- «Блокировка/разблокировка ячейки»
- «Поиск UUID в хранилище»
- «Свободные ячейки хранилища»
- «Очистка ячейки в хранилище»
- «Очистка всего хранилища»
Разберём ТЗ для задуманного устройства.
В устройстве будут два хранилища расположенных EEPROM. В первом хранятся так называемые Master Card. С помощью них можно записывать обычные карты во второе хранилище. Для записи Master Card существует «Секретная кнопка». Так же есть дисплей для отображения необходимой информации, и обычная управляющая кнопка.
Схема устройства.
Видео урок с описанием результата разработки
Карты и брелки используемые вместе со сканером имеют «на борту» 1 кБ памяти которые можно использовать в собственных целях. Давайте расширим ТЗ и будем записывать, какую либо информацию. Для этого соберём еще одно устройство.
Так же доработаем проект созданный в предыдущем видео уроке.
До свидания, надеюсь Вам было интересно.
Как очистить блоки nfc rfid rc522
Найдите лучшие предложения для смарт-гаджетов в одном месте.
Простые и безопасные платежи
Оплата напрямую через PayPal или Klarna среди других способов оплаты.
Местный склад и быстрая доставка
Купите на местном складе и отправьте в течение 48 часов.
Служба поддержки
Круглосуточная поддержка клиентов по всем вашим вопросам.
Документи Как отслеживать О нас Контакты Гарантия Часто задаваемые вопросы Статус заказа Карта сайта
Поддержка Руководство по доставке Информация об оплате Опт / корпоратив Доставка Филиалы Блог
Налоги и сборы Правила и условия Политика возврата Политика Декларация Таможня

Скачать приложение

Свяжитесь с нами:
Популярные запросы
Copyright © 2012-2024 Geekbuying.com. Все права защищены.
Онлайн Чат

Загрузите приложение, чтобы получить скидку до 70% на предложения только для приложений и купоны на сумму 50 долларов США.

Войти/Создать аккаунт Эл. адрес Продолжить в качестве гостя
Или продолжите другими способами
Google Apple
Продолжая, вы соглашаетесь с нашими Условия использования & Персональные данные
Вход Эл. адрес
Забыли пароль?
Регистрация
Создайте свою учетную запись Geekbuying
Регистрация простая, просто введите пароль
Зарегистрируйтесь, чтобы получить G-coins на сумму €1.84
Зарегистрируйтесь, чтобы получить купоны на 55.24 евро и G-монеты на сумму 4.60 евро.
Эл. адрес Пароль
Ваш пароль должен включать следующее:
минимум 8 символов
Хотя бы одно письмо
Хотя бы одна цифра или специальный символ
Я согласен с Geekbuying Условия использования & Персональные данные. Чтобы завершить регистрацию, вы должны согласиться с положениями и условиями сайта GeekBuying. Присылайте мне электронные письма о новых поступлениях, горячих позициях, ежедневных сбережениях и многом другом. Подпишитесь, чтобы получить скидку 55.24 евро (купоны * 5) и 3 G-монеты стоимостью 2.76 евро.
Вы успешно создали свой аккаунт!
Ссылка для активации была отправлена на ваш адрес электронной почты. Активируйте свою учетную запись для доступа к следующему:
- Скидка 2 на скидочный код
- Просмотр информации о выставлении счетов и доставке
- Создание и изменение вашей личной учетной записи
- Проверка статуса вашего заказа, отзывов, корзины и списка пожеланий
- После активации учетной записи вы получите G-coins на сумму 1.84 евро.
- Спасибо за подписку. Вы получили награду. просмотреть это под МОЙ АККАУНТ
Если вы не получили электронное письмо с кодом активации, нажмите ниже, чтобы отправить электронное письмо с кодом активации.
Возмущаться успешно. Пожалуйста, проверьте ваш электронный ящик, чтобы получить скидку!
Работа с Arduino и RFID MFRC522

Технология RFID (Радиочастотная идентификация) позволяет при помощи радиосигнала быстро и безопасно передавать данные между специальными “считывателями” и “метками” – карточками, брелоками, браслетами и т.д. на небольшом расстоянии.
Одно из широко известных развитий технологии – NFC, при помощи которого можно оплачивать покупки или подключать устройства бесконтактно. Нам же доступны менее сложные, но не менее полезные и интересные применения, о которых будет сказано ниже.
Применение
Комплект RFID модуль + метки может быть использован:
- Как часть самодельных охранных систем
- При создании простых электронных замков (метка является ключом)
- В системах контроля доступа (однократный, многократный пропуск)
- В качестве электронного “кошелька” внутри собственного предприятия
- В роли интерактивного предмета в квестах и т.д.
Железо
RFID работает в нескольких частотных диапазонах, в свою очередь RFID модули и метки можно поделить на низкочастотные “LF” (125 кгц) и высокочастотные “HF” (13,56 MHz), существуют так же и ультравысокочастотные “UHF”, но они нас не интересуют.
Наиболее распространенные RFID Arduino-модули основаны на микросхеме MFRC522, работающей с HF метками 13,56 МГц. Поиск модулей и библиотек производится по этому же имени.
Существует два типа модулей MFRC522, с которыми вы скорее всего столкнетесь:

Отвечая на главный вопрос – не смотря на значительную разницу в размере, ощутимой разницы в работе модулей нет, можно брать любой. В комплекте к модулю как правило уже идет несколько меток.
Библиотеки
Для работы с модулем MFRC522 понадобится библиотека https://github.com/miguelbalboa/rfid. Библиотека тяжелая, индусская и имеет немало проблем, но достойных альтернатив просто нет – несколько других “облегченных” библиотек значительно уступают в функциональности и удобстве использования.
Подключение
Модуль MFRC522 подключается по аппаратному интерфейсу SPI, выбранная библиотека предоставляет следующую таблицу подключения к Arduino:
| Сигнал | Модуль MFRC522 | UNO/NANO | Leonardo | Pro micro | Mega |
| Reset | RST | D9 | RST/ISCP-5 | RST | D5 |
| Chip select | SDA (SS) | D10 | D10 | D10 | D53 |
| MOSI | MOSI | D11 | ISCP-4 | D16 | D51 |
| MISO | MISO | D12 | ISCP-1 | D14 | D50 |
| SCK | SCK | D13 | ISCP-3 | D15 | D52 |
- Контакты модуля RST и SDA (SS) указываются в скетче – можно использовать любые.
- У Leonardo подключение производится к 6-ти контактному ICSP разъему программатора.
Пример подключения модуля к Arduino Nano:

О RFID метках
Прежде всего самая сложная для понимания, но и самая важная часть – работа с RFID метками. В комплекте с модулем идут пара меток MIFARE Classic 1K, как понятно из названия – на 1 килобайт (на самом деле меньше, но об этом позже).
Чтобы изучить организацию памяти такой метки, можно воспользоваться примером из библиотеки, открыв Примеры > MFRC522 > DumpInfo. Однако для вашего удобства я подготовил вот такую карту:

Обратите внимание – память организована в виде 16-ти секторов, по 4 блока каждый. Итого – 64 блока по 16 Байт, как раз набегает 1 Килобайт. Деление по секторам носит скорее условный характер, так как адресация в памяти будет производиться по блокам.
Все сектора кроме нулевого имеют одинаковое строение – 3 блока данных + 1 блок безопасности, так называемый sector trailer. Каждый из этих блоков может быть прочитан и перезаписан (при соблюдении условий), исключение составляет нулевой блок (сектор 0).
Нулевой блок хранит в себе уникальный ID “UID”, тип метки и прочую информацию, записанную заводом-изготовителем. Нулевой сектор не может быть перезаписан, если речь идет о “классических” метках, к которым относятся комплектные с модулем. Таким образом UID позволяет отличить две с виду идентичные метки. UID как правило состоит из 4х байт, свободно считываемых из метки. Важно: китайский рынок может предложить вам “перезаписываемые” метки, UID в которых можно менять, путем перезаписи нулевого блока. Если в вашей системе используется только UID – учтите возможность очень простого копирования UID в метки-болванки (в том числе злоумышленниками).
Блоком безопасности является каждый 4й блок, каждый блок безопасности отвечает за свой сектор (предыдущие 3 блока данных) – он хранит 2 ключа доступа по 6 байт (ключи A и B), а также специальные “Access bits” (Биты доступа), грубо говоря настройки доступа. Ключи A и B могут быть использованы для аутентификации и последующего доступа к блокам данных в пределах сектора. То есть да, для того чтобы получить доступ к любому из блоков внутри сектора необходимо “разблокировать” этот сектор, при помощи одного из ключей.
Поэтому будьте уверены, если производитель позаботился о смене секретных ключей в своих RFID метках – скопировать или как-нибудь изменить содержимое штатными средствами вы уже не сможете, а ведь так хотелось? Идем дальше.
Биты доступа позволяют настроить условия доступа и возможности работы каждого блока в отдельности (каждого блока данных + блока безопасности). Наилучшим инструментом в работе с метками MIFARE Classic 1K является вот этот онлайн-калькулятор http://calc.gmss.ru/Mifare1k/. Если хотите разобраться чуть глубже – обязательно полистайте и опробуйте.
Я же хочу сэкономить ваше время, поэтому сразу уточню, что наиболее удачным решением в большинстве ситуаций будет оставить блоки данных в состоянии transport configuration, то есть по умолчанию.

Однако есть возможность настроить блоки на некоторые интересные сценарии, например защитить от записи (конфигурация 1-0-1 или 0-1-0). Или же сделать так, что прочитать блок можно при помощи как ключа A, так и ключа B, а вот для записи обязательно понадобится ключ B (конфигурация 1-0-0), в таком случае можно ограничить права некоторого оборудования и сделать систему безопаснее. И да, конфигурация 1-1-1 превращает блок в кирпич (обратимо).
В примерах ниже мы будем использовать конфигурацию блоков данных по умолчанию (0-0-0) и следующие принципы:
- Создаем ключ B, значение которого знаем только мы, длина ключа – 6 Байт.
- Ключ A будет полностью аналогичен ключу B, однако он не будет использоваться.
- Биты доступа для блоков безопасности будем использовать в конфигурации 0-1-1

Таким образом для всех операций с меткой применяется только ключ B, который невозможно считать из метки (впрочем, как и ключ A), даже если сектор предварительно разблокирован. Если хотите намертво зашить ключи A и B в блок безопасности – подойдет конфигурация 1-0-1, поменять будет уже невозможно. Ну а последняя 1-1-1 конфигурация блока безопасности заблокирует еще и настройки доступа к блокам данных!
Некоторые варианты необратимы, но не переживайте – у вас есть целых 16 попыток! По одной на каждый сектор.
В итоге 3 байта настроек доступа приняли следующие значения: 0x7F 0x07 0x88, байт USER может быть любой.

Важно: изначально ключи A и B от всех секторов метки содержат значение 0xFFFFFFFFFFFF, так что если хотите защитить данные в ваших метках, не забывайте сменить оба ключа! Кстати, нулевой блок и соответственно UID свободно читаются из метки, даже если нулевой сектор был заблокирован секретными ключами.
Ну и последнее, что касается меток – реальный объем пользовательской памяти. Если не создавать костыли, а использовать только блоки для хранения данных – (по 3 блока в 15-ти секторах, и 2 блока в нулевом секторе) получаем 47 доступных блоков по 16 байт или 752 байта, что тоже неплохо.
Начало работы
Подключили модуль, распаковали свежие метки – начинаем работать!
Прежде всего создаем необходимые объекты, инициализируем интерфейс SPI и MFRC522, не забываем про ключ доступа. Изначально все ключи состоят из FF-ок, так что “наполняем” ключ.
#include #include #define RST_PIN 9 // Пин rfid модуля RST #define SS_PIN 10 // Пин rfid модуля SS MFRC522 rfid(SS_PIN, RST_PIN); // Объект rfid модуля MFRC522::MIFARE_Key key; // Объект ключа MFRC522::StatusCode status; // Объект статуса void setup() < Serial.begin(9600); // Инициализация Serial SPI.begin(); // Инициализация SPI rfid.PCD_Init(); // Инициализация модуля for (byte i = 0; i < 6; i++) < // Наполняем ключ key.keyByte[i] = 0xFF; // Ключ по умолчанию 0xFFFFFFFFFFFF >> void loop() <>
Работу с RFID модулем удобнее всего производить в конце главного цикла программы, сейчас поймете почему. Для отслеживания поднесенной метки библиотека предлагает использовать пару методов с замысловатыми названиями:
if (!rfid.PICC_IsNewCardPresent()) return; // Если новая метка не поднесена - вернуться в начало loop if (!rfid.PICC_ReadCardSerial()) return; // Если метка не читается - вернуться в начало loop
Если поднесенная метка успешно считана – программа идет дальше, в противном случае происходит возврат в начало главного цикла, а весь блок кода связанный с RFID пропускается.
В итоге наш скетч имеет следующую структуру:
#include #include #define RST_PIN 9 // Пин rfid модуля RST #define SS_PIN 10 // Пин rfid модуля SS MFRC522 rfid(SS_PIN, RST_PIN); // Объект rfid модуля MFRC522::MIFARE_Key key; // Объект ключа MFRC522::StatusCode status; // Объект статуса void setup() < Serial.begin(9600); // Инициализация Serial SPI.begin(); // Инициализация SPI rfid.PCD_Init(); // Инициализация модуля for (byte i = 0; i < 6; i++) < // Наполняем ключ key.keyByte[i] = 0xFF; // Ключ по умолчанию 0xFFFFFFFFFFFF >> void loop() < // Занимаемся чем угодно if (!rfid.PICC_IsNewCardPresent()) return; // Если новая метка не поднесена - вернуться в начало loop if (!rfid.PICC_ReadCardSerial()) return; // Если метка не читается - вернуться в начало loop // Работаем с RFID >
Теперь давайте идти по порядку, осваивая основные методы для работы с RFID.
Обратите внимание: примеры ниже содержат специальные блоки кода, повышающие стабильность работы, о них подробно сказано в конце статьи.
Чтение UID
Самое простое, что можно сделать с RFID меткой – прочитать UID, в некоторых системах уже этого функционала вполне достаточно, например – в простых электронных замках. Как уже сказано ранее, некоторые метки позволяют сменить UID, в свою очередь запретить считать UID из ваших меток не получится – учтите это при разработке.
Так или иначе пример чтения UID и вывод в порт приведен ниже:
Чтение UID
#include #include #define RST_PIN 9 // Пин rfid модуля RST #define SS_PIN 10 // Пин rfid модуля SS MFRC522 rfid(SS_PIN, RST_PIN); // Объект rfid модуля MFRC522::MIFARE_Key key; // Объект ключа MFRC522::StatusCode status; // Объект статуса void setup() < Serial.begin(9600); // Инициализация Serial SPI.begin(); // Инициализация SPI rfid.PCD_Init(); // Инициализация модуля rfid.PCD_SetAntennaGain(rfid.RxGain_max); // Установка усиления антенны rfid.PCD_AntennaOff(); // Перезагружаем антенну rfid.PCD_AntennaOn(); // Включаем антенну for (byte i = 0; i < 6; i++) < // Наполняем ключ key.keyByte[i] = 0xFF; // Ключ по умолчанию 0xFFFFFFFFFFFF >> void loop() < // Занимаемся чем угодно static uint32_t rebootTimer = millis(); // Важный костыль против зависания модуля! if (millis() - rebootTimer >= 1000) < // Таймер с периодом 1000 мс rebootTimer = millis(); // Обновляем таймер digitalWrite(RST_PIN, HIGH); // Сбрасываем модуль delayMicroseconds(2); // Ждем 2 мкс digitalWrite(RST_PIN, LOW); // Отпускаем сброс rfid.PCD_Init(); // Инициализируем заного >if (!rfid.PICC_IsNewCardPresent()) return; // Если новая метка не поднесена - вернуться в начало loop if (!rfid.PICC_ReadCardSerial()) return; // Если метка не читается - вернуться в начало loop Serial.print("UID: "); for (uint8_t i = 0; i < 4; i++) < // Цикл на 4 итерации Serial.print("0x"); // В формате HEX Serial.print(rfid.uid.uidByte[i], HEX); // Выводим UID по байтам Serial.print(", "); >Serial.println(""); >
После успешного чтения метки, ее UID появляется в массиве rfid.uid.uidByte[] который можно прочитать и использовать.
Чтение блока
Если чтением UID ваш интерес не ограничился – давайте узнаем, как читать блок данных из метки. Прежде чем что-либо читать или писать, необходимо аутентифицировать (разблокировать) сектор, в котором находится интересующий нас блок.

В примерах ниже будем работать с блоком под номером 6 (сектор 1), за первый сектор и соответственно блоки 4, 5 и 6 отвечает блок безопасности под номером 7. То есть запомнили – блок данных 6, блок безопасности 7.
Аутентификацию сектора производит метод PCD_Authenticate() , по умолчанию все манипуляции с меткой возможны при помощи ключа A, а сам процесс аутентификации выглядит следующим образом:
status = rfid.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, 7, &key, &(rfid.uid)); if (status != MFRC522::STATUS_OK) < // Если не окэй Serial.println("Auth error"); // Выводим ошибку return; >
Обратите внимание на …KEY_A в первом аргументе и цифру 7 вторым аргументом – это и есть номер блока безопасности. Отслеживать статус не обязательно, но крайне желательно.
После успешной аутентификации можно свободно манипулировать разблокированным сектором, в нашем случае будем читать содержимое методом MIFARE_Read() . Читать нужно в байтовый массив, размером 18 (!) байт, чтение происходит из блока 6 (первый аргумент) и выглядит так:
uint8_t dataBlock[18]; // Буфер для чтения uint8_t size = sizeof(dataBlock); // Размер буфера status = rfid.MIFARE_Read(6, dataBlock, &size); // Читаем 6 блок в буфер if (status != MFRC522::STATUS_OK) < // Если не окэй Serial.println("Read error"); // Выводим ошибку return; >
Важно: Не смотря на то, что блоки имеют размер 16 байт, буферный массив создается на 18 байт, а количество байт на чтение передается именно в виде указателя на переменную. В противном случае чтение закончится ошибкой, примите это как факт.
В случае успешного чтения, выведем содержимое блока 6 в монитор порта, все как обычно:
Serial.print("Data:"); // Выводим 16 байт в формате HEX for (uint8_t i = 0; i < 16; i++) < Serial.print("0x"); Serial.print(dataBlock[i], HEX); Serial.print(", "); >Serial.println("");
А завершать работу с меткой нужно при помощи еще двух замысловатых методов:
rfid.PICC_HaltA(); // Завершаем работу с меткой rfid.PCD_StopCrypto1();
В итоге полный скетч для чтения блока 6 из новой метки со стандартными ключами выглядит так:
Чтение блока
#include #include #define RST_PIN 9 // Пин rfid модуля RST #define SS_PIN 10 // Пин rfid модуля SS MFRC522 rfid(SS_PIN, RST_PIN); // Объект rfid модуля MFRC522::MIFARE_Key key; // Объект ключа MFRC522::StatusCode status; // Объект статуса void setup() < Serial.begin(9600); // Инициализация Serial SPI.begin(); // Инициализация SPI rfid.PCD_Init(); // Инициализация модуля rfid.PCD_SetAntennaGain(rfid.RxGain_max); // Установка усиления антенны rfid.PCD_AntennaOff(); // Перезагружаем антенну rfid.PCD_AntennaOn(); // Включаем антенну for (byte i = 0; i < 6; i++) < // Наполняем ключ key.keyByte[i] = 0xFF; // Ключ по умолчанию 0xFFFFFFFFFFFF >> void loop() < // Занимаемся чем угодно static uint32_t rebootTimer = millis(); // Важный костыль против зависания модуля! if (millis() - rebootTimer >= 1000) < // Таймер с периодом 1000 мс rebootTimer = millis(); // Обновляем таймер digitalWrite(RST_PIN, HIGH); // Сбрасываем модуль delayMicroseconds(2); // Ждем 2 мкс digitalWrite(RST_PIN, LOW); // Отпускаем сброс rfid.PCD_Init(); // Инициализируем заного >if (!rfid.PICC_IsNewCardPresent()) return; // Если новая метка не поднесена - вернуться в начало loop if (!rfid.PICC_ReadCardSerial()) return; // Если метка не читается - вернуться в начало loop /* Аутентификация сектора, указываем блок безопасности #7 и ключ A */ status = rfid.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, 7, &key, &(rfid.uid)); if (status != MFRC522::STATUS_OK) < // Если не окэй Serial.println("Auth error"); // Выводим ошибку return; >/* Чтение блока, указываем блок данных #6 */ uint8_t dataBlock[18]; // Буфер для чтения uint8_t size = sizeof(dataBlock); // Размер буфера status = rfid.MIFARE_Read(6, dataBlock, &size); // Читаем 6 блок в буфер if (status != MFRC522::STATUS_OK) < // Если не окэй Serial.println("Read error"); // Выводим ошибку return; >/* Выводим содержимое блока в Serial */ Serial.print("Data:"); // Выводим 16 байт в формате HEX for (uint8_t i = 0; i < 16; i++) < Serial.print("0x"); Serial.print(dataBlock[i], HEX); Serial.print(", "); >Serial.println(""); rfid.PICC_HaltA(); // Завершаем работу с меткой rfid.PCD_StopCrypto1(); >
После поднесения метки в мониторе порта должны отобразиться 16 байт – содержимое прочитанного блока.
Запись блока
При записи все 16 байт записываются в блок единовременно, для чего должен быть заранее подготовлен байтовый массив на 16 Байт, например такой:
uint8_t dataToWrite[16] = < 0x00, 0x00, 0x00, 0x00, 0xAA, 0xBB, 0xCC, 0xDD, 0xAA, 0xBB, 0xCC, 0xDD, 0x00, 0x00, 0x00, 0x00 >;
Как в случае и с чтением, сектор в котором находится нужный блок 6 нужно предварительно аутентифицировать, об этом уже сказано выше, так что переходим непосредственно к записи. Запись производится методом MIFARE_Write() , в отличии от MIFARE_Read() тут все несколько проще – указываем записываемый блок, массив и число 16 (количество байт на запись):
status = rfid.MIFARE_Write(6, dataToWrite, 16); // Пишем массив в блок 6 if (status != MFRC522::STATUS_OK) < // Если не окэй Serial.println("Write error"); // Выводим ошибку return; >
Итоговый скетч записи массива в блок 6 выглядит так:
Запись блока
#include #include #define RST_PIN 9 // Пин rfid модуля RST #define SS_PIN 10 // Пин rfid модуля SS MFRC522 rfid(SS_PIN, RST_PIN); // Объект rfid модуля MFRC522::MIFARE_Key key; // Объект ключа MFRC522::StatusCode status; // Объект статуса void setup() < Serial.begin(9600); // Инициализация Serial SPI.begin(); // Инициализация SPI rfid.PCD_Init(); // Инициализация модуля rfid.PCD_SetAntennaGain(rfid.RxGain_max); // Установка усиления антенны rfid.PCD_AntennaOff(); // Перезагружаем антенну rfid.PCD_AntennaOn(); // Включаем антенну for (byte i = 0; i < 6; i++) < // Наполняем ключ key.keyByte[i] = 0xFF; // Ключ по умолчанию 0xFFFFFFFFFFFF >> void loop() < // Занимаемся чем угодно static uint32_t rebootTimer = millis(); // Важный костыль против зависания модуля! if (millis() - rebootTimer >= 1000) < // Таймер с периодом 1000 мс rebootTimer = millis(); // Обновляем таймер digitalWrite(RST_PIN, HIGH); // Сбрасываем модуль delayMicroseconds(2); // Ждем 2 мкс digitalWrite(RST_PIN, LOW); // Отпускаем сброс rfid.PCD_Init(); // Инициализируем заного >if (!rfid.PICC_IsNewCardPresent()) return; // Если новая метка не поднесена - вернуться в начало loop if (!rfid.PICC_ReadCardSerial()) return; // Если метка не читается - вернуться в начало loop /* Аутентификация сектора, указываем блок безопасности #7 и ключ A */ status = rfid.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, 7, &key, &(rfid.uid)); if (status != MFRC522::STATUS_OK) < // Если не окэй Serial.println("Auth error"); // Выводим ошибку return; >/* Запись блока, указываем блок данных #6 */ uint8_t dataToWrite[16] = < // Массив на запись в блок 0x00, 0x00, 0x00, 0x00, 0xAA, 0xBB, 0xCC, 0xDD, 0xAA, 0xBB, 0xCC, 0xDD, 0x00, 0x00, 0x00, 0x00 >; status = rfid.MIFARE_Write(6, dataToWrite, 16); // Пишем массив в блок 6 if (status != MFRC522::STATUS_OK) < // Если не окэй Serial.println("Write error"); // Выводим ошибку return; >Serial.println("Write OK"); // Завершаем работу с меткой rfid.PICC_HaltA(); rfid.PCD_StopCrypto1(); >
После поднесения метки в мониторе порта должно отобразиться сообщение “Write OK“.
К слову ничто не мешает нам объеденить запись и чтение в одном скетче:
Запись + чтение блока
#include #include #define RST_PIN 9 // Пин rfid модуля RST #define SS_PIN 10 // Пин rfid модуля SS MFRC522 rfid(SS_PIN, RST_PIN); // Объект rfid модуля MFRC522::MIFARE_Key key; // Объект ключа MFRC522::StatusCode status; // Объект статуса void setup() < Serial.begin(9600); // Инициализация Serial SPI.begin(); // Инициализация SPI rfid.PCD_Init(); // Инициализация модуля rfid.PCD_SetAntennaGain(rfid.RxGain_max); // Установка усиления антенны rfid.PCD_AntennaOff(); // Перезагружаем антенну rfid.PCD_AntennaOn(); // Включаем антенну for (byte i = 0; i < 6; i++) < // Наполняем ключ key.keyByte[i] = 0xFF; // Ключ по умолчанию 0xFFFFFFFFFFFF >> void loop() < // Занимаемся чем угодно static uint32_t rebootTimer = millis(); // Важный костыль против зависания модуля! if (millis() - rebootTimer >= 1000) < // Таймер с периодом 1000 мс rebootTimer = millis(); // Обновляем таймер digitalWrite(RST_PIN, HIGH); // Сбрасываем модуль delayMicroseconds(2); // Ждем 2 мкс digitalWrite(RST_PIN, LOW); // Отпускаем сброс rfid.PCD_Init(); // Инициализируем заного >if (!rfid.PICC_IsNewCardPresent()) return; // Если новая метка не поднесена - вернуться в начало loop if (!rfid.PICC_ReadCardSerial()) return; // Если метка не читается - вернуться в начало loop /* Аутентификация сектора, указываем блок безопасности #7 и ключ A */ status = rfid.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, 7, &key, &(rfid.uid)); if (status != MFRC522::STATUS_OK) < // Если не окэй Serial.println("Auth error"); // Выводим ошибку return; >/* Запись блока, указываем блок данных #6 */ uint8_t dataToWrite[16] = < // Массив на запись в блок 0x00, 0x00, 0x00, 0x00, 0xAA, 0xBB, 0xCC, 0xDD, 0xAA, 0xBB, 0xCC, 0xDD, 0x00, 0x00, 0x00, 0x00 >; status = rfid.MIFARE_Write(6, dataToWrite, 16); // Пишем массив в блок 6 if (status != MFRC522::STATUS_OK) < // Если не окэй Serial.println("Write error"); // Выводим ошибку return; >/* Чтение блока, указываем блок данных #6 */ uint8_t dataBlock[18]; // Буфер для чтения uint8_t size = sizeof(dataBlock); // Размер буфера status = rfid.MIFARE_Read(6, dataBlock, &size); // Читаем 6 блок в буфер if (status != MFRC522::STATUS_OK) < // Если не окэй Serial.println("Read error"); // Выводим ошибку return; >Serial.print("Data:"); // Выводим 16 байт в формате HEX for (uint8_t i = 0; i < 16; i++) < Serial.print("0x"); Serial.print(dataBlock[i], HEX); Serial.print(", "); >Serial.println(""); rfid.PICC_HaltA(); // Завершаем работу с меткой rfid.PCD_StopCrypto1(); >
Смена ключей безопасности и настройка блоков
Если вы хотите не только уметь читать и писать данные в метки, но и защить хранящуюся там информацию от стороннего вмешательства – необходимо сменить ключи доступа как минимум от тех секторов, в которых вы собираетесь хранить данные, однако в идеале установить новые ключи для всех секторов, чтобы усложнить задачу потенциальным взломащикам.
Для того, чтобы изменить ключи доступа к сектору, необходимо перезаписать блок безопасности, ответственный за данный сектор. В наших примерах фигурировал блок данных под номером 6 и соответственно блок безопасности под номером 7. Задача по смене ключей безопасности сводится к следующим шагам:
- Создать байтовый массив на 16 ячеек, включающий:
- Ключ A
- Байты настроек доступа
- Ключ B
- Провести аутентификацию выбранного сектора, пока что используя стандартный ключ 0xFFFFFFFFFFFF
- Произвести запись подготовленного массива в блок безопасности, в точности так же, как в случае с обычным блоком.
После этого ключи безопасности будут изменены, а мы сможем безопасно хранить данные в одном или нескольких блоках выбранного сектора! Сейчас покажу по шагам.
- Для создания образа блока безопасности (содержимого массива) придется вернуться вверх по тексту и вспомнить, что при выбранных нами настройках сектора, байты доступа получили значения 0x7F 0x07 0x88. Осталось придумать ключи доступа, имеющие длину 6 байт. Я буду использовать ключ 0xABABABABABAB, данный ключ не является безопасным и подходит исключительно для демонстрации! Так же напоминаю, что ключи A и B будут идентичны, однако использоваться будет только ключ B.

-
1 После того, как мы определились с настройками сектора (“Access Bits“) и ключами безопасности – создаем нужный байтовый массив:
uint8_t secBlockDump[16] = < // Дамп блока безопасности 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, // < Ключ A 0x7F, 0x07, 0x88, // < Access Bits 0xFF, // < User байт (любой) 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB // < Ключ B >;
status = rfid.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, 7, &key, &(rfid.uid)); if (status != MFRC522::STATUS_OK) < // Если не окэй Serial.println("Auth error"); // Выводим ошибку return; >
status = rfid.MIFARE_Write(7, secBlockDump, 16); // Пишем массив в блок 6 if (status != MFRC522::STATUS_OK) < // Если не окэй Serial.println("Write error"); // Выводим ошибку return; >
Итоговый скетч записи новых ключей и настроек доступа:
Запись блока безопасности
#include #include #define RST_PIN 9 // Пин rfid модуля RST #define SS_PIN 10 // Пин rfid модуля SS MFRC522 rfid(SS_PIN, RST_PIN); // Объект rfid модуля MFRC522::MIFARE_Key key; // Объект ключа MFRC522::StatusCode status; // Объект статуса void setup() < Serial.begin(9600); // Инициализация Serial SPI.begin(); // Инициализация SPI rfid.PCD_Init(); // Инициализация модуля rfid.PCD_SetAntennaGain(rfid.RxGain_max); // Установка усиления антенны rfid.PCD_AntennaOff(); // Перезагружаем антенну rfid.PCD_AntennaOn(); // Включаем антенну for (byte i = 0; i < 6; i++) < // Наполняем ключ key.keyByte[i] = 0xFF; // Ключ по умолчанию 0xFFFFFFFFFFFF >> void loop() < // Занимаемся чем угодно static uint32_t rebootTimer = millis(); // Важный костыль против зависания модуля! if (millis() - rebootTimer >= 1000) < // Таймер с периодом 1000 мс rebootTimer = millis(); // Обновляем таймер digitalWrite(RST_PIN, HIGH); // Сбрасываем модуль delayMicroseconds(2); // Ждем 2 мкс digitalWrite(RST_PIN, LOW); // Отпускаем сброс rfid.PCD_Init(); // Инициализируем заного >if (!rfid.PICC_IsNewCardPresent()) return; // Если новая метка не поднесена - вернуться в начало loop if (!rfid.PICC_ReadCardSerial()) return; // Если метка не читается - вернуться в начало loop /* Аутентификация сектора, указываем блок безопасности #7 и ключ A */ status = rfid.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, 7, &key, &(rfid.uid)); if (status != MFRC522::STATUS_OK) < // Если не окэй Serial.println("Auth error"); // Выводим ошибку return; >/* Запись блока, указываем блок безопасности #7 */ uint8_t secBlockDump[16] = < // Дамп блока безопасности 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, // < Ключ A 0x7F, 0x07, 0x88, // < Access Bits 0xFF, // < User байт (любой) 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB // < Ключ B >; status = rfid.MIFARE_Write(7, secBlockDump, 16); // Пишем массив в блок 7 if (status != MFRC522::STATUS_OK) < // Если не окэй Serial.println("Write error"); // Выводим ошибку return; >Serial.println("Write OK"); // Завершаем работу с меткой rfid.PICC_HaltA(); rfid.PCD_StopCrypto1(); >
Важно: при повторном поднесении метки мы неизбежно получим ошибку аутентификации, это связано с тем, что стандартный ключ больше не подходит к перенастроенному сектору!
Не забываем сменить “наполнение” ключа в void setup()<> :
for (byte i = 0; i < 6; i++) < // Наполняем ключ key.keyByte[i] = 0xAB; // Пишем свой ключ >
Так же напоминаю, что отныне для сектора 1 (блоков 4…7) мы используем только ключ B, соответственно и команда аутентификации отныне выглядит чуть иначе:
status = rfid.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_B, 7, &key, &(rfid.uid)); if (status != MFRC522::STATUS_OK) < // Если не окэй Serial.println("Auth error"); // Выводим ошибку return; >
Работа с защищенным сектором
Теперь, после того как мы сменили ключи безопасности от сектора 1, в качестве примера будем выводить количество поднесений метки к считывателю в последовательный порт. Количество поднесений хранится в нулевом байте защищенного блока 6 и увеличивается при каждом поднесении:
Инкремент при поднесении
#include #include #define RST_PIN 9 // Пин rfid модуля RST #define SS_PIN 10 // Пин rfid модуля SS MFRC522 rfid(SS_PIN, RST_PIN); // Объект rfid модуля MFRC522::MIFARE_Key key; // Объект ключа MFRC522::StatusCode status; // Объект статуса void setup() < Serial.begin(9600); // Инициализация Serial SPI.begin(); // Инициализация SPI rfid.PCD_Init(); // Инициализация модуля rfid.PCD_SetAntennaGain(rfid.RxGain_max); // Установка усиления антенны rfid.PCD_AntennaOff(); // Перезагружаем антенну rfid.PCD_AntennaOn(); // Включаем антенну for (byte i = 0; i < 6; i++) < // Наполняем ключ B key.keyByte[i] = 0xAB; // Пишем свой ключ >> void loop() < // Занимаемся чем угодно static uint32_t rebootTimer = millis(); // Важный костыль против зависания модуля! if (millis() - rebootTimer >= 1000) < // Таймер с периодом 1000 мс rebootTimer = millis(); // Обновляем таймер digitalWrite(RST_PIN, HIGH); // Сбрасываем модуль delayMicroseconds(2); // Ждем 2 мкс digitalWrite(RST_PIN, LOW); // Отпускаем сброс rfid.PCD_Init(); // Инициализируем заного >if (!rfid.PICC_IsNewCardPresent()) return; // Если новая метка не поднесена - вернуться в начало loop if (!rfid.PICC_ReadCardSerial()) return; // Если метка не читается - вернуться в начало loop /* Аутентификация сектора, указываем блок безопасности #7 и ключ B */ status = rfid.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_B, 7, &key, &(rfid.uid)); if (status != MFRC522::STATUS_OK) < // Если не окэй Serial.println("Auth error"); // Выводим ошибку return; >/* Чтение блока, указываем блок данных #6 */ uint8_t dataBlock[18]; // Буфер uint8_t size = sizeof(dataBlock); // Размер буфера status = rfid.MIFARE_Read(6, dataBlock, &size); // Читаем блок 6 if (status != MFRC522::STATUS_OK) < // Если не окэй Serial.println("Read error"); // Выводим ошибку return; >/* Выводим количество поднесений метки */ Serial.print("Count: "); // Выводим количество Serial.println(dataBlock[0]); // Хранится в нулевом байте массива dataBlock[0]++; // Инкремент /* Запись блока, указываем блок данных #6 */ status = rfid.MIFARE_Write(6, dataBlock, 16); // Пишем массив в блок 6 if (status != MFRC522::STATUS_OK) < // Если не окэй Serial.println("Write error"); // Выводим ошибку return; >rfid.PICC_HaltA(); // Завершаем работу с меткой rfid.PCD_StopCrypto1(); >
Количество поднесений ограничено 255, потому что используется лишь 1 Байт, но для примера это и не важно.
Инкремент и декремент
Наболее продвинутые могут обратить внимание на то, что пример выше не имеет смысла, поскольку метки уже имеют функционал инкремента и декремента, позволяющего использовать защищенный блок в качестве электронного кошелька.
Для реализации данного функционала библиотека имеет методы MIFARE_Increment() и MIFARE_Decrement() , однако независимо от установленных байтов доступа данный функционал не показал работоспособность на десятке меток и нескольких модулях. Возможно всему виной поддельные чипы MFRC522, установленные в модули. В любом случае перечисленные методы возвращают ошибку при поднесении метки, а потому и пример для работы не привожу.
Особенности и костыли
Несмотря на то, что данные модули выпускаются много лет, в течение которых дорабатывалась и библиотека, пара модуль + библиотека имеют критическую проблему зависания (!). Через случайный промежуток времени система просто перестает считывать поднесенные метки – помогает только перезагрузка микроконтроллера. Этот критический баг может сыграть злую шутку, при использовании данного комплекта в электронных замках. Что является причиной? На данный момент достоверного ответа нет… однако есть кое-какие решения!
- Периодическая перезагрузка и повторная инициализация. В главный цикл программы добавляется таймер на millis() с периодом 500…3000 мс, внутри которого производится принудительный сброс и инициализация модуля. Данный код располагается в начале главного цикла программы. Данный костыль является наиболее эффективным в борьбе с зависанием модуля.
static uint32_t rebootTimer = millis(); // Важный костыль против зависания модуля! if (millis() - rebootTimer >= 1000) < // Таймер с периодом 1000 мс rebootTimer = millis(); // Обновляем таймер digitalWrite(RST_PIN, HIGH); // Сбрасываем модуль delayMicroseconds(2); // Ждем 2 мкс digitalWrite(RST_PIN, LOW); // Отпускаем сброс rfid.PCD_Init(); // Инициализируем заного >
rfid.PCD_SetAntennaGain(rfid.RxGain_max); // Установка усиления антенны rfid.PCD_AntennaOff(); // Перезагружаем антенну rfid.PCD_AntennaOn(); // Включаем антенну
if (!rfid.PICC_IsNewCardPresent()) return; // Если новая метка не поднесена - вернуться в начало loop if (!rfid.PICC_ReadCardSerial()) return; // Если метка не читается - вернуться в начало loop
Фокус заключается в добавлении еще одной попытке чтения метки, в случае неудачи. Таким образом наша конструкция принимает следующий вид:
if (!rfid.PICC_IsNewCardPresent()) return; // Если новая метка не поднесена - вернуться в начало loop if (!rfid.PICC_ReadCardSerial()) < // Если метка не читается - пробуем еще раз if (!rfid.PICC_ReadCardSerial()) return; // Все равно не читается - вернуться в начало loop >
Наиболее эффективным и важным является первый костыль, располагайте его перед работой с модулем, желательно в начале цикла void loop()<> , но ни в коем случае не в прерывании таймера. Однако несмотря на то, что приведенные выше хитрости действительно работают и многократно повышают стабильность работы RFID модуля – в случае с электронными замками и прочими системами контроля доступа рекомендуется иметь резервные способы входа, помимо RFID.
RFID-модуль RC522: полное руководство по описанию, подключению и первым шагам в разработке
RFID модуль RC522 – устройство для чтения и записи данных с помощью технологии радиочастотной идентификации (RFID). Этот метод широко применяется в различных областях, где требуется бесконтактная идентификация, контроль доступа, управление запасами и другие подобные задачи. Модули RC522 – популярные узлы, поддерживающие стандарт ISO/IEC 14443 A/MIFARE.
Особенности технологии
По сути, модуль RFID RC522 – считыватель RFID, работающий на частоте 13,56 МГц. Оснащен антенной для обмена данными с метками и микросхемой для обработки информации, в его состав также входит:
- RFID-чип. Обрабатывает сигналы от антенны, декодирует их и взаимодействует с метками. Является основным компонентом.
- Контроллер SPI. Нужен для обмена данными между RFID-чипом и другими устройствами. Использует протокол последовательной связи SPI (Serial Peripheral Interface).
- Сигнальные светодиоды. Узел чаще всего содержит светодиоды, которые индицируют взаимодействие с микроконтроллерами или другими устройствами. Использует радиоволны модуля (например, подключение к питанию).
Для работы с модулем RC522 обычно используют микроконтроллеры (например, RFID модуль Arduino ), которые взаимодействуют с ним через интерфейс. Модуль предоставляет средства для чтения и записи данных на RFID-карты, а также обеспечивает безопасность с помощью методов шифрования и аутентификации, поддерживаемых стандартом ISO/IEC 14443 A/MIFARE.
Принцип работы
Микроконтроллер модуля (узла) инициализирует антенну для генерации радиочастотного поля и обнаружения метки. Когда метка находится в радиусе действия поля, она получает энергию от него и начинает отвечать, передавая свои данные.
Работая, RFID модуль получает данные от метки и декодирует их. При успешном чтении модуль может передать эту информацию другим устройствам. При необходимости он отправляет данные на метку, записывая информацию на нее.
Первые шаги в разработке
Перед началом работы с модулем RC522 необходимо установить библиотеку. При RFID модуль «Ардуино» – это библиотека, предоставляющая удобный интерфейс для дальнейшей работы с модулем. После подключения и инициализации узла вы можете выполнять такие задачи, как чтение уникального идентификатора метки, запись и чтение данных.
Подключение RC522
Для подключения модуля RC522 к платформе, такой как Arduino или Raspberry Pi, вам потребуются следующие соединения:
- VCC – подключение к источнику питания (обычно 3,3 V);
- RST – к пину, который используется для сброса модуля;
- GND – к земле;
- IRQ – необязательное подключение к пину прерывания;
- MISO, MOSI, SCK – к соответствующим пинам для обмена данными по SPI;
- SDA (SS) – к пину выбора рабочего устройства.
Область применения модуля многогранна. Он позволяет управлять доступом через бесконтактные карты или браслеты, что облегчает пользование, усиливает безопасность. Используется в таких сферах:
- В общественном транспорте при бесконтактной оплате – быстрая и удобная оплата проезда.
- В системе умного дома – управление дверными замками, освещением, системами безопасности.
- Аутентификация – обеспечение безопасности данных и доступа к системам.
- Логистика и транспорт – отслеживание грузов и контроль доступа на транспортных узлах, что способствует оптимизации логистических процессов.
- Медицинская идентификация – учет пациентов и медицинского оборудования.
- Образование – отслеживание посещаемости студентов и упрощение процесса регистрации.
- Промышленность – дополнительный компонент системы автоматизации и контроля доступа персонала в опасные зоны.
RFID модуль, купить который вы можете в нашей компании, позволяет реализовать функциональность бесконтактного чтения и записи данных. Оно находит широкое применение в различных системах автоматизации и идентификации, интегрируя соответствующие технологии в ваши проекты.
Независимо от того, нужен вам контроль доступа или управление инвентарем, RFID-считыватель RC522 может быть надежным решением для ваших потребностей.