16 578
правок
(не показано 38 промежуточных версий 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 стоповый бит - если бит четности передается. Такой символ передает 1 байт данных. В устройствах Wiren Board бит контроля четности не передается и используется 2 стоповых бита. В Modbus ASCII каждый байт передается двумя символами, представляющими ASCII-коды младшей и старшей четырехбитной группы байта ([http://www.simplymodbus.ca/ASCII.htm пример]). Modbus RTU передает больше информации при той же скорости последовательной линии и в устройствах Wiren Board используется именно он. Все дальнейшее описание относится к Modbus RTU. | Существует две спецификации протокола: 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--> | ||
Строка 20: | Строка 25: | ||
<!--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 байт. | ||
Строка 26: | Строка 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--> | ||
Строка 77: | Строка 74: | ||
Регистры ввода допускают только чтение (например, текущее значение температуры). Регистры хранения поддерживают как чтение, так и запись (для хранения настроек). В настоящее время во многих устройствах, в частности в устройствах Wiren Board, эти регистры не разделяются. Команды на чтение регистра хранения N и регистра ввода N обратятся к одному и тому же значению в адресном пространстве устройства. | Регистры ввода допускают только чтение (например, текущее значение температуры). Регистры хранения поддерживают как чтение, так и запись (для хранения настроек). В настоящее время во многих устройствах, в частности в устройствах Wiren Board, эти регистры не разделяются. Команды на чтение регистра хранения N и регистра ввода N обратятся к одному и тому же значению в адресном пространстве устройства. | ||
== Адреса регистров == | |||
Регистры в стандарте Modbus адресуются с помощью 16-битных адресов. Адресация начинается с нуля. Адрес регистра, таким образом, может принимать значения от 0 до 65535. | Регистры в стандарте Modbus адресуются с помощью 16-битных адресов. Адресация начинается с нуля. Адрес регистра, таким образом, может принимать значения от 0 до 65535. | ||
Адресные пространства регистров, также называемые таблицами | Адресные пространства регистров, также называемые таблицами или блоками, могут быть различны для всех четырёх типов регистров. Это значит, что значения регистров с одинаковым адресом, но разным типом, в общем случае разные. | ||
Например, при чтении регистра флагов (coil) номер 42, регистра дискретного входа (Discrete), регистров ввода и хранения (Input и Holding) с теми же адресами, можно получить четыре разных значения. | Например, при чтении регистра флагов (coil) номер 42, регистра дискретного входа (Discrete), регистров ввода и хранения (Input и Holding) с теми же адресами, можно получить четыре разных значения. | ||
=== Нестандартная адресация === | |||
В документации на некоторые, особенно старые, устройства адреса элементов (регистров) указываются в формате, не | В документации на некоторые, особенно старые, устройства адреса элементов (регистров) указываются в формате, не соответствующем стандарту. В этом формате тип элемента кодируется первой цифрой адреса, а адресация начинается не с нуля. | ||
Например, регистр хранения с адресом 0 может записываться как 40001 или 400001, а Coil с адресом 0 как 000001. | Например, регистр хранения с адресом 0 может записываться как 40001 или 400001, а Coil с адресом 0 как 000001. | ||
В | В таблице перевода адресов в стандартный формат показаны диапазоны для двух разных нестандартных типов указания адресов и соответствующие им типы данных и диапазоны стандартных адресов. | ||
{|class="wikitable" align="center" | {|class="wikitable" align="center" | ||
Строка 110: | Строка 107: | ||
* Адреса записываются в десятичном формате | * Адреса записываются в десятичном формате | ||
* Во всех адресах пять или шесть цифр | * Во всех адресах пять или шесть цифр | ||
* Адреса с | * Адреса с недискретными данными (показания датчиков и т.п.) начинаются на 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" перечислены регистры и соответствующие им измеряемые параметры, например: | ||
Строка 250: | Строка 247: | ||
|- | |- | ||
! 3 | ! 3 | ||
| Illegal Data Value || | | Illegal Data Value || Неверный формат запроса, например количество байт в запросе не соответствует ожидаемому. | ||
'''Примечание''': несмотря на название, эта ошибка не говорит о том, что само значение регистра неправильное или ошибочное, и должна использоваться только для ошибок формата запроса. | |||
|- | |- | ||
! 4 | ! 4 | ||
| | | Server Device Failure ||Произошла невосстановимая ошибка на устройстве при выполнении запрошенной операции | ||
|- | |- | ||
! 5 | ! 5 | ||
Строка 259: | Строка 257: | ||
|- | |- | ||
! 6 | ! 6 | ||
| | | Server Device Busy ||Устройство занято обработкой предыдущего запроса. | ||
|- | |- | ||
! 7 | ! 7 | ||
Строка 276: | Строка 274: | ||
<!--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> |