Modbus RTU в MQTT: сопоставление регистров, порядок байтов и масштабирование
Надёжная интеграция Modbus RTU с MQTT требует явно согласованного соответствия между картой регистров устройства и приложением, которое использует его измерения. Успешный ответ по последовательному интерфейсу доказывает, что байты получены. При вводе в эксплуатацию также необходимо установить, что означают эти байты и актуально ли полученное значение.
В этом руководстве рассматривается телеметрия только для чтения: преобразование адресов, коды функций, знаковые значения, масштабирование, порядок нескольких регистров и актуальность данных MQTT. Все приведённые ниже назначения регистров, значения и полезные нагрузки служат примерами, а не спецификациями продуктов Obeita или результатами полевых измерений.
Начните с одного проверенного чтения RTU
Соберите сведения о модели устройства, версии прошивки, редакции карты регистров, настройках последовательного интерфейса, адресе станции и известном эталонном значении. Проверьте подключение RS-485, оконечные резисторы и цепи смещения по монтажной документации. Убедитесь, что шиной управляет только предусмотренное ведущее устройство. Устраните тайм-ауты и ошибки CRC, прежде чем пытаться исправить значения масштабированием.
Руководство Modbus для последовательных линий определяет структуру кадров RTU, временные параметры и контроль ошибок. Рабочая система опроса должна соблюдать эти требования и ограничения устройства на ответы. Начните с одной документированной точки измерения; расширяйте набор опрашиваемых точек только после проверки соответствия её необработанного ответа и декодированного значения.
Определяйте адрес регистра и код функции вместе
Спецификация прикладного протокола Modbus использует адреса PDU с отсчётом от нуля. Код функции 03 читает регистры хранения, а код функции 04 — входные регистры. Это разные логические таблицы. Одинаковое числовое смещение не означает, что обе функции возвращают одно и то же измерение.
В традиционной системе обозначений в документации 40001 обозначает первый регистр хранения, а 30001 — первый входной регистр. Начальная цифра указывает таблицу; она не входит в передаваемый адрес PDU. См. пояснение по адресации от Modbus Organization.
| Пример записи в руководстве | Функция | Начальный адрес PDU |
|---|---|---|
| Регистр хранения 40011 | 03 | 10 в десятичной системе, 0x000A |
| Входной регистр 30011 | 04 | 10 в десятичной системе, 0x000A |
Для этой системы обозначений 40011 − 40001 = 10. Однако руководства могут уже содержать смещения с отсчётом от нуля, номера регистров с отсчётом от единицы или шестнадцатеричные адреса. Интерфейсы шлюзов могут выполнять собственное преобразование. Фиксируйте и обозначение в руководстве, и фактическое смещение PDU; никогда не вычитайте единицу автоматически. Не заменяйте FC03 на FC04 ради получения правдоподобного числа, если документация устройства явно не предусматривает такое соответствие.
Для первого примера PDU запроса имеет вид 03 00 0A 00 01: функция 03, начальный адрес 10, количество — один. Это только PDU, а не полный кадр RTU; адрес станции и CRC опущены.
Декодируйте знаковые значения до масштабирования
Создайте описание точки измерения, включающее адрес станции, функцию, смещение PDU, число регистров, тип данных, порядок слов, масштабный коэффициент, смещение значения, единицу измерения, правила обработки недопустимых значений и предельный возраст данных. Сохраняйте необработанные слова регистров в журналах ввода в эксплуатацию, чтобы другой инженер мог воспроизвести преобразование.
Предположим, что точка из примера представляет температуру в виде знакового 16-битного значения с масштабным коэффициентом 0.1 °C и нулевым смещением. Слово ответа 0xFF9C при беззнаковом прочтении равно 65436. Его знаковая интерпретация в дополнительном коде даёт 65436 − 65536 = −100. Применяйте масштабирование после декодирования:
engineering_value = decoded_value × scale + offset
= -100 × 0.1 + 0
= -10.0 °C
Беззнаковый декодер вместо этого опубликовал бы 6543.6 °C. Изменение масштабного коэффициента, чтобы скрыть такой результат, не устранило бы исходную ошибку типа данных. Проверяйте положительные, отрицательные и граничные значения. До масштабирования проверяйте коды недопустимых значений, определённые производителем; служебное значение не должно превращаться в правдоподобный результат измерения.

Разделяйте порядок байтов в 16-битном регистре и порядок слов в нескольких регистрах
В стандартном 16-битном регистре Modbus первым передаётся старший байт. Поэтому 0x4148 передаётся как 41 48. CRC в RTU — отдельное поле, в котором первым отправляется младший байт; его порядок не определяет правила декодирования регистров.
32-битное прикладное значение занимает два регистра, но порядок слов зависит от устройства. Пример Schneider Electric с переставленными словами числа с плавающей точкой показывает, почему старшее и младшее слова иногда нужно менять местами.
Для точно представимого значения 12.5 в формате IEEE 754 float32 из нашего примера битовое представление имеет вид 0x41480000. Карта со старшим словом первым возвращает 0x4148, 0x0000, а карта с младшим словом первым — 0x0000, 0x4148. Расположите слова в порядке, указанном в руководстве, затем интерпретируйте собранные биты как float32. Числовое преобразование собранного целого числа в число с плавающей точкой — другая операция.

Параметр шлюза с названием «little endian» может быть неоднозначным. Документируйте точную перестановку слов и байтов, которую он выполняет. Некоторые карты производителей также предусматривают перестановку байтов на уровне приложения; проверяйте её явно. По возможности считывайте связанные слова одним запросом и выясните, гарантирует ли устройство согласованный снимок данных во время обновления.
Публикуйте актуальность и качество вместе со значением MQTT
Задайте для каждого измерения постоянное имя точки, единицу измерения, состояние качества и временную метку с определённым смыслом. Если устройство не предоставляет время получения измерения, явно укажите, что метка отражает время успешного чтения шлюзом. Более позднее время публикации не должно скрывать возраст старого измерения.
В этом примере полезной нагрузки приложения используются время завершения чтения шлюзом и последовательность в пределах одного запуска:
{
"schema_version": 1,
"device_id": "example-device-07",
"point": "temperature",
"value": -10.0,
"unit": "degC",
"quality": "good",
"read_completed_at": "2026-10-03T12:00:00Z",
"time_source": "gateway_read",
"boot_id": "example-boot-01",
"sequence": 1042
}
Определите поведение после пропущенного опроса: например, сохранять временную метку последнего достоверного значения, указывая в состоянии качества, что данные устарели, либо публиковать явно недоступное значение. Задайте подходящий для процесса порог устаревания, требования к синхронизации часов и ограничения очередей. При повторной передаче буферизованных измерений сохраняйте исходное время их чтения.
Сохранённые сообщения MQTT могут помочь новому подписчику получить последнее опубликованное состояние, но само сохранение не подтверждает актуальность. Механизм Message Expiry в MQTT 5 может ограничивать время жизни сообщений в очереди; приложениям-потребителям всё равно необходимо проверять возраст данных на прикладном уровне. См. разделы 3.3 и 4.3 MQTT 5.0.
Выбирайте QoS без обещаний сквозной обработки ровно один раз
MQTT QoS 0 обеспечивает доставку не более одного раза, QoS 1 — не менее одного раза, а QoS 2 — ровно один раз в рамках своего протокольного обмена. Спецификация ограничивает эту доставку парой из одного отправителя и одного получателя; доставка от брокера подписчику — отдельный обмен. Сам по себе QoS 2 не может гарантировать ровно одно получение показания датчика или обновление базы данных во всей системе.
Проектируйте операции записи приложения-потребителя идемпотентными, если дубликаты имеют значение. Прикладной ключ, объединяющий устройство, идентификатор запуска и номер последовательности, может поддерживать дедупликацию, если определены правила его уникальности и сохранения. Проверяйте повторные подключения и повторные попытки в последующих компонентах с фактической конфигурацией брокера, клиента и хранилища.
Контрольный список ввода в эксплуатацию
- Сравните PDU запроса с утверждённой картой адресов, в том числе проверьте выбор FC03 или FC04.
- Проверьте необработанные слова по известному показанию устройства до включения облачных вычислений.
- Проверьте отрицательные значения, недопустимые коды, изменения порядка слов и частично неудачные опросы.
- Отключите по отдельности устройство с последовательным интерфейсом и брокер; убедитесь, что устаревшие данные остаются распознаваемыми.
- Перезапустите шлюз и приложение-потребитель; проверьте возраст повторно передаваемых данных, обработку дубликатов и поведение последовательности.
- Зафиксируйте проверенную прошивку, редакцию карты, схему полезной нагрузки и результаты приёмки.
Подготовьте требования к интеграции Modbus RTU с MQTT для проверки
Для обсуждения интеграции с Obeita подготовьте соответствующие страницы руководства устройства, пример кадра запроса/ответа, ожидаемые значения в физических единицах, число точек, интервал опроса, требования к брокеру и поведение при отказах. Скройте пароли, ключи, идентификаторы заказчиков, сведения о частных сетях и закрытые данные, на передачу которых у вас нет разрешения. Эти материалы позволяют определить и проверить соответствие регистров до окончательного выбора конфигурации шлюза.
Ознакомьтесь с услугой Obeita по подключению существующего оборудования и реализованным проектом сбора данных на STM32 и интеграции с MQTT (на английском), чтобы узнать о смежных инженерных задачах. Чтобы обсудить собственные требования к сопоставлению регистров, свяжитесь с Obeita.
Первичные источники
- Спецификация прикладного протокола Modbus V1.1b3. Соответствующие разделы: 4.2, 4.3, 4.4, 6.3, 6.4.
- Введение в Modbus — Modbus Organization. Соответствующие разделы: адресация данных Modbus и функция 03.
- Modbus по последовательной линии: спецификация и руководство по реализации V1.02. Соответствующие разделы: 2.2, 2.5.1, 3.
- Schneider Electric — Чтение значений с плавающей точкой с переставленными словами в Modbus. Соответствующий раздел: решение.
- MQTT версии 5.0 — стандарт OASIS. Соответствующие разделы: 3.3.1.3, 3.3.2.3.3, 4.3.