
ODNFC-RS485 Modbus — руководство
NFC/RFID считыватель-контроллер с интерфейсом RS485 Modbus: подключение, карта регистров, тестирование через mbpoll, исполнение «комбо» 13,56 МГц + 125 кГц, веб-интерфейс, встроенный код, восстановление и обновление.
ODNFC-RS485 — NFC/RFID считыватель-контроллер с интерфейсом RS485 и протоколом Modbus RTU. Подключается в сеть RS485 как ведомое устройство; при необходимости можно реализовать другой протокол на базе RS485. Прошивка — Lua, логику работы можно изменить во встроенном редакторе кода.
Для интеграции со СКУД по другому протоколу см. руководство по OSDP. Modbus RTU и OSDP используют один порт RS485 и одновременно не работают.

Быстрый маршрут
| Нужно | Раздел |
|---|---|
| Подключить A/B, питание, замок и кнопку | «Подключение» |
| Прочитать UID из ПЛК или ПК | «Карта регистров Modbus» |
| Проверить устройство без своей программы | «Тестирование через mbpoll» |
| Подстроить карту регистров под существующий контроллер | «Интеграция» |
| Изменить локальную логику | «Встроенный код» |
| Восстановить устройство | «Восстановление устройства» |
Пример внедрения в существующую СКУД
- Подключите один считыватель короткой линией RS485 и оставьте адрес
1. - Прочитайте тестовую карту через
mbpollили ПЛК. - Проверьте команды «разрешено» и «запрещено» без подключённого замка.
- Подключите замок через подходящую схему питания и проверьте ручное управление.
- Только после этого добавляйте остальные устройства на шину и назначайте им уникальные адреса.
Такой порядок отделяет ошибки линии RS485 от ошибок адресации, логики и силовой части замка.
Ключевые возможности
- Поддерживаемые метки. Метки 13,56 МГц: MIFARE Classic 1K/4K/Mini, MIFARE Ultralight, Ultralight Nano, NTAG 213/215/216, S50/S70 — полная поддержка; Ultralight C — только чтение UID. Во встроенной Lua-программе для меток 125 кГц доступны UID EM-Marine EM4100 и HID ProxCard II, распознавание T55xx-копий, а для подготовленных ATA5577 — Trace ID и ротация токена. Может стоять один интерфейс или оба одновременно.
- Работа по RS485 Modbus. Устройство — ведомое в сети Modbus. Одновременно можно использовать Wi-Fi (не основной интерфейс). Есть встроенный веб-интерфейс для настройки.
- Совместимые бесконтактные карты — идентификатор, который отдаёт физическая карта. Мобильный кошелёк может выдавать отдельное и меняющееся значение, а обычный пропуск в Apple Wallet или Google Wallet не становится совместимой NFC-картой автоматически. Подробнее — в статье «Телефон как пропуск».
- Изменяемая логика во встроенном редакторе.
- Дискретный вход и выход — вход для кнопки и выход для управления замком. Проверьте допустимый ток, напряжение и защиту индуктивной нагрузки.
- Управляемая индикация — звуковой излучатель и RGB-светодиод; можно подключить адресную ленту и создавать собственные эффекты. Оценка «до 64 светодиодов» приблизительная: допустимые количество и яркость определяются током ленты и возможностями внутреннего преобразователя.
- Локальное хранение данных — автономная работа или синхронизация с сервером.
Лицевая панель покрыта тонкой защитной транспортировочной плёнкой (это не царапины). Удалите её перед установкой.
Подключение
Назначение выводов:
- A, B — линии RS485;
- GND — «земля»;
- IN — сигнальный входной контакт;
- OUT+ — «+» исполнительного устройства / замка (напряжение равно напряжению питания);
- OUT− — «−» исполнительного устройства / замка;
- +12V — питание, допустимо 7–24 В.
Группа отверстий «GND, OUT, +5» на плате служит для разъёма адресной ленты вместо встроенных светодиодов. При запуске контакты GND-OUT выполняют функцию HARD RESET.

Настройки порта по умолчанию: 115200 8N1, адрес устройства: 1.
Карта регистров Modbus
Согласно спецификации Modbus, регистры хранения занимают адреса 40001–49999, но передаваемый адрес относительный (0 для 40001, 1 для 40002 и т. д.). Здесь используются относительные адреса (с нуля).
Стандартная программа исполнения «комбо» использует следующую карту:
| Адреса | Направление | Назначение |
|---|---|---|
0x00..0x03 | чтение | UID метки 13,56 МГц, до 8 байт |
0x04..0x06 | чтение | UID EM-Marine 125 кГц, 5 байт и нулевое дополнение |
0xF0 | запись | команда замку и индикации |
0xF1 | запись | код однократного включения web/Wi-Fi AP |
0xF2 | запись | новый адрес ведомого Modbus |
UID упакован по два байта на регистр в порядке чтения метки. Например,
четырёхбайтный UID занимает регистры 0x00 и 0x01, а семибайтный UID
MIFARE Ultralight 34772FC11139E7 представлен как
[0x3477, 0x2FC1, 0x1139, 0xE700].
Регистры UID работают как очередь события: после успешного чтения затронутые
регистры обнуляются, а при следующем обнаружении метки заполняются снова.
Считыватели 13,56 МГц и 125 кГц опрашиваются по очереди, поэтому отдельный
опрос может вернуть нули даже при постоянно приложенных метках. Читайте одним
запросом диапазон 0x00..0x06, обрабатывайте ненулевые области независимо и
не считайте нулевой ответ потерей связи.
Команды регистра 0xF0:
1— открыть замок, включить положительную световую и звуковую индикацию;2— закрыть замок, включить отрицательную световую и звуковую индикацию;3— закрыть замок без изменения индикации.
Для включения веб-интерфейса запишите в 0xF1 последние два байта MAC-адреса
устройства как 16-битное число. Неверный или нулевой код игнорируется. Команда
также игнорируется, если веб-интерфейс отключён настройкой sys_web или уже
был запущен.
Регистр 0xF2 принимает только адреса 1..247. При корректном значении
устройство сначала закрывает замок, сохраняет новый адрес и перезагружается.
Значения вне диапазона регистрируются в отладочной консоли и не применяются.
Поведение устройства можно изменить во встроенном редакторе кода.
Тестирование через mbpoll
Для работы используем кроссплатформенную утилиту mbpoll.
Для первичной проверки используйте преобразователь USB–RS485 с надёжным драйвером и гальванической развязкой. Нестабильный адаптер может выглядеть как ошибка считывателя или линии.
# Чтение метки
mbpoll -m rtu -a 1 -r 0 -0 -c 7 -t 4:hex -b 115200 -P none -l 500 -o 0.5 /dev/ttyUSB0
# Разрешено
mbpoll -R -m rtu -a 1 -r 240 -0 -b 115200 -P none -1 -o 0.5 /dev/ttyUSB0 1
# Запрещено
mbpoll -R -m rtu -a 1 -r 240 -0 -b 115200 -P none -1 -o 0.5 /dev/ttyUSB0 2
# Закрыть замок
mbpoll -R -m rtu -a 1 -r 240 -0 -b 115200 -P none -1 -o 0.5 /dev/ttyUSB0 3
# Включить web (значение зависит от s/n)
mbpoll -R -m rtu -a 1 -r 241 -0 -b 115200 -P none -1 -o 0.5 /dev/ttyUSB0 0x3709
# Сменить адрес с 1 на 2
mbpoll -R -m rtu -a 1 -r 242 -0 -b 115200 -P none -1 -o 0.5 /dev/ttyUSB0 2

Преобразование UID в напечатанный номер
На карте бывает напечатан номер, не совпадающий с UID. В общем руководстве «UID и номер карты: форматы, Wiegand и преобразование» приведены прямой и обратный порядок байтов, десятичные варианты, Wiegand 26 и другие профили, формулы для таблиц и примеры для Lua и MicroPython.
Исполнение «комбо» (два интерфейса)

Когда активны оба интерфейса (13,56 МГц и 125 кГц), данные метки 125 кГц
укладываются начиная с регистра 4 — читать нужно вдвое больше регистров. При
включённом чтении HID добавляется ещё 4 регистра. Форматы передачи и упаковку в
регистры можно изменить под логику вашего контроллера.
Чтение меньшего диапазона регистров не отключает физический считыватель: стандартная Lua-программа всё равно чередует оба интерфейса. Если один из них не установлен или не нужен, удалите соответствующий вызов
mfrc522.scan()илиemmarine.uid()из программы и уберите чередование.
Веб-интерфейс
Веб-интерфейс нужен только для изменения кода или настроек, недоступных по
Modbus. Чтобы его включить, запишите в регистр 0xF1 два последних байта
серийного номера — устройство поднимет Wi-Fi-сеть вида odnfc-[s/n].
Основной экран показывает состояние соединения, время работы, доступную память и сообщения программы.
Экран настроек меняет основные настройки. Часть из них (Формат, Тип ключа,
Ключ, Получатель) предназначена для пользовательской программы. Пароль и
отключение веб-интерфейса ограничивают доступ в общей сети (пароль передаётся в открытом
виде). HTTPS работает с самоподписанными сертификатами — медленнее и с ручным
подтверждением в браузере. WebSocket REPL открывает удалённый доступ (IDE
lua.unitx.pro и плагин VS Code).
Редактор кода позволяет менять файл usercode.lua, который загружается
автоматически. Для больших проектов используйте консоль, онлайн-среду или плагин
VS Code.
Экран файлов показывает дополнительные файлы каталога /public. Здесь их
можно загрузить, скачать, обновить или удалить. Системные файлы веб-интерфейса
и автозапуска защищены от операций через этот список.
Экран системы показывает модель устройства, версию прошивки и серийный
номер. На этом же экране загружается файл обновления .ufl или .dfu; во время
записи не отключайте питание.





Технические характеристики
- Дальность считывания: до 6–10 см (зависит от качества метки).
- Габариты: 120 × 76 × 22 мм.
- Проводные интерфейсы: RS485.
- Беспроводные интерфейсы: Wi-Fi.
- Индикация: RGB-светодиод, звуковой излучатель.
- Вход: один канал (3 В, подтянут к «1»).
- Выход: один канал (макс. 1 А), напряжение равно напряжению питания.
- Крепление: четыре отверстия M3.
Интеграция
Стандартная прошивка реализует базовые функции Modbus-считывателя: устройство передаёт данные последней метки через заданную карту регистров и принимает несколько команд управления. Карту регистров и логику работы можно изменить.
Прикладная логика ODNFC-RS485 программируется на Lua. Например, можно:
- подстроить адреса регистров и формат данных под уже существующий контроллер или ПЛК, не меняя программу верхнего уровня;
- читать и записывать нужные блоки или сектора совместимых меток, а результат размещать в выбранных регистрах;
- добавить собственные области регистров для команд, состояния входа и выхода, диагностических и служебных данных;
- фильтровать метки непосредственно в считывателе и передавать контроллеру только нужные события;
- использовать встроенную базу данных для локальной проверки прав и автономного управления доступом;
- объединить работу с метками, замком, кнопкой, индикацией, базой данных и Modbus в одной программе.
Код можно изменить во встроенном редакторе: например, добавить регистры, изменить правила доступа или формат данных.
Встроенный код (исполнение «комбо»)
Этот код установлен в исполнении «комбо» и доступен во встроенном редакторе.
Конкретная версия может отличаться в зависимости от исполнения и прошивки.
Скачать исходник usercode.lua.
local get, set = Settings.get, Settings.set
local setregs, setregs8 = modbus.setregs, modbus.setregs8
local getvalues, sleepms = modbus.getregsvalues, thread.sleepms
local lock_pin = pio.GPIO16
pio.pin.setdir(pio.OUTPUT, lock_pin)
local function lock() pio.pin.setval(1, lock_pin) end
local function unlock() pio.pin.setval(0, lock_pin) end
lock()
local leds = indication.RGBLeds.new { ledPin = pio.GPIO32 }
local snd = indication.Sound.new(pio.GPIO21)
local wdt_on = get("sys_wdt") == "on"
local parity = get("rs485_parity")
parity = parity == "EVEN" and 2 or parity == "ODD" and 3 or 0
modbus.rtu.init(
tonumber(get("rs485_addr")), nil, nil, nil, nil,
tonumber(get("rs485_baudrate")), parity
)
-- Карта регистров:
-- 0..3 — HF UID, максимум 8 байт;
-- 4..6 — EM-Marine UID, 5 байт;
-- F0 — управление: разрешено/запрещено;
-- F1 — код включения web/AP;
-- F2 — новый Modbus-адрес.
local function set_hf_uid(...)
if select("#", ...) > 8 then
eprint("MFRC522: 10-byte UID does not fit registers 0..3")
return
end
-- Очищаем старый хвост 7-байтного UID.
setregs(0, 0, 0, 0, 0)
setregs8(0, ...)
end
local web_started = false
local mac = cpu.getmac(0, 1)
local web_code = mac and tonumber(mac:sub(-4), 16)
local function start_web(code)
if web_started or not web_code or code ~= web_code then return end
if get("sys_web") ~= "on" then
eprint("Web interface is disabled by sys_web")
return
end
pcall(net.wf.stop)
local ok, err = pcall(function()
net.wf.setup(
net.wf.mode.AP, get("net_ssid"), get("net_password"),
net.wf.powersave.NONE, 4, false
)
net.wf.start()
end)
if not ok then
eprint("Web interface start failed: " .. tostring(err))
return
end
web_started = true
end
leds:start()
snd:start()
local em_reader = emmarine.new()
local scan_mfrc = true
local function iteration()
local ok, err
if scan_mfrc then
ok, err = mfrc522.scan(nil, nil, nil, nil, 0, set_hf_uid)
else
ok, err = emmarine.uid(em_reader, setregs8, 4)
end
scan_mfrc = not scan_mfrc
if ok == false then
eprint((scan_mfrc and "EM-Marine: " or "MFRC522: ") .. tostring(err))
end
local action, web_pwd, new_addr = getvalues(0xf0, 3, true)
if action == 1 then
unlock()
leds:ok()
snd:ok()
elseif action == 2 then
lock()
leds:err()
snd:err()
elseif action == 3 then
lock()
end
if web_pwd and web_pwd ~= 0 then
start_web(web_pwd)
end
if new_addr and new_addr ~= 0 then
if new_addr >= 1 and new_addr <= 247 then
lock()
set("rs485_addr", tostring(new_addr))
os.exit()
else
eprint("Invalid Modbus address: " .. tostring(new_addr))
end
end
end
while true do
if wdt_on then cpu.watchdog.reset() end
local ok, err = pcall(iteration)
if not ok then
local message = tostring(err)
if message:find("interrupted!", 1, true) then
error(err, 0)
end
eprint("Main loop: " .. message)
sleepms(250)
else
sleepms(100)
end
end
Восстановление устройства
- Выключите устройство.
- Замкните контакты HARD RESET или RECV на плате (зависит от ревизии).
- Включите устройство, удерживая контакты замкнутыми.
- Подождите несколько секунд (затем контакты можно разомкнуть).
- Устройство создаст Wi-Fi-точку доступа
OD-[серийный номер]без пароля. - Через веб-сервер и telnet измените настройки или программу. Wi-Fi
IP-адрес:
192.168.4.1.
Обновление устройства
- Откройте вкладку «Настройки», отключите сторожевой таймер и перезагрузите устройство.
- Откройте вкладку «Система», нажмите «Из файла» и выберите прошивку.
- Нажмите «Загрузить» — устройство перезагрузится.
- Убедитесь, что отображается нужная версия прошивки.
Дополнительные материалы
- Кнопка, замок, реле, второй считыватель и адресная RGB-лента
- Строка форматирования.
- Консоль.
- Программирование на Lua.
История обновлений ODNFC на Lua
Если установлена версия ниже 1.7.0, сначала обновите её до 1.7.0, а затем до более новой версии. Перед обновлением отключите сторожевой таймер и сотрите пользовательскую программу.
1.8.2
- Улучшена работа устройства и исправлены ошибки.
- Для устройств, работающих с метками 125 кГц, добавлено обнаружение типовых клонов EM-Marine.
1.8.1
Улучшения:
- Новый веб-интерфейс.
- Улучшена работа RFID-модулей MFRC и EM-Marine.
- Улучшена работа Modbus.
- Оптимизирована работа устройства.
1.7.0
Улучшения:
- улучшена работа MFRC и EM-Marine;
- в раздел «Редактор» добавлен простой файловый менеджер;
- улучшена работа сетевых модулей;
- оптимизирована работа устройства.
Исправлена ошибка в HTTP-заголовке Content-Length, из-за которой интерфейс не
работал в некоторых операционных системах.
1.6.2
- Улучшена работа MFRC и EM-Marine.
- Улучшена библиотека Modbus.
- Оптимизирована работа устройства.
- В ODNFC-LAN-LUA добавлена регистрация обработчика успешного чтения.
1.6.1
- Добавлена запись в зашифрованные карты MIFARE Classic.
- Упрощена инициализация RFID: используются значения по умолчанию для каждой
платы, поэтому изменён вызов основного класса и больше не требуются многие
Lua-обёртки из
rfid.lua. - Добавлена функция
mfrc522.scan()— упрощённая версия базового класса для типовых операций. - Исправлены библиотеки EM-Marine и HID.
- Оптимизирована библиотека Modbus.
- Исправлена работа TCP-сервера.
1.6.0
Улучшения:
- обновлён редактор кода: устранена проблема с переводами строк в новых версиях Firefox;
- в веб-сервер добавлена поддержка HTTPS и WebSocket;
- добавлены новые классы для работы с RFID-метками;
- добавлена работа с NDEF и счётчиками Ultralight;
- добавлены встроенные библиотеки
cbor,cobs,mlib, Heatshrink иmicrotar; - расширены библиотеки
osc,net,cutils,utils,cpuиemmarine; - LuaSocket больше не входит в прошивку;
- добавлена загрузка сжатых Heatshrink-библиотек Lua;
- добавлен WebSocket REPL для отладки через веб-IDE или расширение VS Code;
- улучшена консоль: Unicode, автодополнение и история;
- расширена поддержка Modbus;
- Paho MQTT заменён собственной реализацией uMqtt;
- ускорена работа устройства и веб-интерфейса;
- выполнены другие небольшие исправления и оптимизации.
Исправлены ошибки, из-за которых после мягкой перезагрузки Wi-Fi запускался через раз, а RFID-модуль мог не инициализироваться.
1.5.0
Улучшения:
- новый интерфейс и редактор кода;
- добавлена библиотека
tinycobs; - добавлены функции
net.tcp.*; - добавлены функции
eprint,hprintиwprintдля вывода в окно «Инфо»; - трассировка ошибки загрузки теперь показывается в окне «Инфо»;
- расширены возможности Telnet, SSH отключён;
- в режиме восстановления Wi-Fi работает без пароля;
- добавлена поддержка BLE-маяков на устройствах с BLE;
- NTP запускается с задержкой 15 секунд, чтобы сеть успела установиться.
Исправлены режим статического Ethernet-адреса и установка яркости NeoPixel.
1.4.0
- Улучшен встроенный веб-сервер.
- Выполнены небольшие изменения для повышения стабильности.
- Исправлена утечка памяти при HTTP-запросах из Windows.
Известная проблема этой версии: режим статического Ethernet-адреса в настройках не работает. Для обхода проблемы в начало пользовательской программы добавляли:
net.en.setup(
net.packip(Settings.get("net_ip")),
net.packip(Settings.get("net_mask")),
net.packip(Settings.get("net_gw")),
net.packip(Settings.get("net_dns"))
)
net.en.start()
1.3.2
- В
os.df()добавлен дополнительный параметр. - Выполнены небольшие изменения для повышения стабильности.
- Исправлена утечка памяти при запросе метрики в интерфейсе.
Известная проблема этой версии: HTTP-запросы из Windows приводят к утечке памяти. После изменения настроек рекомендовалось закрыть браузер, перезагрузить устройство и не выполнять периодические HTTP-запросы.
1.3.1
- Серийный номер синхронизирован с DataMatrix на корпусе модуля, если он есть.
1.3
- Библиотека
Telegram.luaдобавлена в прошивку. - Библиотека LuaSocket теперь распространяется отдельно.