16 578
правок
Fizikdaos (обсуждение | вклад) |
|||
(не показано 45 промежуточных версий 9 участников) | |||
Строка 1: | Строка 1: | ||
<languages/> | <languages/> | ||
<translate> | <translate> | ||
{{DISPLAYTITLE: Протокол Modbus}} | |||
==Основные понятия== <!--T:1--> | |||
{{YouTube | |||
|link= https://youtu.be/d_olK15Xhkw | |||
|text= Всё о Modbus и модулях Wiren Board | |||
}} | |||
<!--T:2--> | <!--T:2--> | ||
Modbus - это протокол | Modbus - это протокол, который служит для обмена данными между устройствами автоматизации и реализован в виде "протокола ответов на запросы (request-reply protocol)". | ||
<!--T:3--> | <!--T:3--> | ||
В устройствах | В устройствах Wiren Board данные Modbus передаются по последовательным линиям связи RS-485. В последовательных линиях связи протокол RS-485 полудуплексный и работает по принципу «клиент-сервер». Каждое устройство в сети (кроме ведущего см. далее) имеет адрес от 1 до 247, адрес 0 используется для широковещательной передачи данных всем устройствам, а адреса 248–255 считаются зарезервированными согласно спецификации Modbus, их использование не рекомендуется. | ||
<!--T:4--> | <!--T:4--> | ||
Существует две спецификации протокола: Modbus RTU и Modbus ASCII. В Modbus RTU передается 11-битный символ, состоящий из 1 стартового бита, 8 бит данных (начиная с младшего бита), бит четности (необязателен) и 2 стоповых бита - если бит четности не передается, или 1 стоповый бит - если бит четности передается. Такой символ | Существует две спецификации протокола: Modbus RTU и Modbus ASCII. В Modbus RTU передается 11-битный символ, состоящий из 1 стартового бита, 8 бит данных (начиная с младшего бита), бит четности (необязателен) и 2 стоповых бита - если бит четности не передается, или 1 стоповый бит - если бит четности передается. Такой символ передает 1 байт данных. В устройствах Wiren Board по умолчанию бит контроля четности не передается и используется 2 стоповых бита. В Modbus ASCII каждый байт передается двумя символами, представляющими ASCII-коды младшей и старшей четырехбитной группы байта ([http://www.simplymodbus.ca/ASCII.htm пример]). Modbus RTU передает больше информации при той же скорости последовательной линии, и в устройствах Wiren Board используется именно он. Все дальнейшее описание относится к Modbus RTU. | ||
<!--T:5--> | <!--T:5--> | ||
Строка 18: | Строка 22: | ||
<!--T:6--> | <!--T:6--> | ||
[[File:Modbus_Datagram.png| | [[File:Modbus_Datagram.png|700px|thumb|right|Датаграмма Modbus в общем виде]] | ||
<!--T:7--> | <!--T:7--> | ||
Пакет данных Modbus выглядит, как это показано на рисунке. '''PDU''' (Protocol Data Unit) — общая часть пакета MODBUS, включающая код функции и данные пакета. '''ADU''' (Application Data Unit) — полный пакет MODBUS. Включает в себя специфичную для физического уровня часть пакета и PDU. Для последовательных линий в заголовке ADU передается адрес устройства, а в конце — контрольная сумма CRC16. Максимальный размер | Пакет данных Modbus выглядит, как это показано на рисунке. '''PDU''' (Protocol Data Unit) — общая часть пакета MODBUS, включающая код функции и данные пакета. '''ADU''' (Application Data Unit) — полный пакет MODBUS. Включает в себя специфичную для физического уровня часть пакета и PDU. Для последовательных линий в заголовке ADU передается адрес устройства, а в конце — контрольная сумма CRC16. Максимальный размер PDU в последовательных коммуникационных линиях составляет '''253 байта''' (из максимальных, разрешенных спецификацией 256 байт вычитается 1 байт адреса и два байта контрольной суммы). Для справки — в Modbus TCP максимальная длина пакета составляет 260 байт. | ||
Строка 27: | Строка 31: | ||
Функция кодируется одним байтом и определяет, какое действие должно выполнить устройство-сервер. Значение кодов функций лежат в диапазоне от 1 до 255, причем коды от 128 до 255 зарезервированы для сообщений об ошибках со стороны устройства-сервера. Код 0 не используется. Размер блока данных может варьироваться от нуля до максимально допустимого. Если обработка запроса прошла без ошибок, то устройство-сервер возвращает пакет ADU, содержащий запрошенные данные. | Функция кодируется одним байтом и определяет, какое действие должно выполнить устройство-сервер. Значение кодов функций лежат в диапазоне от 1 до 255, причем коды от 128 до 255 зарезервированы для сообщений об ошибках со стороны устройства-сервера. Код 0 не используется. Размер блока данных может варьироваться от нуля до максимально допустимого. Если обработка запроса прошла без ошибок, то устройство-сервер возвращает пакет ADU, содержащий запрошенные данные. | ||
< | <gallery mode="packed" heights="300px"> | ||
File:Modbus_transaction_OK.png|700px|thumb|center|Modbus-транзакция, прошедшая без ошибок | |||
File:Modbus_transaction_ERR.png|700px|thumb|center|Modbus-транзакция с ошибками | |||
</gallery> | |||
<!--T:10--> | <!--T:10--> | ||
При возникновении ошибки устройством возвращается код ошибки. При обычной транзакции код функции в ответе возвращается без изменений; при ошибке старший бит кода функции устанавливается в единицу (то есть ''код функции'' + 0x80). Так же есть таймаут ожидания ответа от ведомого устройства — бессмысленно долго ждать ответ, который, возможно, никогда и не придет. | |||
При возникновении ошибки устройством возвращается код ошибки. | |||
==Структуры данных Modbus== <!--T:14--> | |||
<!--T:15--> | <!--T:15--> | ||
В Modbus принято кодировать адреса и данные в формате big-endian, то есть в формате, когда байты следуют, начиная со старшего: например, при передаче шестнадцатеричного числа 0x1234 сначала устройством будет принят байт 0x12, а затем — 0x34. Для передачи данных другого типа, например, чисел с плавающей запятой (float), текстовых строк, даты и времени суток и т.п. производитель может выбрать свой собственный способ кодирования — для расшифровки получаемых данных важно ознакомится со спецификацией производителя устройства. | В Modbus принято кодировать адреса и данные в формате big-endian, то есть в формате, когда байты следуют, начиная со старшего: например, при передаче шестнадцатеричного числа 0x1234 сначала устройством будет принят байт 0x12, а затем — 0x34. Для передачи данных другого типа, например, чисел с плавающей запятой (float), текстовых строк, даты и времени суток и т.п. производитель может выбрать свой собственный способ кодирования — для расшифровки получаемых данных важно ознакомится со спецификацией производителя устройства. | ||
==Модель данных Modbus== <!--T:16--> | |||
<!--T:17--> | <!--T:17--> | ||
Строка 79: | Строка 74: | ||
Регистры ввода допускают только чтение (например, текущее значение температуры). Регистры хранения поддерживают как чтение, так и запись (для хранения настроек). В настоящее время во многих устройствах, в частности в устройствах Wiren Board, эти регистры не разделяются. Команды на чтение регистра хранения N и регистра ввода N обратятся к одному и тому же значению в адресном пространстве устройства. | Регистры ввода допускают только чтение (например, текущее значение температуры). Регистры хранения поддерживают как чтение, так и запись (для хранения настроек). В настоящее время во многих устройствах, в частности в устройствах Wiren Board, эти регистры не разделяются. Команды на чтение регистра хранения N и регистра ввода N обратятся к одному и тому же значению в адресном пространстве устройства. | ||
=== | == Адреса регистров == | ||
Регистры в стандарте Modbus адресуются с помощью 16-битных адресов. Адресация начинается с нуля. Адрес регистра, таким образом, может принимать значения от 0 до 65535. | |||
Адресные пространства регистров, также называемые таблицами или блоками, могут быть различны для всех четырёх типов регистров. Это значит, что значения регистров с одинаковым адресом, но разным типом, в общем случае разные. | |||
Например, при чтении регистра флагов (coil) номер 42, регистра дискретного входа (Discrete), регистров ввода и хранения (Input и Holding) с теми же адресами, можно получить четыре разных значения. | |||
=== Нестандартная адресация === | |||
В документации на некоторые, особенно старые, устройства адреса элементов (регистров) указываются в формате, не соответствующем стандарту. В этом формате тип элемента кодируется первой цифрой адреса, а адресация начинается не с нуля. | |||
Например, регистр хранения с адресом 0 может записываться как 40001 или 400001, а Coil с адресом 0 как 000001. | |||
В таблице перевода адресов в стандартный формат показаны диапазоны для двух разных нестандартных типов указания адресов и соответствующие им типы данных и диапазоны стандартных адресов. | |||
{|class="wikitable" align="center" | {|class="wikitable" align="center" | ||
! | ! Тип данных || Стандартные адреса || Стандартные адреса (hex) || Нестандартные адреса (5 цифр) || Нестандартные адреса (6 цифр) | ||
|- | |- | ||
! | ! Флагов (Coils) | ||
| 0 || 000001 || 0 || | | 0-65535 || 0x0000 - 0xFFFF || 00001 - 09999 || 000001 - 065536 | ||
|- | |||
! Дискретных входов (Discrete) | |||
| 0-65535 || 0x0000 - 0xFFFF || 10001 - 19999 || 100001 - 165536 | |||
|- | |- | ||
! | ! Регистры входов (Input Registers) | ||
| | | 0-65535 || 0x0000 - 0xFFFF || 30001 - 39999 || 300001 - 365536 | ||
|- | |- | ||
! Регистры хранения (Holding Registers) | ! Регистры хранения (Holding Registers) | ||
| 0-65535 || 0x0000 - 0xFFFF || 40001 - 49999 || 400001 - 465536 | |||
| | |||
|} | |} | ||
Признаки использования нестандартной адресации: | |||
* Адреса записываются в десятичном формате | |||
* Во всех адресах пять или шесть цифр | |||
* Адреса с недискретными данными (показания датчиков и т.п.) начинаются на 30 или 40 | |||
Часто рядом с нестандартными адресами указываются и адреса соответствующие стандарту, обычно в шестнадцатеричном формате. | |||
Стоит отметить, что физически в пакете данных передаются адреса в стандартном формате, независимо от способа представления их в документации. | |||
=== Пример описания регистров в документации === | |||
<!--T:26--> | <!--T:26--> | ||
В готовых шаблонах устройств контроллера Wiren Board | В готовых шаблонах устройств для контроллера Wiren Board есть шаблон для однофазного счетчика электроэнергии SDM220 (/usr/share/wb-mqtt-serial/templates/config-sdm220.json). В документации от производителя "Eastron SDM | ||
220 Modbus Smart Meter Modbus Protocol Implementation V1.0" перечислены регистры и соответствующие им измеряемые параметры, например: | 220 Modbus Smart Meter Modbus Protocol Implementation V1.0" перечислены регистры и соответствующие им измеряемые параметры, например: | ||
Строка 165: | Строка 170: | ||
|- | |- | ||
! 6 | ! 6 | ||
| 0x06 ||Write Single Register || Запись одного регистра | | 0x06 ||Write Single Register || Запись одного регистра хранения | ||
|- | |- | ||
! 15 | ! 15 | ||
Строка 171: | Строка 176: | ||
|- | |- | ||
! 16 | ! 16 | ||
| 0x10 ||Write Multiple Register || Запись нескольких регистров | | 0x10 ||Write Multiple Register || Запись нескольких регистров хранения | ||
|- | |- | ||
|} | |} | ||
Строка 177: | Строка 182: | ||
<!--T:34--> | <!--T:34--> | ||
Команды условно можно разделить по типам: чтение значений — запись значений; операция с одним значением — операция с несколькими значениями. | Команды условно можно разделить по типам: чтение значений — запись значений; операция с одним значением — операция с несколькими значениями. | ||
=== Формат данных запросов и ответов Modbus === <!--T:35--> | === Формат данных запросов и ответов Modbus === <!--T:35--> | ||
Строка 223: | Строка 227: | ||
<!--T:42--> | <!--T:42--> | ||
Если запрос не может по той или иной причине быть обработан устройством-сервером, то в ответ он отправляет сообщение об ошибке. Соообщение об ошибке содержит адрес Modbus-устройства, код функции, при выполнении которой произошла ошибка, увеличенный на 0x80, код ошибки и контрольную сумму: | |||
<!--T:43--> | <!--T:43--> | ||
Строка 243: | Строка 247: | ||
|- | |- | ||
! 3 | ! 3 | ||
| Illegal Data Value || | | Illegal Data Value || Неверный формат запроса, например количество байт в запросе не соответствует ожидаемому. | ||
'''Примечание''': несмотря на название, эта ошибка не говорит о том, что само значение регистра неправильное или ошибочное, и должна использоваться только для ошибок формата запроса. | |||
|- | |- | ||
! 4 | ! 4 | ||
| | | Server Device Failure ||Произошла невосстановимая ошибка на устройстве при выполнении запрошенной операции | ||
|- | |- | ||
! 5 | ! 5 | ||
Строка 252: | Строка 257: | ||
|- | |- | ||
! 6 | ! 6 | ||
| | | Server Device Busy ||Устройство занято обработкой предыдущего запроса. | ||
|- | |- | ||
! 7 | ! 7 | ||
Строка 261: | Строка 266: | ||
|- | |- | ||
|} | |} | ||
=== Вычисление контрольной суммы Modbus === <!--T:46--> | === Вычисление контрольной суммы Modbus === <!--T:46--> | ||
<!--T:47--> | <!--T:47--> | ||
Для протокола Modbus RTU 16-битная контрольная сумма (CRC) вычисляется по алгоритму, описанному в [http://www.modbus.org/specs.php спецификации Modbus], в документе "Modbus Serial Line Protocol and Implementation Guide", раздел "CRC-generation". Передающее устройство формирует два байта контрольной суммы на основе данных сообщения, а принимающее устройство заново вычисляет контрольную сумму и сравнивает с полученной. Совпадение принятой и вычисленной контрольной суммы | Для протокола Modbus RTU 16-битная контрольная сумма (CRC) вычисляется по алгоритму, описанному в [http://www.modbus.org/specs.php спецификации Modbus], в документе "Modbus Serial Line Protocol and Implementation Guide", раздел "CRC-generation". Передающее устройство формирует два байта контрольной суммы на основе данных сообщения, а принимающее устройство заново вычисляет контрольную сумму и сравнивает с полученной. Совпадение принятой и вычисленной контрольной суммы Modbus RTU считается индикатором успешного обмена данными. | ||
<!--T:48--> | <!--T:48--> | ||
В случае ограниченных вычислительных ресурсов для вычисления контрольной суммы существует функция, использующая табличные значения ( | В случае ограниченных вычислительных ресурсов для вычисления контрольной суммы существует функция, использующая табличные значения (также приведена в спецификации). | ||
== Расширение протокола Modbus от Wiren Board == | |||
{{Anchor|modbus-ext}} | |||
Мы производим устройства, которые работают по стандартному протоколу Modbus RTU. Но протокол очень старый и имеет ряд недостатков, которые мы решили устранить. | |||
Мы добавили к стандартному протоколу новые функции: настраиваемое время задержки, игнорирование стопбитов и режим сплошного чтения регистров. | |||
Также выпустили расширение протокола под названием «Быстрый Modbus». В нем появились события и быстрое сканирование устройств на шине RS-485. | |||
Ниже описаны новые функции, а про расширение «Быстрый Modbus» читайте на [[Fast_Modbus |странице с описанием]]. | |||
Всё описываемое справедливо только для Modbus-устройств Wiren Board. | |||
=== Настраиваемое время задержки ответа устройством === | |||
Устройства работают по стандарту, поэтому отвечают master-устройству через 3.5 символа после конца кадра запроса. | |||
Но некоторые сторонние master-устройства могут не соблюдать стандарт и после отправки запроса продолжают удерживать приемопередатчик в режиме отправки некоторое время. | |||
В устройствах есть специальный регистр 113, в котором можно настроить время ответа slave-устройства в миллисекундах. Нужное значение подбирается опытным путём. | |||
=== Игнорирование стопбитов === | |||
Устройства всегда ожидают от мастера 1 стопбит, а отправляют ответ с 2. | |||
Благодаря этому невозможно неправильно настроить стопбиты в master- и в slave-устройстве. Передача ответов более надежная даже, если мастер ожидает 1 стопбит. В последних прошивках настройка стопбита в регистре 112 игнорируется. | |||
=== Режим сплошного чтения регистров === | |||
Часто на устройствах регистры расположены с зазором, который не позволяет читать все необходимые регистры подряд одной командой. | |||
Мы добавили режим сплошного чтения, который активируется записью 1 в регистр 114. При активации можно запрашивать любой регион, который укладывается по длине в ограничения команды чтения. | |||
При таком запросе устройство вернёт пакет со значением регистров. Если регистры отсутствуют в устройстве, то для них будет возвращено значение 0xFFFE. | |||
</translate> | </translate> |