В заметке описывается один из вариантов реализации системы управления на базе Raspberry Pi с установленной средой исполнения Codesys и подключенной по последовательной линии платы Arduino. Программа управления использует язык программирования ST, а в качестве драйвера Modbus используется функциональный блок ModbusRequest из системной библиотеки IoDrvModbus. Со стороны Arduino используется библиотека Modbus-Master-Slave-for-Arduino.

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

Базовая схема управления на базе Raspberry Pi и Arduino может выглядеть следующим образом

Вариант 1. Прямое соединение через USB.

Вариант 2. Удалённое подключение Arduino с использованием интерфейса RS-485.

На обеих схемах Raspberry Pi является программируемым модулем управления, т.е. реализует функцию ПЛК. Arduino используется как удалённый универсальный модуль ввода-вывода, функция которого – преобразование логических/числовых управляющих сигналов в физические и обратное преобразование физических величин в логические/числовые.

С программной точки зрения обе эти схемы практически эквивалентны. Нужно лишь отметить, что длина линии RS-485 и наводимые на неё помехи могут потребовать снижения скорости обмена, увеличение времени ожидания ответа и повторения запросов.
Также во второй схеме желательно иметь гальванические развязки в местах соединения последовательной линии с устройствами управления. В промышленных устройствах автоматики преобразователи интерфейсов имеют отдельное питание и гальваническую развязку сигнальных линий. В бытовом применении, для обучения или в малой автоматизации такие средства защиты можно не использовать если есть уверенность в том, что наводимые помехи не будут приводить к неустойчивой связи, перезагрузке устройства или выходу из его строя.

В качестве преобразователей USB/RS-485 можно использовать устройства на базе специализированных микросхем типа FTDI, PL2303, CH340 и прочих, доступных на AliExpress. Для преобразователя RS-485/TTL также есть доступные модули.

Настройка Codesys для работы с последовательным портом

При подключении к Raspberry Pi преобразователя интерфейса USB/RS-485 или Arduino в большинстве случаев в файловой системе появляется устройство /dev/ttyUSBn, где n – это номер назначенного интерфейса для каждого подключенного по USB устройства.
Как правило, если мы выполним команду ls /dev/ | grep ttyUSB, то получим в ответ строку ttyUSB0.

Среда исполнения Codesys по умолчанию ничего не знает о внешних интерфейсах и предварительно необходимо настроить файл конфигурации. Пользовательские настройки конфигурации хранятся в файле /etc/CODESYSControl_User.cfg.

Чтобы получить доступ к файловой системе лучше воспользоваться сторонней программой WinSCP, которая позволит удобно работать с файловой системой по протоколу SFTP. Установим, запустим программу и создадим новое соединение, установив тип протокола, ip-адрес, логин и пароль (pi/raspberry по умолчанию).

Для возможности записи в расширенных настройках подключения установим:

Среда -> SFTP -> Параметры протокола:
Сервер SFTP: sudo /usr/lib/sftp-server

Далее находим файл конфигурации /etc/CODESYSControl_User.cfg и открываем его на редактирование (в программе WinSCP можно назначить внешний редактор).

Для подключения внешнего последовательного устройства в файле конфигурации добавим/изменим секцию:

То же можно сделать, используя инструменты ОС Raspbian, если есть прямой доступ к Raspberry Pi. Ещё можно установить панельный файловый менеджер Midnight Commander с помощью команды:

С помощью встроенного в него редактора можно изменить файл конфигурации. Запуск Midnight Commander выполняется командой:

После правки конфигурации необходимо перезапустить Codesys RTS. Сделать это можно из среды разработки Codesys (Tools\Update Raspberry Pi) или при помощи команд:

Программа для Arduino

В качестве программы, реализующей работу по протоколу modbus-rtu slave, возьмём пример, который идёт в составе библиотеки Modbus-Master-Slave-for-Arduino: examples\simple_slave\simple_slave.ino.

Сначала установим саму библиотеку. Для этого нужно перейти в корень репозитория и нажать кнопку Clone or download, а в появившемся окне выбрать Download ZIP.

В окне сохранения измените имя архива на ModbusRtu.zip. Это понадобится при установке библиотеки в Arduino IDE.

После загрузки откройте Arduino IDE, вызовите пункт меню Скетч\Подключить библиотеку\Добавить .ZIP библиотеку… и выберите загруженный архив.

После установки содержимое архива ModbusRtu должно находиться в папке: C:\Users\User\Documents\Arduino\libraries. Откройте пример ModbusRtu\examples\simple_slave\simple_slave.ino и загрузите его в свою плату Arduino.

Проект для Codesys

В качестве тестового проекта предлагаю программу на языке ST, использующую библиотеки SysCom и IoDrvModbus. Первая используется для управления портом при помощи набора функций, а вторая – для реализации протокола modbus rtu master, используя функциональный блок ModbusRequest:


Проект с именем Raspberry.RTUMasterAsyncTest.ST.project находится в git репозитории codesys. Содержимое репозитория codesys доступно в виде zip архива (см. кнопку ZIP).
Также его можно клонировать стандартными средствами git, используя адрес репозитория в качестве ссылки:

При этом репозиторий будет доступен только в режиме чтения (push запрещён).

Проект Raspberry.RTUMasterAsyncTest.ST.project сохранён в формате Codesys 3.5.12.20, используется пакет Raspberry Pi 3.5.12.30. При первом открытии возможно понадобится загрузить отсутствующие библиотеки через Library Manager в дереве проекта.
Проект может быть использован и на ранних версиях Codesys, вплоть до 3.5.10.0, но для этого его нужно вручную сохранить в нужной версии и исправить все зависимости (библиотеки, устройства), что требует некоторого опыта. Можно также скопировать текст программы, а все зависимости добавить, создав новый проект в имеющейся версии среды разработки.
Текст программы можно посмотреть в pdf файле, имеющем то же имя, что и файл проекта Codesys: Raspberry.RTUMasterAsyncTest.ST.pdf .

Имейте в виду, если Codesys RTS использует последовательный порт в проекте, то при переподключении Arduino имя устройства может измениться, т.к. текущее устройство считается занятым. Чтобы этого не происходило нужно останавливать среду исполнения перед подключениями устройств по USB.

Не забывайте перезапускать Codesys RTS, т.к. демо версия среды исполнения работает только 2 часа.

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

Описание алгоритма тестового проекта Codesys

Программа имеет вид автомата состояний. Используются следующие состояния:

  • MODE_CONNECT – здесь осуществляется открытие и настройка последовательного порта;
  • MODE_SET_DATA – здесь происходит заполнение буфера данными;
  • MODE_REQUEST – здесь в зависимости от текущего номера функции выполняется запрос к slave устройству,  анализируется ответ от него и переключается номер функции;
  • MODE_IDLE – здесь реализован интервал между запросами и из сброс;
  • MODE_ERROR – в случае ошибки делается попытка восстановления соединения.

Алгоритм программы осуществляет циклический последовательный перебор асинхронных запросов modbus rtu. Тестируется следующий набор функций modbus:

  • READ_COILS – используется для чтения значений дискретных выходов (DO),
  • READ_DISCRETE_INPUTS – используется для чтения значений дискретных входов (DI),
  • READ_HOLDING_REGISTERS – используется для чтения значений аналоговых выходов (AO),
  • READ_INPUT_REGISTERS – используется для чтения значений аналоговых входов (AI),
  • WRITE_SINGLE_COIL, – используется для записи значения одного дискретного выхода (DO)
  • WRITE_SINGLE_REGISTER – используется для записи значения одного аналогового выхода (AO),
  • WRITE_MULTIPLE_COILS – используется для записи значений последовательности дискретных выходов (DO),
  • WRITE_MULTIPLE_REGISTERS – используется для записи значений последовательности аналоговых выходов (AO).

Тестирование

Если поставить точку останова внутри условия if xDone then, то можно, анализируя содержимое буфера tmpbuf, проверить корректность работы программы на Arduino для каждой функции modbus. Нетрудно заметить, что все запросы выполняются успешно, а содержимое буфера при первом чтении соответствует содержимому кода программы для Arduino.

Итоги

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

Приложение

Обсудить на форуме.

Управление Arduino по протоколу Modbus RTU в Codesys
Метки:                

Комментарии:

Управление Arduino по протоколу Modbus RTU в Codesys: 8 комментариев

  • 11 июля 2018 в 11:39
    Постоянная ссылка

    Вячеслав, с удовольствием прочел Ваши статьи. Также интересует тема малина и кодесис. Вопрос такой, не нашел пока информации по реализации modbus TCP на малине. Штатный конфигуратор не интересует. С ним понятно. Может есть готовая библиотека? Или лепить из например из OSCAT NET + либа Modbus ОВЕН.
    Спасибо.

    Ответить
  • 12 июля 2018 в 11:00
    Постоянная ссылка

    Спасибо! то что нужно! Один вопрос возник – библиотека AgavaModbusEx ссылается на Util 3.5.9.0, у меня 3.5.11.0. Не компилится, ошибки выдает. Не подскажите как победить?
    Библиотеки и таргет обновил. Остальные примеры которые смотрел нормально собираются.
    Спасибо.

    Ответить
    • 12 июля 2018 в 16:32
      Постоянная ссылка

      Нужно подробно пояснять:
      – версия SDK (имя файла архива);
      – название проекта из примера;
      – версия Codesys, включая номер патча.
      При работе с Codesys нужно быть очень аккуратным с зависимостями. Для RaspberryPi можно использовать Codesys 3.5.12.x и вообще не стесняться последних версий. Библиотеки из SDK собраны в Codesys 3.5.10.40 и, как правило, могут быть использованы в старших версиях.
      Если требуется другая версия библиотеки, то можно попробовать принудительно установить нужную версию в менеджере библиотек (см. дерево проекта, ПКМ, свойства библиотеки).

      Ответить
  • 13 июля 2018 в 16:15
    Постоянная ссылка

    А в примере CODESYS, что в статье, как работает это часть:

    // Переходим к следующему запросу.
    case nfunc of

    // Function 01 (0x01) Read Coils
    READ_COILS: nfunc := READ_DISCRETE_INPUTS;

    // Function 02 (0x02) Read Discrete Inputs
    READ_DISCRETE_INPUTS: nfunc := READ_HOLDING_REGISTERS;

    // Function 03 (0x03) Read Holding Registers
    READ_HOLDING_REGISTERS: nfunc := READ_INPUT_REGISTERS;

    // Function 04 (0x04) Read Input Registers
    READ_INPUT_REGISTERS: nfunc := WRITE_SINGLE_COIL;

    // Function 05 (0x05) Write Single Coil
    WRITE_SINGLE_COIL: nfunc := WRITE_SINGLE_REGISTER;

    // Function 06 (0x06) Write Single Register
    WRITE_SINGLE_REGISTER: nfunc := WRITE_MULTIPLE_COILS;

    // Function 15 (0x0F) Write Multiple Coils
    WRITE_MULTIPLE_COILS: nfunc := WRITE_MULTIPLE_REGISTERS;

    // Function 16 (0x10) Write Multiple Registers
    WRITE_MULTIPLE_REGISTERS: nfunc := READ_COILS;

    end_case

    Как я понял вошли в CASE после получения ответа xDone, присвоили nfunc следующее значение и вышли…. А для чего? Таким образом перебираем все функции Modbus? Это для примера? А в реальном приложении какая будет конструкция?

    Ответить
    • 13 июля 2018 в 16:24
      Постоянная ссылка

      Перебор всех функций нужен для примера, чтобы проверить корректность работы для каждой в одном примере. Это упрощённый минимальный пример, который позволяет это сделать. Воспользовавшись монитором последовательного порта можно проверить процесс обмена данными на соответствие протоколу modbus и таблице регистров в slave устройстве.
      Реальное приложение может использовать эти функции как угодно в зависимости от постановки задачи. Короче говоря, это должен определять программист, исходя из имеющейся документации на библиотеку (см. SDK).

      Ответить

Добавить комментарий для Салихов Ильдар Отменить ответ

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