SCADA опрашивает holding register 40001, ожидает температуру 85 °C, получает 0 или 65280. Интегратор открывает утилиту шлюза - там значение верное. Меняют адрес на 40002 - приходит давление с соседнего прибора. Классика: карта преобразования на шлюзе Modbus RTU-TCP сдвинута на один регистр, перепутан byte swap или несколько slave за одним TCP-портом разведены не тем Unit ID.
Здесь не курс Modbus с нуля и не сравнение RTU с TCP. Разбираем шлюз, который снаружи говорит Modbus TCP, а внутри опрашивает RS-485: mapping table, offset, byte order, несколько slave на одном сокете. Статья не дублирует три режима Modbus - для фрейминга есть отдельный материал.
Короткий ответ
Когда шлюз Modbus RTU-TCP отдает «не те» регистры, в 80% случаев ошибка в карте преобразования: неверный стартовый адрес (offset 0-based vs 1-based), смещение блока, перепутан тип (holding vs input), byte swap (ABCD vs CDAB), неверный Unit ID для нужного slave. Диагностика: сравнить запрос SCADA, ответ TCP и фактический опрос на стороне RS-485 в утилите шлюза; сверить таблицу mapping построчно.
Исправление - не «подобрать адрес на глаз», а зафиксировать в паспорте объекта: для каждого тега - адрес TCP, адрес RTU, тип регистра, порядок байт, slave ID. Одна строка ошибки в Excel на пуске превращается в год «магических» смещений.
Как устроена карта на шлюзе
Шлюз принимает Modbus TCP (MBAP + PDU) от SCADA. В PDU - function code, start address, quantity. Шлюз переводит запрос в кадр Modbus RTU на UART: другой slave ID, иногда другой адрес и длина. Ответ RTU упаковывается обратно в TCP. Между «адресом, который видит SCADA» и «адресом на приборе» лежит таблица mapping.
Типичные колонки таблицы: TCP start, RTU start, length, function, slave ID, byte order. Если TCP 40001 мапится на RTU 0 (а не 1) - SCADA с адресацией «как в мануале 4xxxx» уедет на регистр. Если в карте указан input register (3x), а клиент читает holding (4x) - придут другие данные или exception.
Offset: ноль или единица
Вечный спор: адрес 40001 - это регистр 0 или 1 в PDU? Modbus PDU нумерует с 0. Документация приборов часто пишет с 1. Шлюз может показывать «Modbus address 1», драйвер SCADA - «40001». Ошибка на единицу дает сдвиг всего блока: температура читается как статус, статус как температура.
Проверка: прочитать один известный регистр с прибора напрямую по RS-485 (USB-адаптер) и сравнить с тем, что отдает шлюз на тот же logical address. Затем сдвинуть mapping на ±1 и повторить. Зафиксировать правило для проекта в одном месте.
Byte swap и 32-битные значения
Два регистра под float или DINT требуют согласованного порядка слов и байт. Шлюз отдал big-endian AB CD, SCADA ждет CD AB - число выглядит огромным или нулевым. Особенно часто на счетчиках энергии и частотниках.
Симптом: «младшие байты на месте, старшие нули» или наоборот. В утилите шлюза часто есть переключатель Byte Order per mapping line. Сверьте с мануалом slave, не с привычкой «как на прошлом объекте».
Несколько slave за одним TCP
Один IP:502, разные Unit ID в MBAP - разные устройства на RS-485. Ошибка Unit ID - «живой» ответ с чужого прибора. SCADA думает, что читает расходомер, а получает данные температуры с ID=2.
Проверьте: в Wireshark поле Unit Identifier, в карте шлюза - привязка ID к порту RS-485. При нескольких шлюзах на одном IP (разные порты) не перепутайте порты в драйвере.
Подробнее про Unit ID и транзакции - в «Modbus TCP для интегратора: Unit ID, транзакции, таймауты». Про выбор режима RTU/TCP/RTU-over-TCP - в «Три режима Modbus: RTU, TCP и RTU-over-TCP».
Таблица: запрос, неверный ответ, где ошибка в карте
| Запрос SCADA | Неверный ответ | Где ошибка в карте |
|---|---|---|
| 40001, FC03, 2 reg | нули или мусор | неверный RTU адрес / offset ±1 |
| 40010 float | огромное число | byte swap или word swap |
| 30001 input | exception или нули | в карте holding вместо input |
| Unit ID=1 | данные другого прибора | slave ID в строке mapping |
| блок 20 регистров | обрезанный ответ | length меньше, чем в запросе |
| после замены прибора | все сдвинуто | новая карта регистров не обновлена |
Диагностика по шагам
Захватите TCP в Wireshark: function, address, quantity, Unit ID. Откройте веб-интерфейс шлюза - trace RS-485: какой кадр ушел на шину. Сравните адреса. Прочитайте тот же регистр утилитой производителя slave. Если на RS-485 верно, а в TCP нет - ошибка в mapping или swap. Если на RS-485 неверно - шлюз правильно транслирует неправильный запрос.
Не меняйте сразу и адрес в SCADA, и строку в шлюзе. Меняйте одно звено, иначе «заработало» случайно и сломается на следующем теге.
Документирование карты для сдачи объекта
Выгрузите таблицу mapping в Excel или PDF: TCP tag, TCP address, RTU slave, RTU address, FC, type, byte order, комментарий (единицы, масштаб). Привяжите к as-built. На объекте без этой таблицы каждый новый интегратор снова подбирает смещение.
Для панелей оператора с Modbus-картой экрана те же правила - см. «Modbus-карта экрана оператора: масштаб и bad quality».
Три режима на одном объекте: не перепутать шлюз и клиент
На схеме часто стоят и прозрачный serial server (RTU-over-TCP), и полноценный Modbus TCP-RTU шлюз с mapping, и прибор с нативным Modbus TCP. SCADA настроили «как на прошлом заводе» - и половина тегов читается, половина со сдвигом. Перед правкой карты убедитесь, какой тип узла перед вами. Признак TCP-шлюза с mapping - веб-таблица адресов; признак туннеля - один к одному адрес на обеих сторонах.
Материал «Три режима Modbus: RTU, TCP и RTU-over-TCP» помогает не смешивать разбор кадра на проводе с настройкой драйвера. Ошибка режима выглядит как «неверные регистры», хотя карта правильная для другого типа транспорта.
Масштаб и тип данных после mapping
Даже при верном адресе температура приходит как сырой int16 в тысячных долях, а SCADA ждет float в градусах. Интегратор двигает адрес - становится «другое неверное число». Сначала сверяют raw value в утилите шлюза и в SCADA без масштаба. Потом - множитель. В карте mapping некоторые шлюзы позволяют задать scale на строку; если нет - масштаб только в SCADA, но адрес должен быть стабильным.
Для 32-битных счетчиков проверяют, что запрос читает два регистра подряд и swap согласован на всей цепочке. Типичная ошибка: в карте одно слово, в SCADA - DINT из двух регистров со сдвигом.
Несколько TCP-клиентов и «плавающие» ответы
Два мастера опрашивают один шлюз агрессивно. Шлюз перемешивает ответы или отвечает с задержкой - SCADA иногда получает PDU от предыдущего запроса. Симптом: «неверный регистр» случайно, исчезает после снижения частоты опроса. В Wireshark смотрят Transaction ID: ответ не тому запросу - проблема очереди, не mapping.
Решение: один мастер на линию RS-485 за шлюзом, таймауты с запасом, групповое чтение блоков вместо сотен одиночных регистров. Подробнее про таймауты и Unit ID - в статье для интегратора Modbus TCP.
Приемка шлюза: короткий FAT
Перед сдачей объекта для каждого slave: прочитать 3-5 эталонных регистров напрямую по RS-485, тем же адресом через TCP, сверить с паспортом прибора. Зафиксировать скрин mapping и строку в таблице сигналов. При замене прибора на той же позиции - обновить только строку карты, не «подбирать на глаз» в SCADA.
Если шлюз перепрошили и конфигурация слетела, а бэкапа нет, восстановление идет неделями. Бэкап XML/CSV карты - в тот же архив, что и проект ПЛК.
Типичная ошибка «плюс 40000»
В драйвере SCADA включена опция «Modicon addressing» - к адресу прибавляется 40001 для holding. В карте шлюза адрес уже «человеческий». В итоге запрос уезжает на сотни регистров. Симптом: стабильно неверные данные на всех тегах блока. Лечение: выключить лишнее смещение в одном месте - либо в драйвере, либо в шлюзе, не в обоих.
Аналогично для input registers (3xxxx) и coils (0xxxx). Таблица сигналов должна явно писать: «адрес в PDU», «адрес в SCADA», «адрес в шлюзе».
Инструменты: что открыть на объекте
Утилита веб-интерфейса шлюза с trace RS-485, Modbus Poll или аналог для прямого опроса slave, Wireshark на порту TCP 502, таблица сигналов Excel. Порядок работы: сначала прямой опрос slave (эталон), затем trace шлюза, затем запрос SCADA. Не наоборот - иначе неделю «крутят» offset в SCADA, хотя карта шлюза изначально верна.
При замене модели прибора с другой картой регистров не копируют старую строку mapping с новым IP. Делают новую строку с нуля по мануалу - это быстрее, чем объяснять цеху, почему «температура» показывает счетчик моточасов.
Связь с кабелем: когда mapping верный, а число «плывет»
Иногда регистр читается верно, но значение скачет из-за помех на RS-485, а интегратор снова крутит offset. Сначала стабилизируют поле: терминатор, GND, один мастер, скорость. Сравнение «напрямую RS-485» и «через шлюз» при одном и том же запросе за минуту отделяет ошибку карты от ошибки шины. Материал про стабильную связь Modbus RTU vs TCP дополняет эту диагностику.
Вопросы при работе
Почему утилита шлюза показывает верно, SCADA - нет?
Разные адреса опроса или swap в драйвере SCADA, не в шлюзе.
Нужно ли дублировать карту в SCADA и в шлюзе?
Лучше один источник истины. Либо шлюз прозрачный (1:1), либо вся адресация на шлюзе, SCADA читает «виртуальные» регистры.
Exception 02 - illegal address
Запрос выходит за карту или за память slave. Проверьте length и max address в mapping.
Обсуждение