Введение


Если в качестве инструмента у Вас имеется лишь молоток, каждая проблема начинает напоминать гвоздь.

Абрахам Маслоу

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



Популярность данного протокола обусловлена его открытостью и простотой. Сфера применимости достаточно широка: от профессиональных промышленных систем автоматизации до любительских DIY-проектов распределенных управляющих систем, «умных» домов и так далее. Данный протокол был выбран и мной, когда моя команда занималась создание ПО тренажера электропоезда. Протокол Modbus RTU на физическом интерфейсе RS485 используется на данном тренажере для обеспечения ввода в управляющий компьютер данных с органов управления, смонтированных на пульте машиниста (не стоит думать что Modbus используется на настоящем подвижном составе!).

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

«Надо писать ПО, когда готовы рабочие прототипы всего железа» — скажете вы и будете правы, но… ха-ха-ха, в реальном мире такое случается редко. И вот тут нам на помощь приходят программные эмуляторы.

1. Кратко о Modbus RTU


Подробно рассказывать о протоколе не буду. Те, кого интересуют подробности могут воспользоваться поиском — протокол открыт, в сети доступна его официальная спецификация и масса информации. Скажу лишь, что в Modbus RTU описывает двоичный формат передаваемых данных и в качестве среды передачи использует дифференциальную витую пару стандарта RS485. Может использоваться и RS232, если в сети один передатчик и один приемник, или RS422 для однонаправленной передачи данных.

Нас будет интересовать именно RS485, который является полудуплексным интерфейсом, что допускает лишь одно передающее данные устройство в каждый момент времени. Арбитраж шины в Modbus осуществляется за счет выдержки обязательного интервала тишины длиной 3,5 символа при данной скорости передачи. Каждое сообщение должно начинаться и завершаться интервалом тишины. В сети существует одно ведущее устройство (master) и несколько ведомых устройств (slave) (до 31 в одном сегменте сети, без применения репитеров). Каждое ведомое устройство имеет уникальный идентификатор ID (от 1 до 31). Передача данных ведомым осуществляется лишь в том случае, если мастер послал запрос на получение данных с этого устройства.

Типичный запрос мастера выглядит так

ID Код функции Адрес данных Количество данных (2 байта) Данные CRC16

CRC16 используется для контроля целостности передаваемых данных. Modus использует Big Endian нотацию представления данных: для значений размером 2 байта старший байт внутри сообщения идет первым). В протоколе используется четыре типа данных:

  1. Coils — дискретные выходы (1 бит) доступные для чтения/записи
  2. Discrete inputs — дискретные входы (1 бит) доступные для чтения
  3. Holding registers — регистры вывода (2 байта) доступные для чтения/записи
  4. Input registers — регистры ввода (2 байта) доступные для чтения

В ответ на запрос ведомое устройство отдает данные в следующем формате

ID Код функции Количество данных в байтах Данные CRC16

Сообщение, принятое от мастера попадает в приемный буфер всех устройств. Однако, если первый байт приемного буфера не совпадает с ID устройства, оно игнорирует принятые данные, очищая приемный буфер. Если сообщение предназначено данному устройству, то оно формирует ответ и, выдержав интервал тишины посылает его мастеру.

Как говорится, простенько, но со вкусом. Подробнее обо всем этом можно прочитать в официальной спецификации протокола. О методах реализации протокола на последовательном интерфейсе читаем здесь. Собрались мы здесь не за этим.

Разрабатывая ПО верхнего уровня (master реализуемый на базе ПК, например) для подобной сети, хорошо бы иметь набор программных средств, позволяющих реализовать такую концепцию

image

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



Один из адаптеров используется для подключения ПО разрабатываемого мастера. Другой — для подключения эмулятора будущей сети слейвов. К отводу с белым коннектором подключаем ту часть сети, которая уже реализована аппаратно. Таким образом мы получаем возможность спокойно работать со штатным протоколом связи, постепенно вводя в работу реальную аппаратуру. К тому же, отдав объект заказчику мы не лишаемся возможность модифицировать его ПО в комфортной обстановке лаборатории без доступа к объекту. QSlave на схеме как раз таки часть сети, эмулируемая программно. Естественно, придется написать соответствующий софт, что и было сделано автором.

2. QSlave — эмуляция сети ведомых


QSlave — открытый кроссплатформенный эмулятор сети Modbus RTU. Получить его можно по лицензии GPL v2.0 на Github по вышеприведенной ссылке.



Приложение разработано на C++ с использованием фреймворка Qt. Qt, вообще говоря, имеет библиотеки для работы с Modbus, но специфика задачи — имитация сети слейвов а не одного слейва, привела к тому, что встроенные библиотеки Qt для Modbus тут не использовались. Для обработки данных, принимаемых с виртуального последовательного порта была создана самописная библиотека modbus. Код этой библиотеки реализован в виде отдельного проекта, совершенно не зависит от интерфейса пользователя и может быть использован для сознания программных имитаций с более продвинутым функционалом. Из-за того, что эмуляция Modbus отвязана от UI, конфигурирование сети происходит с применением конфигурационных файлов. Был выбран формат XML (мы часто его используем в своих проектах). Пример конфигурации доступен в коде проекта. Комплект конфигов состоит из главного файла с расширением *.net, который выглядит так

example.net
<?xml version="1.0" encoding="UTF-8" ?>
<Config>
	<Slave>
		<!-- Описание слейва, отображаемое в списке устройств -->
		<Description>Traffic light</Description>
		<!-- Идентификатор слейва -->
		<id>1</id>
		<!-- Имя XML-файла конфигурации (без расширения *.xml) -->
		<config>traffic-light</config>
	</Slave>
</Config>

и XML-файлов конфигурации для каждого из слейвов

traffic-light.xml
<?xml version="1.0" encoding="UTF-8" ?>
<Config>
	<!-- Дискретные выходы -->
	<Coil>
		<address>16</address>
		<description>Red signal</description>
		<value>0</value>
	</Coil>
	<Coil>
		<address>17</address>
		<description>Yellow signal</description>
		<value>0</value>
	</Coil>
	<Coil>
		<address>18</address>
		<description>Green signal</description>
		<value>0</value>
	</Coil>
	
	<!-- Дискретные входы -->
	<DiscreteInput>
		<address>0</address>
		<description>Ready</description>
		<value>1</value>
	</DiscreteInput>
	
	<!-- Регистры вывода -->
	<HoldingRegister>
		<address>5</address>
		<description>Signal activity time</description>
		<value>15</value>
	</HoldingRegister>
	
	<!-- Регистры ввода -->
	<InputRegister>
		<address>2</address>
		<description>Signals count</description>
		<value>3</value>
	</InputRegister>
</Config>

Последний файл содержит описание всех данных, доступных в устройстве. Для того, чтобы загрузить конфигурацию необходимо открыть файл *.net из меню программы QSlave (File > Open config). Все файлы конфигурации должны лежать в одном каталоге. Конфигурация примера описывает сеть из одного ведомого устройства, некий виртуальный дорожный светофор, дискретные выходы которого описывают сигналы, дискретный вход обозначает некий бит готовности устройства к работе (Ready), регистр ввода сообщает число сигналов светофора, а регистр вывода задает время, в течение которого горит каждый из сигналов.

image

Естественно, данный симулятор никак не имитирует внутреннюю логику работы устройства. Он позволяет лишь задавать значения ячеек памяти, доступных ведущему устройству. Любое из значений можно задать по своему усмотрению, отредактировав соответствующую ячейку таблицы.

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



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

3. QMaster — эмуляция мастер-устройства


Для создания ведомых устройств, отладки их прошивок нужна имитация мастера. Существует ряд открытых эмуляторов, таких как например QModbus. Мы использовали его в своей работе, до тех пор, пока не решили увеличить скорость передачи данных до 250 кБит/с. QModbus этого не позволяет. Его удалось пересобрать из исходников под Linux, но наши электронщики сидят на Windows, а где сборка не пошла по ряду причин. Выяснилось, что это приложение написано на Qt 4, использует сторонную библиотеку libmodbus. Хотелось иметь кроссплатформенное решение на Qt5, тем более что Qt5 уже работает с Modbus «из коробки». Поэтому был написан свой аналог, использующий стек библиотек Qt Modbus - QMaster. Он тоже доступен на Github на тех же условиях.

image

Заключение


В заключении скажу, что работаю (на работе) в основном над закрытыми проектами. Однако, описанные инструменты разработаны лично мной в инициативном порядке в свободное время. К тому же они, в Windows-версии, статически линкованы с GPL-кодом Qt, поэтому я обязан передать их сообществу на тех же условиях, что и получил Qt. К тому же, эти инструменты могут быть полезны для читателя.

Благодарю за внимание!

Комментарии (10)


  1. FDA
    24.12.2017 11:22

    Спасибо! Очень полезные программы!


  1. shadson
    24.12.2017 13:51

    Естественно, данный симулятор никак не имитирует внутреннюю логику работы устройства. Он позволяет лишь задавать значения ячеек памяти, доступных ведущему устройству. Любое из значений можно задать по своему усмотрению, отредактировав соответствующую ячейку таблицы.

    Наверное, стоило бы добавить возможность подвязать хотя бы какие-то базовые генераторы функций (синусоида, пила, прямоугольник и т.д.).
    Я, когда эмуляторы RTU и TCP писал в универе (20 лет, блин!), делал возможность подключения функций из внешних DLL (т.е. и к матмодели можно было подключать).
    Еще лежат в интернетах программы (тогда гитхаба не было): http://tracker2.narod.ru/


    1. maisvendoo Автор
      24.12.2017 15:12

      возможность подключения функций из внешних DLL

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

      Пока мне это не требовалось, но я обмозгую эту идею


      1. shadson
        24.12.2017 15:32

        Дифуравнения и всё такое — это уже реальная модель должна быть (чего очень часто просто нет, или делается постфактум, когда система уже давно работает), будет прекрасно иметь интерфейс для ее подключения, но если Вы сделаете хотя бы шаблонные простые встроенные/внешние_уже_сделанные функции типа синусоиды или пилы — будет намного веселее делать отладку, даже если все будут знать, что это фэйковые данные.


        1. jaiprakash
          24.12.2017 16:59

          VisSim. Можете изобразить там модель и подключить dll. 3-я версия бесплатна*.


    1. ffpss
      25.12.2017 09:59

      Под эти задачи подходит Process simulator 2 от Alexor
      На хабре была статейка habrahabr.ru/post/151125
      Симулятор с протоколами modbus tcp/rtu/ascii, mqtt, opc/ua, S7 TCP/Sim
      На один коннект rtu можно подвязать сигналы разных виртуальных слейвов.
      И функционал по работе с сигналами достаточный — бинарная логика, математика, аналоговые сигналы + встроенный c# для своих задач. Конфиг в XML

      Использовал для отладки ПО контроллера, когда железо еще не было изготовлено, а сигналов море, + часть завязана на временные задержки, и вручную сотни значений менять не вариант (modbus не тестировал, конектил по S7). Удобно вышло

      В будущем планирую для подобных целей использовать LabView. Мощный инструментарий по моделированию, более менее удобный интерфейс, над большими моделями работать удобно — проект можно разделить по отдельным подпрограммам (SubVI), и по основным интерфейсам готовые блоки можно найти.


  1. zabadal
    25.12.2017 09:59

    А почему «не стоит думать что Modbus используется на настоящем подвижном составе»?
    Вроде подходящий промышленный протокол, помехозащищенный физический интерфейс.
    Мешают какие-то особенности именно жд транспорта? Или просто исторически сложилось?


    1. maisvendoo Автор
      25.12.2017 10:03

      исторически сложилось

      На отечественном подвижном составе, в частности электровозах выпускаемых НЭВЗ, начиная с ЭП1 используется CAN. Почему так, я сказать не могу.
      За рубежом, тот же сименс использует MVB и WTB. Отечественный ЭП20 использует CAN в частях системы управления разработанных в России, а на тяговых преобразователях Alstom шина MVB. И для взаимодействия между CAN и MVB используется шлюз.


  1. Borjomy
    25.12.2017 09:59

    Все это давно уже пройдено и называется OPC сервер.


  1. ffpss
    25.12.2017 10:49

    Спасибо за программы, кажется будет удобно и для полевой наладки. То что пробовал раньше — либо интерфейс неудобный, либо платные (пару минут и отрубается), а чаще и то и другое.

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