Из данной статьи вы узнаете о протоколе Modbus RTU, который широко применяется в АСУ ТП. Англоязычная версия статьи доступна на сайте ipc2u.com. Описание протокола Modbus TCP можно найти в статье.
Оглавление:
Modbus —коммуникационный протокол, основан на архитектуре ведущий-ведомый (master-slave). Использует для передачи данных интерфейсы RS-485, RS-422, RS-232, а также Ethernet сети TCP/IP (протокол Modbus TCP).
Сообщение Modbus RTU состоит из адреса устройства SlaveID, кода функции, специальных данных в зависимости от кода функции и CRC контрольной суммы.
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
11 | Адрес устройства SlaveID (17 = 11 hex) |
03 | Функциональный код Function Code (читаем Analog Output Holding Registers) |
006B | Адрес первого регистра (40108-40001 = 107 =6B hex) |
0003 | Количество требуемых регистров (чтение 3-х регистров с 40108 по 40110) |
7687 | Контрольная сумма CRC |
В ответе от Modbus RTU Slave устройства мы получим:
11 03 06 AE41 5652 4340 49AD
Где:
11 | Адрес устройства | 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.
Код функции | Что делает функция | Тип значения | Тип доступа | |
---|---|---|---|---|
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 битное | Запись |
Наверх к оглавлению
Эта команда используется для чтения значений дискретных выходов 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 | Адрес первого регистра Hi байт | 05 | Количество байт далее |
13 | Адрес первого регистра Lo байт | 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 битов справа были запрошены, а остальные биты заполнены нулями до полного байта (0001 1011).
Каналы | — | — | — | DO 56 | DO 55 | DO 54 | DO 53 | DO 52 |
---|---|---|---|---|---|---|---|---|
Биты | 0 | 0 | 0 | 1 | 1 | 0 | 1 | 1 |
Hex | 1B |
Наверх к оглавлению
Эта команда используется для чтения значений дискретных входов 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 |
Наверх к оглавлению
Эта команда используется для чтения значений аналоговых выходов 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 |
Наверх к оглавлению
Эта команда используется для чтения значений аналоговых входов 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 |
Наверх к оглавлению
Эта команда используется для записи одного значения дискретного выхода 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.
Наверх к оглавлению
Эта команда используется для записи одного значения аналогового выхода 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 |
Наверх к оглавлению
Эта команда используется для записи нескольких значений дискретного выхода 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 | Кол-во записанных рег. Hi байт |
0A | Количество регистров Lo байт | 0A | Кол-во записанных рег. Lo байт |
02 | Количество байт далее | 26 | Контрольная сумма CRC |
CD | Значение байт DO 27-20 (1100 1101) | 99 | Контрольная сумма CRC |
01 | Значение байт DO 29-28 (0000 0001) | ||
BF | Контрольная сумма CRC | ||
0B | Контрольная сумма CRC |
В ответе возвращается количество записанных регистров.
Наверх к оглавлению
Эта команда используется для записи нескольких значений аналогового выхода 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 |
Наверх к оглавлению
Если устройство получило запрос, но запрос не может быть обработан, то устройство ответит кодом ошибки.
Ответ будет содержать измененный Функциональный код, старший бит будет равен 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) | Название поля |
0A | Адрес устройства | 0A | Адрес устройства |
01 | Функциональный код | 81 | Функциональный код с измененным битом |
04 | Адрес первого регистра Hi байт | 02 | Код ошибки |
A1 | Адрес первого регистра Lo байт | B0 | Контрольная сумма CRC |
00 | Количество регистров Hi байт | 53 | Контрольная сумма CRC |
01 | Количество регистров Lo байт | ||
AC | Контрольная сумма CRC | ||
63 | Контрольная сумма CRC |
Расшифровка кодов ошибок
01 | Принятый код функции не может быть обработан. |
02 | Адрес данных, указанный в запросе, недоступен. |
03 | Значение, содержащееся в поле данных запроса, является недопустимой величиной. |
04 | Невосстанавливаемая ошибка имела место, пока ведомое устройство пыталось выполнить затребованное действие. |
05 | Ведомое устройство приняло запрос и обрабатывает его, но это требует много времени. Этот ответ предохраняет ведущее устройство от генерации ошибки тайм-аута. |
06 | Ведомое устройство занято обработкой команды. Ведущее устройство должно повторить сообщение позже, когда ведомое освободится. |
07 | Ведомое устройство не может выполнить программную функцию, заданную в запросе. Этот код возвращается для неуспешного программного запроса, использующего функции с номерами 13 или 14. Ведущее устройство должно запросить диагностическую информацию или информацию об ошибках от ведомого. |
08 | Ведомое устройство при чтении расширенной памяти обнаружило ошибку паритета. Ведущее устройство может повторить запрос, но обычно в таких случаях требуется ремонт. |
Наверх к оглавлению
Ниже перечислены программы, которые облегчают работу с Modbus.
DCON Utility Pro с поддержкой Modbus RTU, ASCII, DCON. Скачать
Modbus Master Tool с поддержкой Modbus RTU, ASCII, TCP. Скачать
Modbus TCP client с поддержкой Modbus TCP. Скачать
Наверх к оглавлению
Шлюзы для преобразования протоколов Modbus RTU в Modbus TCP, Profibus, Ethernet/IP, BacNet, CAN, HART, IEC 61850, IEC 60870-5-101, 103 и 104.
ПодробнееСерия M-7000 по функционалу идентична серии I-7000, только отличается поддержкой протокола Modbus RTU. Одновременно M-7000 может работать только по одному протоколу или по DCON, или по Modbus RTU.
ПодробнееПассивные модули ввода-вывода серии R1000, R2000, работающие по RS-485 стандарту, по протоколу Modbus RTU. В отличие от R2000 серия R1000 имеет 2 порта RS-485 и 1 USB разъем для настройки модуля.
ПодробнееМодули аналогового и дискретного ввода-вывода серии ADAM-4000 с интерфейсом RS-485 и протоколами ASCII и Modbus RTU.
ПодробнееКорзины серии RU-87Pn и I-87Kn (где n число слотов для модулей расширения) для увеличения каналов ввода-вывода у контроллеров или компьютеров.
ПодробнееМодули серии LC для экономичного управления осветительными устройствами через контроллер или компьютер.
ПодробнееМодули серии IR для управления различными устройствами (телевизоры, кондиционеры и др.) по инфракрасному каналу.
ПодробнееКомпактные терминалы ввода-вывода серий TPD и VPD с цветным экраном, сенсорным управлением и коммуникационными интерфейсами Ethernet и COM.
ПодробнееПриборы серий PM-2000 и PM-3000 для измерения параметров однофазных или трехфазных электрических сетей питания и передавать данные по протоколам Modbus RTU, Modbus TCP, CANbus или CANopen.
ПодробнееУстройства серии DL для измерения температуры, влажности и концентрации CO2, ведения архива измерений и передачи информации по протоколам DCON, Modbus TCP или Modbus RTU.
ПодробнееНаверх к оглавлению
За более подробной информацией обращайтесь к специалистам IPC2U по телефону: +7 (495) 232 0207 или по e-mail: [email protected]
ipc2u.ru
В промышленности (да и не только) очень часто используется протокол Modbus при настройке и программирования оборудования (Приборы, программируемые контроллеры, датчики, клапана, пускатели, расходомеры, тепловычислители, электросчётчики и даже манометры). Сам по себе протокол представляет собой некие инструкции для извлечения, обработки и передачи различных данных, зачастую физические параметры (температура, давление, влажность, расход, потреблённая электроэнергия и т.д.)
Из этой статьи вы узнаете:
Описание протокола Modbus RTU
Какие бывают команды Modbus RTU?
Как послать команду Modbus RTU на чтение дискретного вывода? Команда 0×01
Как послать команду Modbus RTU на чтение дискретного ввода? Команда 0×02
Как послать команду Modbus RTU на чтение аналогового вывода? Команда 0×03
Как послать команду Modbus RTU на чтение аналогового ввода? Команда 0×04
Как послать команду Modbus RTU на запись дискретного вывода? Команда 0×05
Как послать команду Modbus RTU на запись аналогового вывода? Команда 0×06
Как послать команду Modbus RTU на запись нескольких дискретных выводов? Команда 0x0F
Как послать команду Modbus RTU на запись нескольких аналоговых выводов? Команда 0×10
Какие бывают ошибки запроса Modbus?
Приветствую уважаемые подписчики и читатели. С вами на связи Гридин Семён. Я созрел для этой статьи, которую хотел опубликовать уже давно. Сразу оговорюсь, что основной источник статьи находится на официальном сайте IPC2U. Они являются основными поставщиками промышленного оборудования.
Фактически я переписываю статью. Это поможет мне хоть как-то врубиться в тему, что-то отложится в памяти. Ну и вам проще найти информацию.
Modbus —коммуникационный протокол, основан на архитектуре ведущий-ведомый (master-slave). Использует для передачи данных интерфейсы RS-485, RS-422, RS-232, а также Ethernet сети TCP/IP (протокол Modbus TCP).
Сообщение Modbus RTU состоит из адреса устройства SlaveID, кода функции, специальных данных в зависимости от кода функции и CRC контрольной суммы.
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
11 | Адрес устройства SlaveID (17 = 11 hex) |
03 | Функциональный код Function Code (читаем Analog Output Holding Registers) |
006B | Адрес первого регистра (40108-40001 = 107 =6B hex) |
0003 | Количество требуемых регистров (чтение 3-х регистров с 40108 по 40110) |
7687 | Контрольная сумма CRC |
В ответе от 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.
Код функции | Что делает функция | Тип значения | Тип доступа | |
---|---|---|---|---|
01 (0×01) | Чтение DO | Read Coil Status | Дискретное | Чтение |
02 (0×02) | Чтение DI | Read Input Status | Дискретное | Чтение |
03 (0×03) | Чтение AO | Read Holding Registers | 16 битное | Чтение |
04 (0×04) | Чтение AI | Read Input Registers | 16 битное | Чтение |
05 (0×05) | Запись одного DO | Force Single Coil | Дискретное | Запись |
06 (0×06) | Запись одного AO | Preset Single Register | 16 битное | Запись |
15 (0x0F) | Запись нескольких DO | Force Multiple Coils | Дискретное | Запись |
16 (0×10) | Запись нескольких AO | Preset Multiple Registers | 16 битное | Запись |
Эта команда используется для чтения значений дискретных выходов 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 | Адрес первого регистра Hi байт | 05 | Количество байт далее |
13 | Адрес первого регистра Lo байт | 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 битов справа были запрошены, а остальные биты заполнены нулями до полного байта (0001 1011).
Каналы | — | — | — | DO 56 | DO 55 | DO 54 | DO 53 | DO 52 |
---|---|---|---|---|---|---|---|---|
Биты | 0 | 0 | 0 | 1 | 1 | 0 | 1 | 1 |
Hex | 1B |
Эта команда используется для чтения значений дискретных входов 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 |
Эта команда используется для чтения значений аналоговых выходов 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 |
Эта команда используется для чтения значений аналоговых входов 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 |
Эта команда используется для записи одного значения дискретного выхода 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.
Эта команда используется для записи одного значения аналогового выхода 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 |
Эта команда используется для записи нескольких значений дискретного выхода 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 | Кол-во записанных рег. Hi байт |
0A | Количество регистров Lo байт | 0A | Кол-во записанных рег. Lo байт |
02 | Количество байт далее | 26 | Контрольная сумма CRC |
CD | Значение байт DO 27-20 (1100 1101) | 99 | Контрольная сумма CRC |
01 | Значение байт DO 29-28 (0000 0001) | ||
BF | Контрольная сумма CRC | ||
0B | Контрольная сумма CRC |
В ответе возвращается количество записанных регистров.
Эта команда используется для записи нескольких значений аналогового выхода 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 |
Если устройство получило запрос, но запрос не может быть обработан, то устройство ответит кодом ошибки.
Ответ будет содержать измененный Функциональный код, старший бит будет равен 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) | Название поля |
0A | Адрес устройства | 0A | Адрес устройства |
01 | Функциональный код | 81 | Функциональный код с измененным битом |
04 | Адрес первого регистра Hi байт | 02 | Код ошибки |
A1 | Адрес первого регистра Lo байт | B0 | Контрольная сумма CRC |
00 | Количество регистров Hi байт | 53 | Контрольная сумма CRC |
01 | Количество регистров Lo байт | ||
AC | Контрольная сумма CRC | ||
63 | Контрольная сумма CRC |
Расшифровка кодов ошибок
01 | Принятый код функции не может быть обработан. |
02 | Адрес данных, указанный в запросе, недоступен. |
03 | Значение, содержащееся в поле данных запроса, является недопустимой величиной. |
04 | Невосстанавливаемая ошибка имела место, пока ведомое устройство пыталось выполнить затребованное действие. |
05 | Ведомое устройство приняло запрос и обрабатывает его, но это требует много времени. Этот ответ предохраняет ведущее устройство от генерации ошибки тайм-аута. |
06 | Ведомое устройство занято обработкой команды. Ведущее устройство должно повторить сообщение позже, когда ведомое освободится. |
07 | Ведомое устройство не может выполнить программную функцию, заданную в запросе. Этот код возвращается для неуспешного программного запроса, использующего функции с номерами 13 или 14. Ведущее устройство должно запросить диагностическую информацию или информацию об ошибках от ведомого. |
08 | Ведомое устройство при чтении расширенной памяти обнаружило ошибку паритета. Ведущее устройство может повторить запрос, но обычно в таких случаях требуется ремонт. |
kip-world.ru
Протокол ModBus, несмотря на множество специализированных протоколов, появившихся в последние десятилетия, все еще занимает лидирующие позиции в задачах автоматизации и диспетчеризации зданий и технологических процессов. Многие специалисты уже привыкли к его использованию, несмотря на его явную архаичность. Тем не менее, судя по статистике поисковых запросов и популярности статей о ModBus, явно существует пласт специалистов, надеюсь, что это молодое поколение, для которых будет полезно, еще раз на пальцах объяснить, что такое ModBus.
В российской википедии существует довольно обширная статья, в которой рассказывается история протокола, его основные достоинства и недостатки, терминология, модель данных и функционал. Не претендуя на полноту изложения, но в то же время, не боясь повториться, рассмотрим некоторые базовые вещи для тех, кому надо всего-то «два байта переслать».
Прежде всего, как представлены данные в устройстве поддерживающем ModBus. Это четыре таблицы с данными:
Таблица | Тип элемента | Тип доступа |
Дискретные входы (Discrete Inputs) | один бит | только чтение |
Регистры флагов (Coils) | один бит | чтение и запись |
Регистры ввода (Input Registers) | 16-битное слово | только чтение |
Регистры хранения (Holding Registers) | 16-битное слово | чтение и запись |
В реальной практике чаще всего встречаются устройства, в которых есть только таблица Holding Registers, иногда объединённая с таблицей Input Registers.
Для доступа к этим таблицам существует ряд стандартный функций ModBus:
Чтение:
Запись одного значения:
Запись нескольких значений:
Из сказанного выше следует, что самые часто используемые функции ModBus это 3, 6 и 16 («Read Holding Registers», «Preset Single Register» и «Preset Multiple Registers» — соответственно).
Что происходит при чтении или записи регистра в ModBus устройство? Рассмотрим, для начала, протокол ModBus RTU. Он применяется для передачи данных по последовательным интерфейсам, таким как RS-232 или RS-485. Большинство современных устройств используют RS-485, так как он, во первых, как правило, двух проводной и во вторых, позволяет подключить несколько устройств в один шлейф.
Важно то, что при подобной топологии на одном шлейфе может быть только один ModBus Master, то есть устройства не могут свободно «общаться» между собой. На каждом шлейфе организуется четкая иерархия Master – Slave («Ведущий» – «Ведомый»). Ведомых, как уже было сказано, может быть несколько, а ведущий только один!
Адресная модель ModBus позволяет использовать адреса устройств с 1 по 247, что иногда вводит в заблуждение некоторых «проектологов», т.к. RS-485 позволяет подключить к одной шине, без усилителей и репитеров, только 32 устройства. На самом деле я рекомендую для стабильной работы, с приемлемым количеством повторных запросов, не превышать значение 20 устройств на одну шину RS-485.
Итак, для чтения одного Holding Register ведущий посылает запрос на адрес ведомого устройства с кодом функции 3 (Read Holding Registers), указанием адреса интересующего регистра и количеством регистров для чтения, в данном случае = 1. На что ведомый отвечает пакетом, в котором повторяет собственный адрес, номер обрабатываемой функции и, в поле данных размещает значение запрашиваемого регистра. Для чтения нескольких последовательных регистров в запросе ведущий просто указывает адрес первого и их количество.
В общем виде, работу функции 3 (Read Holding Registers) протокола ModBus можно представить так:
Теперь рассмотрим, чем отличается ModBus TCP от ModBus RTU. Во первых, нет ограничения на одного ведущего в сети, все устройства могут практически свободно «общаться» между собой. Во вторых используется другой формат пакета, добавился заголовок, что более типично для данной среды передачи.
Так как транспортом для передачи служит протокол TCP, то для адресации устройств ведущему необходимо знать IP адрес ведомого устройства и порт, на котором ведомый ожидает запросов. Стандартный порт для ModBus TCP протокола 502 , но некоторые среды программирования контроллеров, например CODESYS, позволяют его изменить. Тот же самый CODESYS, а точнее контроллеры, запрограммированные в этой среде или средах производных от CODESYS, при работе по протоколу ModBus TCP игнорируют поле «Unit ID» и отвечают на запросы для любого «Unit ID», а не выдают сообщение об ошибке. Это значит, что иногда, достаточно знать IP адрес и порт контроллера.
Довольно часто сталкиваюсь с непониманием модели OSI среди инженеров и проектировщиков АСУ ТП и АСУЗ. Поэтому вот еще одна картинка, разъясняющая то, как пакет ModBus TCP передается по Ethernet сети:
UPD (26.09.2016): Довольно неплохое русскоязычное видео на тему:
comments powered by HyperCommentscleverhouse.club
Примеры подключения индикатора Овен СМИ2 к разным контроллерам.
ModBus один из самых простых протоколов взаимодействия устройств между собой который я встречал. Он одновременно прост в реализации для производителей оборудования, что является первопричиной его распространенности, и в то же время сложен для инженера, программиста, пусконаладчика потому что перекладывает на его плечи все сложности внедрения в конечном решении, требуя выполнить работу с многостраничными таблицами регистров и переменных, их адресами, различными функциями записи и чтения и преобразованием данных.
В этой статье я хочу рассмотреть практические аспекты конфигурирования и программирования взаимодействия ModBus устройств между собой на простейших примерах. Для этого я выбрал ModBus индикатор СМИ2, Российской компании Овен. Устройство предназначено для индикации аналогового значения получаемого от контроллера. Не буду описывать все возможные сферы его применения, с этой задачей отлично справился сам производитель.
Давайте для начала разберемся с конфигурированием самого устройства, а потом перейдем к примерам его подключения к различным контроллерам.
Для связи с устройством я использовал двух портовый асинхронный преобразователь Moxa NPort 5230.
Устройство может предоставлять доступ к последовательным портам как инкапсулируя UART в TCP, так и более привычным способом — эмуляция последовательных портов (port mapping). Я «промапил» RS485 преобразователя на COM4.
Для конфигурования индикатора служит поставляемая вместе с ним программа «Конфигуратор СМИ2″, ее так же без труда можно найти на сайте производителя. Перед тем как подключаться к СМИ2 необходимо «вогнать» его в режим «заводские настройки» , для этого предназначена единственная кнопка на устройстве. Нажатие ее в течении трех секунд переключает устройство к заводским настройкам связи, которые также прописаны по умолчанию в утилите конфигурации. Порт естественно необходимо выбрать.
После подключения к устройству жмем кнопку «считать» и редактируем параметры связи, адрес устройства и используемый протокол в соответствии с возможностями контроллеров, линий связи между ними и личными предпочтениями. После чего не забываем нажать «записать».
Конфигуратор СМИ2
Для проверки правильности настроек, корректности работы устройства и нюансов типа порядка расположения данных, полезно проверить работу устройства чем нибудь вроде этого:
В результате всех проделанных действий имеем следующую таблицу параметров устройства.
Параметры связи:
Speed — 115200
Parity — NON
Data Bits — 8
Stop Bits — 1
Параметры устройства и регистра:
Protocol — ModBus RTU
Slave Address — 20
Register Type — FLOAT
Register Address — 27
Теперь давайте подключим его к контроллеру ПЛК150 фирмы Овен, программируемому из среды CoDeSys 2.3.9.40 . Будем считать что вы обладаете базовыми навыками работы в среде CoDeSys, поэтому опустим процесс установки target файлов, создания нового проекта и выбора целевой платформы, перейдем сразу к конфигурированию ModBus. Для этого в разделе «Конфигурация ПЛК» добавим подэлемент «Modbus Master» c интерфейсом «RS-485″ и зададим его параметры связи в соответствии с параметрами заданными нами при конфигурировании СМИ2.
После чего добавим подэлемент «Universal Modbus device» где зададим адрес Slave устройства, т.е. нашего СМИ2.
После чего добавим переменную типа REAL ( «Real output module» ) где зададим адрес регистра в котором она хранится.
Ну и наконец, дадим некоторое осмысленное имя переменной.
После этого к данной переменной уже можно обращаться из программы. Вроде ничего сложного, но представьте что Slave устройство имеет не один регистр, как в данном примере а, например, пятьдесят. При этом сорок из них доступны только на чтение, а десять на чтение и запись. Каждый регистр надо явно объявить, верно указать его размерность, адрес и так далее.
Еще один пример, как реализована работа с ModBus устройствами в среде программирования Honeywell Care 10.03 .
Создадим новый проект и в нем новый контроллер, в данном примере я буду использовать контроллер серии Excel Web 2 — XL2026B2A. При создании контроллера в проекте сразу можно задать какие протоколы будут использоваться его интерфейсами. Я «повесил» ModBus на первый порт RS485.
Сразу же сконфигурируем параметры связи интерфейса.
После этого откроем «Device Library» и создадим новое устройство.
В новом устройстве создаем «Holding Register» типа Float с нужным адресом, именем и разрешением на запись.
После чего просто «перетащим» устройство на наш канал связи.
Зададим адрес устройства.
Создадим «точку» — переменную типа «аналоговый выход» и «перетащим» ее на нужный вход устройства.
Отредактируем «точку» — напишем описание и зададим единицы измерения.
Для этого примера я вывел на индикатор значение температуры измеряемое датчиком подключенным к первому универсальному входу.
Как по мне так наиболее логичное решение поставленной задачи. Может быть это связано с тем что работа с устройствами в данной среде изначально была построена через библиотеку устройств, причем подход унифицирован как для ModBus, так и для BACNet (есть импорт из EDE), LonWorks (есть импорт из XIF или онлайн из самого устройства) и M-Bus — все через библиотеку. К тому же один раз создав или импортировав устройство в библиотеку вы можете использовать его неоднократно, без необходимости каждый раз заново описывать в новом проекте.
В продолжении статьи я расскажу как сделать то же самое, но в CoDeSys v3 на контроллере Овен Модус 5684-0 и в SMLogix — среде программирования российских контроллеров Segnetics на примере контроллера Pixel.
comments powered by HyperCommentscleverhouse.club
Статья посвящена промышленному протоколу ModBus — наиболее простому, а потому широко распространённому цифровому протоколу передачи данных.
Стандарт ModBus был изобретён ещё в 1979 году компанией Modicon (ныне Schneider Electric) и с того времени не утратил своей актуальности, а даже наоборот получил широкое распространение и большую популярность среди разработчиков АСУ ТП.
Преимущества:
Недостатки:
ModBus сеть объединяет одно ведущее (мастер) и несколько ведомых (слейвов). Обмен данными в сети происходит по инициативе мастера. Он может отправить запрос одному из подчинённых устройств или широковещательное сообщение сразу всем ведомым устройствам сети.
После отправки запроса мастер ожидает ответ в течение заданного времени («время таймаута»). Если в течение этого времени ответ не получен, мастер считает, что связь с ведомым отсутствует. На широковещательное сообщение ответ не предусмотрен.
Слейвы (ведомые устройства) не могут самостоятельно инициировать передачу данных. Они могут передать данные только после запроса мастера (и только те данные, которые мастер запросит).
Существует три разновидности протокола:
Для передачи ModBus сообщений используется последовательные асинхронные интерфейсы (RS232, RS485, RS422) в случае использования протоколов ASCII и RTU и Ethernet интерфейс для протокола ModBus TCP.
Использование стандартных интерфейсов делает ModBus удобным для пользователей и разработчиков.
Любой узел сети ModBus — это интеллектуальное устройство (контроллер, регулятор, датчик и др.). Согласно спецификации узел сети может иметь следующие структуры данных:
Указанные типы данных необязательны для всех устройств, поддерживающих ModBus. Например, Discrete Inputs и Coils характерны больше для ПЛК.
Производитель устройства сам решает, какой тип данных сделать доступным для чтения и записи по ModBus, и об этом написано в руководстве устройства. В большинстве случае пользуются типом Holding Registers, поскольку он самый универсальный.
Как уже было сказано, обмен данными по ModBus состоит из запросов и ответов. Ведущее устройство посылает запрос одному из подчинённых устройств, указывая в запросе его адрес, или всем устройствам сразу, указывая адрес 0.
Типовой запрос или ответ состоит из следующих блоков:
Состав данных блоков отличается для RTU и TCP реализаций ModBus. Далее мы подробно рассотрим каждый из них.
ModBus ASCII мы не будем подробно рассматривать, поскольку он используется крайне редко. Состав пакета в ModBus ASCII такой же как и ModBus RTU, и отличается только типом кодирования и способом разделения пакетов.
Номер функции определяет тип запрашиваемых данных и что с ними нужно сделать (прочитать/записать).
Функций ModBus достаточно много и они разделены на три категории:
Однако, это всё лирика… На практике в большинстве случаев используются всего несколько функций, мы подробно поговорим о них в отдельной статье, а в этой будем рассматривать всё на примере функции Read Holding Registers (чтение регистров общего назначения).
Функция Read Holding Registers (0x03)
Функция под номером 3 — одна из самых употребимых функций, предназначена для чтения регистров общего назначения устройства.
В запросе указывается количество регистров, которые нужно прочитать и адрес первого из них.
Ответ содержит количество байт (количество регистров умноженное на 2) и значения запрошенных регистров.
Количество байт в ответе помогает ведущему устройству по мере получения данных понять, когда все данные уже получены. То есть если мастер получил третий байт с числом 200 — это означает, что ему осталось получить еще 100 байт + 2 байта контроля целостности. Это позволит ему посчитать количество пришедших байт и закончить приём, не дожидаясь, когда закончится время таймаута, отведённое слейву на ответ.
Вместо нормального ответа, содержащего запрошенные данные, подчинённое устройство может ответить ошибкой. При этом к номеру функции в ответе добавляется код 0х80 в шестнадцатеричной системе исчисления.
Обратимся к предыдущему примеру. Там подчинённое устройство ответило без ошибки и второй байт в ответе был 0х03. Если бы ответ содержал код ошибки, то к номеру функции подчинённое устройство добавило бы 0х80 и получилось бы 0х83. Вот так:
В этом примере код ошибки 02 — это один из стандартных кодов. Вот какие они бывают:
01 — функция не поддерживается. Это значит, что, возможно, функция не стандартная или просто не реализована конкретно в этом устройстве.
02 — запрошенная область памяти не доступна. Каждое устройство содержит определённое количество данных определённого типа. Например, в устройстве доступно 100 регистров общего назначения. Если при этом запросить чтение 101 регистров — возникнет ошибка 02.
03 — функция не поддержит запрошенное количество данных. Например, функция №3 «Read Holding Registers» позволяет читать от 1 до 2000 регистров общего назначения. Поэтому, даже если в подчинённом устройстве доступно для чтения 10 000 регистров, при запросе более 2000 с помощью функции №3 — возникнет эта ошибка.
04 — функция выполнена с ошибкой. Такой код ошибки будет возвращён, если есть какое-то иное препятствие для нормального выполнения команды, не охваченное тремя предыдущими кодами ошибки. Проще говоря, это такая заглушка «на всякий случай», если что-то пошло не так, но в протоколе специального кода для такой ошибки не предусмотрено.
Нужно помнить, что существуют не только стандартные функции, но ещё и пользовательские и зарезервированные. Поэтому, производители устройств, которые дополнили протокол своими функциями, возможно заложили туда другие коды ошибок. Но это всё очень большая экзотика…
Как уже говорилось, в протоколе ModBus RTU данные передаются в виде сообщений, разделённых между собой временными паузами длиной в 3,5 символа при заданной скорости передачи.
В сообщении обязательно указывается адрес получателя (или 0, если сообщение широковещательное) и номер функции.Номер функции определяет какие данные содержит сообщение и как их интерпретировать.
За номером функции идут данные. Регистры данных в ModBus 32-битные, а передаются ввиде двух 16-битных сло. Сначала идёт старший байт, затем младший.
Пример. Допустим, мы хотим прочитать из удалённого модуля сбора данных 2 регистра, начиная с первого. Адрес удалённого модуля в сети ModBus «4». Для этого воспользуемся функцией №3 Read Holding Registers.
В ответе подчинённое устройство повторяет свой адрес и номер функции, далее следует количество полезных байт в ответе. Каждый регистр состоит из двух байт (сначала идёт старший, затем младший). Значение запрошенных регистров оказались равны 11 и 22 в десятичной системе исчисления (0B и 16 в шестнадцатеричной соответственно).
О том, как использовать другие ModBus функции мы выпустим отдельную статью.
В предыдущем примере за байтами данных идут два байта проверки целостности пакета. Они являются результатом вычисления кода CRC-16 для всего сообщения.
Мастер, передавая запрос, вычисляет CRC-код и добавляет его в конец сообщения. Слейв, получив сообщение, проверяет сообщение на целостность согласно алгоритму CRC-16. Затем подчинённое устройство составляет ответ, точно так же вычисляет для него CRC и добавляет в конец пакета.
Подробно рассматривать алгоритм CRC-16 мы не будем, т.к. мы стараемся быть ближе к практике… А на практике программисту практически никогда не приходится писать блок вычисления CRC — в любой среде программирования можно найти соответствующую функцию или функциональный блок.
В данной статье мы рассмотрели общую структуру протокола ModBus и его классическую разновидность ModBus RTU. Вообще говоря, ModBus RTU — это и есть «истинный Modbus» (если отбросить ModBus ASCII, который уже устарел).
В следующей статье мы поговорим о разновидности протокола ModBus TCP, который является «притягиванием за уши» классического ModBus с целью использования его в Ethernet-сетях, что, конечно же, накладывает определённые ограничения. Но об этом в следующей статье. Следите за обновлениями на LAZY SMART.
lazysmart.ru
В этой статье я попытаюсь рассказать как устроен протокол Modbus, какие данные он может хранить, в каком виде они могут храниться, как они могут быть считаны. Эта статья даст представление о том, что же такое Modbus протокол и как он может применяться.
Для хранения информации в ведомых устройствах (slave device) используются 4 таблицы (или массива). Каждая таблица хранит информацию для схожих переменных в регистрах. Каждый регистр имеет свой размер и адрес. Так же регистры могут быть только для чтения, или для чтения – записи. Давайте рассмотрим эти 4 типа данных, которые можно хранить в регистрах:
Это цифровые выходы (Digital Outputs). Каждый coil можно записать или считать. Его размер – 1 бит (т.е. 0 или 1). Исторически эти регистры связаны с реальными цифровыми выходами на сенсорах или терминальных устройствах. Цифровые выходы используются для управления, например светодиодами, реле или моторами. Т.е. записывая в такой регистр 1 мы можем включить светодиод, а записав 0 – выключить его (это условно, на самом деле 0 может включать, а 1 – выключать).
При чтении данного регистра мы можем узнать состояние выхода (т.е. включен он или выключен). Результат чтения так же 1 бит, т.е. 1 или 0.
Это цифровые входы (Digital Inputs). Цифровой вход можно только читать, т.е считывая данный регистр мы узнаем состояние реального цифрового входа на сенсоре или устройстве. Цифровые входы используются для контроля состояние – например, включен свет или выключен, достигла жидкость нужного уровня или нет, включено реле или нет, и т.д.
Под этим обычно имеются в виду аналоговые входы (Analog Inputs). Аналоговые входы можно только читать, т.е их нельзя записывать, а можно только считать текущее состояние налогового входа. Обычно аналоговые входы применяются на сенсорах для измерение некоторых значений: входного тока или входного напряжения. Затем, полученное значение можно конвертировать в некоторую реальную величину, например в температуру, влажность воздуха, давление или еще что то. Для этого используются специальные формулы, которые идут вместе с сенсором. Но чаще сенсор сразу возвращает реальное значение. Например, сенсор измеряющий температуру, может возвращать измеренное значение как градусы по Цельсию умноженные на 10. Т.е. 253 означает 25.3°С. Этот прием часто используется, если нужно вернуть дробные значения через целочисленный регистр.
Эти регистры 16 битные, т.е. каждый регистр может хранить всего 2 байта.
Под этим обычно имеются в виду аналоговые выходы (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 устройствами. Поэтому, если вы хотите, что бы ваше устройство могло работать со стандартными клиентами, то не нужно использовать расширенные регистры.
Но если вы уверены, что ваше устройство будет работать с вашим мастером, который знает как работать с расширенными регистрами, или вы точно знаете, что мастер устройство, которое будет использоваться для вашего продукта знает о расширенных регистрах, тогда используйте их.
Выше мы разобрались, как адресуются регистры внутри устройства. Теперь посмотрим, как адресуются сами устройства.
Для адресации устройств используется специальный идентификатор, который называется 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 протоколе приведены ниже:
Код Функции | Тип Действия | Описание |
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 регистров |
Каждая функция будет рассмотрена позже, подробно и с примерами.
Каждая команда в 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 регистры на устройстве, их адреса, назначение, доступные значения, значения по умолчанию, способ доступа.
Некоторые устройства поставляются с фиксированным описанием регистров. Т.е. список регистров, их адресов, хранимых данных и т.д. жестко задан производителем и описан в документации.
А есть настраиваемая конфигурация. Т.е. на устройстве нет фиксированных адресов для регистров. Пользователь может сконфигурировать 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 не поддерживает сообщения (events). Т.е. конечное устройство не может послать сообщение мастеру. Только мастер может опросить конечное устройство.
Modbus не поддерживает чтение исторических данных (накопленных за некоторый промежуток времени). Хотя это ограничение можно легко обойти, создав командные регистры, регистры адреса и перегружаемые регистры. Это будет обсуждаться в одной из следующих статей.
Стандартный Modbus не может хранить сложные структурированные данные (по крайней мере это не так просто реализовать).
Кроме того, Modbus не поддерживает идентификации и шифрования. Т.е вся коммуникация идет в незащищённом режиме. Хотя, при некотором желании можно реализовать некоторое подобие идентификации в Modbus TCP в большинстве случаев это сделать невозможно. Есть некоторые варианты как защитить данные от несанкционированного доступа и изменения, но они все не очень надежные (хотя и могут применятся). Я опишу их в следующих статьях.
И кажется, это все явные недостатки для этого протокола. В остальном он очень прост и отлично подходит для простых систем мониторинга, которые должны следить за некоторыми показателями системы и предоставлять доступ к ним через чтение регистров.
В следующей статье мы рассмотрим все основные функции, которые поддерживаются протоколом Modbus.
www.siv-blog.com
В этой статье вы узнаете о протоколе Modbus TCP, который является развитием протокола Modbus RTU. Англоязычная версия статьи доступна на ipc2u.com.
Оглавление:
В сети Ethernet адресом устройства является его IP-адрес. Обычно устройства находятся в одной подсети, где IP адреса отличаются последними цифрами 192.168.1.20 при использовании самой распространённой маски подсети 255.255.255.0.
Интерфейсом является сеть Ethernet, протоколом передачи данных – TCP/IP.
Используемый TCP-порт: 502.
Наверх к оглавлению
Команда 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.
Код функции | Что делает функция | Тип значения | Тип доступа | |
---|---|---|---|---|
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 битное | Запись |
Наверх к оглавлению
Эта команда используется для чтения значений дискретных выходов 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 |
Наверх к оглавлению
Эта команда используется для чтения значений дискретных входов 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 будет первым справа (младший бит).
Шесть остальных битов заполнены нулями.
Наверх к оглавлению
Эта команда используется для чтения значений аналоговых выходов 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.
Наверх к оглавлению
Эта команда используется для чтения значений аналоговых входов 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.
Наверх к оглавлению
Эта команда используется для записи одного значения дискретного выхода 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.
Наверх к оглавлению
Эта команда используется для записи одного значения аналогового выхода 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.
Наверх к оглавлению
Эта команда используется для записи нескольких значений дискретного выхода 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.
Наверх к оглавлению
Эта команда используется для записи нескольких значений аналогового выхода 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.
Наверх к оглавлению
Если после получения запроса устройство не может обработать его, то будет отослан ответ с кодом ошибки.
Ответ будет содержать измененный Функциональный код, его старший бит будет равен 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 | Ведомое устройство при чтении расширенной памяти обнаружило ошибку паритета. Ведущее устройство может повторить запрос, но обычно в таких случаях требуется ремонт. |
Наверх к оглавлению
Ниже представлены программы, которые помогут легко взаимодействовать с устройствами Modbus TCP.
Modbus Master Tool с поддержкой Modbus RTU, ASCII, TCP. Скачать
Modbus TCP client с поддержкой Modbus TCP. Скачать
Наверх к оглавлению
Ethernet-шлюзы для преобразования протоколов Modbus TCP в Modbus RTU/ASCII, Profibus, Ethernet/IP, BacNet, CAN, HART, IEC 61850, IEC 60870-5-101, 103 и 104.
ПодробнееСерии ET-7000, PET-7000, tET — это модули ввода-вывода с интерфейсом Ethernet и протоколом Modbus TCP.
ПодробнееEthernet модули ввода-вывода серии ioLogik E1200 с протоколом Modbus TCP и SNMP, сертифицированные для использования на железнодорожном транспорте.
ПодробнееМодули ввода-вывода серии ADAM-6000 с интерфейсом Ethernet и протоколом Modbus TCP.
ПодробнееМодули серии WISE-4000/LAN предназначены для применения в современных системах IoT (Internet of Things). Связь с модулями осуществляется по сети Ethernet, протоколам Modbus TCP, MQTT.
ПодробнееEthernet-корзины со слотами расширения для модулей I-87K серии ET-87Pn (где n число слотов для модулей расширения).
ПодробнееEthernet-корзины с функцией резервирования модулей, что позволяет резервировать каналы ввода-вывода. Протокол Modbus TCP.
ПодробнееМодули серии WF-2000 с беспроводным интерфейсом Wi-Fi и управлением по протоколу Modbus TCP.
ПодробнееМодули серии WISE-4000 предназначены для применения в современных системах IoT (Internet of Things). Связь с модулями осуществляется по Wi-Fi, протоколам Modbus TCP, MQTT.
ПодробнееКомпактные терминалы ввода-вывода серий TPD и VPD с цветным экраном, сенсорным управлением и коммуникационными интерфейсами Ethernet и COM.
ПодробнееПриборы серий PM-2000 и PM-3000 для измерения параметров однофазных или трехфазных электрических сетей питания и передавать данные по протоколам Modbus RTU, Modbus TCP, CANbus или CANopen.
ПодробнееУстройства серии DL для измерения температуры, влажности и концентрации CO2, ведения архива измерений и передачи информации по протоколам DCON, Modbus TCP или Modbus RTU.
ПодробнееНаверх к оглавлению
За более подробной информацией обращайтесь к специалистам IPC2U по телефону: +7 (495) 232 0207 или по e-mail: [email protected]
ipc2u.ru