Arduino® и протокол Modbus

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

Автор: Hannes Siebeneicher

Последнее обновление: 12.04.2023

Введение

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

Совместимое с Modbus оборудование

Библиотеки

Примечание

Понятия «controller/peripheral» (контроллер/периферия) ранее назывались «master/slave» (ведущий/ведомый). Arduino больше не использует эту терминологию. Устройства, ранее называвшиеся master, теперь называются controller (контроллер), а устройства, ранее называвшиеся slave, — peripheral (периферийное устройство).

Что такое Modbus?

Modbus — открытый протокол последовательной связи, используемый для передачи информации по последовательным линиям между электронными устройствами. Он был первоначально опубликован компанией Modicon (ныне Schneider Electric) в 1979 году. Протокол Modbus является старейшим и, безусловно, самым популярным протоколом автоматизации в области промышленной автоматизации. Он позволяет устройствам, таким как счётчики электроэнергии или датчики влажности, подключённым к одной сети, передавать результаты на управляющий компьютер или программируемый логический контроллер (ПЛК).

Существует несколько версий протокола Modbus: Modbus RTU, Modbus ASCII, Modbus TCP и Modbus Plus. Он основан на архитектуре контроллер-периферия (ранее известной как master-slave), а обмен данными между узлами осуществляется с помощью сообщений типа «отправить запрос и прочитать ответ». Modbus взаимодействует через несколько типов физических носителей, таких как RS-232/RS-485 или Ethernet. Изначально интерфейс Modbus работал на последовательной связи RS-232, однако большинство более поздних реализаций Modbus используют RS-485, поскольку это позволяет обеспечить большие расстояния, более высокие скорости и возможность подключения нескольких устройств в одной многоточечной сети. Передача данных по последовательному физическому носителю RS-485 осуществляется через двухпроводные соединения передачи и приёма.

На интерфейсах, таких как RS-485 и RS-232, сообщения Modbus передаются по сети в открытом виде, и сеть будет предназначена исключительно для связи по Modbus. Однако если ваша сеть требует нескольких разнородных устройств, рекомендуется использовать протокол на основе TCP/IP через Ethernet. В этом случае Modbus и другие типы смешанных протоколов могут сосуществовать на одном физическом интерфейсе одновременно. Основная структура сообщений Modbus является одноранговой (peer-to-peer), но она также может функционировать в сетях «точка-точка» и многоточечных сетях. Как упоминалось, протокол Modbus взаимодействует с использованием техники «контроллер-периферия», при которой только одно устройство может инициировать транзакции, называемые запросами.

Схема протокола Modbus

Как работает Modbus?

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

Запросы Modbus следуют простой структуре:

Структура кадра запроса Modbus

Адрес устройства

Каждое периферийное устройство имеет собственный адрес, на который оно откликается при обращении контроллера. Все остальные устройства игнорируют сообщение, если адрес не совпадает с их собственным. Адреса устройств назначаются в диапазоне от 1 до 247, однако без дополнительного оборудования стабильное количество устройств следует ограничивать 32, поскольку подключение большего числа устройств может вызвать нестабильность.

Код функции

Код функции сообщает периферийному устройству, должно ли оно читать или записывать данные из внутренних регистров памяти. Многие типы данных названы по их использованию для управления реле; например, однобитный физический выход называется катушкой (coil), а однобитный физический вход называется дискретным входом (discrete input) или контактом. Следующие функции поддерживаются опросом Modbus:

  • 01 READ COIL (чтение катушки)

  • 02 READ DISCRETE INPUT (чтение дискретного входа)

  • 03 READ HOLDING REGISTERS (чтение регистров хранения)

  • 04 READ INPUT REGISTERS (чтение входных регистров)

  • 05 WRITE SINGLE COIL (запись одной катушки)

  • 06 WRITE SINGLE REGISTER (запись одного регистра)

  • 15 WRITE MULTIPLE COILS (запись нескольких катушек)

  • 16 WRITE MULTIPLE REGISTERS (запись нескольких регистров)

Данные

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

Контроль ошибок CRC

CRC расшифровывается как Cyclic Redundancy Check (циклический контроль избыточности) и представляет собой код обнаружения ошибок, широко используемый в цифровых сетях для обнаружения случайных изменений в цифровых данных. CRC получил своё название потому, что проверочное (верификационное) значение данных является избыточным (расширяет сообщение, не добавляя информации), а алгоритм основан на циклических кодах. Они просты в реализации в двоичном оборудовании, легко поддаются математическому анализу и особенно хорошо справляются с обнаружением распространённых ошибок, вызванных шумом в каналах передачи.

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

Порядок байтов и слов

Спецификация Modbus не определяет точно, как данные хранятся в регистрах. Поэтому некоторые производители реализовали Modbus в своём оборудовании таким образом, что старший байт хранится и передаётся первым, а за ним следует младший байт. Другие же, напротив, хранят и передают сначала младший байт. Аналогично, когда регистры объединяются для представления 32-битных типов данных, одни устройства хранят старшие 16 бит (старшее слово) в первом регистре, а оставшееся младшее слово — во втором, тогда как другие делают наоборот. Не важно, в каком порядке байты или слова отправляются, главное, чтобы принимающее устройство знало, в каком порядке их ожидать. (Schneider Electric, 2022)

Использование Modbus с Arduino

Теперь, когда вы узнали об основах и возможностях Modbus, пришло время поговорить о том, как можно использовать Arduino для установки связи Modbus между устройствами. Вы можете использовать Arduino либо в качестве контроллера, либо в качестве периферийного устройства в зависимости от конфигурации. Чтобы упростить работу, можно воспользоваться библиотекой Arduino Modbus, которая позволяет реализовать протокол Modbus через два различных типа транспорта: последовательную связь через RS485 с RTU или связь по Ethernet и Wi-Fi с использованием протокола TCP. Поскольку библиотека Modbus зависит от библиотеки RS-485, необходимо включить обе библиотеки в свой код.

Многие платы Arduino совместимы с Modbus, особенно если рассматривать сообщения типа Ethernet. Если вы хотите использовать RS-485, MKR 485 Shield поможет вам превратить любую плату MKR в устройство, совместимое с Modbus. Ознакомьтесь с этим руководством, чтобы узнать больше об отправке данных между двумя MKR 485 Shield.

При использовании библиотеки Modbus отправка сообщений достаточно проста, как можно увидеть в примере функции запроса ниже:

Адрес устройства

Код функции

Начальный регистр

Количество регистров

0x21

INPUT REGISTERS

30107

2

Примечание

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

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

Пример

Предположим, у вас есть совместимый с Modbus счётчик электроэнергии, работающий через RS-485. В нашем случае мы используем модель от Finder, которая использует протокол Modbus RTU, но вы можете использовать другую.

Посмотрите на кадр запроса из документации Finder:

Кадр запроса Finder в документации

Мы видим, что адрес устройства равен 33 (или 0x21).

Код функции равен 04, что, как мы знаем, обозначает INPUT REGISTERS (см. раздел Код функции).

Начальный регистр равен 00 6B (или 0x6B), но для работы библиотеки Modbus нам нужно перевести его из шестнадцатеричного формата в десятичный. В данном примере начальный регистр указан в шестнадцатеричном формате, но если прокрутить документацию чуть ниже, можно увидеть, что регистры записаны в десятичном формате:

Таблица измерений Modbus в документации Finder

Мы также видим, что регистр для U1 занимает 30107 и 30108, что означает, что количество регистров равно 2.

Используя функцию

readVoltage()

определённую с параметрами, которые мы обсудили, можно получить измерение напряжения со счётчика электроэнергии Finder.

Внутри функции можно увидеть, как вызывается

requestFrom()

с параметрами Адрес устройства, Код функции, Начальный регистр и Количество регистров.

/**
  Функция для чтения информации о напряжении с совместимого с Modbus счётчика электроэнергии Finder 7M.24.

  @param none
  @return Возвращает полученные данные о напряжении.
*/
float readVoltage() {
  float volt = 0.;
  // Отправка запроса на чтение через RS485
  if (!ModbusRTUClient.requestFrom(0x21, INPUT_REGISTERS, 30107, 2)) {
    // Обработка ошибки
    Serial.print("- Failed to read the voltage! ");
    Serial.println(ModbusRTUClient.lastError());
  } else {
    // Обработчик ответа
    uint16_t word1 = ModbusRTUClient.read();  // Читаем word1 из буфера
    uint16_t word2 = ModbusRTUClient.read();  // Читаем word2 из буфера
    uint32_t millivolt = word1 << 16 | word2; // Объединяем word1 и word2 для получения значения напряжения в милливольтах
    volt = millivolt/1000.0;                  // Конвертируем в вольты
  }

  return volt;
}

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

Читайте также