RFID запись.
Третий урок из цикла «Всё про RFID».
Сегодня мы продолжим изучать RFID считыватель на базе микросхемы RC522.
В первой части была теория, во второй мы сделали электронный rfid замок с доступом по карте или брелоку. Теперь настала очередь рассмотреть запись на карту.
Давайте представим, что мы некое предприятие и у нас есть группа сотрудников и нам надо выпустить именные карты для допуска этих сотрудников в офис.
В этом уроке мы научимся писать на карту свою фамилию и имя, номер офиса, а в следующем уроке добавим время прихода и ухода.
Чтение и запись rfid меток не сложный процесс. Надо просто понять принцип и знать структуру rfid карты, а с модулем RFID RC522 и Ардуино – это вообще просто, так как большинство функций прописано в библиотеке MFRC522.h.
Rfid карта состоит из секторов и блоков, подробнее смотрите урок 1.
Сначала посмотрим, как подключить модуль считывания RC522 к Ардуино. Для тех, кто смотрел предыдущий урок и не поленился собрать свой замок мои поздравления. Напишите кто собрал замок.
Объяснять схему не буду, и так всё понятно. Если что не понятно пишите в комментариях.

Сначала посмотрим, что получилось, а потом рассмотрим скетч.
Сначала давайте посмотрим дамп карты. Для этого загружаем из скетч dumpinfo.
Прикладываем карту к считывателю и ждём пока не считаются все данные.
Нас интересуют сектора 1 и 2.
В нулевом блоке хранится служебная информация. Эта информация не перезаписываемая и прошита производителем. По крайней мере на картах которые идут в комплекте с модулем. Существуют карты где и эту информацию можно перезаписывать.
В первых 4 байтах находится серийный номер карты, а в оставшихся байтах информация о производителе.
В первом блоке сейчас находятся нули, это говорит о том что там нет информации. Её также нет и во втором и четвёртом блоке. Эти блоки мы будем использовать для записи и хранения нашей информации.
Сначала запускаем Пример 1.
Нас просят поднести карту для считывания.
Что же, давайте так и сделаем.
Дождёмся окончания.
Что мы здесь видим, точнее, увижу только я, так как у вас пока чистая карта и вы ничего не увидите, ну кроме НОМЕРА КАРТЫ.
- В сектор 1 у меня записана ФАМИЛИЯ.
- В секторе 2 ИМЯ
- Третий сектор использовать нельзя, так как это трейлер.
- А в четвёртом секторе НОМЕР КАБИНЕТА.
Давайте рассмотрим скетч.
Как подключен модуль rc522 я рассказывать не буду. Давайте сразу перейдём к считыванию секторов.
В самом начале мы должны проверить ключ карты и если он совпадает, то продолжаем работу.
По умолчанию для новой карты ключ равен FFFFFF.
Потом ждём пока не появится новая карта.
Выводим номер КАРТЫ в шестнадцатеричной системе. С этим всё понятно из предыдущего урока.
Код для вывода фамилии, имени и кабинета одинаков.
Меняется только номер блока. Поэтому я расскажу только про фамилию.
- Создаём массив – буфер — для хранения значений.
- Указываем номер блока.
- Затем в статус загружаем разные значения.
Такие как — Ключ карты, номер блока, UID карты.
Если всё правильно то можно работать дальше, а если нет, то выскочит ошибка и скетч прекратит работу.
Дальше мы в цикле выводим все 16 байт из блока.
И так со всеми блоками, то есть с блоками 1, 2 и 4.
Со считыванием разобрались, теперь давайте разбираться с записью.
Загружаем скетч Пример 2.
Поднести карту.
Кстати там есть ограничение на время ожидания ввода текста. Я установил 60 секунд.
Сначала вводим ФАМИЛИЮ и символ «решётка». Этот символ даёт знать, что ввод окончен и надо обработать текст. Нажимаем ENTER.
Затем вводим ИМЯ и снова вводим решётку и нажимаем ENTER.
Теперь вводим номер кабинета, решётку и ENTER.
И если после каждого ввода у вас не было ошибок и вы видите надпись УБЕРИТЕ КАРТУ, то значит всё прошло хорошо, и теперь можно перейти к ПРИМЕРУ 1 и считать ваши записи с карты.
Записывать на карту можно до 200 тыс. раз, так что можете тренироваться и не ограничивать себя.
Ну вот и всё. Всё работает. И как всегда в конце урока я прошу вас поставить лайк этому видео если оно вам понравилось. И жду ваших комментариев.
Следующее видео будет про копирование и клонирование карт.
И чем больше ваших положительных отзывов, тем быстрее оно выйдет.
До встречи в следующих уроках.
Как и обещал, хочу рассказать про русский шрифт. Если вы будете делать записи на латинице, то в каждом блоке вы можете сохранить до 16 символов. А вот если вы будете писать на кириллице, то всего лишь 8 букв.
Это потому, что для хранения будут использован формат Unicode , а он требует для хранения 2 байта.
Постскриптум.
Я ещё написал код для очистки блоков карт. Правда, это только набросок, но он вполне рабочий.
Эмулятор RFID

RFID (англ. Radio Frequency IDentification, радиочастотная идентификация) — имеет достаточно широкий частотный диапазон и достаточно большое количество различных стандартов, которые так или иначе применимы к данной технологии. Для справки: используются частоты: 125-135кГц, 400 кГц, 6.78МГц, 13.56МГц (карты метро и банковские карты), 27.125МГц, 40.68 МГц, 433.29 МГц, 869 МГц, 915 МГц, 2.45 ГГц, 5.8 ГГц и 24.125ГГц. Как видно частотный диапазон очень широкий.
Мы же будем говорить о самых распространённых и наименее защищённых картах частотного диапазона 125 кГц. Я разберу стандарт EM Marine 4102, так как именно с ним лучше всего знаком. Однако код эмулятора позволяет работать и с другими стандартами, работающими на частоте 125 кГц.
Чтобы мы могли дальше углубиться в теорию, следует рассказать пару слов о принципе работы RFID. Далее в тексте будет приводиться информация, относящаяся к стандарту 125 кГц EM Marine, прочие RFID решения устроены подобным образом.

Считыватель, кроме информационного обмена осуществляет подачу питания. Метка из себя представляет ПЗУ, которое питается от электромагнитного поля, и после подачи питания просто отдаёт записанную информацию.

Из этой схемы хорошо видно, как устроен передатчик и приёмник. Оба колебательных контура настроены в резонанс и используются для передачи данных и передачи энергии, для питания пассивной метки, в роли которой выступает наша карта.
Более детально о принципе работы можно прочитать в [1]

Внутренности разобранной карты
Если разобрать карту, то можно увидеть антенну в виде катушки и чип залитый компаундом, в котором находится ПЗУ и конденсатор ёмкостью 75 пФ.
Описание протокола EM4102
Прежде, чем мы пойдём дальше, давайте разберёмся со стандартом EM4102, который мы будем эмулировать. EM4102 совместимая RFID-метка содержит 64 бита памяти только для чтения. По сути — это и есть ПЗУ, то есть информация может быть считана из неё, но не может быть изменена либо записана, проще говоря этот чип единожды прошивается на заводе. Структуру памяти метки можно посмотреть на рисунке ниже.

Когда метка попадает в электромагнитное поле, излучаемое считывателем RFID, она получает энергию от поля (питание) и начинает передачу данных. Первые 9 битов – это логическая единица. Эти биты используются как последовательность маркеров для обозначения начала передачи. Поскольку во всех остальных данных используется контроль чётности, эта девятибитная последовательность единиц больше не встретится ни в каком другом месте. Далее идут 10 групп по 4 бита данных и 1 бит чётности на каждую группу. Наконец, есть 4 бита контрольной суммы и последний стоповый бит, который всегда равен нулю.
Метка повторяет цикл передачи данных, пока на неё приходит питание. Поэтому мы на ридере наблюдаем постоянное считывание метки.
Приведу пример данных, которые передаёт метка с номером: 0x06 — номер версии, и 0x001259E3 — данные.

Кстати, номер, напечатанный на карте можно перевести в hex-номер, который получит считыватель. Например, на карте записан номер: 116,23152
- 116 в десятичной системе счисления – это 0x74 в шестадцатиричной;
- 23152 в десятичной – это 0x5A70 в шестнадцатиричной;
Модуляция сигнала
Передача данных от метки до считывателя осуществляется с помощью модуляции несущего сигнала считывателя (в нашем случае несущей частоты 125 кГц). Обратите внимание, что от этой несущей частоты идёт и питание и ей же осуществляется модуляция сигнала. Для начала рассмотрим упрощённую схему взаимодействия считывателя и метки. Запомните эту картинку, мы ещё будем к ней обращаться.

Как видно у метки есть колебательный контур LC, диод, служащий для выпрямления переменного тока, конденсатор для сглаживания пульсаций (это часть питания метки), и транзистор, управляя которым мы можем модулировать сигнал. На считывателе это будет отражаться в изменении тока протекающего в катушке. Проще говоря, при попадании в поле считывателя, метка потребляет электрический ток (примерно постоянно), при передаче информации она транзистором изменяет значение потребляемого тока и таким образом считыватель может получить сигнал, измеряя потребляемую мощность.
Считыватель генерирует магнитное поле, с помощью модулятора и катушки и снимает промодулированный сигнал, затем декодирует его.

Пример модуляции несущего сигнала
Если я вас окончательно не запутал, то едем дальше. Для того чтобы передать данные, нам необходимо модулировать сигнал. То есть на несущую частоту наложит биты передаваемой информации.
По стандарту RFID есть три популярных схемы модуляции:
- Манчестер код
- Двухфазный манчестер код
- Кодирование фазовым сдвигом

При таком кодировании метка изменяет уровень передачи сигнала строго в середине периода передачи одного бита. Переход от низкого к высокому уровню в эти моменты означает состояние логической «1», а переход от высокого уровня к низкому, представляет состояние логического «0».

Реальный промодулированный сигнал, снятый на катушке считывателя.
Делаем RFID-эмулятор
Ну что же, если вы ещё здесь и голова не опухла, от таких выкладок, то пришла пора делать RFID-эмулятор, всего из двух деталей. В этой простоте кроется гениальность. Устройство я собрал, позаимствовав идею и код у Micah Dowty, фотографии мои.

Вот такой миниатюрный таракан, вполне может эмулировать метку
Сайт проекта . Код очень интересен, можно сказать гениален и лаконичен (используется ассемблер). Остановимся на нём подробно. Его мы и разберём. Ознакомиться с кодом можно вот тут.
Для начала разберёмся, как же эта штука вообще функционирует, хотя по определению работать не должна, так как противоречит привычной схеме подключения микроконтроллера. Схема устройства взята из исходного кода.

Катушка индуктивности около 1 мкГн и микроконтроллер ATtiny85
Вот это дамы и господа и есть настоящее Хакерство, когда уровень понимания особенностей работы оборудования позволяет создавать технические решения, выходящие за рамки, обозначенные производителем! И это работает, проверено лично. Вот истинное значение слова «хакер», это не про взлом и воровство.
Забегая вперёд скажу, что данной катушки для нормальной работы недостаточно, и всё же пришлось cделать нормальную антенну, повесить конденсаторы по питанию, резонансный конденсатор. Но вот для демонстрации принципов работы вполне подойдёт.
Как же это работает:
- Катушка фактически питает микроконтроллер AVR через контакты ввода/вывода. Каждый такой контроллер имеет диоды на портах ввода/вывода, которые предотвращает повышение напряжения на этом выводе выше напряжения питания микросхемы или опускание уровня сигнала ниже уровня земли. Они используются также для предотвращения статического пробоя, который приводит к выходу из строя микросхемы. При поднесении катушки к считывателю, в ней наводится ЭДС равная нескольким вольтам. Когда напряжение на катушке превышает напряжение питания контроллера, то часть этой энергии через эти ограничивающие диоды передаются к шине питания микросхемы. В результате получается, что микроконтроллер получает питание. А верх и низ синусоидальной волны усекается, и сигнал становится более похож на прямоугольный меандр.
- Фильтрация питания с использованием ёмкости кристалла AVR. Обычно, когда ставят микросхему, то ставят конденсаторы по питанию, для фильтрации помех (обычно 0,1 мкФ керамику и электролит параллельно). В данном решении фильтрация осуществляется только внутренней ёмкостью шин питания в кремниевом кристалле микроконтроллера AVR. Она небольшая, но даже её достаточно для стабильного питания и работы, при питании от импульсов с частотой 125кГц!
- Работа осуществляется при очень низком напряжении. Микроконтроллер ATtiny85 предназначен для работы при напряжении всего 2,5 В. Существует версия с расширенным диапазоном напряжений до 1,8 В. При этих напряжениях обычные тактовые генераторы AVR не работают, но этого можно избежать применив следующий хак.
- Катушка индуктивности применяется не только для питания микросхемы, но ещё и для тактирования микроконтроллера! Выше мы говорили, что получаем прямоугольную волну, которая остаётся после того как ограничивающие диоды забрали немного энергии. Эта форма волны является входом Clock нашего микроконтроллера! И весь код работает на частоте 125 кГц, синхронно с несущей частотой считывателя RFID. Это гениально, ребята!
- Прошивка? На таких низких скоростях микропрограммное обеспечение микросхемы больше похоже на последовательность операций ввода-вывода, выполняемых синхронно с каждым тактовым циклом несущей. Но остается много лишних циклов. В протоколе EM4102 вы потенциально можете выполнить некоторую полезную работу с 32 тактовыми циклами между каждым битом. Однако с протоколом HID вам необходимо выводить фронт FSK каждые 4 тактовых цикла. В результате прошивка на RFID-метке крайне тупая. «Исходный код» на самом деле представляет собой просто набор причудливых макросов ассемблера, которые преобразуют код метки RFID в длинную последовательность инструкций ввода-вывода.
Прежде чем мы пойдём разбирать код данного эмулятора давайте сделаем ему нормальную антенну. Мои эксперименты с текущей схемотехникой выявили крайнюю нестабильность её работы. Она работает только совсем рядом со считывателем и то не всегда. Поэтому сначала я припаял конденсатор 0,1 мкФ на ножки питания контроллера, а потом решил сделать настоящий большой колебательный контур, как в настоящей метке.

Первая модификация — конденсатор 0,1 мкФ по питанию
Создание антенны
Никаких хитростей в создании катушечной антенны нет, но всё же необходимо ознакомиться с документацией и понимать физику процесса… Это не сложно, и справится даже школьник, требуется только немного терпения и усидчивости.
Собрать и настроить антенну очень просто, прямо как в картинке из [1].


Параллельный колебательный контур
Если оставить всю математику и перейти к сути, у колебательного контура есть такой параметр, как резонансная частота, которая определяется по формуле.
Где f — частота колебаний, L — индуктивность катушки, C — ёмкость конденсатора.
В данном случае у нас есть фиксированный параметр — частота, а с ёмкостью и индуктивностью мы можем играться. Для того чтобы рассчитать катушку, воспользуемся документом [2]. Все кто хоть как-то собираются делать антенны для RFID меток (любых частот), обязаны с ним ознакомиться!
Многие умельцы, как для ридеров, так и для эмуляторов (суть не важна) делают круглые катушки. Их проще считать и изготавливать, но они имеют существенный недостаток — их линейные размеры больше карточки. Я хочу изготовить катушку индуктивности в форме прямоугольника, с линейными размерами меньше размеров стандартной карты и, чтобы результирующее устройство было размером со стандартную карту RFID. В результате выбираю размер будущей катушки индуктивности практически такой же, как стоит в настоящей метке, то есть примерно 70х40 мм. Если конденсатор выбрать 10 нФ, то индуктивность катушки (из формулы выше), должна составлять у нас 162 мкГн. Теперь смотрим в документацию по расчёту прямоугольной катушки. Для намотки катушки выбрал провод сечением 0,2 мм. В результате открываем соответствующий раздел документации, и нашему взору представляется следующая славная формула.

Как видим параметры толщины и ширины катушки у нас неизвестные и изменяемые (упираются в толщину провода 0,2 мм), но общие прикидки мне дали цифру в 42 витка. Можно было бы сделать несколько итераций, и сделать прям точный-точный расчёт, но в нашем штучном случае, и так сойдёт.
После чего, необходимо изготовить каркас 70х40 мм для намотки катушки. Его я изготовил из текстолита и на него намотал катушку.

Каркас из текстолита


Намотка и готовая катушка
К сожалению, измерителя индуктивности у меня нет, поэтому пришлось действовать далее методом научного тыка. Поскольку я наверняка ошибся в расчётах, и в количестве витков, когда наматывал катушку, так как делал их приблизительно и на глаз, то я решил подобрать резонансную ёмкость вручную. Для этого закрепил катушку на картридере, воткнул её концы в макетную плату (“матрац с дырками”), затем начал поочерёдно подключать ёмкости, при этом регистрируя сигнал на осциллографе.

Начнём подбор резонансного конденсатора
Сначала я проверил конденсатор емкостью 10 нФ, который должен быть резонансным. Но амплитуда сигнала сразу просела, по сравнению с пустой катушкой. Тогда я взял конденсатор меньшего номинала. И так перебирал конденсаторы, пока не поймал резонанс. Таким образом резонансная ёмкость конденсатора составила 3,2 нФ.

Сигнал без конденсатора, пустая катушка

Сигнал 10 нФ


3 нФ, 4 нФ, 2,2 нФ

Видно, что пробовал разные варианты, и было ясно что максимум лежит где-то между 3 и 4 нФ и результатом стал конденсатор 3,2 нФ (состоящий из двух конденсаторов в параллели). Всё, наша катушка готова к дальнейшим опытам.
Вообще, хочу заметить, что катушку можно сделать вообще в виде дорожек на печатной плате, и при небольшой серии изделий так и стоит делать. Вот, пример такой платы, именно на 125 кГц от Alexander Guthmann. К сожалению, сайт практически умер, а автор давно не выходит на связь, так что довольствуемся только моими фото. Если кто поможет его найти, буду признателен! Не знаю что с ним случилось.

Таким образом, делать эмулятор сразу в виде печатной платы — нет никаких проблем. Думаю имея руководство [2], сможете рассчитать такое самостоятельно, раз это смог сделать четырнадцатилетний немецкий школьник.
Пробежимся по коду
Давайте кратенько пробежимся по коду, который можно посмотреть вот тут. Там пример эмуляции двух типов карт, я разберу только EM4102.
Перво-наперво, как гласит код, нам при прошивке микроконтроллера надо прошить fuse-биты в значение lfuse to 0xC0: таким образом, чтобы контроллер тактировался от внешнего генератора. Обращаю внимание, что любая перепрошивка контроллера будет сопряжена с тем, что его надо будет тактировать от внешнего источника, так как мы устанавливаем fuse биты с генерацией от внешнего генератора!
Весь код основан на макросах. Напомню, что такое макросы — это программа, которая подготавливает код к компиляции. Наша программа состоит всего из нескольких ассемблеровских инструкций: rjmp, call (2 такта), nop, ldi, out и ret (все по 1 такту)! Всё, весь остальной код формируется макросами в зависимости от макроса серийного номера (дефайна). Особенность работы в том, что у нас достаточно мало тактов для нормальной работы. Попробуй успей за 32 такта сделать что-то, учитывая что инструкции перехода в контроллере AVR занимают 2 такта. Поэтому весь код генерируют макросы в зависимости от ID-карты.
Дефайнами задаём какой тип карты мы эмулируем и задаём ID-карты. Это главный макрос, на основании которого и формируется остальной код. И, тадам, его величество макросы.
Макрос задержки, принимает на вход количество тактов задержки. Достаточно очевидный рекурсивный макрос, осуществляет задержку с помощью команды nop (нет операции, 1 такт) и команды rjmp .+0 (перейти на следующую строку, 2 такта). Комбинируя эти команды между собой, можно сделать задержку нужной длинны в тактах. По сути код ничего не делает, только тратит машинное время.
Если вы ещё соображаете, то дальше я вам совсем изнасилую мозг, но код так гениален что вам придётся потерпеть.
Рекурсивный макрос кодирования манчестер-кодом.
Собственно тут и осуществляется вся логика. Принимает на вход битовую маску и счётчик битов. Если счётчик не нуль, то вызываем ещё раз сами себя, декрементируя счётчик (рекурсивный макрос, ага). Далее в самом теле идут вызовы макросов baseband_0, baseband_1 и baseband_1_last. В зависимости от того, какой бит у нас “1” или “0”, мы модулируем сигнал манчестер кода с нуля на единицу или с единицы на нуль.
Помните выше я приводил таблицу в статье, как идёт кодирование содержимого карты, где идут биты чётности, и стоп биты в конце. Так вот, наша задача теперь ID-метки закодировать этим методом, для этого у нас существуют два макроса.
ROW_PARITY — расчёт бита чётности в строке из четырёх бит, COLUMN_PARITY — расчёт контрольной суммы всей посылки.
Вся логика работы у нас описывается в макросе в .main
Ну то есть, так же точно передаём заголовочные 9 бит, потом манчестер кодинг, высчитывая бит чётности для каждых 4-х бит, в конце контрольная сумма и стоп бит.
Осталось разобраться, что же такое baseband. Для этого у нас служат ещё одни макросы обёртки (да сколько можно-то, а?).
Макросы baseband* — выполняют ассемблеровский код: вызывают соответствующие функции, и потом делают переход на другую команду. Макрос baseband_1_last — аналогична макросу baseband_1, кроме того что делает безусловный переход не на команду ниже, а в начало функции main. Макрос header — служит для вывода заголовка из девяти однотипных бит равных единице, и вызывает макрос манчестера с передачей числа и количества передаваемых бит.
Последнее, что осталось разобрать — это функции baseband30_0 и baseband30_1. Они описываются следующим кодом.
В зависимости от того, какая функция вызывается baseband30_0 или baseband30_1 в регистр r16 записывается значение того что должно быть на пине ввода/вывода: 1 или 0. После этого идёт безусловный переход на baseband30 осуществляется вывод и задержка на 19 тактов, после чего идёт возврат.
Самая большая магия этого кода, что он просчитан точно до каждого такта, каждый такт передачи манчестерского кода занимает ровно столько периодов, сколько допустимо стандартом, а именно 32 такта процессора! Это фантастически гениально, надо помнить сколько тактов занимает каждая команда.
Давайте его скорее скомпилируем и посмотрим как он выглядит, как развернутся все эти макросы. Компилируем командой make (предварительно установив avr-gcc) и дизассемблируем получившийся elf-файл
Вначале у нас вектора прерываний, но нас интересует только первый jump. Так как остальные вектора никуда не ведут.
Здесь мы настраиваем порты ввода/вывода, и вызываем функцию main. A main состоит из безумного количества вызовов функций baseband30* и jump (так развернулся наша адский цирк макросов).
И так далее… пока не джампнемся снова на main
Ну и глянем как же выглядит наш baseband модуль.
В конце видно как delay развернулся в список jump и nop для задержки. Вот такая красивая магия.
Ну что же, с кодом разобрались. Соберите вытекший мозг с ушей, переходим к испытаниям.
Испытания
Применим все полученные знания и проведём испытания. Компилируем прошивку, прошиваем контроллер, не забывая правильно выставить Fuse-биты.

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

Испытательный стенд
И, о чудо! Оно работает, корректно считывается и в цикле даёт корректный ID! Без внешнего питания, с работой только от поля. Осталось всё это привести в порядок и сделать настоящую RFID-метку.

Окончательный “заламинированный” вариант метки
Итого
Могу честно признаться, что до конца не верил, что это заработает. Питание от поля, нестандартные режимы работы контроллера, работа строго по тактам, самодельная катушка индуктивности. Плюс ещё работа самого RFID. И вот, вроде плёвая поделка растекается на пару месяцев чтения документации и разбора полётов. Но это работает, и эта штука по-настоящему гениальна. Так что ребята, вот такие штуки и есть настоящее хакерство. Дерзайте!
Домашнее задание
Раз вы всё-таки прочитали эту крутую статью, я её писал, старался, делал, теперь пора и вам что-то попробовать сделать. В коде эмулятора есть раздел, который эмулирует карты стандарта HID Proximity, с кодированием фазовым сдвигом. Вам в качестве развлечения и лучшего усвоения материала следует разобраться со стандартом HID и этим кодированием. Решение присылайте в комментарии. Удачи.
Работа с 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:
- Контакты модуля 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 конфигурация блока безопасности заблокирует еще и настройки доступа к блокам данных!
В итоге 3 байта настроек доступа приняли следующие значения: 0x7F 0x07 0x88, байт USER может быть любой.

Начало работы
Работу с RFID модулем удобнее всего производить в конце главного цикла программы, сейчас поймете почему. Для отслеживания поднесенной метки библиотека предлагает использовать пару методов с замысловатыми названиями:
Если поднесенная метка успешно считана – программа идет дальше, в противном случае происходит возврат в начало главного цикла, а весь блок кода связанный с RFID пропускается.
В итоге наш скетч имеет следующую структуру:
Теперь давайте идти по порядку, осваивая основные методы для работы с RFID.
Чтение UID
Самое простое, что можно сделать с RFID меткой – прочитать UID, в некоторых системах уже этого функционала вполне достаточно, например – в простых электронных замках. Как уже сказано ранее, некоторые метки позволяют сменить UID, в свою очередь запретить считать UID из ваших меток не получится – учтите это при разработке.
Так или иначе пример чтения UID и вывод в порт приведен ниже:
Чтение блока
Если чтением UID ваш интерес не ограничился – давайте узнаем, как читать блок данных из метки. Прежде чем что-либо читать или писать, необходимо аутентифицировать (разблокировать) сектор, в котором находится интересующий нас блок.

В примерах ниже будем работать с блоком под номером 6 (сектор 1), за первый сектор и соответственно блоки 4, 5 и 6 отвечает блок безопасности под номером 7. То есть запомнили – блок данных 6, блок безопасности 7.
Аутентификацию сектора производит метод PCD_Authenticate() , по умолчанию все манипуляции с меткой возможны при помощи ключа A, а сам процесс аутентификации выглядит следующим образом:
Обратите внимание на …KEY_A в первом аргументе и цифру 7 вторым аргументом – это и есть номер блока безопасности. Отслеживать статус не обязательно, но крайне желательно.
После успешной аутентификации можно свободно манипулировать разблокированным сектором, в нашем случае будем читать содержимое методом MIFARE_Read() . Читать нужно в байтовый массив, размером 18 (!) байт, чтение происходит из блока 6 (первый аргумент) и выглядит так:
Важно: Не смотря на то, что блоки имеют размер 16 байт, буферный массив создается на 18 байт, а количество байт на чтение передается именно в виде указателя на переменную. В противном случае чтение закончится ошибкой, примите это как факт.
В случае успешного чтения, выведем содержимое блока 6 в монитор порта, все как обычно:
А завершать работу с меткой нужно при помощи еще двух замысловатых методов:
В итоге полный скетч для чтения блока 6 из новой метки со стандартными ключами выглядит так:
После поднесения метки в мониторе порта должны отобразиться 16 байт – содержимое прочитанного блока.
Запись блока
При записи все 16 байт записываются в блок единовременно, для чего должен быть заранее подготовлен байтовый массив на 16 Байт, например такой:
Как в случае и с чтением, сектор в котором находится нужный блок 6 нужно предварительно аутентифицировать, об этом уже сказано выше, так что переходим непосредственно к записи. Запись производится методом MIFARE_Write() , в отличии от MIFARE_Read() тут все несколько проще – указываем записываемый блок, массив и число 16 (количество байт на запись):
Итоговый скетч записи массива в блок 6 выглядит так:
После поднесения метки в мониторе порта должно отобразиться сообщение “Write OK“.
К слову ничто не мешает нам объеденить запись и чтение в одном скетче:
Смена ключей безопасности и настройка блоков
Если вы хотите не только уметь читать и писать данные в метки, но и защить хранящуюся там информацию от стороннего вмешательства – необходимо сменить ключи доступа как минимум от тех секторов, в которых вы собираетесь хранить данные, однако в идеале установить новые ключи для всех секторов, чтобы усложнить задачу потенциальным взломащикам.
Для того, чтобы изменить ключи доступа к сектору, необходимо перезаписать блок безопасности, ответственный за данный сектор. В наших примерах фигурировал блок данных под номером 6 и соответственно блок безопасности под номером 7. Задача по смене ключей безопасности сводится к следующим шагам:
- Создать байтовый массив на 16 ячеек, включающий:
- Ключ A
- Байты настроек доступа
- Ключ B
- Провести аутентификацию выбранного сектора, пока что используя стандартный ключ 0xFFFFFFFFFFFF
- Произвести запись подготовленного массива в блок безопасности, в точности так же, как в случае с обычным блоком.
После этого ключи безопасности будут изменены, а мы сможем безопасно хранить данные в одном или нескольких блоках выбранного сектора! Сейчас покажу по шагам.
- Для создания образа блока безопасности (содержимого массива) придется вернуться вверх по тексту и вспомнить, что при выбранных нами настройках сектора, байты доступа получили значения 0x7F 0x07 0x88. Осталось придумать ключи доступа, имеющие длину 6 байт. Я буду использовать ключ 0xABABABABABAB, данный ключ не является безопасным и подходит исключительно для демонстрации! Так же напоминаю, что ключи A и B будут идентичны, однако использоваться будет только ключ B.

-
1 После того, как мы определились с настройками сектора (“Access Bits“) и ключами безопасности – создаем нужный байтовый массив:
Итоговый скетч записи новых ключей и настроек доступа:
Не забываем сменить “наполнение” ключа в void setup()<> :
Так же напоминаю, что отныне для сектора 1 (блоков 4…7) мы используем только ключ B, соответственно и команда аутентификации отныне выглядит чуть иначе:
Работа с защищенным сектором
Теперь, после того как мы сменили ключи безопасности от сектора 1, в качестве примера будем выводить количество поднесений метки к считывателю в последовательный порт. Количество поднесений хранится в нулевом байте защищенного блока 6 и увеличивается при каждом поднесении:
Количество поднесений ограничено 255, потому что используется лишь 1 Байт, но для примера это и не важно.
Инкремент и декремент
Наболее продвинутые могут обратить внимание на то, что пример выше не имеет смысла, поскольку метки уже имеют функционал инкремента и декремента, позволяющего использовать защищенный блок в качестве электронного кошелька.
Для реализации данного функционала библиотека имеет методы MIFARE_Increment() и MIFARE_Decrement() , однако независимо от установленных байтов доступа данный функционал не показал работоспособность на десятке меток и нескольких модулях. Возможно всему виной поддельные чипы MFRC522, установленные в модули. В любом случае перечисленные методы возвращают ошибку при поднесении метки, а потому и пример для работы не привожу.
Особенности и костыли
- Периодическая перезагрузка и повторная инициализация. В главный цикл программы добавляется таймер на millis() с периодом 500…3000 мс, внутри которого производится принудительный сброс и инициализация модуля. Данный код располагается в начале главного цикла программы. Данный костыль является наиболее эффективным в борьбе с зависанием модуля.
- Принудительная установка усиления и перезагрузка антенны. Полезность сомнительная, однако по некоторым заявлениям библиотека не всегда корректно настраивает антенну после инициализации модуля. Решается добавлением соответствующих строк помимо инициализации модуля в функции void setup()<> :
- Повторное чтение или второй шанс. В примерах выше мы использовали следующую конструкцию для отслеживания поднесенной метки:
Фокус заключается в добавлении еще одной попытке чтения метки, в случае неудачи. Таким образом наша конструкция принимает следующий вид:
Наиболее эффективным и важным является первый костыль, располагайте его перед работой с модулем, желательно в начале цикла void loop()<> , но ни в коем случае не в прерывании таймера. Однако несмотря на то, что приведенные выше хитрости действительно работают и многократно повышают стабильность работы RFID модуля – в случае с электронными замками и прочими системами контроля доступа рекомендуется иметь резервные способы входа, помимо RFID.
Чтение и запись RFID меток. Модуль RC522 для Arduino.
Сегодня я расскажу про RFID модуль RC522, на базе чипа MFRC522. Питание 3.3В, дальность обнаружения до 6см. Предназначен для чтения и записи RFID меток с частотой 13.56 МГц. Частота в данном случае очень важна, так как RFID метки существуют в трех частотных диапазонах:
- Метки диапазона LF (125—134 кГц)
- Метки диапазона HF (13,56 МГц)
- Метки диапазона UHF (860—960 МГц)
Конкретно этот модуль работает с метками диапазона HF, в частности с протоколом MIFARE.
Для работы с модулем можно использовать стандартную библиотеку RFID входящую в Arduino IDE, однако есть и другая библиотека, написанная специально под данный модуль — MFRC522 (1 Мб). Обе библиотеки вполне удобны, однако в MFRC522 больше специальных функций, позволяющих максимально сократить итоговый код программы.
Подключение
Некоторые столкнуться с проблемой — название пинов в большинстве уроков и руководств может не соответствовать распиновке на вашем модуле. Если в скетчах указан пин SS, а на вашем модуле его нет, то скорее всего он помечен как SDA. Ниже я приведу таблицу подключения модуля для самых распространенных плат.
Arduino Leonardo/ Micro
Пины управления SS(SDA) и RST задаются в скетче, так что если ваша плата отличается от той, что я буду использовать в своих примерах, а использую я UNO R3, указывайте пины из таблицы в начале скетча:
Пример №1: Считывание номера карты
Рассмотрим пример из библиотеки RFID — cardRead. Он не выдает данные из карты, а только ее номер, чего обычно бывает достаточно для многих задач.
Скетч залился, светодиод питания на модуле загорелся, но модуль не реагирует на карту? Не стоит паниковать, или бежать искать "правильные" примеры работы. Скорее всего, на одном из пинов просто нет контакта — отверстия на плате немного больше чем толщина перемычки, так что стоит попробовать их переставить. На плате не горит светодиод? Попробуйте переставить перемычку, ведующую в 3.3В, и убедитесь, что на плате она подключена именно к 3.3В, подача питания в 5В может вашу плату запросто убить.
Допустим, все у вас заработало. Тогда, считывая модулем RFID метки, в мониторе последовательного порта увидим следующее:
Здесь я считывал 3 разных метки, и как видно все 3 он успешно считал.
Пример №2: Считывание данных с карты
Рассмотрим более проработанный вариант — будет считывать не только номер карты, но и все доступные для считывания данные. На этот раз возьмем пример из библиотеки MFRC522 — DumpInfo.
Если предыдущий пример работал без ошибок, то и в этом проблем возникнуть не должно. Хотя, проездной на метро, без проблем выдававший номер карты в предыдущем примере, в этом оказался с неопределяемым типом данных, и модуль ничего кроме номера карты считать не смог.
Как результат, считав данные с карты, получим ее тип, идентификатор, и данные из 16 секторов памяти. Следует отметить, что карты стандарта MIFARE 1K состоят из 16 секторов, каждый сектор состоит из 4 блоков, а каждый блок содержит 16 байт данных.
Пример №3: Запись нового идентификатора на карту
В этом примере мы рассмотрим смену идентификатора карты (UID). Важно знать, что далеко не все карты поддерживают смену идентификатора. Карта может быть перезаписываемой, но это означает лишь перезаписываемость данных. К сожалению, те карты, которые были у меня на руках, перезапись UID не поддерживали, но код скетча я здесь на всякий случай приведу.
Пример №4: Запись данных на карту
Вот и наконец то, до чего мы так долго добирались — запись данных на карту. Самая "сладкая" часть работы с модулем — возможность сделать копию уже существующей карты, что то добавить или изменить, это гораздо интереснее, чем простое считывание.
Изменим один из блоков данных на карте:
И как результат, получаем карту с измененным блоком данных:
Теперь, научившись считывать и записывать блоки данных карты, вы можете поэксперементировать с метками, которые скорее всего есть у вас — пропуски, проездные общественного транспорта. Попробуйте считывать и записывать данные с этих карт, пара дубликатов пропуска никогда не помешает, так ведь?)
На этом все, подписывайтесь, и следите за публикациями. В следующий раз я расскажу и покажу, как на стандартный символьный дисплей 1602 добавлять пользовательские символы, фактически добавляя на дисплей графику.
