Modbus/en: различия между версиями
FuzzyBot (обсуждение | вклад) (Часть переводимой страницы Протокол Modbus.) |
(Новая страница: «900px|thumb|left|Modbus datagram in general») |
||
(не показано 46 промежуточных версий 3 участников) | |||
Строка 1: | Строка 1: | ||
<languages/> | <languages/> | ||
=== | ===Basics=== | ||
Modbus is a | Basic concept | ||
Modbus is a Protocol of the applied (seventh) level of the [https://en.wikipedia.org/wiki/OSI_model OSI] model for data exchange, most often between automation devices and is implemented in the form of "request-reply protocol". | |||
In Wirenboard devices, Modbus data is transmitted over RS-485 serial communication lines. In serial lines RS-485 Protocol is half-duplex and works on the principle of "client-server". Each device on the network (except the master, see below) has an address from 1 to 247, address 0 is used for broadcasting to all devices, and addresses 248-255 are considered reserved according to the Modbus specification, their use is not recommended. | In Wirenboard devices, Modbus data is transmitted over RS-485 serial communication lines. In serial lines RS-485 Protocol is half-duplex and works on the principle of "client-server". Each device on the network (except the master, see below) has an address from 1 to 247, address 0 is used for broadcasting to all devices, and addresses 248-255 are considered reserved according to the Modbus specification, their use is not recommended. | ||
There are two protocol specifications: Modbus RTU and Modbus ASCII. An 11-bit character consisting of 1 start bit, 8 data bits (starting with the lower bit), a parity bit (optional), and 2 stop bits if no parity bit is transmitted, or 1 stop bit if parity bit is transmitted, is transmitted to the Modbus RTU. This character allows you to transfer 1 byte of data. In Wiren Board devices, the parity bit is not transmitted and 2 stop bits are used. In Modbus ASCII, each byte is transmitted in two characters representing the ASCII codes of the lower and upper four-bit byte groups ([http://www.simplymodbus.ca/ASCII.htm пример]). The Modbus RTU allows you to transmit more information at the same serial line speed and it is used in the Wiren Board devices. All further description applies to Modbus RTU. | There are two protocol specifications: Modbus RTU and Modbus ASCII. An 11-bit character consisting of 1 start bit, 8 data bits (starting with the lower bit), a parity bit (optional), and 2 stop bits if no parity bit is transmitted, or 1 stop bit if no parity bit is transmitted, is transmitted to the Modbus RTU. This character allows you to transfer 1 byte of data. In Wiren Board devices, the parity bit is not transmitted and 2 stop bits are used. In Modbus ASCII, each byte is transmitted in two characters representing the ASCII codes of the lower and upper four-bit byte groups ([http://www.simplymodbus.ca/ASCII.htm пример]). The Modbus RTU allows you to transmit more information at the same serial line speed and it is used in the Wiren Board devices. All further description applies to Modbus RTU. | ||
The master device periodically polls the slave or server. The master has no address, the transmission of messages from the device server to the host without asking the host in the protocol is not provided. | The master device periodically polls the slave or server. The master has no address, the transmission of messages from the device server to the host without asking the host in the protocol is not provided. | ||
[[ | [[Special:MyLanguage/Файл:Modbus_Datagram.png|900px|thumb|left|Modbus datagram in general]] | ||
Пакет данных 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, содержащий запрошенные данные. | |||
[[ | [[Special:MyLanguage/Файл:Modbus_transaction_OK.png|700px|thumb|center|Modbus-транзакция, прошедшая без ошибок]] | ||
---- | ---- | ||
При возникновении ошибки устройством возвращается код ошибки. В случае обычной транзакции код функции в ответе возвращается без изменений; в случае ошибки старший бит кода функции устанавливается в единицу (то есть ''код функции'' + 0x80) | |||
[[ | [[Special:MyLanguage/Файл:Modbus_transaction_ERR.png|700px|thumb|center|Modbus-транзакция с ошибками]] | ||
---- | ---- | ||
Стоит определить таймаут ожидания ответа от ведомого устройства — бессмысленно долго ждать ответ, который, возможно, из-за какой-то ошибки никогда и не придет. | |||
===Modbus | ===Структуры данных Modbus=== | ||
В Modbus принято кодировать адреса и данные в формате big-endian, то есть в формате, когда байты следуют, начиная со старшего: например, при передаче шестнадцатеричного числа 0x1234 сначала устройством будет принят байт 0x12, а затем — 0x34. Для передачи данных другого типа, например, чисел с плавающей запятой (float), текстовых строк, даты и времени суток и т.п. производитель может выбрать свой собственный способ кодирования — для расшифровки получаемых данных важно ознакомится со спецификацией производителя устройства. | |||
===Modbus | ===Модель данных Modbus=== | ||
Обмен данными с Modbus-устройствами происходит через регистры. В протоколе Modbus определяется четыре типа регистров, показанных в таблице: | |||
{|class="wikitable" align="center" | {|class="wikitable" align="center" | ||
! | ! Таблица || Размер || Доступ | ||
|- | |- | ||
! Coils | ! Регистры флагов (Coils) | ||
| 1 | | 1 бит || чтение и запись | ||
|- | |- | ||
! Discrete Inputs | ! Дискретные входы (Discrete Inputs) | ||
| 1 | | 1 бит || только чтение | ||
|- | |- | ||
! Holding Registers | ! Регистры хранения (Holding Registers) | ||
| 16- | | 16-битное слово || чтение и запись | ||
|- | |- | ||
! Input Registers | ! Регистры ввода (Input Registers) | ||
| 16- | | 16-битное слово || только чтение | ||
|} | |} | ||
Coils | '''Регистры флагов''' (Coils) хранят однобитные значения - то есть могут находится в состоянии 0 или 1. Такие регистры могут обозначать текущее состояние выхода (включено реле). Название "coil" буквально и означает обмотку-актюатор электромеханического реле. Регистры флагов допускают как чтение, так и запись. | ||
Discrete | '''Дискретные входы''' (Discrete Inputs) также являются однобитными регистрами, описывающими состояние входа устройства (например подано напряжение — 1). Эти регистры поддерживают только чтение. | ||
Holding Registers | '''Регистры хранения''' (Holding Registers) и '''регистры ввода''' (Input Registers) представлены двухбайтовым словом и могут хранить значения от 0 до 65535 (0x0000 — 0xFFFFF). | ||
Регистры ввода допускают только чтение (например, текущее значение температуры). Регистры хранения поддерживают как чтение, так и запись (для хранения настроек). В настоящее время во многих устройствах, в частности в устройствах Wiren Board, эти регистры не разделяются. Команды на чтение регистра хранения N и регистра ввода N обратятся к одному и тому же значению в адресном пространстве устройства. | |||
===Адреса и номера регистров=== | |||
В стандарте Modbus для каждого из четырех типов регистров используются разные таблицы с номерами 0,1,3,4. Таким образом, регистр определенного типа с определенным номером (иначе его называют физическим адресом) имеет свой адрес в соответствующей таблице. | |||
{|class="wikitable" align="center" | {|class="wikitable" align="center" | ||
! | ! Таблица || Номер таблицы || Начальный логический адрес || Номер регистра (физический адрес) || Диапазон логических адресов | ||
|- | |- | ||
! Coils | ! Регистры флагов (Coils) | ||
| 0 || 000001 || 0 || 000001 — 065535 | | 0 || 000001 || 0 || 000001 — 065535 | ||
|- | |- | ||
! Discrete Inputs | ! Дискретные входы (Discrete Inputs) | ||
| 1 || 100001 || 0 || 100001 — 165535 | | 1 || 100001 || 0 || 100001 — 165535 | ||
|- | |- | ||
! Holding Registers | ! Регистры хранения (Holding Registers) | ||
| 3 || 300001 || 0 || 300001 — 365535 | | 3 || 300001 || 0 || 300001 — 365535 | ||
|- | |- | ||
! Input Registers | ! Регистры ввода (Input Registers) | ||
| 4 || 400001 || 0 || 400001 — 465535 | | 4 || 400001 || 0 || 400001 — 465535 | ||
|} | |} | ||
Это вносит некоторую путаницу в понимание, по какому же адресу обратиться к регистру с нужным номером. Более того, понятия "адрес" и "регистр" могут применяться производителем произвольно. Чаще всего указываются номера регистров, как, например для устройств Wiren Board.В некоторых устройствах применяются более короткие логические адреса (.0001 — .9999), и для адреса используется 5, а не 6 цифр. | |||
Иногда в описаниях устройства указываются только логические адреса. Например, coil-регистр 0 имеет адрес 000001, регистр ввода 4 — 400005 и т.д. | |||
В готовых шаблонах устройств контроллера Wiren Board 5 есть шаблон для однофазного счетчика электроэнергии SDM220 (/usr/share/wb-mqtt-serial/templates/config-sdm220.json). В документации от производителя "Eastron SDM | |||
220 Modbus Smart Meter Modbus Protocol Implementation V1.0" перечислены регистры и соответствующие им измеряемые параметры, например: | |||
{|class="wikitable" align="center" | {|class="wikitable" align="center" | ||
Строка 110: | Строка 113: | ||
|} | |} | ||
Производитель в таблице приводит и логические, и физические адреса регистров, что позволяет нам с легкостью создать шаблон устройства и проиллюстрировать связь между логическими и физическими адресами Modbus-регистров. | |||
[[ | [[Special:MyLanguage/Файл:SDM220_Template.png|700px|thumb|center|Фрагмент шаблона счетчика SDM220]] | ||
=== Коды функций чтения и записи регистров === | |||
В следующей таблице приведены наиболее распространенные коды функций Modbus: | |||
{|class="wikitable" align="center" | {|class="wikitable" align="center" | ||
! | !Код функции || HEX || Название || Действие | ||
|- | |- | ||
! 1 | ! 1 | ||
| 0x01 || Read Coils | | 0x01 || Read Coils || Чтение значений нескольких регистров флагов | ||
|- | |- | ||
! 2 | ! 2 | ||
| 0x02 ||Read Discrete Inputs | | 0x02 ||Read Discrete Inputs || Чтение значений нескольких дискретных входов | ||
|- | |- | ||
! 3 | ! 3 | ||
| 0x03 ||Read Holding Registers | | 0x03 ||Read Holding Registers || Чтение значений нескольких регистров хранения | ||
|- | |- | ||
! 4 | ! 4 | ||
| 0x04 ||Read Input Registers | | 0x04 ||Read Input Registers || Чтение значений нескольких регистров ввода | ||
|- | |- | ||
! 5 | ! 5 | ||
| 0x05 ||Write Single Coil | | 0x05 ||Write Single Coil || Запись одного регистра флагов | ||
|- | |- | ||
! 6 | ! 6 | ||
| 0x06 ||Write Single Register | | 0x06 ||Write Single Register || Запись одного регистра (ввода или хранения) | ||
|- | |- | ||
! 15 | ! 15 | ||
| 0x0F ||Write Multiple Coils | | 0x0F ||Write Multiple Coils || Запись нескольких регистров флагов | ||
|- | |- | ||
! 16 | ! 16 | ||
| 0x10 ||Write Multiple Register | | 0x10 ||Write Multiple Register || Запись нескольких регистров (ввода или хранения) | ||
|- | |- | ||
|} | |} | ||
Команды условно можно разделить по типам: чтение значений — запись значений; операция с одним значением — операция с несколькими значениями. | |||
=== Формат данных запросов и ответов Modbus === | |||
[[ | Рассмотрим подробнее, как происходит обмен данными между устройством-клиентом, отправляющим запрос, и устройством-сервером, отвечающим ему. | ||
На следующем рисунке показан обмен данными контроллера с устройством с адресом 0x01. Мы хотим прочесть 8 coil-регистров, начиная с первого. | |||
[[Special:MyLanguage/Файл:Read_8_Coils_2.png|600px|thumb|center|Обмен данными в Modbus]] | |||
В качестве данных мы получили шестнадцатеричное число 0x2D, то есть состояние восьми coil-регистров в двоичном виде такое: 0b10110100. | |||
---- | ---- | ||
В следующей таблице приведены структуры данных запросов и ответов для основных функций Modbus. | |||
{|class="wikitable" align="center" | {|class="wikitable" align="center" | ||
! | !Код функции || Запрос || Ответ | ||
|- | |- | ||
! 1 (Read Coils) и 2 (Read Discrete Inputs) | ! 1 (Read Coils) и 2 (Read Discrete Inputs) | ||
|<ul><li> | |<ul><li>Адрес первого регистра флагов или входного регистра (16 бит)</li><li>Количество данных (8 значений на байт) (16 бит)</li><ul>|| <ul><li>Число передаваемых байт (8 бит)</li><li>Значения регистров флагов или входных регистров (8 значений на байт)</li></ul> | ||
|- | |- | ||
! 3 (Read Holding Registers) и 4 (Read Input Registers) | ! 3 (Read Holding Registers) и 4 (Read Input Registers) | ||
|<ul><li> | |<ul><li>Адрес первого регистра (16 бит)</li><li>Количество регистров, которые нужно прочесть</li><ul>|| <ul><li>Число передаваемых байт (8 бит)</li><li>Значения регистров (16 бит на 1 регистр)</li></ul> | ||
|- | |- | ||
! 5 (Write Single Coil) | ! 5 (Write Single Coil) | ||
|<ul><li> | |<ul><li>Адрес регистра (16 бит)</li><li>Значение, которое нужно записать (0 — выключить, 0xFF00 — включить)</li><ul>|| Ответ аналогичен запросу | ||
|- | |- | ||
! 6 (WriteSingle Register) | ! 6 (WriteSingle Register) | ||
|<ul><li>Адрес регистра(16 бит)</li><li> | |<ul><li>Адрес регистра(16 бит)</li><li>Новое значение регистра (16 бит)</li></ul>|| Ответ аналогичен запросу | ||
|- | |- | ||
! 15 (WriteMultipleCoils) | ! 15 (WriteMultipleCoils) | ||
| <ul><li> | | <ul><li>Адрес первого регистра флагов для записи (16 бит)</li><li>Количество регистров флагов для записи (16 бит)</li><li>Количество передаваемых байт данных для регистров флагов (8 бит)</li><li>Данные (8 регистров флагов на байт)</li></ul> || <ul><li>Адрес первого coil-регистра (16 бит)</li><li>Количество записанных coil-регистров(16 бит)</li></ul> | ||
|- | |- | ||
! 16 (Write Multiple register ) | ! 16 (Write Multiple register ) | ||
| <ul><li> | | <ul><li>Адрес первого регистра хранения для записи (16 бит)</li><li>Количество регистров хранения для записи (16 бит)</li><li>Количество передаваемых байт данных для регистров (8 бит)</li><li>Данные (16 байт на регистр)</li></ul> || <ul><li>Адрес первого регистра хранения (16 бит)</li><li>Количество записанных регистров хранения(16 бит)</li></ul> | ||
|- | |- | ||
|} | |} | ||
=== | === Коды исключений (ошибки) Modbus === | ||
В случае, если запрос не может по той или иной причине быть обработан устройством-сервером, то в ответ он отправляет сообщение об ошибке. Соообщение об ошибке содержит адрес Modbus-устройства, код функции, при выполнении которой произошла ошибка, увеличенный на 0x80, код ошибки и контрольную сумму: | |||
[[ | [[Special:MyLanguage/Файл:Read_8_Coils_ERR.png|600px|thumb|center|Транзакция завершилась с ошибкой]] | ||
В этом случае мы попытались обратиться к несуществующему адресу регистра 0xFFFF и попытались прочесть 8 регистров флагов. В результате мы получили код ошибки 0x03 — "В поле данных передано неверное значение". | |||
Наиболее распространенные коды ошибок Modbus приведены в следующей таблице: | |||
{|class="wikitable" align="center" | {|class="wikitable" align="center" | ||
! | !Код ошибки || Название ошибки|| Что означает | ||
|- | |- | ||
! 1 | ! 1 | ||
| Illegal Function || | | Illegal Function || В запросе был передан недопустимый код функции | ||
|- | |- | ||
! 2 | ! 2 | ||
| Illegal Data Address || | | Illegal Data Address ||Указанный в запросе адрес не существует | ||
|- | |- | ||
! 3 | ! 3 | ||
| Illegal Data Value || | | Illegal Data Value || В поле данных передано неверное значение | ||
|- | |- | ||
! 4 | ! 4 | ||
| Slave Device Failure || | | Slave Device Failure ||Произошла невосстановимая ошибка на устройстве при выполнении запрошенной операции | ||
|- | |- | ||
! 5 | ! 5 | ||
| Acknowledge || | | Acknowledge ||Запрос принят, выполняется, но выполнение потребует много времени; необходимо увеличить таймаут. | ||
|- | |- | ||
! 6 | ! 6 | ||
| Slave Device Busy || | | Slave Device Busy ||Устройство занято обработкой предыдущего запроса. | ||
|- | |- | ||
! 7 | ! 7 | ||
| Negative Acknowledge || | | Negative Acknowledge || Устройство не может выполнить запрос, необходимо получить от устройства дополнительную диагностическую информацию. Возможно, требуется тех. обслуживание. | ||
|- | |- | ||
! 8 | ! 8 | ||
| Memory Parity Error || | | Memory Parity Error || Ошибка четности при обращении к внутренней памяти устройства. | ||
|- | |- | ||
|} | |} | ||
Строка 226: | Строка 230: | ||
=== Modbus | === Вычисление контрольной суммы Modbus === | ||
Для протокола Modbus RTU 16-битная контрольная сумма (CRC) вычисляется по алгоритму, описанному в [http://www.modbus.org/specs.php спецификации Modbus], в документе "Modbus Serial Line Protocol and Implementation Guide", раздел "CRC-generation". Передающее устройство формирует два байта контрольной суммы на основе данных сообщения, а принимающее устройство заново вычисляет контрольную сумму и сравнивает с полученной. Совпадение принятой и вычисленной контрольной суммы Modbud RTU считается индикатором успешного обмена данными. | |||
В случае ограниченных вычислительных ресурсов для вычисления контрольной суммы существует функция, использующая табличные значения (так же приведена в спецификации). |
Версия 14:23, 3 июня 2019
Basics
Basic concept Modbus is a Protocol of the applied (seventh) level of the OSI model for data exchange, most often between automation devices and is implemented in the form of "request-reply protocol".
In Wirenboard devices, Modbus data is transmitted over RS-485 serial communication lines. In serial lines RS-485 Protocol is half-duplex and works on the principle of "client-server". Each device on the network (except the master, see below) has an address from 1 to 247, address 0 is used for broadcasting to all devices, and addresses 248-255 are considered reserved according to the Modbus specification, their use is not recommended.
There are two protocol specifications: Modbus RTU and Modbus ASCII. An 11-bit character consisting of 1 start bit, 8 data bits (starting with the lower bit), a parity bit (optional), and 2 stop bits if no parity bit is transmitted, or 1 stop bit if no parity bit is transmitted, is transmitted to the Modbus RTU. This character allows you to transfer 1 byte of data. In Wiren Board devices, the parity bit is not transmitted and 2 stop bits are used. In Modbus ASCII, each byte is transmitted in two characters representing the ASCII codes of the lower and upper four-bit byte groups (пример). The Modbus RTU allows you to transmit more information at the same serial line speed and it is used in the Wiren Board devices. All further description applies to Modbus RTU.
The master device periodically polls the slave or server. The master has no address, the transmission of messages from the device server to the host without asking the host in the protocol is not provided.
900px|thumb|left|Modbus datagram in general
Пакет данных 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, содержащий запрошенные данные.
700px|thumb|center|Modbus-транзакция, прошедшая без ошибок
При возникновении ошибки устройством возвращается код ошибки. В случае обычной транзакции код функции в ответе возвращается без изменений; в случае ошибки старший бит кода функции устанавливается в единицу (то есть код функции + 0x80)
700px|thumb|center|Modbus-транзакция с ошибками
Стоит определить таймаут ожидания ответа от ведомого устройства — бессмысленно долго ждать ответ, который, возможно, из-за какой-то ошибки никогда и не придет.
Структуры данных 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 — 0xFFFFF). Регистры ввода допускают только чтение (например, текущее значение температуры). Регистры хранения поддерживают как чтение, так и запись (для хранения настроек). В настоящее время во многих устройствах, в частности в устройствах Wiren Board, эти регистры не разделяются. Команды на чтение регистра хранения N и регистра ввода N обратятся к одному и тому же значению в адресном пространстве устройства.
Адреса и номера регистров
В стандарте Modbus для каждого из четырех типов регистров используются разные таблицы с номерами 0,1,3,4. Таким образом, регистр определенного типа с определенным номером (иначе его называют физическим адресом) имеет свой адрес в соответствующей таблице.
Таблица | Номер таблицы | Начальный логический адрес | Номер регистра (физический адрес) | Диапазон логических адресов |
---|---|---|---|---|
Регистры флагов (Coils) | 0 | 000001 | 0 | 000001 — 065535 |
Дискретные входы (Discrete Inputs) | 1 | 100001 | 0 | 100001 — 165535 |
Регистры хранения (Holding Registers) | 3 | 300001 | 0 | 300001 — 365535 |
Регистры ввода (Input Registers) | 4 | 400001 | 0 | 400001 — 465535 |
Это вносит некоторую путаницу в понимание, по какому же адресу обратиться к регистру с нужным номером. Более того, понятия "адрес" и "регистр" могут применяться производителем произвольно. Чаще всего указываются номера регистров, как, например для устройств Wiren Board.В некоторых устройствах применяются более короткие логические адреса (.0001 — .9999), и для адреса используется 5, а не 6 цифр.
Иногда в описаниях устройства указываются только логические адреса. Например, coil-регистр 0 имеет адрес 000001, регистр ввода 4 — 400005 и т.д.
В готовых шаблонах устройств контроллера Wiren Board 5 есть шаблон для однофазного счетчика электроэнергии 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-регистров.
700px|thumb|center|Фрагмент шаблона счетчика 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-регистров, начиная с первого. 600px|thumb|center|Обмен данными в Modbus
В качестве данных мы получили шестнадцатеричное число 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, код ошибки и контрольную сумму:
600px|thumb|center|Транзакция завершилась с ошибкой В этом случае мы попытались обратиться к несуществующему адресу регистра 0xFFFF и попытались прочесть 8 регистров флагов. В результате мы получили код ошибки 0x03 — "В поле данных передано неверное значение".
Наиболее распространенные коды ошибок Modbus приведены в следующей таблице:
Код ошибки | Название ошибки | Что означает |
---|---|---|
1 | Illegal Function | В запросе был передан недопустимый код функции |
2 | Illegal Data Address | Указанный в запросе адрес не существует |
3 | Illegal Data Value | В поле данных передано неверное значение |
4 | Slave Device Failure | Произошла невосстановимая ошибка на устройстве при выполнении запрошенной операции |
5 | Acknowledge | Запрос принят, выполняется, но выполнение потребует много времени; необходимо увеличить таймаут. |
6 | Slave Device Busy | Устройство занято обработкой предыдущего запроса. |
7 | Negative Acknowledge | Устройство не может выполнить запрос, необходимо получить от устройства дополнительную диагностическую информацию. Возможно, требуется тех. обслуживание. |
8 | Memory Parity Error | Ошибка четности при обращении к внутренней памяти устройства. |
Вычисление контрольной суммы Modbus
Для протокола Modbus RTU 16-битная контрольная сумма (CRC) вычисляется по алгоритму, описанному в спецификации Modbus, в документе "Modbus Serial Line Protocol and Implementation Guide", раздел "CRC-generation". Передающее устройство формирует два байта контрольной суммы на основе данных сообщения, а принимающее устройство заново вычисляет контрольную сумму и сравнивает с полученной. Совпадение принятой и вычисленной контрольной суммы Modbud RTU считается индикатором успешного обмена данными.
В случае ограниченных вычислительных ресурсов для вычисления контрольной суммы существует функция, использующая табличные значения (так же приведена в спецификации).