8-900-374-94-44
[email protected]
Slide Image
Меню

Libmodbus использование: Добавляем modbus в Embox RTOS и используем на STM32 и не только / Хабр

Применение протокола Modbus с устройствами мониторинга транспорта / Хабр

Протокол Modbus – самый распространенный промышленный протокол для M2M- взаимодействия. Является стандартом де-факто и поддерживается почти всеми производителями промышленного оборудования.

Благодаря универсальности и открытости, стандарт позволяет интегрировать оборудование разных производителей. Modbus используется для сбора показаний с датчиков, управления реле и контроллерами, мониторинга и т.д.

Существует 3 формата протокола Modbus: Modbus RTU, Modbus TCP, Modbus ASCII. Modbus ASCII в природе почти не встречается и по этой причине нам сейчас не интересен.

Modbus TCP предназначен для работы в локальных сетях. Тоже не наш случай.

Modbus RTU наиболее распространенный вариант. Работает поверх RS-485/232. То, что надо. Далее под термином Modbus будет описываться именно это формат.

Так как Modbus предназначен для работы с пром. автоматикой, то и внутренняя структура протокола в первую очередь описывает параметры пром.

автоматики, такие как дискретные входы и выходы, аналоговые входы и выходы. Тем, кому этого не хватает (а таких подавляющее большинство) делают свои надстройки над протоколом.

Ниже приведена картинка с описанием и некоторыми терминами из протокола.

Все параметры делятся с одной стороны на входы и выходы. Входы можно только читать, а выходы читать и писать.

С другой стороны, бывают дискретные входы/выходы размером в один бит и 16- битные регистры (что характерно, размером 16 бит).

Для работы с этими четырьмя группами параметров существуют функции чтения и записи.

Например, для чтения дискретных входов используется функция «READ DISCRETE INPUTS» с кодом 2.

В настоящий момент в терминалах УМКа302 реализованы функции чтения всех стандартных типов, такие как 1, 2, 3 и 4.

Кроме того, на протокол Modbus предполагает, что есть устройства с двумя разными ролями:
Master – ведущее устройство, которое опрашивает все остальные устройства. Мастер на шине может быть только один.

Slave – ведомое устройство. Его опрашивает мастер. У каждого ведомого есть адрес в диапазоне от 1 до 247. Ведомых устройств на шине может быть несколько. Адреса ведомых в одной шине должны быть уникальными.


1. Реализация Modbus в терминале УМКа302

Поддержка протокола Modbus для УМКа302 реализована с версии 2.11.0

Терминалы УМКа302 берут на себя роль Master в шине Modbus и опрашивают Slave устройства.
Терминалы УМКа302 поддерживают чтение до 32 параметров. Возможно чтение 32 параметров с одного подключенного Slave устройства, чтение одного параметра с 32 подключенных Slave устройств и все промежуточные комбинации.

Перед началом работы с Modbus необходимо настроить интерфейс. Настройка интерфейса RS-485 производится командой «RS485 8,19200», где 8 – режим Modbus, а 19200 – скорость работы интерфейса.

Далее (хотя это можно сделать и в последнюю очередь), определяем список параметров, которые будут передаваться на сервер. Допустим, у нас 2 устройства, с каждого из которых мы будем снимать по 9 параметров.

Кроме того, мы хотим, чтобы между первым и вторым устройством была дырка в 7 параметров на дальнейшее расширение. В этом случаю мы должны включить передачу параметров Modbus и настроить маску передаваемых параметров. Воспользуемся командой «SetMdb 1,0x1FF01FF», где 1 – включить передачу параметров на сервер, а 0x1FF01FF маска передаваемых параметров, полученная с помощью калькулятора.

После перезагрузки на вкладке истории мы должны получить следующее:

На сервер в протоколах Wialon IPS 1.1 и 2.0 параметры передаются с такими же именами, как и на вкладке истории. Т.е. Mdb0- Mdb8, Mdb16- Mdb24.

В протоколе Wialon Combine параметры передаются с типом «Custom Parameters» начиная с параметра 256 по 287. Т.е. Mdb0 передается как param256, Mdb1 передается как param257 и т.д.


2. Пример подключения устройства

После предварительной настройки необходимо выполнить настройку отдельных параметров для работы с конкретным устройством. Для этого необходима так называемая

карта регистров устройства. В ней описываются адреса и типы параметров конкретного устройства.

Возьмем для примера станцию катодной защиты «СИГНАЛ» СКЗ-ИП-Б1. У меня есть для нее эмулятор. Сама станция показана на картинке.

Пример куска карты регистров приведен на рисунке ниже.

В карте как раз 9 параметров, адреса которых идут подряд. Особенностью протокола Modbus является то, что такие параметры могут быть запрошены как 9 отдельными запросами, так и одним общим.

УМКа302 умеет автоматически строить план опроса Modbus устройств таким образом, чтобы уменьшить количество запросов. Это позволяет значительно сократить время опроса устройства.

Для имитации станции воспользуемся программой-имитатором.
Внешний вид программы приведен на рисунке ниже.

Для настройки параметров служит команда вида «MDBPARAMn [X[,Y[,Z[,A[,B]]]]]», где n – номер параметра от 0 до 31.
X – адрес устройства на шине от 1 до 247 или 0, если опрос отключен.
Y – тип запрос. Про типы запросов ниже.
Z – начальный адрес регистра или входа для выбранного запроса.
A – формула пересчета. Как в CAN-фильтрах.
B – имя параметра. Как в CAN-фильтрах.

Тип запроса Y выбирается из следующих соображений:

Y=0 – функция 1. Чтение 1 бита типа Coils;
Y=1 – функция 2. Чтение 1 бита типа Input Discrete;
Y=2 – функция 3. Чтение 1 регистра типа Holding Registers. Беззнаковое. 0…65535. Y=3 – функция 3. Чтение 1 регистра типа Holding Registers. Знаковое -32768…32767 Y=4 – функция 4. Чтение 1 регистра типа Input Register. Беззнаковое. 0…65535.

Y=5 – функция 4. Чтение 1 регистра типа Input Register. Знаковое -32768…32767
Y=6 – функция 3. Чтение 2 регистров типа Holding Registers. Регистры обрабатываются как float. Младшая половина в младшем регистре (Порядок байт 1023).
Y=7 – функция 4. Чтение 2 регистров типа Input Register. Регистры обрабатываются как float. Младшая половина в младшем регистре (Порядок байт 1023).
Y=8 – функция 3. Чтение 2 регистров типа Holding Registers. Регистры обрабатываются как знаковое целое. Младшая половина в младшем регистре (Порядок байт 1023).
Y=9 – функция 4. Чтение 2 регистров типа Input Register. Регистры обрабатываются как знаковое целое. Младшая половина в младшем регистре (Порядок байт 1023).

Данный список не является полным и будет расширятся по необходимости. В нем приведены только наиболее часто встречающиеся в практике форматы представления данных. Значительно большее их количество встречается от случая к случаю или не встречается в принципе.

Настроем имитатор на работу по 1 адресу. Смотрим карту. Видим следующее:

Настраиваем первые 5 параметров командами:
MdbParam0 1,7,0,,I
MdbParam1 1,7,2,,U
MdbParam2 1,7,4,,PP
MdbParam3 1,7,6,,E
MdbParam4 1,7,8,,Uin

Настраиваем температуру:
MdbParam5 1,5,12,,T

Настраиваем время работы:
MdbParam6 1,9,13,,Twork
MdbParam7 1,9,15,,Tstab

Настраиваем последний параметр
MdbParam8 1,7,18,,SP

Перезагружаем. Смотрим командой «Mdb»

Видим следующее: параметры с 0, 1, 2, 4, 5 отображаются корректно.

Параметр 3 отображается с коэффициентом 3200. Это стандартный коэффициент для счетчика. Введем в настройки терминала формулу пересчета.
MdbParam3 1,7,6,x/3200,E

Параметры 6 и 7 отображаются в секундах. Переведем в часы через формулу пересчета:
MdbParam6 1,9,13,x/3600,Twork
MdbParam7 1,9,15,x/3600,Tstab
Параметр 8 не отображается. Имитатор не поддерживает этот параметр. Видимо параметр появился в карте позже.

Перезагружаем. Смотрим историю.

Опрос настроен. Смотрим результат в системе мониторинга транспорта.

Протокол Modbus: особенности, преимущества и недостатки

Modbus — это сетевой протокол прикладного уровня, широко используемый в промышленном производстве для обмена данными между устройствами (Machine-to-Machine, M2M).

С момента разработки в 1979 году он не теряет своей популярности. Согласно статистике HMS Industrial Networks в 2021 году Modbus занимает 10% мирового рынка промышленных сетей (по 5% приходится на Modbus RTU и Modbus TCP).

В статье расскажем об основных особенностях протокола Modbus, его преимуществах и недостатках, а также наиболее частых сценариях использования.

Базовые принципы работы Modbus

Modbus использует архитектуру Master-Slave, которая относительно недавно была переименована разработчиком в Client-Server. Согласно этому подходу в сети выделяется клиентское (ведущее) устройство, которое периодически отправляет запросы на серверные (ведомые) устройства с целью чтения или записи их параметров.

Все запросы может инициировать только клиентское устройство: передача сообщений от серверных устройств без предварительного опроса со стороны клиента в протоколе не предусмотрена.

Архитектура Client-Server (ранее Master-Slave), лежащая в основе протокола Modbus

Пакет данных Modbus включает в себя постоянную часть PDU (Protocol Data Unit), общую для всех реализаций протокола и состоящую из кода функции и данных. Кроме этого, возможен ряд специфических полей, которые будут различаться в зависимости от физического уровня сети — чаще всего это адрес серверного устройства и контрольная сумма для выявления ошибок. С учетом дополнительных полей полный пакет Modbus носит название ADU (Application Data Unit). Рассмотрим более подробно каждое поле пакета ADU в обобщенном виде. Особенности, присущие различным вариантам протокола, будут описаны в следующем разделе.

  • Адрес серверного устройства (Additional address). Определяет, по какому адресу следует отправить клиентский запрос. Может принимать значения в диапазоне от 1 до 247. Адрес 0 используется для широковещательной передачи данных от клиента всем серверным устройствам (ответ сервера при этом не предусмотрен), а адреса 248–255 считаются зарезервированными.

    В некоторых реализациях протокола поле игнорируется — например, в Modbus TCP, где чаще всего применяется стандартная IP-адресация.

  • Код функции (Function code). Определяет, какое действие необходимо выполнить серверному устройству. Значения кодов функций лежат в диапазоне от 1 до 255, причем коды от 128 до 255 зарезервированы для сообщений об ошибках. Код 0 не используется.

    Для кодов из диапазонов 65-72 и 100-110 пользователи могут реализовать собственные функции (

    User-Defined Function Codes). Некоторые коды, например 9, 10, 13 и другие, зарезервированы определенными поставщиками для своего оборудования и закрыты для общего использования (Reserved Function Codes). Не входящие в эти два подмножества коды относятся к публичным (Public Function Codes) — это задокументированные функции, находящиеся в открытом доступе.

  • Данные (Data). Данные, необходимые для выполнения выбранной функции на серверном устройстве. Чаще всего это адреса регистров для чтения или записи, их количество и так далее. Длина и формат поля зависят от кода функции. Некоторые функции не требуют передачи данных.
  • Контрольная сумма (Error check). Содержит рассчитанное при помощи специального алгоритма число для проверки целостности пакета. В качестве алгоритма для расчетов используется CRC-16 или LRC-8. В некоторых реализациях протокола поле отсутствует — например, в Modbus TCP, где контроль целостности пакета обеспечивается средствами протокола TCP/IP.
Структура пакета данных Modbus в обобщенном виде

Рассмотрим передачу пакетов в Modbus. Протокол обеспечивает клиент-серверное взаимодействие в режиме Request/Response. Клиент инициирует запрос в серверное устройство, передавая в PDU код функции и данные. В зависимости от физического уровня сети в пакете могут быть дополнительные поля, рассмотренные выше.

Если обработка запроса проходит без ошибок, то сервер возвращает пакет, содержащий исходный код функции и запрошенные данные.

Схема работы Modbus в случае отсутствия ошибок на серверном устройстве

При возникновении ошибки серверное устройство возвращает в качестве данных код исключения, а вместо исходного кода функции — его значение, увеличенное на 128 (0x80 в шестнадцатеричной системе HEX).

Также предусмотрены тайм-ауты на стороне клиента во избежание длительного ожидания ответа от вышедших из строя устройств.

Схема работы Modbus в случае ошибок на серверном устройстве

Разновидности Modbus: ASCII, TCP и RTU

Modbus — это протокол прикладного (седьмого) уровня модели OSI (Open Systems Interconnection model). Он не зависит от нижележащих уровней и может использоваться совместно с другими протоколами, например Ethernet TCP/IP или UDP/IP, а в качестве физической среды для передачи сигналов применять последовательные интерфейсы RS-232, RS-422, RS-485, оптоволокно, радиоканалы и другое.

Разновидности протокола Modbus

Опишем отличия наиболее известных реализаций протокола Modbus: RTU, ASCII и TCP.

Modbus RTU (Remote Terminal Unit). Это разновидность протокола, которая в качестве физического уровня сети чаще всего использует последовательный интерфейс RS-485, реже — RS-232 и RS-422. По сути, все эти интерфейсы определяют связь с помощью витых пар, но различаются характеристиками вида максимальной длины кабеля, количества узлов и так далее.

Формат пакета Modbus RTU в целом совпадает с обобщенной формой, описанной ранее: дополнительные поля не используются. Контроль целостности пакетов ведется с помощью алгоритма CRC-16.

Важная особенность Modbus RTU в том, что для разделения пакетов должны использоваться временные паузы продолжительностью не менее чем произведение 3,5*t, где t — время передачи одного байта в текущей сети. А передача байтов данных в пределах одного пакета производится последовательно с промежутком времени между соседними байтами не более 1,5*t, иначе передача будет считаться ложной. Эти правила не дают использовать Modbus RTU в медленных, например модемных, сетях.

Структура пакета данных в Modbus RTU

Modbus ASCII. Это разновидность протокола, также работающая поверх интерфейсов RS-232/RS-485, но для кодирования сообщений использующая ASCII-символы.

По сравнению с Modbus RTU в формате пакета добавляются еще два поля — специальные символы для отметки начала и конца сообщения: двоеточие и символы возврата каретки / перевода строки. Временные паузы между пакетами не нужны. Для проверки целостности применяется алгоритм LRC-8.

В целом этот вариант протокола сейчас используется крайне редко — из-за сложностей кодирования и большого размера сообщений. Однако он может стать хорошей альтернативой Modbus RTU на линиях с сетевыми задержками и оборудовании с менее точными таймерами.

Структура пакета данных в Modbus ASCII

Modbus TCP. Это реализация ModBus в сетях Ethernet. Работает поверх TCP/IP стека.

В отличие от Modbus RTU и ASCII, в Modbus TCP соединение устанавливается с конкретным устройством средствами TCP/IP. Поэтому адрес в пакете Modbus чаще всего игнорируется, а широковещательная рассылка сообщений не используется. Однако адрес может потребоваться, если соединение устанавливается со шлюзом, который, в свою очередь, выводит на сеть RS485 — чтобы далее общаться с устройствами уже на языке Modbus.

Контроль целостности пакетов также обеспечивается средствами протокола TCP/IP, поэтому нет необходимости в его Modbus-реализации.

Наряду с адресом в заголовке пакета Modbus TCP присутствует ряд дополнительных полей:

  1. ID транзакции (или ID обмена)

    Чаще всего заполняется нулями. Необходим для случаев, когда клиентское устройство отправляет несколько сообщений, не дожидаясь ответа на предыдущие, чтобы затем связать ответы с запросами.

  2. ID протокола

    Всегда заполняется нулями, зарезервирован для будущего использования.

  3. Длина остатка пакета

    Длина оставшейся части пакета: адреса и PDU (кода функции и данных).

Структура пакета данных в Modbus TCP

Мы рассмотрели только открытые и самые распространенные реализации протокола Modbus. Но их гораздо больше, например MODBUS Plus — проприетарный протокол от Schneider Electric, поддерживающий режим Multi-Master.

Регистры и функции Modbus

Так как Modbus предназначен для работы с промышленной автоматикой, обмен данными с Modbus-устройствами происходит через регистры. Они делятся на входы и выходы. Входы можно только читать, а выходы — читать и писать. Бывают 1-битные регистры Modbus для описания дискретных входов/выходов (Discrete Inputs и Coils) и 16-битные регистры для аналоговых входов/выходов (Input Registers и Holding Registers).

Доступ к регистрам осуществляется с помощью 16-битного адреса. Первому элементу в каждой группе регистров соответствует адрес 0. То есть адрес любого регистра может принимать значения из диапазона 0-65535 (0x0000-0xFFFF в HEX-формате). При этом спецификация протокола не определяет, что физически из себя представляют адресные пространства и по каким внутренним адресам устройства должны быть доступны регистры. В общем случае значения регистров с одинаковым адресом, но разными типами отличаются друг от друга.

Примечание

В документации ряда производителей на некоторые, особенно старые устройства адреса регистров могут быть указаны в других форматах — где адресация начинается не с нуля и первая цифра адреса определяет тип регистра. Например, Input Register с адресом 0 может быть описан как 30001, а Holding Register — как 40001. В таких случаях в пакетах данных следует передавать адреса в стандартном формате Modbus независимо от способа представления их в документации. Для получения верного адреса достаточно вычесть смещение, соответствующее типу регистра. В некоторые программные пакеты заложена автоматическая корректировка адресов.

Тип регистров Назначение Размер Доступ Стандартный адрес Примеры нестандартных адресов
Coils Регистры флагов, обозначающие текущее состояние выхода устройства. Например, при включенном реле значение 1. 1 бит Чтение и запись (выход) 0-65535 (0x0000-0xFFFF в HEX-формате) 00001-09999 или 000001-065536
Discrete Inputs Дискретные входы, описывающие состояние входа устройства. Например, при поданном напряжении значение 1. 1 бит Чтение (вход) 0-65535 (0x0000-0xFFFF в HEX-формате) 10001-19999 или 100001-165536
Input Registers Регистры ввода, предназначенные для чтения настроек (например, текущего значения температуры). 16 битов Чтение (вход) 0-65535 (0x0000-0xFFFF в HEX-формате) 30001-39999 или 300001-365536
Holding Registers Регистры, предназначенные для хранения настроек с возможностью их чтения и записи. 16 битов Чтение и запись (выход) 0-65535 (0x0000-0xFFFF в HEX-формате) 40001-49999 или 400001-465536

Для работы с каждым типом регистров определены функции чтения и записи. Наиболее часто используемые функции описаны ниже.

Код HEX-код для PDU Название функции Тип данных Назначение
1 0x01 Read Coils Coils Чтение значений нескольких регистров флагов
2 0x02 Read Discrete Inputs Discrete Inputs Чтение значений нескольких дискретных входов
3 0x03 Read Holding Registers Holding Registers Чтение значений нескольких регистров хранения
4 0x04 Read Input Registers Input Registers Чтение значений нескольких регистров ввода
5 0x05 Write Single Coil Coils Запись одного регистра флагов
6 0x06 Write Single Register Holding Registers Запись одного регистра хранения
15 0x0F Write Multiple Coils Coils Запись нескольких регистров флагов
16 0x10 Write Multiple Register Holding Registers Запись нескольких регистров хранения

Для каждой функции в спецификации протокола Modbus определена структура PDU: какие данные и в каком порядке должны использоваться в запросах и ответах. Рассмотрим формирование пакетов Modbus RTU на примере функции Read Coils с кодом 1. Эта функция, кроме передачи собственного кода, требует наличия в запросе адреса первого Coil-регистра и количества регистров, которые необходимо прочитать. В случае успешного выполнения запроса в ответе будут возвращены код функции, число байт, необходимое для вывода запрошенных Coil-регистров, и статус всех этих регистров.

Предположим, нам нужно обратиться к серверному устройству с адресом 1 и прочитать 19 его Coil-регистров с номерами 20–38. Адресация регистров ведется с 0, поэтому адрес первого нужного нам регистра будет 0x13 (это 19 в HEX-системе). Требуемое для чтения количество регистров также будет равно 0x13 (для чтения запрошено 19). В качестве адреса и кода функции указываем 01. Контрольная сумма формируется по алгоритму CRC-16 на основе других полей пакета.

В случае отсутствия ошибок в ответе вернутся без изменений адрес серверного устройства и код функции. Для расчета числа байтов, которые потребуются для возврата состояния регистров, нужно разделить запрошенное количество регистров на 8 и к результату прибавить 1, если остаток от деления не равен 0. В нашем случае результат деления 19 на 8 равен 2, но остаток положительный — поэтому для вывода регистров потребуется 2+1=3 байта. Это значение будет указано в ответе после кода функции. И далее будут следовать 3 байта, описывающие состояние выбранных регистров. Например, первый байт будет описывать состояние 8 Coil-регистров с номерами 27-20. Если в поле, к примеру, содержится HEX-значение CD — статус соответствующих 8 регистров такой: 1100 1101.

Пример успешного выполнения функции Read Coils

Если в процессе обработки запроса на серверном устройстве возникнет ошибка (например, обнаружен несуществующий адрес регистра), то в ответе будет содержаться измененный код функции, равный исходному коду плюс смещение 0x80 — в нашем примере 0x81, и код исключения — в нашем примере 03, что значит неверный формат запроса. С полным перечнем возможных исключений можно ознакомиться в документации.

Пример возврата исключения для функции Read Coils

Преимущества и недостатки Modbus

К преимуществам Modbus относятся:

  1. Простота реализации, диагностики и отладки

    Использование стандартных интерфейсов (RS-232/RS-485 и Ethernet) делает Modbus удобным как для разработчиков, так и для пользователей оборудования. При разработке контроллеров и устройств не нужно устанавливать заказные микросхемы для реализации протокола, в отличие от конкурентов-аналогов Profibus и CAN.

  2. Высокая скорость внедрения

    Для развертывания первого Modbus-решения нужно всего пара дней, тогда как некоторые протоколы требуют месяцев на подготовку.

  3. Нетребовательность к ресурсам

    Разработанный в эпоху 8-битных процессоров, Modbus не предъявляет высоких требований к CPU и RAM. Для начала работы требуется минимум оборудования, и разработка проста в любой операционной системе.

  4. Высокая надежность и достоверность при передаче данных

    Поддержка CRC и LRC позволяет определять ошибки в передаче данных с высокой точностью.

  5. Универсальность и открытость

    Практически все промышленные АСУ ТП имеют программные драйверы для работы с Modbus-сетями. Благодаря этому Modbus принято считать стандартом де-факто в интеграции мультивендорного оборудования. Протокол реализован сотнями поставщиков на множестве различных датчиков и исполнительных устройств для передачи дискретной и аналоговой информации. Благодаря единому протоколу устройства от различных производителей могут без труда общаться друг с другом.

Разумеется, у использования протокола есть и недостатки:

  1. Отсутствие встроенной аутентификации и шифрования передаваемых данных

    Поэтому при использовании протокола Modbus TCP необходимо настраивать дополнительные VPN-тоннели. Относительно недавно для Modbus TCP было разработано расширение Modbus Security (с поддержкой TLS), но оно пока не получило широкого распространения.

  2. Отсутствие начальной инициализации системы

    Назначать сетевые адреса и настраивать параметры каждого конкретного устройства требуется вручную. Некоторые производители разрабатывают шаблоны для своих Modbus-устройств, но это не упрощает их взаимодействие с контроллерами и ПО других производителей.

  3. Спецификации для ограниченного набора типов данных

    В протоколе определен метод передачи только для битов и 16-битных регистров. С другими типами данных (строки, числа с плавающей запятой и так далее) различные производители Modbus-решений поступали по собственному усмотрению. По этой причине впоследствии невозможно было внести дополнения в протокол, так как это могло привести к проблемам из-за уже существующего несовпадения форматов.

  4. Недостатки Master-Slave-взаимодействия

    Модель «ведущий — ведомый», изначально положенная в основу протокола, предполагает обмен данными только по инициативе клиентского (ведущего) устройства, которое по очереди опрашивает все серверные (ведомые). Из-за этого возникают следующие ограничения:

    • У серверных устройств нет возможности отправить оперативную информацию клиенту (например, сигнал прерывания): нужно ждать своей очереди в опросе.
    • Серверные устройства не способны обнаружить потерю связи с клиентом.
    • Серверные устройства не могут обмениваться данными друг с другом без участия клиента.
  5. Отсутствие поддержки режима Multi-Master для интерфейсов RS-232/RS-485

    Другие протоколы, основанные на этих же интерфейсах, поддерживают работу с несколькими ведущими устройствами (например, CAN и Profibus).

Однако стоит отметить, что именно описанные выше недостатки обеспечивают простоту использования протокола и высокую скорость его промышленного внедрения. В какой-то степени отсутствие «лишнего» функционала в Modbus и есть его главное достоинство.

Где используется Modbus

Чаще всего Modbus применяется для передачи сигналов от контрольно-измерительных приборов к главному контроллеру или системе сбора данных. Основные сценарии использования Modbus:

  • Клиент-серверные приложения для мониторинга и программирования устройств (в том числе дистанционного) в промышленности, строительстве, инфраструктуре, транспорте, энергетике. Примеры: мониторинг энергопотребления, контроль производственных процессов, надзор за ходом строительства и так далее.
  • Передача данных от датчиков и приборов интеллектуальным устройствам в интернете вещей (Internet of Things, IoT).
  • Связь диспетчерских компьютеров с удаленными терминалами в SCADA-системах.
  • Приложения, где требуется беспроводная связь, например в газовой и нефтяной промышленности.

Несмотря на свой возраст, Modbus активно используется и с современными технологиями — например, он отлично чувствует себя в облаке. Многие провайдеры предлагают возможность создания облачных IoT-платформ — для снижения затрат на разработку IoT-сервисов, обеспечения сбора данных и управления устройствами в real-time-режиме. И поддержка Modbus — обязательный пункт для подобных решений, так как невозможно построить межмашинное взаимодействие без протокола, реализованного множеством поставщиков на тысячах различных устройств.

Такая сочетаемость с современными трендами лишний раз показывает, что за прошедшие годы Modbus не только не утратил своей популярности, но и до сих пор остается одним из самых востребованных протоколов в промышленной производственной среде.

libmodbus — libmodbus

Функциональная и портативная библиотека Modbus с открытым исходным кодом.

Описание

libmodbus — это библиотека для отправки/получения данных с помощью устройства, Протокол Modbus. Эта библиотека содержит различные бэкенды для связи через различные сети (например, последовательный в режиме RTU или Ethernet в TCP IPv4/IPv6). На сайте http://www.modbus.org представлена ​​документация по Modbus. Спецификации и руководства по внедрению.

libmodbus обеспечивает абстракцию нижних коммуникационных уровней и предлагает один и тот же API на всех поддерживаемых платформах.

В этой документации представлен обзор концепций libmodbus, описано, как libmodbus абстрагирует связь Modbus с различным оборудованием и платформами и предоставляет справочное руководство по функциям, предоставляемым libmodbus. библиотека.

Варианты использования

Библиотека может быть использована для записи:

  • клиент , приложение считывает/записывает данные с различных устройств.
  • сервер приложение предоставляет данные нескольким клиентам.

Клиент libmodbus, который считывает только температуру с датчиков.

Сервер libmodbus, который предоставляет данные сервису Grafana.

Контексты

Протокол Modbus поддерживает несколько транспортных протоколов (например, последовательный RTU, Ethernet TCP) вызывал бэкенды в libmodbus .

Первым шагом является выделение и установка контекста modbus_t в соответствии с требуется серверная часть (RTU или TCP) со специальной функцией, такой как modbus_new_rtu. Функция вернет непрозрачную структуру с именем 9.0037 modbus_t , содержащий все необходимая информация для установления соединения с другими устройствами Modbus в соответствии с выбранным бэкендом.

После создания этого контекста вы можете использовать общий API, предоставляемый libmodbus для чтения/записи или установки различных тайм-аутов. С помощью этого общего API легко переключить серверную часть вашего приложения с RTU на TCP IPv6 для пример.

Контекст RTU

Серверная часть RTU (удаленный терминал) используется в последовательной связи и делает использование компактного двоичного представления данных для протокола связи. Формат RTU следует за командами/данными с контрольной суммой проверки циклическим избыточным кодом. в качестве механизма проверки ошибок для обеспечения надежности данных. Modbus RTU — это наиболее распространенная реализация, доступная для Modbus. Сообщение Modbus RTU должно быть передается непрерывно без межсимвольных запинок (отрывок из Википедия, Modbus от 13 марта 2011 г., 20:51 по Гринвичу).

Кадрирование Modbus RTU вызывает ведомое устройство или службу, которые обрабатывают Modbus запросы, и мастер, клиент, который отправляет запросы. Связь всегда инициируется мастером.

Многие устройства Modbus могут быть соединены вместе по одному и тому же физическому каналу, поэтому перед отправкой сообщения необходимо установить ведомое устройство (приемник) с помощью modbus_set_slave. Если вы используете подчиненное устройство, его номер подчиненного устройства будет использоваться для фильтрации полученных сообщений.

Реализация libmodbus RTU не основана на времени, как указано в оригинале. спецификации Modbus, вместо этого все байты отправляются как можно быстрее, а ответ или указание считается завершенным, когда все ожидаемые символы были получены. Эта реализация предлагает очень быструю связь, но вы должен позаботиться о том, чтобы установить тайм-аут ответа ведомых устройств меньше, чем тайм-аут ответа ведущий (в противном случае другие ведомые могут игнорировать запросы ведущего, когда один из ведомых не отвечает).

Для создания контекста Modbus RTU следует использовать modbus_new_rtu.

Вы можете настроить последовательный режим со следующими функциями:

  • modbus_rtu_get_serial_mode
  • modbus_rtu_set_serial_mode
  • modbus_rtu_get_rts
  • modbus_rtu_set_rts
  • modbus_rtu_set_custom_rts
  • modbus_rtu_get_rts_delay
  • modbus_rtu_set_rts_delay

Контекст TCP (IPv4)

Базовая часть TCP реализует вариант Modbus, используемый для связи по Сети TCP/IPv4. Не требует вычисления контрольной суммы, так как нижний уровень заботится о том же.

Для создания контекста Modbus TCP следует использовать modbus_new_tcp.

Контекст TCP PI (IPv4 и IPv6)

Серверная часть TCP PI (независимая от протокола) реализует вариант Modbus, используемый для связь по сетям TCP IPv4 и IPv6. Не требует контрольной суммы расчет, поскольку нижний уровень заботится о том же.

В отличие от серверной части TCP IPv4, серверная часть TCP PI предлагает имя хоста разрешение, но потребляет около 1 КБ дополнительной памяти.

Создайте контекст Modbus TCP PI, вы должны использовать modbus_new_tcp_pi.

Соединение

Для установления и закрытия соединения с Устройства Modbus:

  • modbus_connect устанавливает соединение.
  • modbus_close закрывает соединение.
  • modbus_flush сбросил соединение.

В RTU вы должны определить ведомый идентификатор вашего клиента с помощью modbus_set_slave.

Для анализа обмениваемых данных можно включить режим отладки с помощью modbus_set_debug.

После того, как вы завершили общение или в конце вашей программы, вы следует освободить ресурсы с помощью общей функции modbus_free

Чтение и запись от клиента

Протокол Modbus определяет различные типы данных и функции для чтения и записи. их с/на удаленные устройства. Клиенты используют следующие функции для отправлять запросы Modbus:

Для чтения данных:

  • modbus_read_bits
  • modbus_read_input_bits
  • modbus_read_registers
  • modbus_read_input_registers
  • modbus_report_slave_id

Для записи данных:

  • modbus_write_bit
  • modbus_write_register
  • modbus_write_bits
  • modbus_write_registers

Для записи и чтения данных за одну операцию:

  • modbus_write_and_read_registers

Для отправки и получения низкоуровневых запросов:

  • modbus_send_raw_request
  • modbus_receive_confirmation

Для ответа на исключение:

  • modbus_reply_exception

Обработка запросов с сервера

Сервер ожидает запроса от клиентов и должен ответить, когда он будет обеспокоен запросом. libmodbus предлагает следующие функции для обработка запросов:

Отображение данных:

  • modbus_mapping_new
  • modbus_mapping_free

Получить:

  • modbus_receive

Ответ:

  • modbus_reply
  • modbus_reply_exception

Дополнительные функции

Настройки времени ожидания:

  • modbus_get_byte_timeout
  • modbus_set_byte_timeout
  • modbus_get_response_timeout
  • modbus_set_response_timeout

Режим восстановления после ошибки:

  • modbus_set_error_recovery

Сеттер/геттер внутреннего сокета:

  • modbus_set_socket
  • modbus_get_socket

Информация о заголовке:

  • modbus_get_header_length

Обработка данных

Макросы для обработки данных:

  • MODBUS_GET_HIGH_BYTE(данные) , извлекает старший байт из байта
  • MODBUS_GET_LOW_BYTE(данные) , извлекает младший байт из байта
  • MODBUS_GET_INT64_FROM_INT16(tab_int16, index) , строит int64 из четырех первых int16, начиная с tab_int16[index]
  • MODBUS_GET_INT32_FROM_INT16(tab_int16, index) , создает int32 из двух первых int16, начиная с tab_int16[index]
  • MODBUS_GET_INT16_FROM_INT8(tab_int8, index) , создает int16 из двух первых int8, начиная с tab_int8[index]
  • MODBUS_SET_INT16_TO_INT8(tab_int8, index, value) , установите значение int16 в два первых байта, начиная с tab_int8[index]
  • MODBUS_SET_INT32_TO_INT16 (tab_int16, индекс, значение) , установите значение int32 в два первых int16, начиная с tab_int16[index]
  • MODBUS_SET_INT64_TO_INT16(tab_int16, index, value) , установите значение int64 в четыре первых int16, начиная с tab_int16[index]

Обработка битов и байтов:

  • modbus_set_bits_from_byte
  • modbus_set_bits_from_bytes
  • modbus_get_byte_from_bits

Установка или получение чисел с плавающей запятой:

  • modbus_get_float_abcd
  • modbus_set_float_abcd
  • modbus_get_float_badc
  • modbus_set_float_badc
  • modbus_get_float_cdab
  • modbus_set_float_cdab
  • modbus_get_float_dcba
  • modbus_set_float_dcba
  • modbus_get_float устарело
  • modbus_set_float устарело

Обработка ошибок

Функции libmodbus обрабатывают ошибки, используя стандартные соглашения, найденные на POSIX-системы. Как правило, это означает, что в случае сбоя функция libmodbus должен возвращать либо значение NULL (если возвращается указатель), либо отрицательное значение (если возвращается целое число), а фактический код ошибки должен храниться в ошибка переменная.

Функция modbus_strerror() предназначена для преобразования специфичных для libmodbus коды ошибок в строки сообщений об ошибках; подробности см. modbus_strerror.

Разное

Чтобы отклониться от стандарта Modbus, вы можете включить или отключить причуды с помощью:

  • modbus_disable_quirks
  • modbus_enable_quirks

Константа _LIBMODBUS_VERSION_STRING_ указывает версию libmodbus, программа была скомпилирована против. Переменные ‘libmodbus_version_major’, ‘libmodbus_version_minor’, ‘libmodbus_version_micro’ дают версии программа связана против.

Копирование

Бесплатное использование этого программного обеспечения предоставляется в соответствии с условиями GNU Lesser General Публичная лицензия (LGPL v2. 1+). Подробнее см. в файле COPYING.LESSER . с дистрибутивом libmodbus.

Библиотека Modbus для Python — Stack Overflow

Примерно в то же время я столкнулся с той же проблемой — какую библиотеку выбрать для основной реализации Modbus на Python, но в моем случае для последовательной связи (modbus RTU), поэтому мои наблюдения действительны только для Modbus RTU.

Во время моего исследования я не обращал особого внимания на документацию, но примеры для последовательного RTU master было проще всего найти для modbus-tk, однако все еще в исходном коде, а не на вики и т. д.

короче говоря:

MinimalModbus:

  • плюсы:
    • облегченный модуль
    • Производительность
    • может быть приемлемой для приложений, считывающих ~10 регистров
  • минусы:
    • неприемлемо (для моего приложения) медленно при чтении ~64 регистра
    • относительно высокая загрузка процессора

pymodbus:

отличительная особенность: полагается на последовательный поток (сообщение автора) и последовательный тайм-аут должен быть установлен динамически, иначе производительность будет низкой (серийный тайм-аут должен быть скорректирован для максимально длинного ответа)

  • плюсы:
    • низкая загрузка процессора
    • приемлемая производительность
  • минусы:
    • даже при динамической установке тайм-аута производительность в 2 раза ниже по сравнению с modbus-tk; если тайм-аут оставить постоянным, производительность намного хуже (но время запроса остается постоянным)
    • чувствителен к оборудованию (я думаю, в результате зависимости от обработки потока из последовательного буфера) или может быть внутренняя проблема с транзакциями: вы можете получить перепутанные ответы, если разные операции чтения или чтения/записи выполняются примерно 20 раз в секунду или более. Более длительные тайм-ауты помогают, но не всегда делают реализацию pymodbus RTU по последовательной линии недостаточно надежной для использования в производстве.
    • добавление поддержки динамической настройки тайм-аута последовательного порта требует дополнительного программирования: наследования базового класса клиента синхронизации и реализации методов модификации тайм-аута сокета
    • Проверка ответов
    • не такая подробная, как в modbus-tk. Например, в случае сбоя шины выдается только исключение, тогда как modbus-tk возвращает в той же ситуации неправильный адрес подчиненного устройства или ошибку CRC, что помогает определить основную причину проблемы (которая может быть слишком коротким тайм-аутом, неправильным окончанием шины/отсутствием такового или плавучий грунт и т. д.)

modbus-tk:

отличительная черта: зондирует последовательный буфер для данных, собирает и возвращает ответ быстро.

  • профи
    • лучшая производительность; ~ в 2 раза быстрее, чем pymodbus с динамическим тайм-аутом
  • минусы:
    • ок. В 4 раза выше нагрузка на ЦП по сравнению с pymodbus // можно значительно улучшить, сделав этот пункт недействительным; см. раздел РЕДАКТИРОВАТЬ в конце
    • Загрузка процессора увеличивается для больших запросов // может быть значительно улучшена, что делает этот пункт недействительным; см. раздел РЕДАКТИРОВАТЬ в конце
    • Код
    • не такой элегантный, как pymodbus

В течение более 6 месяцев я использовал pymodbus из-за наилучшего соотношения производительности и загрузки ЦП, но ненадежные ответы стали серьезной проблемой при более высоких скоростях запросов, и в конце концов я перешел на более быструю встроенную систему и добавил поддержку modbus-tk, который работает лучше всего для меня.

Для тех, кто интересуется подробностями

Моей целью было добиться минимального времени отклика.

установка:

  • скорость передачи: 153600
    • синхронно с тактовой частотой 16 МГц микроконтроллера, реализующего ведомый модуль Modbus)
    • у моего автобуса rs-485 всего 50м
  • Преобразователь FTDI FT232R, а также последовательный мост через TCP (с использованием com4com в качестве моста в режиме RFC2217)
  • в случае преобразователя USB в последовательный порт наименьшие тайм-ауты и размеры буфера, настроенные для последовательного порта (для уменьшения задержки)
  • адаптер auto-tx rs-485 (шина имеет доминирующее состояние)

Сценарий использования:

  • Опрос 5, 8 или 10 раз в секунду с поддержкой асинхронного доступа между
  • Запросы на чтение/запись от 10 до 70 регистров

Типичная долгосрочная (недели) производительность:

  • MinimalModbus: исключен после первоначальных тестов
  • pymodbus: ~30 мс для чтения 64 регистров; эффективно до 30 запросов/сек
    • , но ответы ненадежны (в случае синхронизированного доступа из нескольких потоков)
    • , возможно, на github есть потокобезопасный форк, но он находится за мастером, и я его не пробовал (https://github. com/xvart/pymodbus/network)
  • modbus-tk: ~16 мс для чтения 64 регистров; эффективно до 70-80 запросов/сек для меньших запросов

тест

код:

 время импорта
обратная трассировка импорта
серийный номер импорта
импортировать modbus_tk.defines как tkCst
импортировать modbus_tk.modbus_rtu как tkRtu
импортировать minimodbus как mmRtu
из pymodbus.client.sync импортировать ModbusSerialClient как pyRtu
рабыАрр = [2]
итерСп = 100
regsSp = 10
номер порта = 21
имя_порта = 'com22'
скорость = 153600
timeoutSp=0,018 + regsSp*0
напечатать "время ожидания: %s [s]" % timeoutSp
mmc=mmRtu.Instrument(portName, 2) # имя порта, адрес подчиненного устройства
mmc.serial.baudrate=скорость передачи
mmc.serial.timeout=timeoutSp
тб = нет
ошибкаCнт = 0
startTs = время.время()
для i в диапазоне (iterSp):
  для slaveId в slavesArr:
    mmc.address = идентификатор раба
    пытаться:
        mmc.read_registers(0,regsSp)
    кроме:
        tb = traceback. format_exc()
        errCnt += 1
stopTs = время.время()
timeDiff = StopTs - StartTs
mmc.serial.close ()
печать mmc.serial
print "mimalmodbus:\ttime to read %s x %s (x %s regs): %.3f [s] / %.3f [s/req]" % (len(slavesArr),iterSp, regsSp, timeDiff, timeDiff/ iterSp)
если errCnt >0:
    print " !mimalmodbus:\terrCnt: %s; последний tb: %s" % (errCnt, tb)
pymc = pyRtu (метод = 'rtu', порт = portNbr, скорость = скорость передачи, тайм-аут = timeoutSp)
ошибкаCнт = 0
startTs = время.время()
для i в диапазоне (iterSp):
  для slaveId в slavesArr:
    пытаться:
        pymc.read_holding_registers(0,regsSp,unit=slaveId)
    кроме:
        errCnt += 1
        tb = traceback.format_exc()
stopTs = время.время()
timeDiff = StopTs - StartTs
print "pymodbus:\ttime to read %s x %s (x %s regs): %.3f [s] / %.3f [s/req]" % (len(slavesArr),iterSp, regsSp, timeDiff, timeDiff/ iterSp)
если errCnt >0:
    print " !pymodbus:\terrCnt: %s; последний tb: %s" % (errCnt, tb)
pymc.close()
tkmc = tkRtu.RtuMaster(serial.Serial(port=portNbr, baudrate=baudrate))
tkmc. set_timeout(timeoutSp)
ошибкаCнт = 0
startTs = время.время()
для i в диапазоне (iterSp):
  для slaveId в slavesArr:
    пытаться:
        tkmc.execute(slaveId, tkCst.READ_HOLDING_REGISTERS, 0,regsSp)
    кроме:
        errCnt += 1
        tb = traceback.format_exc()
stopTs = время.время()
timeDiff = StopTs - StartTs
print "modbus-tk:\ttime to read %s x %s (x %s regs): %.3f [s] / %.3f [s/req]" % (len(slavesArr),iterSp, regsSp, timeDiff, timeDiff/iterSp)
если errCnt >0:
    print " !modbus-tk:\terrCnt: %s; последняя tb: %s" % (errCnt, tb)
tkmc.close()
 

результаты:

 платформа:
P8700 @2,53 ГГц
WinXP sp3 32bit
Питон 2.7.1
Серия FTDI FT232R 1220-0
Драйвер FTDI 2.08.26 (обратите внимание на возможные проблемы с версией 2.08.30 для Windows)
Пимодбус версии 1.2.0
Минимальная версия Modbus 0.4
modbus-tk версия 0.4.2
 

чтение 100 x 64 регистров:

без энергосбережения

 тайм-аут: 0,05 [с]
Serial(port='com22', скорость передачи=153600, размер в байтах=8, четность='N', стоповые биты=1, время ожидания=0,05, xonxoff=False, rtscts=False, dsrdtr=False )
mimalmodbus: время чтения 1 x 100 (x 64 регистра): 90,135 [с] / 0,091 [с/запрос]
pymodbus: время чтения 1 x 100 (x 64 регистра): 6,151 [с] / 0,062 [с/треб. ]
modbus-tk: время чтения 1 x 100 (x 64 регистров): 2,280 [с] / 0,023 [с/запрос]
время ожидания: 0,03 [с]
Serial(port='com22', скорость передачи=153600, размер в байтах=8, четность='N', стоповые биты=1, время ожидания=0,03, xonxoff=False, rtscts=False, dsrdtr=False )
mimalmodbus: время чтения 1 x 100 (x 64 регистра): 7,292 [с] / 0,073 [с/треб.]
pymodbus: время чтения 1 x 100 (x 64 регистра): 3,170 [с] / 0,032 [с/треб.]
modbus-tk: время чтения 1 x 100 (x 64 регистров): 2,342 [с] / 0,023 [с/запрос]
время ожидания: 0,018 [с]
Serial(port='com22', скорость передачи=153600, размер байта=8, четность='N', стоповые биты=1, время ожидания=0,018, xonxoff=False, rtscts=False, dsrdtr=False )
mimalmodbus: время чтения 1 x 100 (x 64 регистра): 4,481 - 7,198 [с] / 0,045 - 0,072 [с/запрос]
pymodbus: время чтения 1 x 100 (x 64 регистра): 3,045 [с] / 0,030 [с/треб.]
modbus-tk: время чтения 1 x 100 (x 64 регистров): 2,342 [с] / 0,023 [с/запрос]
 

максимальное энергосбережение

 время ожидания: 0,05 [с]
Serial(port='com22', скорость передачи=153600, размер в байтах=8, четность='N', стоповые биты=1, время ожидания=0,05, xonxoff=False, rtscts=False, dsrdtr=False )
mimalmodbus: время чтения 1 x 100 (x 64 регистра): 10,289 [с] / 0,103 [с/запрос]
pymodbus: время чтения 1 x 100 (x 64 регистра): 6,074 [с] / 0,061 [с/запрос]
modbus-tk: время чтения 1 x 100 (x 64 регистров): 2,358 [с] / 0,024 [с/запрос]
время ожидания: 0,03 [с]
Serial(port='com22', скорость передачи=153600, размер в байтах=8, четность='N', стоповые биты=1, время ожидания=0,03, xonxoff=False, rtscts=False, dsrdtr=False )
mimalmodbus: время чтения 1 x 100 (x 64 регистра): 8,166 [с] / 0,082 [с/запрос]
pymodbus: время чтения 1 x 100 (x 64 регистра): 4,138 [с] / 0,041 [с/треб. ]
modbus-tk: время чтения 1 x 100 (x 64 регистров): 2,327 [с] / 0,023 [с/запрос]
время ожидания: 0,018 [с]
Serial(port='com22', скорость передачи=153600, размер байта=8, четность='N', стоповые биты=1, время ожидания=0,018, xonxoff=False, rtscts=False, dsrdtr=False )
mimalmodbus: время чтения 1 x 100 (x 64 регистра): 7,776 [с] / 0,078 [с/запрос]
pymodbus: время чтения 1 x 100 (x 64 регистра): 3,169[с] / 0,032 [с/треб.]
modbus-tk: время чтения 1 x 100 (x 64 регистров): 2,342 [с] / 0,023 [с/запрос]
 

чтение 100 x 10 регистров:

без энергосбережения

 тайм-аут: 0,05 [с]
Serial(port='com22', скорость передачи=153600, размер байта=8, четность='N', стоповые биты=1, время ожидания=0,05, xonxoff=False, rtscts=False, dsrdtr=False )
mimalmodbus: время чтения 1 x 100 (x 10 регистров): 6,246 [с] / 0,062 [с/треб.]
pymodbus: время чтения 1 x 100 (x 10 регистров): 6,199 [с] / 0,062 [с/треб.]
modbus-tk: время чтения 1 x 100 (x 10 регистров): 1,577 [с] / 0,016 [с/запрос]
время ожидания: 0,03 [с]
Serial(port='com22', скорость передачи=153600, размер в байтах=8, четность='N', стоповые биты=1, время ожидания=0,03, xonxoff=False, rtscts=False, dsrdtr=False )
mimalmodbus: время чтения 1 x 100 (x 10 регистров): 3,088 [с] / 0,031 [с/запрос]
pymodbus: время чтения 1 x 100 (x 10 регистров): 3,143 [с] / 0,031 [с/треб. ]
modbus-tk: время чтения 1 x 100 (x 10 регистров): 1,533 [с] / 0,015 [с/запрос]
время ожидания: 0,018 [с]
Serial(port='com22', скорость передачи=153600, размер в байтах=8, четность='N', стоповые биты=1, время ожидания=0,018, xonxoff=False, rtscts=False, dsrdtr=False )
mimalmodbus: время чтения 1 x 100 (x 10 регистров): 3,066 [с] / 0,031 [с/треб.]
pymodbus: время чтения 1 x 100 (x 10 регистров): 3,006 [с] / 0,030 [с/треб.]
modbus-tk: время чтения 1 x 100 (x 10 регистров): 1,533 [с] / 0,015 [с/запрос]
 

максимальное энергосбережение

 тайм-аут: 0,05 [с]
Serial(port='com22', скорость передачи=153600, размер байта=8, четность='N', стоповые биты=1, время ожидания=0,05, xonxoff=False, rtscts=False, dsrdtr=False )
mimalmodbus: время чтения 1 x 100 (x 10 регистров): 6,386 [с] / 0,064 [с/запрос]
pymodbus: время чтения 1 x 100 (x 10 регистров): 5,934 [с] / 0,059 [с/треб.]
modbus-tk: время чтения 1 x 100 (x 10 регистров): 1,499 [с] / 0,015 [с/запрос]
время ожидания: 0,03 [с]
Serial(port='com22', скорость передачи=153600, размер в байтах=8, четность='N', стоповые биты=1, время ожидания=0,03, xonxoff=False, rtscts=False, dsrdtr=False )
mimalmodbus: время чтения 1 x 100 (x 10 регистров): 3,139[с] / 0,031 [с/треб. ]
pymodbus: время чтения 1 x 100 (x 10 регистров): 3,170 [с] / 0,032 [с/треб.]
modbus-tk: время чтения 1 x 100 (x 10 регистров): 1,562 [с] / 0,016 [с/запрос]
время ожидания: 0,018 [с]
Serial(port='com22', скорость передачи=153600, размер в байтах=8, четность='N', стоповые биты=1, время ожидания=0,018, xonxoff=False, rtscts=False, dsrdtr=False )
mimalmodbus: время чтения 1 x 100 (x 10 регистров): 3,123 [с] / 0,031 [с/запрос]
pymodbus: время чтения 1 x 100 (x 10 регистров): 3,060 [с] / 0,031 [с/треб.]
modbus-tk: время чтения 1 x 100 (x 10 регистров): 1,561 [с] / 0,016 [с/запрос]
 

реальное приложение:

Пример загрузки для моста modbus-rpc (~3% вызвано серверной частью RPC)

РЕДАКТИРОВАТЬ: библиотеку modbus-tk можно легко улучшить, чтобы снизить нагрузку на ЦП. В исходной версии после отправки запроса и перехода в спящий режим T3.5 мастер собирает ответ по одному байту за раз. Профилирование показало, что больше всего времени тратится на доступ к последовательному порту. Это можно улучшить, попытавшись прочитать ожидаемую длину данных из последовательного буфера. Согласно документации pySerial, это должно быть безопасно (без зависания, когда ответ отсутствует или слишком короткий), если установлено время ожидания:

 чтение (размер=1)
Параметры: size — количество байтов для чтения.
Возвращает: байты, прочитанные из порта.
Прочитать размер байтов из последовательного порта. Если установлен тайм-аут, он может возвращать меньше символов, поскольку
просил. Без тайм-аута он будет блокироваться до тех пор, пока не будет прочитано запрошенное количество байтов.
 

после изменения `modbus_rtu.py’ следующим образом:

 def _recv(self, expect_length=-1):
 """Получить ответ от ведомого"""
 ответ = ""
 read_bytes = "фиктивный"
 итерКнт = 0
 в то время как read_bytes:
 если iterCnt == 0:
 read_bytes = self._serial.read(expected_length) # снижает нагрузку на процессор для более длинных кадров; тайм-аут последовательного порта используется в любом случае
 еще:
 read_bytes = self.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *