В этой статье вы узнаете о протоколе Modbus TCP, который является развитием протокола Modbus RTU. Англоязычная версия статьи доступна на ipc2u.com.
Оглавление:
- Куда посылать команду Modbus TCP?
- Описание протокола Modbus TCP
- Типы команд Modbus TCP
- Как послать команду на чтение дискретного вывода? Команда 0x01
- Как послать команду на чтение дискретного ввода? Команда 0x02
- Как послать команду на чтение аналогового вывода? Команда 0x03
- Как послать команду на чтение аналогового ввода? Команда 0x04
- Как послать команду на запись дискретного вывода? Команда 0x05
- Как послать команду на запись аналогового вывода? Команда 0x06
- Как послать команду на запись нескольких дискретных выводов? Команда 0x0F
- Как послать команду на запись нескольких аналоговых выводов? Команда 0x10
- Ошибки запроса Modbus TCP
- Программы для работы с протоколом Modbus TCP
Куда посылать команду Modbus TCP?
В сети Ethernet адресом устройства является его IP-адрес. Обычно устройства находятся в одной подсети, где IP адреса отличаются последними цифрами 192.168.1.20 при использовании самой распространённой маски подсети 255.255.255.0.
Интерфейсом является сеть Ethernet, протоколом передачи данных – TCP/IP.
Используемый TCP-порт: 502.
Наверх к оглавлению
Описание протокола Modbus TCP
Команда Modbus TCP состоит из части сообщения Modbus RTU и специального заголовка.
О Modbus RTU написано в этой статье.
Из сообщения Modbus RTU удаляется SlaveID адрес в начале и CRC контрольная сумма в конце, что образует PDU, Protocol Data Unit.
Ниже приведен пример запроса Modbus RTU для получения значения AO аналогового выхода (holding registers) из регистров от #40108 до 40110 с адресом устройства 17.
11 03 006B 0003 7687
11 | Адрес устройства SlaveID (17 = 11 hex) |
03 | Функциональный код Function Code (читаем Analog Output Holding Registers) |
006B | Адрес первого регистра (40108-40001 = 107 =6B hex) |
0003 | Количество требуемых регистров (чтение 3-х регистров с 40108 по 40110) |
7687 | Контрольная сумма CRC |
Отбрасываем адрес устройства SlaveID и контрольную сумму CRC и получаем PDU:
03 006B 0003
К началу получившегося сообщения PDU добавляется новый 7-байтовый заголовок, который называется MBAP Header (Modbus Application Header). Этот заголовок имеет следующие данные:
Transaction Identifier (Идентификатор транзакции): 2 байта устанавливаются Master, чтобы однозначно идентифицировать каждый запрос. Может быть любыми. Эти байты повторятся устройством Slave в ответе, поскольку ответы устройства Slave не всегда могут быть получены в том же порядке, что и запросы.
Protocol Identifier (Идентификатор протокола): 2 байта устанавливаются Master, всегда будут = 00 00, что соответствует протоколу Modbus.
Length (Длина): 2 байта устанавливаются Master, идентифицирующие число байтов в сообщении, которые следуют далее. Считается от Unit Identifier до конца сообщения.
Unit Identifier (Идентификатор блока или адрес устройства): 1 байт устанавливается Master. Повторяется устройством Slave для однозначной идентификации устройства Slave.
Итого получаем:
Modbus RTU | Slave ID | Запрос | CRC |
---|---|---|---|
Modbus RTU | 11 | 03 006B 0003 | 7687 |
Modbus TCP | 0001 0000 0006 11 | 03 006B 0003 | |
Modbus TCP | MBAP Header | PDU | |
Modbus TCP | ADU, Application Data Unit |
Где:
0001 | Идентификатор транзакции | Transaction Identifier |
0000 | Идентификатор протокола | Protocol Identifier |
0006 | Длина (6 байтов идут следом) | Message Length |
11 | Адрес устройства (17 = 11 hex) | Unit Identifier |
03 | Функциональный код (читаем Analog Output Holding Registers) | Function Code |
006B | Адрес первого регистра (40108-40001 = 107 =6B hex) | Data Address of the first register |
0003 | Количество требуемых регистров (чтение 3-х регистров с 40108 по 40110) | The total number of registers |
В ответе от Modbus TCP Slave устройства мы получим:
0001 0000 0009 11 03 06 022B 0064 007F
Где:
0001 | Идентификатор транзакции | Transaction Identifier |
0000 | Идентификатор протокола | Protocol Identifier |
0009 | Длина (9 байтов идут следом) | Message Length |
11 | Адрес устройства (17 = 11 hex) | Unit Identifier |
03 | Функциональный код (читаем Analog Output Holding Registers) | Function Code |
06 | Количество байт далее (6 байтов идут следом) | Byte Count |
02 | Значение старшего разряда регистра (02 hex) | Register value Hi (AO0) |
2B | Значение младшего разряда регистра (2B hex) | Register value Lo (AO0) |
00 | Значение старшего разряда регистра (00 hex) | Register value Hi (AO1) |
64 | Значение младшего разряда регистра (64 hex) | Register value Lo (AO1) |
00 | Значение старшего разряда регистра (00 hex) | Register value Hi (AO2) |
7F | Значение младшего разряда регистра (7F hex) | Register value Lo (AO2) |
Регистр аналогового выхода AO0 имеет значение 02 2B HEX или 555 в десятичной системе.
Регистр аналогового выхода АО1 имеет значение 00 64 HEX или 100 в десятичной системе.
Регистр аналогового выхода АО2 имеет значение 00 7F HEX или 127 в десятичной системе.
Наверх к оглавлению
Типы команд Modbus TCP
Приведем таблицу с кодами функций чтения и записи регистров Modbus TCP.
Код функции | Что делает функция | Тип значения | Тип доступа | |
---|---|---|---|---|
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 TCP на чтение дискретного вывода? Команда 0x01
Эта команда используется для чтения значений дискретных выходов DO.
В запросе PDU задается начальный адрес первого регистра DO и последующее количество необходимых значений DO. В PDU значения DO адресуются, начиная с нуля.
Значения DO в ответе находятся в одном байте и соответствуют значению битов.
Значения битов определяются как 1 = ON и 0 = OFF.
Младший бит первого байта данных содержит значение DO адрес которого указывался в запросе. Остальные значения DO следуют по нарастающей к старшему значению байта. Т.е. справа налево.
Если запрашивалось меньше восьми значений DO, то оставшиеся биты в ответе будут заполнены нулями (в направлении от младшего к старшему байту). Поле Byte Count Количество байт далее указывает количество полных байтов данных в ответе.
Байт | Запрос | Байт | Ответ |
---|---|---|---|
(Hex) | Название поля | (Hex) | Название поля |
01 | Идентификатор транзакции | 01 | Идентификатор транзакции |
02 | 02 | ||
00 | Идентификатор протокола | 00 | Идентификатор протокола |
00 | 00 | ||
00 | Длина сообщения | 00 | Длина сообщения |
06 | 04 | ||
01 | Адрес устройства | 01 | Адрес устройства |
01 | Функциональный код | 01 | Функциональный код |
00 | Адрес первого регистра Hi байт | 01 | Количество байт далее |
00 | Адрес первого регистра Lo байт | 02 | Значение регистра DO 0-1 |
00 | Количество регистров Hi байт | ||
02 | Количество регистров Lo байт |
Состояния выходов DO0-1 показаны как значения байта 02 hex, или в двоичной системе 0000 0010.
Значение DO1 будет вторым справа, а значение DO0 будет первым справа (младший бит).
Шесть остальных битов заполнены нулями до полного байта, т.к. их не запрашивали.
Каналы | — | — | — | — | — | — | DO 1 | DO 0 |
Биты | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 |
Hex | 02 |
Модули с дискретным выводом: ioLogik E1211, ET-7060, ADAM-6060
Наверх к оглавлению
Как послать команду Modbus TCP на чтение дискретного ввода? Команда 0x02
Эта команда используется для чтения значений дискретных входов DI.
Запрос и ответ для DI похож на запрос для DO.
Байт | Запрос | Байт | Ответ |
---|---|---|---|
(Hex) | Название поля | (Hex) | Название поля |
01 | Идентификатор транзакции | 01 | Идентификатор транзакции |
02 | 02 | ||
00 | Идентификатор протокола | 00 | Идентификатор протокола |
00 | 00 | ||
00 | Длина сообщения | 00 | Длина сообщения |
06 | 04 | ||
01 | Адрес устройства | 01 | Адрес устройства |
02 | Функциональный код | 02 | Функциональный код |
00 | Адрес первого регистра Hi байт | 01 | Количество байт далее |
00 | Адрес первого регистра Lo байт | 03 | Значение регистра DI 0-1 |
00 | Количество регистров Hi байт | ||
02 | Количество регистров Lo байт |
Состояния выходов DI 0-1 показаны как значения байта 03 hex, или в двоичной системе 0000 0011.
Значение DI1 будет вторым справа, а значение DI0 будет первым справа (младший бит).
Шесть остальных битов заполнены нулями.
Модули с дискретным вводом: ioLogik E1210, ET-7053, ADAM-6050
Наверх к оглавлению
Как послать команду Modbus TCP на чтение аналогового вывода? Команда 0x03
Эта команда используется для чтения значений аналоговых выходов AO.
Байт | Запрос | Байт | Ответ |
---|---|---|---|
(Hex) | Название поля | (Hex) | Название поля |
01 | Идентификатор транзакции | 01 | Идентификатор транзакции |
02 | 02 | ||
00 | Идентификатор протокола | 00 | Идентификатор протокола |
00 | 00 | ||
00 | Длина сообщения | 00 | Длина сообщения |
06 | 07 | ||
01 | Адрес устройства | 01 | Адрес устройства |
03 | Функциональный код | 03 | Функциональный код |
00 | Адрес первого регистра Hi байт | 04 | Количество байт далее |
00 | Адрес первого регистра Lo байт | 02 | Значение регистра Hi (AO0) |
00 | Количество регистров Hi байт | 2B | Значение регистра Lo (AO0) |
02 | Количество регистров Lo байт | 00 | Значение регистра Hi (AO1) |
64 | Значение регистра Lo (AO1) |
Состояния выхода AO0 показаны как значения байта 02 2B hex, или в десятичной системе 555.
Состояния выхода AO1 показаны как значения байта 00 64 hex, или в десятичной системе 100.
Модули с дискретным вводом: ioLogik E1210, ET-7053, ADAM-6050
Наверх к оглавлению
Как послать команду Modbus TCP на чтение аналогового ввода? Команда 0x04
Эта команда используется для чтения значений аналоговых входов AI.
Байт | Запрос | Байт | Ответ |
---|---|---|---|
(Hex) | Название поля | (Hex) | Название поля |
01 | Идентификатор транзакции | 01 | Идентификатор транзакции |
02 | 02 | ||
00 | Идентификатор протокола | 00 | Идентификатор протокола |
00 | 00 | ||
00 | Длина сообщения | 00 | Длина сообщения |
06 | 07 | ||
01 | Адрес устройства | 01 | Адрес устройства |
04 | Функциональный код | 04 | Функциональный код |
00 | Адрес первого регистра Hi байт | 04 | Количество байт далее |
00 | Адрес первого регистра Lo байт | 00 | Значение регистра Hi (AI0) |
00 | Количество регистров Hi байт | 0A | Значение регистра Lo (AI0) |
02 | Количество регистров Lo байт | 00 | Значение регистра Hi (AI1) |
64 | Значение регистра Lo (AI1) |
Состояния выхода AI0 показаны как значения байта 00 0A hex, или в десятичной системе 10.
Состояния выхода AI1 показаны как значения байта 00 64 hex, или в десятичной системе 100.
Модули с аналоговым вводом: ioLogik E1240, ET-7017-10, ADAM-6217
Наверх к оглавлению
Как послать команду Modbus TCP на запись дискретного вывода? Команда 0x05
Эта команда используется для записи одного значения дискретного выхода DO.
Значение FF 00 hex устанавливает выход в состояние включен ON.
Значение 00 00 hex устанавливает выход в состояние выключен OFF.
Все остальные значения недопустимы и не будут влиять на состояние выхода.
Нормальный ответ на такой запрос — это эхо (повтор запроса в ответе), возвращается после того, как состояние DO было изменено.
Байт | Запрос | Байт | Ответ |
---|---|---|---|
(Hex) | Название поля | (Hex) | Название поля |
01 | Идентификатор транзакции | 01 | Идентификатор транзакции |
02 | 02 | ||
00 | Идентификатор протокола | 00 | Идентификатор протокола |
00 | 00 | ||
00 | Длина сообщения | 00 | Длина сообщения |
06 | 06 | ||
01 | Адрес устройства | 01 | Адрес устройства |
05 | Функциональный код | 05 | Функциональный код |
00 | Адрес регистра Hi байт | 00 | Адрес регистра Hi байт |
01 | Адрес регистра Lo байт | 01 | Адрес регистра Lo байт |
FF | Значение Hi байт | FF | Значение Hi байт |
00 | Значение Lo байт | 00 | Значение Lo байт |
Состояние выхода DO1 поменялось с выключен OFF на включен ON.
Модули с дискретным выводом: ioLogik E1211, ET-7060, ADAM-6060
Наверх к оглавлению
Как послать команду Modbus TCP на запись аналогового вывода? Команда 0x06
Эта команда используется для записи одного значения аналогового выхода AO.
Байт | Запрос | Байт | Ответ |
---|---|---|---|
(Hex) | Название поля | (Hex) | Название поля |
01 | Идентификатор транзакции | 01 | Идентификатор транзакции |
02 | 02 | ||
00 | Идентификатор протокола | 00 | Идентификатор протокола |
00 | 00 | ||
00 | Длина сообщения | 00 | Длина сообщения |
06 | 06 | ||
01 | Адрес устройства | 01 | Адрес устройства |
06 | Функциональный код | 06 | Функциональный код |
00 | Адрес регистра Hi байт | 00 | Адрес регистра Hi байт |
01 | Адрес регистра Lo байт | 01 | Адрес регистра Lo байт |
55 | Значение Hi байт | 55 | Значение Hi байт |
FF | Значение Lo байт | FF | Значение Lo байт |
Состояние выхода AO0 поменялось на 55 FF hex, или в десятичной системе 22015.
Модули с аналоговым выводом: ioLogik E1241, ET-7028, ADAM-6224
Наверх к оглавлению
Как послать команду Modbus TCP на запись нескольких дискретных выводов? Команда 0x0F
Эта команда используется для записи нескольких значений дискретного выхода DO.
Байт | Запрос | Байт | Ответ |
---|---|---|---|
(Hex) | Название поля | (Hex) | Название поля |
01 | Идентификатор транзакции | 01 | Идентификатор транзакции |
02 | 02 | ||
00 | Идентификатор протокола | 00 | Идентификатор протокола |
00 | 00 | ||
00 | Длина сообщения | 00 | Длина сообщения |
08 | 06 | ||
01 | Адрес устройства | 01 | Адрес устройства |
0F | Функциональный код | 0F | Функциональный код |
00 | Адрес первого регистра Hi байт | 00 | Адрес первого регистра Hi байт |
00 | Адрес первого регистра Lo байт | 00 | Адрес первого регистра Lo байт |
00 | Количество регистров Hi байт | 00 | Кол-во записанных рег. Hi байт |
02 | Количество регистров Lo байт | 02 | Кол-во записанных рег. Lo байт |
01 | Количество байт далее | ||
02 | Значение байт |
Состояние выхода DO1 поменялось с выключен OFF на включен ON.
Состояние выхода DO0 осталось выключен OFF.
Модули с дискретным выводом: ioLogik E1211, ET-7060, ADAM-6060
Наверх к оглавлению
Как послать команду Modbus TCP на запись нескольких аналоговых выводов? Команда 0x10
Эта команда используется для записи нескольких значений аналогового выхода AO.
Байт | Запрос | Байт | Ответ |
---|---|---|---|
(Hex) | Название поля | (Hex) | Название поля |
01 | Идентификатор транзакции | 01 | Идентификатор транзакции |
02 | 02 | ||
00 | Идентификатор протокола | 00 | Идентификатор протокола |
00 | 00 | ||
00 | Длина сообщения | 00 | Длина сообщения |
0B | 06 | ||
01 | Адрес устройства | 01 | Адрес устройства |
10 | Функциональный код | 10 | Функциональный код |
00 | Адрес первого регистра Hi байт | 00 | Адрес первого регистра Hi байт |
00 | Адрес первого регистра Lo байт | 00 | Адрес первого регистра Lo байт |
00 | Количество регистров Hi байт | 00 | Кол-во записанных рег. Hi байт |
02 | Количество регистров Lo байт | 02 | Кол-во записанных рег. Lo байт |
04 | Количество байт далее | ||
00 | Значение Hi AO0 байт | ||
0A | Значение Lo AO0 байт | ||
01 | Значение Hi AO1 байт | ||
02 | Значение Lo AO1 байт |
Состояние выхода AO0 поменялось на 00 0A hex, или в десятичной системе 10.
Состояние выхода AO1 поменялось на 01 02 hex, или в десятичной системе 258.
Модули с аналоговым выводом: ioLogik E1241, ET-7028, ADAM-6224
Наверх к оглавлению
Ошибки запроса Modbus TCP
Если после получения запроса устройство не может обработать его, то будет отослан ответ с кодом ошибки.
Ответ будет содержать измененный Функциональный код, его старший бит будет равен 1.
Пример:
Было | Стало |
---|---|
Функциональный код в запросе | Функциональный код ошибки в ответе |
01 (01 hex) 0000 0001 | 129 (81 hex) 1000 0001 |
02 (02 hex) 0000 0010 | 130 (82 hex) 1000 0010 |
03 (03 hex) 0000 0011 | 131 (83 hex) 1000 0011 |
04 (04 hex) 0000 0100 | 132 (84 hex) 1000 0100 |
05 (05 hex) 0000 0101 | 133 (85 hex) 1000 0101 |
06 (06 hex) 0000 0110 | 134 (86 hex) 1000 0110 |
15 (0F hex) 0000 1111 | 143 (8F hex) 1000 1111 |
16 (10 hex) 0001 0000 | 144 (90 hex) 1001 0000 |
Пример запроса и ответ с ошибкой:
Байт | Запрос | Байт | Ответ |
---|---|---|---|
(Hex) | Название поля | (Hex) | Название поля |
01 | Идентификатор транзакции | 01 | Идентификатор транзакции |
02 | 02 | ||
00 | Идентификатор протокола | 00 | Идентификатор протокола |
00 | 00 | ||
00 | Длина сообщения | 00 | Длина сообщения |
06 | 03 | ||
0A | Адрес устройства | 0A | Адрес устройства |
01 | Функциональный код | 81 | Функциональный код с измененным битом |
04 | Адрес первого регистра Hi байт | 02 | Код ошибки |
A1 | Адрес первого регистра Lo байт | ||
00 | Количество регистров Hi байт | ||
01 | Количество регистров Lo байт |
Расшифровка кодов ошибок
01 | Принятый код функции не может быть обработан. |
02 | Адрес данных, указанный в запросе, недоступен. |
03 | Значение, содержащееся в поле данных запроса, является недопустимой величиной. |
04 | Невосстанавливаемая ошибка имела место, пока ведомое устройство пыталось выполнить затребованное действие. |
05 | Ведомое устройство приняло запрос и обрабатывает его, но это требует много времени. Этот ответ предохраняет ведущее устройство от генерации ошибки тайм-аута. |
06 | Ведомое устройство занято обработкой команды. Ведущее устройство должно повторить сообщение позже, когда ведомое освободится. |
07 | Ведомое устройство не может выполнить программную функцию, заданную в запросе. Этот код возвращается для не успешного программного запроса, использующего функции с номерами 13 или 14. Ведущее устройство должно запросить диагностическую информацию или информацию об ошибках от ведомого. |
08 | Ведомое устройство при чтении расширенной памяти обнаружило ошибку паритета. Ведущее устройство может повторить запрос, но обычно в таких случаях требуется ремонт. |
10 (0A hex) |
Шлюз неправильно настроен или перегружен запросами. |
11 (0B hex) |
Slave устройства нет в сети или от него нет ответа. |
Наверх к оглавлению
Программы для работы с протоколом Modbus TCP
Ниже представлены программы, которые помогут легко взаимодействовать с устройствами Modbus TCP.
Modbus Master Tool с поддержкой Modbus RTU, ASCII, TCP. Скачать
Modbus TCP client с поддержкой Modbus TCP. Скачать
Наверх к оглавлению
Оставить заявку
Это утверждённая версия страницы. Она же — наиболее свежая версия.
Основные понятия
Modbus — это протокол прикладного (седьмого) уровня модели OSI. Чаще всего он служит для обмена данными между устройствами автоматизации и реализован в виде «протокола ответов на запросы (request-reply protocol)».
В устройствах Wiren Board данные Modbus передаются по последовательным линиям связи RS-485. В последовательных линиях связи протокол RS-485 полудуплексный и работает по принципу «клиент-сервер». Каждое устройство в сети (кроме ведущего см. далее) имеет адрес от 1 до 247, адрес 0 используется для широковещательной передачи данных всем устройствам, а адреса 248–255 считаются зарезервированными согласно спецификации Modbus, их использование не рекомендуется.
Существует две спецификации протокола: Modbus RTU и Modbus ASCII. В Modbus RTU передается 11-битный символ, состоящий из 1 стартового бита, 8 бит данных (начиная с младшего бита), бит четности (необязателен) и 2 стоповых бита — если бит четности не передается, или 1 стоповый бит — если бит четности передается. Такой символ передает 1 байт данных. В устройствах Wiren Board по умолчанию бит контроля четности не передается и используется 2 стоповых бита. В Modbus ASCII каждый байт передается двумя символами, представляющими ASCII-коды младшей и старшей четырехбитной группы байта (пример). Modbus RTU передает больше информации при той же скорости последовательной линии, и в устройствах Wiren Board используется именно он. Все дальнейшее описание относится к Modbus RTU.
Ведущее устройство («мастер», или «клиент») периодически опрашивает «ведомое», или «сервер». Ведущее устройство не имеет адреса, передача сообщений от устройства-сервера ведущему без запроса ведущего в протоколе не предусмотрена.
Датаграмма Modbus в общем виде
Пакет данных Modbus выглядит, как это показано на рисунке. PDU (Protocol Data Unit) — общая часть пакета MODBUS, включающая код функции и данные пакета. ADU (Application Data Unit) — полный пакет MODBUS. Включает в себя специфичную для физического уровня часть пакета и PDU. Для последовательных линий в заголовке ADU передается адрес устройства, а в конце — контрольная сумма CRC16. Максимальный размер ADU в последовательных коммуникационных линиях составляет 253 байта (из максимальных, разрешенных спецификацией 256 байт вычитается 1 байт адреса и два байта контрольной суммы). Для справки — в Modbus TCP максимальная длина пакета составляет 260 байт.
Функция кодируется одним байтом и определяет, какое действие должно выполнить устройство-сервер. Значение кодов функций лежат в диапазоне от 1 до 255, причем коды от 128 до 255 зарезервированы для сообщений об ошибках со стороны устройства-сервера. Код 0 не используется. Размер блока данных может варьироваться от нуля до максимально допустимого. Если обработка запроса прошла без ошибок, то устройство-сервер возвращает пакет ADU, содержащий запрошенные данные.
-
Modbus-транзакция, прошедшая без ошибок
-
Modbus-транзакция с ошибками
При возникновении ошибки устройством возвращается код ошибки. При обычной транзакции код функции в ответе возвращается без изменений; при ошибке старший бит кода функции устанавливается в единицу (то есть код функции + 0x80). Так же есть таймаут ожидания ответа от ведомого устройства — бессмысленно долго ждать ответ, который, возможно, никогда и не придет.
Структуры данных Modbus
В Modbus принято кодировать адреса и данные в формате big-endian, то есть в формате, когда байты следуют, начиная со старшего: например, при передаче шестнадцатеричного числа 0x1234 сначала устройством будет принят байт 0x12, а затем — 0x34. Для передачи данных другого типа, например, чисел с плавающей запятой (float), текстовых строк, даты и времени суток и т.п. производитель может выбрать свой собственный способ кодирования — для расшифровки получаемых данных важно ознакомится со спецификацией производителя устройства.
Модель данных Modbus
Обмен данными с Modbus-устройствами происходит через регистры. В протоколе Modbus определяется четыре типа регистров, показанных в таблице:
Таблица | Размер | Доступ |
---|---|---|
Регистры флагов (Coils) | 1 бит | чтение и запись |
Дискретные входы (Discrete Inputs) | 1 бит | только чтение |
Регистры хранения (Holding Registers) | 16-битное слово | чтение и запись |
Регистры ввода (Input Registers) | 16-битное слово | только чтение |
Регистры флагов (Coils) хранят однобитные значения — то есть могут находится в состоянии 0 или 1. Такие регистры могут обозначать текущее состояние выхода (включено реле). Название «coil» буквально и означает обмотку-актюатор электромеханического реле. Регистры флагов допускают как чтение, так и запись.
Дискретные входы (Discrete Inputs) также являются однобитными регистрами, описывающими состояние входа устройства (например, подано напряжение — 1). Эти регистры поддерживают только чтение.
Регистры хранения (Holding Registers) и регистры ввода (Input Registers) представлены двухбайтовым словом и могут хранить значения от 0 до 65535 (0x0000 — 0xFFFF).
Регистры ввода допускают только чтение (например, текущее значение температуры). Регистры хранения поддерживают как чтение, так и запись (для хранения настроек). В настоящее время во многих устройствах, в частности в устройствах Wiren Board, эти регистры не разделяются. Команды на чтение регистра хранения N и регистра ввода N обратятся к одному и тому же значению в адресном пространстве устройства.
Адреса регистров
Регистры в стандарте Modbus адресуются с помощью 16-битных адресов. Адресация начинается с нуля. Адрес регистра, таким образом, может принимать значения от 0 до 65535.
Адресные пространства регистров, также называемые таблицами иди блоками, могут быть различны для всех четырёх типов регистров. Это значит, что значения регистров с одинаковым адресом, но разным типом, в общем случае разные.
Например, при чтении регистра флагов (coil) номер 42, регистра дискретного входа (Discrete), регистров ввода и хранения (Input и Holding) с теми же адресами, можно получить четыре разных значения.
Нестандартная адресация
В документации на некоторые, особенно старые, устройства адреса элементов (регистров) указываются в формате, не соответствующем стандарту. В этом формате тип элемента кодируется первой цифрой адреса, а адресация начинается не с нуля.
Например, регистр хранения с адресом 0 может записываться как 40001 или 400001, а Coil с адресом 0 как 000001.
В таблице перевода адресов в стандартный формат показаны диапазоны для двух разных нестандартных типов указания адресов и соответствующие им типы данных и диапазоны стандартных адресов.
Тип данных | Стандартные адреса | Стандартные адреса (hex) | Нестандартные адреса (5 цифр) | Нестандартные адреса (6 цифр) |
---|---|---|---|---|
Флагов (Coils) | 0-65535 | 0x0000 — 0xFFFF | 00001 — 09999 | 000001 — 065536 |
Дискретных входов (Discrete) | 0-65535 | 0x0000 — 0xFFFF | 10001 — 19999 | 100001 — 165536 |
Регистры входов (Input Registers) | 0-65535 | 0x0000 — 0xFFFF | 30001 — 39999 | 300001 — 365536 |
Регистры хранения (Holding Registers) | 0-65535 | 0x0000 — 0xFFFF | 40001 — 49999 | 400001 — 465536 |
Признаки использования нестандартной адресации:
- Адреса записываются в десятичном формате
- Во всех адресах пять или шесть цифр
- Адреса с недискретными данными (показания датчиков и т.п.) начинаются на 30 или 40
Часто рядом с нестандартными адресами указываются и адреса соответствующие стандарту, обычно в шестнадцатеричном формате.
Стоит отметить, что физически в пакете данных передаются адреса в стандартном формате, независимо от способа представления их в документации.
Пример описания регистров в документации
В готовых шаблонах устройств для контроллера Wiren Board есть шаблон для однофазного счетчика электроэнергии SDM220 (/usr/share/wb-mqtt-serial/templates/config-sdm220.json). В документации от производителя «Eastron SDM
220 Modbus Smart Meter Modbus Protocol Implementation V1.0» перечислены регистры и соответствующие им измеряемые параметры, например:
Address (Register) | Description | Units | Modbus Protocol Start Address Hex (Hi Byte Lo Byte) |
---|---|---|---|
30001 | Line to neutral volts. | Volts | 00 00 |
30007 | Current. | Amps. | 00 06 |
30013 | Active power | Whatts | 00 0C |
30019 | Apparent power | VoltAmps | 00 12 |
… | … | … | … … |
Производитель в таблице приводит и логические, и физические адреса регистров, что позволяет нам с легкостью создать шаблон устройства и проиллюстрировать связь между логическими и физическими адресами Modbus-регистров.
Фрагмент шаблона счетчика SDM220
Коды функций чтения и записи регистров
В следующей таблице приведены наиболее распространенные коды функций Modbus:
Код функции | HEX | Название | Действие |
---|---|---|---|
1 | 0x01 | Read Coils | Чтение значений нескольких регистров флагов |
2 | 0x02 | Read Discrete Inputs | Чтение значений нескольких дискретных входов |
3 | 0x03 | Read Holding Registers | Чтение значений нескольких регистров хранения |
4 | 0x04 | Read Input Registers | Чтение значений нескольких регистров ввода |
5 | 0x05 | Write Single Coil | Запись одного регистра флагов |
6 | 0x06 | Write Single Register | Запись одного регистра хранения |
15 | 0x0F | Write Multiple Coils | Запись нескольких регистров флагов |
16 | 0x10 | Write Multiple Register | Запись нескольких регистров хранения |
Команды условно можно разделить по типам: чтение значений — запись значений; операция с одним значением — операция с несколькими значениями.
Формат данных запросов и ответов Modbus
Рассмотрим подробнее, как происходит обмен данными между устройством-клиентом, отправляющим запрос, и устройством-сервером, отвечающим ему.
На следующем рисунке показан обмен данными контроллера с устройством с адресом 0x01. Мы хотим прочесть 8 coil-регистров, начиная с первого.
В качестве данных мы получили шестнадцатеричное число 0x2D, то есть состояние восьми coil-регистров в двоичном виде такое: 0b10110100.
В следующей таблице приведены структуры данных запросов и ответов для основных функций Modbus.
Код функции | Запрос | Ответ |
---|---|---|
1 (Read Coils) и 2 (Read Discrete Inputs) |
|
|
3 (Read Holding Registers) и 4 (Read Input Registers) |
|
|
5 (Write Single Coil) |
|
Ответ аналогичен запросу |
6 (WriteSingle Register) |
|
Ответ аналогичен запросу |
15 (WriteMultipleCoils) |
|
|
16 (Write Multiple register ) |
|
|
Коды исключений (ошибки) Modbus
Если запрос не может по той или иной причине быть обработан устройством-сервером, то в ответ он отправляет сообщение об ошибке. Соообщение об ошибке содержит адрес Modbus-устройства, код функции, при выполнении которой произошла ошибка, увеличенный на 0x80, код ошибки и контрольную сумму:
Транзакция завершилась с ошибкой
В этом случае мы попытались обратиться к несуществующему адресу регистра 0xFFFF и попытались прочесть 8 регистров флагов. В результате мы получили код ошибки 0x03 — «В поле данных передано неверное значение».
Наиболее распространенные коды ошибок Modbus приведены в следующей таблице:
Код ошибки | Название ошибки | Что означает |
---|---|---|
1 | Illegal Function | В запросе был передан недопустимый код функции |
2 | Illegal Data Address | Указанный в запросе адрес не существует |
3 | Illegal Data Value | Неверный формат запроса, например количество байт в запросе не соответствует ожидаемому.
Примечание: несмотря на название, эта ошибка не говорит о том, что само значение регистра неправильное или ошибочное, и должна использоваться только для ошибок формата запроса. |
4 | Server Device Failure | Произошла невосстановимая ошибка на устройстве при выполнении запрошенной операции |
5 | Acknowledge | Запрос принят, выполняется, но выполнение потребует много времени; необходимо увеличить таймаут. |
6 | Server Device Busy | Устройство занято обработкой предыдущего запроса. |
7 | Negative Acknowledge | Устройство не может выполнить запрос, необходимо получить от устройства дополнительную диагностическую информацию. Возможно, требуется тех. обслуживание. |
8 | Memory Parity Error | Ошибка четности при обращении к внутренней памяти устройства. |
Вычисление контрольной суммы Modbus
Для протокола Modbus RTU 16-битная контрольная сумма (CRC) вычисляется по алгоритму, описанному в спецификации Modbus, в документе «Modbus Serial Line Protocol and Implementation Guide», раздел «CRC-generation». Передающее устройство формирует два байта контрольной суммы на основе данных сообщения, а принимающее устройство заново вычисляет контрольную сумму и сравнивает с полученной. Совпадение принятой и вычисленной контрольной суммы Modbus RTU считается индикатором успешного обмена данными.
В случае ограниченных вычислительных ресурсов для вычисления контрольной суммы существует функция, использующая табличные значения (также приведена в спецификации).
Расширение протокола Modbus от Wiren Board
Мы производим устройства, которые работают по стандартному протоколу Modbus RTU. Но протокол очень старый и имеет ряд недостатков, которые мы решили устранить с помощью своего расширения протокола.
Всё описываемое ниже справедливо только для Modbus-устройств Wiren Board.
Торговое название расширения протокола «Быстрый Modbus».
Настраиваемое время задержки ответа устройством
Устройства работают по стандарту, поэтому отвечают master-устройству через 3.5 символа после конца кадра запроса.
Но некоторые сторонние master-устройства могут не соблюдать стандарт и после отправки запроса продолжают удерживать приемопередатчик в режиме отправки некоторое время.
В устройствах есть специальный регистр 113, в котором можно настроить время ответа slave-устройства в миллисекундах. Нужное значение подбирается опытным путём.
Стопбиты
Устройства всегда ожидают от мастера 1 стопбит, а отправляют ответ с 2.
Благодаря этому невозможно неправильно настроить стопбиты в master- и в slave-устройстве. Передача ответов более надежная даже, если мастер ожидает 1 стопбит. В последних прошивках настройка стопбита в регистре 112 игнорируется.
Режим сплошного чтения регистров
Часто на устройствах регистры расположены с зазором, который не позволяет читать все необходимые регистры подряд одной командой.
Мы добавили режим сплошного чтения, который активируется записью 1 в регистр 114. При активации можно запрашивать любой регион, который укладывается по длине в ограничения команды чтения.
При таком запросе устройство вернёт пакет со значением регистров. Если регистры отсутствуют в устройстве, то для них будет возвращено значение 0xFFFE.
Сканирование устройств на шине
Обычно инсталляция содержит несколько slave-устройств в щите или в поле на одной шине RS-485. Каждое устройство имеет адрес, который пользователь может менять. Обычно при монтаже адреса slave-устройств переписываются с корпуса устройства и вносятся вручную в конфигурацию мастера. Это не очень удобно.
Раньше для сканирования шины использовался специальный скрипт, который перебирал все возможные адреса на шине и ждал от них ответа в течение определённого времени. Процесс занимал несколько минут и зависел от настроек связи устройств: скорости, стоповых битов и т.п.
В расширении протокола мы добавили возможность быстро сканировать шину без необходимости выжидать таймаут для каждого несуществующего адреса. Более того, при сканировании могут быть обнаружены устройства с одинаковыми адресами, которым можно задать новые адреса не отключая устройства от шины! Также функция сканирования способна обнаружить на одной шине устройства с разными настройками связи.
Теперь можно собрать щит не обращая внимания на modbus-адреса устройств. В процессе сканирования будут прочитаны модели устройств, настройки связи, их серийные номера и адреса на шине. Притом, вы можете изменить адреса подключённых устройств, обращаясь к устройству по уникальному серийному номеру.
Описание расширенных команд и референсная реализация утилиты сканирования доступны в репозитории.
Поддержка быстрого Modbus в прошивках
Устройство | Версия прошивки с поддержкой «быстрого Modbus» |
---|---|
WB-MRx, WB-MWAC | 1.19.0 |
WB-MDM3 | 2.6.0 |
WB-LED, WB-MRGBW-D | 3.2.0 |
WB-MSx, WB-MSWx, WB-MIR, WB-M1W2 | 4.23.0 |
WB-MAI11 | не поддерживается |
WB-MAI6 | 2.0.0 |
WB-MAO4 | 2.2.0 |
WB-MAPx | 2.4.0 |
WB-MIO | 1.6.0 |
WB-REF-U | 1.4.0 |
WB-REF-DF | 1.1.0 |
Содержание:
- Компоненты СИМП Лайт
- Редактор каналов
- Источники данных
- Modbus driver
- Коды ошибок Modbus
Расшифровка кодов ошибок Modbus:
01
|
Принятый код функции не может быть обработан. |
02 |
Адрес данных, указанный в запросе, недоступен. |
03 |
Значение, содержащееся в поле данных запроса, является недопустимой величиной. |
04 |
Невосстанавливаемая ошибка имела место, пока ведомое устройство пыталось выполнить затребованное действие. |
05 |
Ведомое устройство приняло запрос и обрабатывает его, но это требует много времени. Этот ответ предохраняет ведущее устройство от генерации ошибки тайм-аута. |
06 |
Ведомое устройство занято обработкой команды. Ведущее устройство должно повторить сообщение позже, когда ведомое освободится. |
07 |
Ведомое устройство не может выполнить программную функцию, заданную в запросе. Этот код возвращается для неуспешного программного запроса, использующего функции с номерами 13 или 14. Ведущее устройство должно запросить диагностическую информацию или информацию об ошибках от ведомого. |
08 |
Ведомое устройство при чтении расширенной памяти обнаружило ошибку паритета. Ведущее устройство может повторить запрос, но обычно в таких случаях требуется ремонт. |
10 (0A hex)
|
Шлюз неправильно настроен или перегружен запросами |
11 (0B hex)
|
Slave устройства нет в сети или от него нет ответа |