Сайт о телевидении

Сайт о телевидении

» » Таблица адресов modbus. Структура Modbus RTU сообщения

Таблица адресов modbus. Структура Modbus RTU сообщения

Modbus -коммуникационный протокол, основан на архитектуре ведущий-ведомый (master-slave). Использует для передачи данных интерфейсы RS-485, RS-422, RS-232, а также Ethernet сети TCP/IP (протокол Modbus TCP).

Сообщение Modbus RTU состоит из адреса устройства SlaveID, кода функции, специальных данных в зависимости от кода функции и CRC контрольной суммы.

Если отбросить SlaveID адрес и CRC контрольную сумму, то получится PDU, Protocol Data Unit.

SlaveID – это адрес устройства, может принимать значение от 0 до 247, адреса с 248 до 255 зарезервированы.

Данные в модуле хранятся в 4 таблицах.

Две таблицы доступны только для чтения и две для чтения-записи.

В каждой таблице помещается 9999 значений.

Номер регистра Адрес регистра HEX Тип Название Тип
1-9999 0000 до 270E Чтение-запись Discrete Output Coils DO
10001-19999 0000 до 270E Чтение Discrete Input Contacts DI
30001-39999 0000 до 270E Чтение Analog Input Registers AI
40001-49999 0000 до 270E Чтение-запись Analog Output Holding Registers AO

В сообщении Modbus используется адрес регистра.

Например, первый регистр AO Holding Register, имеет номер 40001, но его адрес равен 0000.

Разница между этими двумя величинами есть смещение offset.

Каждая таблица имеет свое смещение, соответственно: 1, 10001, 30001 и 40001.

Ниже приведен пример запроса Modbus RTU для получения значения AO аналогового выхода (holding registers) из регистров от #40108 до 40110 с адресом устройства 17.

11 03 006B 0003 7687

В ответе от Modbus RTU Slave устройства мы получим:

11 03 06 AE41 5652 4340 49AD

11 Адрес устройства (17 = 11 hex) SlaveID
03 Функциональный код Function Code
06 Количество байт далее (6 байтов идут следом) Byte Count
AE (AE hex) Register value Hi (AO0)
41 (41 hex) Register value Lo (AO0)
56 Значение старшего разряда регистра (56 hex) Register value Hi (AO1)
52 Значение младшего разряда регистра (52 hex) Register value Lo (AO1)
43 Значение старшего разряда регистра (43 hex) Register value Hi (AO2)
40 Значение младшего разряда регистра (40 hex) Register value Lo (AO2)
49 Контрольная сумма CRC value Lo
AD Контрольная сумма CRC value Hi

Регистр аналогового выхода AO0 имеет значение AE 41 HEX или 44609 в десятичной системе.

Регистр аналогового выхода AO1 имеет значение 56 52 HEX или 22098 в десятичной системе.

Регистр аналогового выхода AO2 имеет значение 43 40 HEX или 17216 в десятичной системе.

Значение AE 41 HEX - это 16 бит 1010 1110 0100 0001, может принимать различное значение, в зависимости от типа представления.

Значение регистра 40108 при комбинации с регистром 40109 дает 32 бит значение.

Пример представления.

Тип представления Диапазон значений Пример в HEX Будет в десятичной форме
16-bit unsigned integer 0 до 65535 AE41 44,609
16-bit signed integer -32768 до 32767 AE41 -20,927
two character ASCII string 2 знака AE41 ® A
discrete on/off value 0 и 1 0001 0001
32-bit unsigned integer 0 до 4,294,967,295 AE41 5652 2,923,517,522
32-bit signed integer -2,147,483,648 до 2,147,483,647 AE41 5652 -1,371,449,774
32-bit single precision IEEE floating point number 1,2·10−38 до 3,4×10+38 AE41 5652 -4.395978 E-11
four character ASCII string 4 знака AE41 5652 ® A V R

Какие бывают команды Modbus RTU?

Приведем таблицу с кодами функций чтения и записи регистров Modbus RTU.

Код функции Что делает функция Тип значения Тип доступа
01 (0x01) Чтение DO Read Coil Status Дискретное Чтение
02 (0x02) Чтение DI Read Input Status Дискретное Чтение
03 (0x03) Чтение AO Read Holding Registers 16 битное Чтение
04 (0x04) Чтение AI Read Input Registers 16 битное Чтение
05 (0x05) Запись одного DO Force Single Coil Дискретное Запись
06 (0x06) Запись одного AO Preset Single Register 16 битное Запись
15 (0x0F) Запись нескольких DO Force Multiple Coils Дискретное Запись
16 (0x10) Запись нескольких AO Preset Multiple Registers 16 битное Запись

Как послать команду Modbus RTU на чтение дискретного вывода? Команда 0x01

Эта команда используется для чтения значений дискретных выходов DO.

В запросе PDU задается начальный адрес первого регистра DO и последующее количество необходимых значений DO. В PDU значения DO адресуются, начиная с нуля.

Значения DO в ответе находятся в одном байте и соответствуют значению битов.

Значения битов определяются как 1 = ON и 0 = OFF.

Младший бит первого байта данных содержит значение DO адрес которого указывался в запросе. Остальные значения DO следуют по нарастающей к старшему значению байта. Т.е. справа на лево.

Если запрашивалось меньше восьми значений DO, то оставшиеся биты в ответе будут заполнены нулями (в направлении от младшего к старшему байту). Поле Byte Count Количество байт далее указывает количество полных байтов данных в ответе.

Пример запроса DO с 20 по 56 для SlaveID адреса устройства 17. Адрес первого регистра будет 0013 hex = 19, т.к. счет ведется с 0 адреса (0014 hex = 20, -1 смещение нуля = получаем 0013 hex = 19).

Байт Запрос Байт Ответ
(Hex) Название поля (Hex) Название поля
11 Адрес устройства 11 Адрес устройства
01 Функциональный код 01 Функциональный код
00 05 Количество байт далее
13 CD Значение регистра DO 27-20 (1100 1101)
00 Количество регистров Hi байт 6B Значение регистра DO 35-28 (0110 1011)
25 Количество регистров Lo байт B2 Значение регистра DO 43-36 (1011 0010)
0E Контрольная сумма CRC 0E Значение регистра DO 51-44 (0000 1110)
84 Контрольная сумма CRC 1B Значение регистра DO 56-52 (0001 1011)
45 Контрольная сумма CRC
E6 Контрольная сумма CRC

Состояния выходов DO 27-20 показаны как значения байта CD hex, или в двоичной системе 1100 1101.

В регистре DO 56-52 5 битов справа были запрошены, а остальные биты заполнены нулями до полного байта (000 1 1011).

Модули с дискретным выводом: M-7065 , ioLogik R1214 , ADAM-4056S

Как послать команду Modbus RTU на чтение дискретного ввода? Команда 0x02

Эта команда используется для чтения значений дискретных входов DI.

Пример запроса DI с регистров от #10197 до 10218 для SlaveID адреса устройства 17. Адрес первого регистра будет 00C4 hex = 196, т.к. счет ведется с 0 адреса.

Байт Запрос Байт Ответ
(Hex) Название поля (Hex) Название поля
11 Адрес устройства 11 Адрес устройства
02 Функциональный код 02 Функциональный код
00 Адрес первого регистра Hi байт 03 Количество байт далее
C4 Адрес первого регистра Lo байт AC Значение регистра DI 10204-10197 (1010 1100)
00 Количество регистров Hi байт DB Значение регистра DI 10212-10205 (1101 1011)
16 Количество регистров Lo байт 35 Значение регистра DI 10218-10213 (0011 0101)
BA Контрольная сумма CRC 20 Контрольная сумма CRC
A9 Контрольная сумма CRC 18 Контрольная сумма CRC

Модули с дискретным вводом: M-7053 , ioLogik R1210 , ADAM-4051

Как послать команду Modbus RTU на чтение аналогового вывода? Команда 0x03

Эта команда используется для чтения значений аналоговых выходов AO.

Пример запроса AO с регистров от #40108 до 40110 для SlaveID адреса устройства 17. Адрес первого регистра будет 006B hex = 107, т.к. счет ведется с 0 адреса.

Байт Запрос Байт Ответ
(Hex) Название поля (Hex) Название поля
11 Адрес устройства 11 Адрес устройства
03 Функциональный код 03 Функциональный код
00 Адрес первого регистра Hi байт 06 Количество байт далее
6B Адрес первого регистра Lo байт AE Значение регистра Hi #40108
00 Количество регистров Hi байт 41 Значение регистра Lo #40108
03 Количество регистров Lo байт 56 Значение регистра Hi #40109
76 Контрольная сумма CRC 52 Значение регистра Lo #40109
87 Контрольная сумма CRC 43 Значение регистра Hi #40110
40 Значение регистра Lo #40110
49 Контрольная сумма CRC
AD Контрольная сумма CRC

Модули с аналоговым выводом: M-7024 , ioLogik R1241 , ADAM-4024

Как послать команду Modbus RTU на чтение аналогового ввода? Команда 0x04

Эта команда используется для чтения значений аналоговых входов AI.

Пример запроса AI с регистра #30009 для SlaveID адреса устройства 17. Адрес первого регистра будет 0008 hex = 8, т.к. счет ведется с 0 адреса.

Байт Запрос Байт Ответ
(Hex) Название поля (Hex) Название поля
11 Адрес устройства 11 Адрес устройства
04 Функциональный код 04 Функциональный код
00 Адрес первого регистра Hi байт 02 Количество байт далее
08 Адрес первого регистра Lo байт 00 Значение регистра Hi #30009
00 Количество регистров Hi байт 0A Значение регистра Lo #30009
01 Количество регистров Lo байт F8 Контрольная сумма CRC
B2 Контрольная сумма CRC F4 Контрольная сумма CRC
98 Контрольная сумма CRC

Модули с аналоговым вводом: M-7017 , ioLogik R1240 , ADAM-4017+

Как послать команду Modbus RTU на запись дискретного вывода? Команда 0x05

Эта команда используется для записи одного значения дискретного выхода DO.

Значение FF 00 hex устанавливает выход в значение включен ON.

Значение 00 00 hex устанавливает выход в значение выключен OFF.

Все остальные значения недопустимы и не будут влиять значение на выходе.

Нормальный ответ на такой запрос - это эхо (повтор запроса в ответе), возвращается после того, как состояние DO было изменено.

Пример записи в DO с регистром #173 для SlaveID адреса устройства 17. Адрес регистра будет 00AC hex = 172, т.к. счет ведется с 0 адреса.

Байт Запрос Байт Ответ
(Hex) Название поля (Hex) Название поля
11 Адрес устройства 11 Адрес устройства
05 Функциональный код 05 Функциональный код
00 Адрес первого регистра Hi байт 00 Адрес первого регистра Hi байт
AC Адрес первого регистра Lo байт AC Адрес первого регистра Lo байт
FF Значение Hi байт FF Значение Hi байт
00 Значение Lo байт 00 Значение Lo байт
4E Контрольная сумма CRC 4E Контрольная сумма CRC
8B Контрольная сумма CRC 8B Контрольная сумма CRC

Состояние выхода DO173 поменялось с выключен OFF на включен ON.

Модули с дискретным выводом: M-7053 , ioLogik R1210 , ADAM-4051

Как послать команду Modbus RTU на запись аналогового вывода? Команда 0x06

Эта команда используется для записи одного значения аналогового выхода AO.

Пример записи в AO с регистром #40002 для SlaveID адреса устройства 17. Адрес первого регистра будет 0001 hex = 1, т.к. счет ведется с 0 адреса.

Байт Запрос Байт Ответ
(Hex) Название поля (Hex) Название поля
11 Адрес устройства 11 Адрес устройства
06 Функциональный код 06 Функциональный код
00 Адрес первого регистра Hi байт 00 Адрес первого регистра Hi байт
01 Адрес первого регистра Lo байт 01 Адрес первого регистра Lo байт
00 Значение Hi байт 00 Значение Hi байт
03 Значение Lo байт 03 Значение Lo байт
9A Контрольная сумма CRC 9A Контрольная сумма CRC
9B Контрольная сумма CRC 9B Контрольная сумма CRC

Модули с аналоговым выводом: M-7024 , ioLogik R1241 , ADAM-4024

Как послать команду Modbus RTU на запись нескольких дискретных выводов? Команда 0x0F

Эта команда используется для записи нескольких значений дискретного выхода DO.

Пример записи в несколько DO с регистрами от #20 до #29 для SlaveID адреса устройства 17. Адрес регистра будет 0013 hex = 19, т.к. счет ведется с 0 адреса.

Байт Запрос Байт Ответ
(Hex) Название поля (Hex) Название поля
11 Адрес устройства 11 Адрес устройства
0F Функциональный код 0F Функциональный код
00 Адрес первого регистра Hi байт 00 Адрес первого регистра Hi байт
13 Адрес первого регистра Lo байт 13 Адрес первого регистра Lo байт
00 Количество регистров Hi байт 00
0A Количество регистров Lo байт 0A
02 Количество байт далее 26 Контрольная сумма CRC
CD Значение байт DO 27-20 (1100 1101) 99 Контрольная сумма CRC
01 Значение байт DO 29-28 (0000 0001)
BF Контрольная сумма CRC
0B Контрольная сумма CRC

В ответе возвращается количество записанных регистров.

Модули с дискретным выводом: M-7053 , ioLogik R1210 , ADAM-4051

Как послать команду Modbus RTU на запись нескольких аналоговых выводов? Команда 0x10

Эта команда используется для записи нескольких значений аналогового выхода AO.

Пример записи в несколько AO с регистрами #40002 и #40003 для SlaveID адреса устройства 17. Адрес первого регистра будет 0001 hex = 1, т.к. счет ведется с 0 адреса.

Байт Запрос Байт Ответ
(Hex) Название поля (Hex) Название поля
11 Адрес устройства 11 Адрес устройства
10 Функциональный код 10 Функциональный код
00 Адрес первого регистра Hi байт 00 Адрес первого регистра Hi байт
01 Адрес первого регистра Lo байт 01 Адрес первого регистра Lo байт
00 Количество регистров Hi байт 00 Кол-во записанных рег. Hi байт
02 Количество регистров Lo байт 02 Кол-во записанных рег. Lo байт
04 Количество байт далее 12 Контрольная сумма CRC
00 Значение Hi 40002 98 Контрольная сумма CRC
0A Значение Lo 40002
01 Значение Hi 40003
02 Значение Lo 40003
C6 Контрольная сумма CRC
F0 Контрольная сумма CRC

Мы разобрали общую структуру протокола ModBus. Сегодня мы рассмотрим разновидность этого протокола — ModBus TCP, которая используется для реализации ModBus в сетях Ethernet.

ModBus TCP всегда работает поверх TCP/IP стека, поэтому не может считаться полноценным ModBus протоколом в его классическом виде.

Основное отличие, которое накладывает TCP/IP на ModBus при их совместном использовании — непосредственное подключение к определённому адресу. Протокол TCP/IP устроен по принципу «клиент-сервер». Для обмена данными клиент открывает сеанс связи с сервером, указывая его адрес.

Переходя на терминологию протокола ModBus ведущее устройство (мастер) в TCP-сети становится клиентом (т.к. именно клиент является инициатором обмена данными), а подчинённое устройство (слейв) — сервером.

Таким образом, для того чтобы передать запрос подчинённому устройству в TCP-сети мастер должен сначала открыть сеанс связи с ним. Причём открытие сеанса реализуется не на уровне протокола ModBus, а на уровне TCP/IP. Поэтому ведущее устройство не может средствами ModBus передавать запросы разным устройствам, так же, как это происходит в ModBus RTU или ASCII.

По этой же причине в ModBus TCP отсутствуют широковещательные сообщения (сразу всем подчинённым устройствам).

Однако, Master-устройство может подключаться к необходимому узлу (слейву) средствами протокола TCP/IP, а затем уже общаться с ним на языке ModBus.

На рисунке рабочее место диспетчера под управлением SCADA-системы является сервером сбора данных и одновременно мастером в сети ModBus TCP. Оно последовательно подключается к каждому удалённому контроллеру, открывая сеанс связи в сети TCP/IP и обменивается с ним ModBus-пакетами.

Безусловно, такой обмен происходит дольше, чем в случае ModBus RTU, т.к. дополнительное время уходит на открытие и закрытие сеанса TCP/IP. Однако, это даёт возможность объединить устройства находящиеся на значительном удалении витой парой или даже по WiFi.

Кроме того, протокол ModBus TCP может использоваться в сетях со шлюзом, где шлюз является интеллектуальным устройством и маршрутизирует сообщения остальным устройствам сети ModBus.

При такой конфигурации клиент сети TCP (он же мастер сети ModBus) подключается к шлюзу (серверу) и ведёт общение только с ним. Шлюз же переадресует сообщение внутри шины ModBus (RTU или ASCII) тому устройству, адрес которого указан в ModBus-пакете.

Структура пакета ModBus TCP

Сначала вспомним структуру классического ModBus-пакета (RTU или ASCII):

Он состоит из четырёх блоков: адрес слейва, номер функции, блок данных и блок контроля чётности.

А вот так выглядит структура пакета ModBus TCP:

Как вы можете видеть, в пакете ModBus TCP по сравнению с ModBus RTU добавлены блоки идентификаторов обмена и протокола, а так же от отсутствует блок контроля подлинности пакета. Последнее объясняется тем, что контроль целостности пакета обеспечивается средствами протокола TCP/IP, поэтому отпадает необходимость в его ModBus-реализации.

Рассмотрим что означает каждый из блоков пакета ModBus TCP:

  • id обмена — чаще всего два нуля. Применяется только в том случае, если мастер отсылает подчинённому устройству несколько запросов подряд без ожидания ответа. При этом id позволяет затем понять какому из запросов какой ответ соответствует.
  • id протокола — всегда нули, не применяется. Поле оставлено в качестве резерва для будующих применений.
  • длина пакета — совокупная длина блоков «адрес», «номер функции» и «данные». Длина пакета передаётся двумя байтами, первым из которых идет старший.
  • адрес ведомого устройства — аналог такого же блока в структуре пакета ModBus RTU, но обычно не используется, т.к. ,как уже говорилось, в ModBus TCP мастер и так открывает сеанс обмена только с одним слейвом (у которого, конечно, есть и IP адрес в сети TCP/IP). Данное поле используется только в варианте ModBus TCP-сети со шлюзом. Тогда шлюз сам перенаправляет пакет по указанному адресу.
  • поля код функции и данные аналогичны соответствующим полям в классическом ModBus-пакете.

Одним из преимуществ Modbus является отсутствие необходимости в специальных интерфейсных контроллерах (Profibus и CAN требуют для своей реализации заказные микросхемы), простота программной реализации и элегантность принципов функционирования. Все это снижает затраты на освоение стандарта как системными интеграторами, так и разработчиками контроллерного оборудования. Высокая степень открытости протокола обеспечивается также полностью бесплатными текстами стандартов, которые можно скачать с сайта www.modbus.org.

В России Modbus по распространенности конкурирует только с Profibus. Популярность протокола в настоящее время объясняется, прежде всего, совместимостью с большим количеством оборудования, которое имеет протокол Modbus. Кроме того, Modbus имеет высокую достоверность передачи данных, связанную с применением надежного метода контроля ошибок. Modbus позволяет унифицировать команды обмена благодаря стандартизации номеров (адресов) регистров и функций их чтения-записи.

Основным недостатком Modbus является сетевой обмен по типу "ведущий/ведомый", что не позволяет ведомым устройствам передавать данные по мере их появления и поэтому требует интенсивного опроса ведомых устройств ведущим.

Разновидностями Modbus являются протоколы Modbus Plus [Modicon ] - многомастерный протокол с кольцевой передачей маркера и Modbus TCP [Modbus ], рассчитанный на использование в сетях Ethernet и интернет.

Протокол Modbus имеет два режима передачи: RTU (Remote Terminal Unit – «удаленное терминальное устройство») и ASCII. Стандарт предусматривает, что режим RTU в протоколе Modbus должен присутствовать обязательно, а режим ASCII является опционным. Пользователь может выбирать любой из них, но все модули, включенные в сеть Modbus, должны иметь один и тот же режим передачи.

Мы рассмотрим только протокол Modbus RTU, поскольку Modbus ASCII в России практически не используется. Отметим, что Modbus ASCII нельзя путать с частно-фирменным протоколом DCON, который используется в модулях фирм Advantech и ICP DAS и не соответствует стандарту Modbus.

Стандарт Modbus предусматривает применение физического интерфейса RS-485, RS-422 или RS-232. Наиболее распространенным для организации промышленной сети является 2-проводной интерфейс RS-485. Для соединений точка-точка может быть использован интерфейс RS-232 или RS-422.

В стандарте Modbus имеются обязательные требования, рекомендуемые и опционные (необязательные). Существует три степени соответствия стандарту: «полностью соответствует» - когда протокол соответствует всем обязательным и всем рекомендуемым требованиям, «условно соответствует» - когда протокол соответствует только обязательным требованиям и не соответствует рекомендуемым, и «не соответствует».

Модель OSI протокола Modbus содержит три уровня: физический, канальный и прикладной.

По умолчанию в RTU режиме бит паритета устанавливают равным 1, если количество двоичных единиц в байте нечетное, и равным 0, если оно четное. Такой паритет называют четным (even parity) и метод контроля называют контролем четности .

Стартовый бит

Бит паритета

Рис. 2.26. Последовательность битов в режиме RTU; МЗР – младший значащий разряд. При отсутствии бита паритета на его место записывается второй стоп-бит

При четном количестве двоичных единиц в байте бит паритета может быть равен 1. В этом случае говорят, что паритет является нечетным (odd parity).

Контроль четности может отсутствовать вообще. В этом случае вместо бита паритета должен использоваться второй стоповый бит. Для обеспечения максимальной совместимости с другими продуктами рекомендуется использовать возможность замены бита паритета на второй стоповый бит.

Ведомые устройства могут воспринимать любой из вариантов: четный, нечетный паритет или его отсутствие.

Структура Modbus RTU сообщения

Сообщения Modbus RTU передаются в виде кадров, для каждого из которых известно начало и конец. Признаком начала кадра является пауза (тишина) продолжительностью не менее 3,5 шестнадцатеричных символов (14 бит). Кадр должен передаваться непрерывно. Если при передаче кадра обнаруживается пауза продолжительностью более 1,5 шестнадцатеричных символа (6 бит), то считается, что кадр содержит ошибку и должен быть отклонен принимающим модулем. Эти величины пауз должны строго соблюдаться при скоростях ниже 19200 бит/с, однако при более высоких скоростях рекомендуется использовать фиксированные значения паузы, 1,75 мс и 750 мкс соответственно.

Контроль ошибок

В режиме RTU имеется два уровня контроля ошибок в сообщении:

    контроль паритета для каждого байта (опционно);

    контроль кадра в целом с помощью CRC метода.

CRC метод используется независимо от проверки паритета. Значение CRC устанавливается в ведущем устройстве перед передачей. При приеме сообщения вычисляется CRC для всего сообщения и сравнивается с его значением, указанным в поле CRC кадра. Если оба значения совпадают, считается, что сообщение не содержит ошибки.

Стартовые, стоповые биты и бит паритета в вычислении CRC не участвуют.

2.8.3. Прикладной уровень

Прикладной уровень Modbus RTU версии 1.1а описан в [Modbus ]. Он обеспечивает коммуникацию между устройствами типа "ведущий/ведомый". Прикладной уровень является независимым от физического и канального, в частности, он может использовать протоколы Ethernet TCP/IP (Modbus TCP/IP), Modbus Plus (многомастерная сеть с передачей маркера), интерфейсы RS-232, RS-422, RS-485, оптоволоконные, радиоканалы и другие физические среды для передачи сигналов.

Прикладной уровень Modbus основан на запросах с помощью кодов функций . Код функции указывает ведомому устройству, какую операцию оно должно выполнить.

При использовании протокола прикладного уровня с различными протоколами транспортного и канального уровня сохраняется неизменным основной блок Modbus-сообщения, включающий код функции и данные (этот блок называется PDU - "Protocol Data Unit" - "элемент данных протокола"). К блоку PDU могут добавляться дополнительные поля при использовании его в различных промышленных сетях и тогда он называется "ADU " - "Application Data Unit" - "элемент данных приложения".

Коды функций

Стандартом Modbus предусмотрены три категории кодов функций: установленные стандартом, задаваемые пользователем и зарезервированные.

Коды функций являются числами в диапазоне от 1 до 127. Коды в диапазоне от 65 до 72 и от 100 до 110 относятся к задаваемым пользователем функциям, в диапазоне от 128 до 255 зарезервированы для пересылки кодов ошибок в ответном сообщении. Код «0» не используется.

Коды ошибок используются ведомым устройством, чтобы определить, какое действие предпринять для их обработки. Значения кодов и их смысл описаны в стандарте на Modbus RTU [Modbus ].

Обозначение регистра

HEX адрес регистра

Что читается или записывается

Код функции чтения регистра

Код функции записи в регистр

Примечание

Дискр. выход 0

Дискр. выход 1

Дискр. вход 0

Дискр. вход 1

Дискр. вход 2

Дискр. вход 3

Дискр. вход 4

Дискр. вход 5

Дискр. вход 6

Дискр. вход 7

Дискр. вход 8

Дискр. вход 9

Дискр. вход 10

Дискр. вход 11

Дискр. вход 12

Дискр. вход 13

Дискр. вход 14

Дискр. вход 15

Имя модуля

Версия программы

Адрес модуля

0001h-00 F7h (Допустимый диапазон значений)

Скорость UART

(Допустимый диапазон значений)

Протокол

0000h– ASCII,

Значение на выходе после включения питания модуля Power On Value0

0000h-0003 h (Допустимый диапазон значений)

Ну что же, пора рассмотреть, чем протокол Modbus TCP отличается от протокола Modbus RTU . Так как отличий не очень много, то и статья будет не очень большая.
Итак, в предыдущей стать о функциях Modbus RTU можно узнать, какие есть функции и их бинарный формат. Теперь стоит рассказать что такое Modbus TCP , как он применяется и чем отличается от стандартного Modbus RTU .

Modbus RTU через TCP соединение

Самый простой способ обмена Modbus сообщениями через сеть – просто передавать Modbus RTU пакеты через TCP сокет (соединение). В этом случае формат пакетов такой же, как и для Modbus RTU протокола. В принципе на этом можно и закончить по этому типу протокола.

Modbus TCP

Для обмена Modbsu сообщениями по сети решили использовать модифицированный протокол. Взяли стандартный Modbus RTU и немного его изменили. Во-первых убрали из него последних 2 байта CRC16 . Так как каждый пакет TCP/IP содержит свою контрольную суму, решили что делать проверку еще раз не нужно. Кроме того убрали первый байт Slave ID . В принципе, Как будет видно дальше, Его не убрали, а просто переименовали. Вот эти байты, без Slave ID и CRC16 назвали PDU – Protocol Data Unit .

Например, возьмем запрос Modbus RTU , который читает несколько HOLDING регистров с устройства #17 (Slave ID = 17)

11 03 006B 0003 7687

Теперь убираем первый и последних 2 байта. Получаем PDU !

03 006B 0003

С этим вроде все ясно. Теперь, что бы получить полноценный пакет Modbus TCP нам нужно добавить впереди MBAP Header — Modbus Application Header . Т.е. нам нужно добавить некий заголовок. Этот заголовок включает в себя Transaction ID , Protocol ID , Length и Unit ID .

Transaction ID – 2 байта, которые устанавливаются клиентом, что бы однозначно идентифицировать каждый запрос. Т.е. это просто число от 0 до 65535 уникальное для каждого запроса.

Protocol ID – 2 байта, которые определяют версию протокола. В текущей реализации всегда должны быть равны 0x00 0x00

Length – 2 байта, которые определяют длину пакета (за исключением байтов Protocol ID , Transaction ID и Length )

Unit ID – уникальный адрес устройства, которое опрашивается данной командой. Идентично Slave ID .

Небольшое отступление по поводу адресации. Может показаться что это излишне, так как TCP соединение может быть установлено только на конкретный IP адрес и порт. Т.е. у нас уже есть конкретный адрес сервера, поэтому назначение Unit ID не совсем понятно.

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

Пример Modbus TCP сервера, который используется как шлюз для перенаправления запросов на Modbus RTU устройства

Вот пример из жизни. Есть некое устройство основанное на Linux. Это устройство выступает Modbus TCP сервером. Любой клиент может подсоединиться к публичному IP адресу на порт 502 и инициировать Modbus TCP соединение. К данному Linux устройству подключены сенсоры, которые использую последовательный порт RS485. Сенсоров много, они очень простые и не могут быть подключены к Internet, у них есть только порт RS485 и они понимают только Modbus RTU . Поэтому клиенты посылают Modbus TCP запросы с Unit ID сенсоров на Modbus TCP Сервер. Сервер декодирует Modbus TCP запрос и преобразует его в Modbus RTU и отправляет в порт RS485. После того как сенсор отвечает ему, он преобразует Modbus RTU ответ в Modbus TCP ответ и отсылает его назад, к Modbus TCP клиенту, который инициировал запрос. Таким образом, имея всего один публичный IP адрес можно опрашивать онлайн сотню сенсоров, которые даже не могут быть подсоединены к Интернету или локальной сети.

А теперь наглядная схема, чем отличается Modbus RTU запрос от Modbus TCP запроса.

Посмотрим пример байтов для двух запросов:

Modbus RTU: 11 03 006B 0003 7687 Modbus TCP: 0001 0000 0006 11 03 006B 0003

Пример ответа:

Modbus TCP: 0001 0000 0009 11 03 06 AE41 5652 4340 Modbus RTU: 11 03 06 AE41 5652 4340 49AD

Как видите, конвертировать запросы между Modbus RTU и Modbus TCP очень просто. Хотя реализация Modbus RTU через TCP может показаться самым простым способом для маршрутизации запросов, на самом деле в Modbus TCP есть несколько положительных моментов:

  • Не нужно вычислять CRC16
  • Есть возможность идентифицировать пару ответ / запрос используя Transaction ID
  • Можно легко добавлять свои версии протоколов, меняя константу Protocol ID

В этой статье я попытаюсь рассказать как устроен протокол Modbus , какие данные он может хранить, в каком виде они могут храниться, как они могут быть считаны. Эта статья даст представление о том, что же такое Modbus протокол и как он может применяться.

Адресация данных в Modbus протоколе

Для хранения информации в ведомых устройствах (slave device ) используются 4 таблицы (или массива). Каждая таблица хранит информацию для схожих переменных в регистрах. Каждый регистр имеет свой размер и адрес. Так же регистры могут быть только для чтения, или для чтения – записи. Давайте рассмотрим эти 4 типа данных, которые можно хранить в регистрах:

COILS

Это цифровые выходы (Digital Outputs ). Каждый coil можно записать или считать. Его размер – 1 бит (т.е. 0 или 1). Исторически эти регистры связаны с реальными цифровыми выходами на сенсорах или терминальных устройствах. Цифровые выходы используются для управления, например светодиодами, реле или моторами. Т.е. записывая в такой регистр 1 мы можем включить светодиод, а записав 0 – выключить его (это условно, на самом деле 0 может включать, а 1 – выключать).

При чтении данного регистра мы можем узнать состояние выхода (т.е. включен он или выключен). Результат чтения так же 1 бит, т.е. 1 или 0.

CONTACTS

Это цифровые входы (Digital Inputs ). Цифровой вход можно только читать, т.е считывая данный регистр мы узнаем состояние реального цифрового входа на сенсоре или устройстве. Цифровые входы используются для контроля состояние – например, включен свет или выключен, достигла жидкость нужного уровня или нет, включено реле или нет, и т.д.

ANALOG INPUT REGISTERS

Под этим обычно имеются в виду аналоговые входы (Analog Inputs ). Аналоговые входы можно только читать, т.е их нельзя записывать, а можно только считать текущее состояние налогового входа. Обычно аналоговые входы применяются на сенсорах для измерение некоторых значений: входного тока или входного напряжения. Затем, полученное значение можно конвертировать в некоторую реальную величину, например в температуру, влажность воздуха, давление или еще что то. Для этого используются специальные формулы, которые идут вместе с сенсором. Но чаще сенсор сразу возвращает реальное значение. Например, сенсор измеряющий температуру, может возвращать измеренное значение как градусы по Цельсию умноженные на 10. Т.е. 253 означает 25.3°С. Этот прием часто используется, если нужно вернуть дробные значения через целочисленный регистр.

ANALOG OUTPUT HOLDING REGISTERS

Под этим обычно имеются в виду аналоговые выходы (Analog Outputs ) но так же часто просто регистры, которые хранят некоторые значения, которые можно как записывать, так и считывать. Т.е. эти регистры можно как читать, так и писать. Наиболее часто используются для записи DAC устройств (Digital to Analog Converter) или просто как регистры, хранящие некоторые значения. DAC часто используются для управления чем либо, например: яркостью свечения светодиода, или громкостью сирены, или скоростью вращения двигателя.

Эти регистры 16 битные, т.е. каждый регистр может хранить всего 2 байта.

Вот эти четыре типа регистров поддерживаются в стандартном Modbus . И используя только их, нужно строить систему. Если взглянуть с точки зрения конечного устройства (slave device), то регистры логичнее всего использовать для следующих нужд:

Coils – для управления устройствами через цифровые порты вывода или булевыми флагами типа включен/выключен, открыт / закрыт и т.д.

Contacts – для хранения значений булевых флагов или для отображения информации с цифровых входов.

Inputs –для значений, которые нужно только читать на стороне мастера, и которые могут быть представлены как 16 битные целые числа. Например, входы ADC, или какие о значения, генерируемые системой которые нужно читать (например количество запущенных процессов или внутренняя температура устройства может быть считана через некий Input регистр)

Holding – эти регистры можно использовать для хранения конфигурации устройства, для управления DAC устройствами, для хранения некоторой служебной информации. В принципе, эти регистры можно использовать для чего угодно, на что хватит фантазии разработчика системы.

Кроме того, каждый регистр в схеме Modbus может иметь уникальный адрес, который определяется типом регистра. Посмотрите таблицу ниже:

Имя Тип Доступа Адреса Доступно Регистров
Coils Чтение / Запись 1 – 9999 9999
Contacts Чтение 10001 – 19999 9999
Inputs Чтение 30001 – 39999 9999
Holdings Чтение / Запись 40001 – 49999 9999

Как видно из таблицы, каждый тип регистров может вмещать максимум 9999 регистров. Но все они начинаются с некоторого смещения: 0, 10000, 30000, 40000.

На самом деле, внутри команд протокола Modbus , используется не полный адрес, а только его смещение относительно базового адреса. Т.е. для всех типов регистров реальный адрес внутри команды будет 0 -9998. А команда определяет какой именно базовый адрес может быть использован.

Проще всего представить себе, что устройство хранит 4 массива элементов по 9999 элементов в каждом. Индекс внутри массива – это и есть адрес, который задается внутри команды. А команда определяет, какой массив нужно использовать.

Если внимательно посмотреть на таблицу, то видно, что при желании можно использовать больше адресов для Holding регистров: 40001 – 105537, т.е. всего 65535 регистров. То же самое для Contacts : 10001 – 29999, т.е. всего 19999. Это так называемые расширенные регистры. Они не поддерживаются стандартными Modbus устройствами. Поэтому, если вы хотите, что бы ваше устройство могло работать со стандартными клиентами, то не нужно использовать расширенные регистры.

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

Выше мы разобрались, как адресуются регистры внутри устройства. Теперь посмотрим, как адресуются сами устройства.

Адресация Modbus устройств

Для адресации устройств используется специальный идентификатор, который называется Slave Id . Это однобайтное значение, которое определяет уникальный адрес устройства на всей сети Modbus . По стандарту Modbus это может быть число от 1 до 247. Т.е. всего в сети может находиться 247 конечных устройств (slave device) с уникальными адресами.

Когда мастер посылает команду в сеть, первый байт – это Slave Id . Это позволяет устройствам уже после первого байта определить, должны они обрабатывать команду, или могут ее проигнорировать. Это справедливо для Modbus RTU . Для Modbus TCP протокола используется Unit Id значение. Хотя если разобраться, это просто другое название Slave Id . Unit Id – это так же однобайтный адрес устройства, от 1 до 247.

Это очень сильно ограничивает количество устройств, которые одновременно могут находиться в сети. Поэтому есть вариант, когда используется 2 байта для адресации устройств. В таком случае количество устройств увеличивается до 65535. Этого более чем достаточно. Но есть одно условие. Мастер и Конечное устройство должны использовать 2 байте для адресации. Т.е. они должны быть настроены, что бы использовать одинаковую схему адресации устройств: 1 или 2 байта. Так же, все устройства в сети должны использовать ту же самую схему адресации – 1 или 2 байта. Не может быть в сети устройств с разной схемой адресации.

Функции Modbus

Для того, что бы запросить данные или записать их, мастер должен указать функции, которую он хочет исполнить на конечном устройстве. Все доступные функции в стандартном Modbus протоколе приведены ниже:

Код Функции Тип Действия Описание
01 (01 hex) Чтение Читает значение Coil регистра
02 (02 hex) Чтение Читает значение Contact регистра
03 (03 hex) Чтение Читает значение Holding регистра
04 (04 hex) Чтение Читает значение Input регистра
05 (05 hex) Запись одного регистра Записывает значение в Coil регистр
06 (06 hex) Запись одного регистра Записывает значение в Holding регистр
15 (0F hex) Запись нескольких регистров Записывает значение в несколько Coil регистров
16 (10 hex) Запись нескольких регистров Записывает значение в несколько Holding регистров

Каждая функция будет рассмотрена позже, подробно и с примерами.

CRC 16 как способ избежать ошибок

Каждая команда в Modbus RTU протоколе заканчивается двумя байтами, которые содержать CRC16 значение всех байт команды. Добавление CRC16 позволяет найти поврежденные запросы и игнорировать их. Так как для вычисления контрольной суммы используется каждый байт в команде, то даже изменение одного бита в любом байте вызовет расхождение в переданной контрольной сумме и вычисленной на основе полученных байт. Это достаточно надежный способ обезопасить передаваемые данные от повреждений (имеется в виду, найти поврежденные данные). Клиент, как и мастер, должны проверять CRC16 из полученной команды с CRC16 сгенерированным на основе полученных байт. Если контрольные суммы не совпадают, значит полученный запрос содержит поврежденные байты, что искажает смысл посланной команды. Такая команда должна быть проигнорирована.

Нужно заметить, CRC16 не используется в Modbus TCP протоколе. Так как TCP пакеты уже имеют свою встроенную контрольную сумму и проверяются на целостность данных, нет никакой необходимости для вычисления CRC16.

Еще в одной разновидности Modbus протокола, Modbus ASCII , используется LRC (Longitudinal Redundancy Check) вместо CRC16. LRC намного проще чем CRC16 и результатом является 1 байт. LRC менее надежно для детектирования ошибок повреждения данных, но исторически так сложилось что Modbus ASCII использует именно этот метод.

О том, как вычислять CRC16 для Modbus RTU протокола и LRC для Modbus ASCII протокола, я напишу отдельно.

Типы данных, которые хранятся в регистрах.

Поговорим о том, какие данные могут храниться в регистрах. Самый простой случай – это Coil и Contac регистры. В этих регистрах может храниться 1 бит информации – 0 или 1. Когда мастер читает эти регистры, он получает в результате 0 или 1. Для записи регистров используются специальные константы:

0xFF00 – означает логическую 1

0x0000 – означает логический 0

Если используется команда для записи нескольких регистров, то каждый регистр будет записан при помощи 1 бита: 0 или 1.

Все остальные регистры – это 16 битные данные (2 байта)

И вот тут самое интересное.

Интерпретация данных должна быть задана в описании Modbus регистров (так называемом Modbus Map документе). В этом документе нужно точно прописать, какой регистр хранит какие джанные, и какие значение для него приемлемы.

Начнём с простых случаев.

Если мы считываем 1 Input или Holding регистр, то мы получаем 16 бит данных. Например, это может быть значение 0x8D05 – два байта 0x8D и 0x05 .

В самом простом случае это может быть без знаковое целое значение: 36101

Но это может быть целое число со знаком: -29435

Другой пример. Мы прочитали значение 0x4D4F

Это может быть как целое без знака, целое со знаком, так и 2 символа в кодировке ASCII:

0x4D = M

0x4F = O

Теперь случай поинтереснее. Комбинируя несколько регистров вместе, мы можем хранить типы данных, размер которых больше 16 бит.

К примеру, мы прочитали 2 регистра, и получили следующие данные: 0xAE53 0x544D

Это может быть:

32 битное целое без знака

0xAE53 0x544D = 2924696653

32 битное целое со знаком

0xAE53 0x544D = -1370270643

32 битный float – число с плавающей точкой

0xAE53 0x544D = -4.80507e-11

Или хранить 4 символа в кодировке ASCII

0xAE53 0x544D = 0xAE 0x53 0x54 0x4D = ®STM

Если продолжать, то комбинируя больше регистров, можно хранить 64 битные значения, 128 битные значения, строки и в принципе любые типы данных.

Но, комбинируя регистры, у нас встает следующий вопрос:

Порядок байт и слов

К сожалению протокол Modbus не определяет как должны храниться байты внутри регистра. Т.е. различные устройства от различных производителей могут хранить байты в произвольном порядке.

Например, читая регистр, мы получили значение 0xA543

В зависимости от того, в каком порядке хранились байты в исходном регистре, это могут быть два абсолютно разных значения:

Если использовался Big Endian формат (старший байт первый), то у нас будет значение 42307

Но если использовался Little Endian формат (младший байт первым), то у нас будет значение 17317

Еще интереснее, когда мы формируем 32 битное значение из двух регистров.

Вариантов комбинации байтов становится 4. К примеру 32 битное число 4014323619 (0xEF45B7A3 ) может быть передано 4 следующими последовательностями байтов:

0xEF45 0xB7A3

0x45EF 0x A3B7

0xB7A3 0xEF45

0x A3B7 0x45EF

На самом деле это не важно, какой порядок байт / слов реализован на конечном устройстве. Главное, мастер должен знать этот порядок, и уметь формировать правильные значения из полученных байтов. Зная точный формат данных на конечном устройстве, мастер всегда будет правильно формировать значения регистров. И именно для этого существует такое понятие как Modbus Map (Карта Modbus ).

Modbus Map

Modbus Map – это документация, которая полностью описывает все возможные Modbus регистры на устройстве, их адреса, назначение, доступные значения, значения по умолчанию, способ доступа.

Некоторые устройства поставляются с фиксированным описанием регистров. Т.е. список регистров, их адресов, хранимых данных и т.д. жестко задан производителем и описан в документации.

А есть настраиваемая конфигурация. Т.е. на устройстве нет фиксированных адресов для регистров. Пользователь может сконфигурировать Modbus Map так, как ему нужно (например соединив некоторые регистры в непрерывную последовательность адресов, что бы считывать их одной командой).

Пример фиксированного Modbus Map , который имеет смысл применять для своих устройств, может выглядеть так, как в таблице ниже.

Адрес Описание Доступ Значение по умолчанию Доступные значения
40001 Код продукта Чтение 1 1
40002 Командный регистр, для записи команд Запись 0 – сброс устройства
1 – Разблокировать uSD карту для записи
2 – Заблокировать uSD карту для записи
3 – Созранить конфигурацию на uSD карту
40003 Время работы, в секундах
Младшее слово
Чтение 0 0 .. 0xFFFF
40004 Время работы, в секундах
Старшее слово
Чтение 0 0 .. 0xFFFF
40005 Системная ошибка Чтение / Запись 0 Смотри приложение с кодами ошибок.
Запись 0 для сброса ошибки и выключения ERROR LED

Чего не может Modbus

Modbus очень простой протокол, поэтому он поддерживает далеко не все, что может потребоваться.

Modbus не поддерживает сообщения (events). Т.е. конечное устройство не может послать сообщение мастеру. Только мастер может опросить конечное устройство.

Modbus не поддерживает чтение исторических данных (накопленных за некоторый промежуток времени). Хотя это ограничение можно легко обойти, создав командные регистры, регистры адреса и перегружаемые регистры. Это будет обсуждаться в одной из следующих статей.

Стандартный Modbus не может хранить сложные структурированные данные (по крайней мере это не так просто реализовать).

Кроме того, Modbus не поддерживает идентификации и шифрования. Т.е вся коммуникация идет в незащищённом режиме. Хотя, при некотором желании можно реализовать некоторое подобие идентификации в Modbus TCP в большинстве случаев это сделать невозможно. Есть некоторые варианты как защитить данные от несанкционированного доступа и изменения, но они все не очень надежные (хотя и могут применятся). Я опишу их в следующих статьях.

И кажется, это все явные недостатки для этого протокола. В остальном он очень прост и отлично подходит для простых систем мониторинга, которые должны следить за некоторыми показателями системы и предоставлять доступ к ним через чтение регистров.

В следующей статье мы рассмотрим все основные функции, которые поддерживаются протоколом Modbus .