Arduino -> FLProg -> RS-485 -> Modbus
Вышла новая версия программы FLProg c номером 1.9.1. Я подумал что нововведения в программе заслуживают освещения на хабре.Так же расскажу немного теории о протоколе Modbus и особенностях его реализации на борту Arduino.
Modbus — протокол, работающий по принципу «клиент-сервер».
Широко применяется в промышленности.
Modbus может использоваться для передачи данных через последовательные линии связи RS-485, RS-422, RS-232, а также сети TCP/IP.
Пока в программе FLProg реализована передача данных только по через RS-485.
В основе интерфейса RS-485 лежит принцип дифференциальной (балансной) передачи данных. Суть его заключается в передаче одного сигнала по двум проводам. Причем по одному проводу (условно A) идет оригинальный сигнал, а по другому (условно B) — его инверсная копия. Другими словами, если на одном проводе »1», то на другом »0» и наоборот. Таким образом, между двумя проводами витой пары всегда есть разность потенциалов: при »1» она положительна, при »0» — отрицательна.
Именно этой разностью потенциалов и передается сигнал. Такой способ передачи обеспечивает высокую устойчивость к синфазной помехе. Синфазной называют помеху, действующую на оба провода линии одинаково. К примеру, электромагнитная волна, проходя через участок линии связи, наводит в обоих проводах потенциал. Если сигнал передается потенциалом в одном проводе относительно общего, как в RS-232, то наводка на этот провод может исказить сигнал относительно хорошо поглощающего наводки общего («земли»). Кроме того, на сопротивлении длинного общего провода будет падать разность потенциалов земель — дополнительный источник искажений. А при дифференциальной передаче искажения не происходит. В самом деле, если два провода пролегают близко друг к другу, да еще перевиты, то наводка на оба провода одинакова. Потенциал в обоих одинаково нагруженных проводах изменяется одинаково, при этом информативная разность потенциалов остается без изменений.
Так выглядит типичная посылка, от Ведущего — Ведомому.
Так выглядит ответ Ведомого — Ведущему
ID — Адрес ведомого устройства. Он может иметь значения от 1 до 247. Адрес 0 используется для широковещательной передачи, его распознаёт каждое устройство, адреса в диапазоне 248…255 — зарезервированы.
В программе FLProg для ведущего (Master) реализована поддержка 32 ведомых (Slave) устройств что обусловлено применяемыми конвертерами UART → RS-485.
Команда (код функции):
в данном примере одна, на чтение 0×03.
Но в действительности их намного больше.
Все коды функций делятся на:
— Публичные коды, описанные в стандарте MODBUS-IDA. Их список включает уже назначенные и используемые коды, а также коды для будущего использования;
0×02) — чтение значений из нескольких дискретных входов (Read Discrete Inputs).
(0×03) — чтение значений из нескольких регистров хранения (Read Holding Registers).
(0×04) — чтение значений из нескольких регистров ввода (Read Input Registers).
(0×05) — запись значения одного флага (Force Single Coil).
(0×06) — запись значения в один регистр хранения (Preset Single Register).
(0×07) — Чтение сигналов состояния (Read Exception Status)
(0×0F) — запись значений в несколько регистров флагов (Force Multiple Coils)
(0×10) — запись значений в несколько регистров хранения (Preset Multiple Registers)
(0×16) — запись в один регистр хранения с использованием маски «И» и маски «ИЛИ» (Mask Write Register).
(0×18) — Чтение данных из очереди (Read FIFO Queue)
(0×14) — Чтение из файла (Read File Record)
(0×15) — Запись в файл (Write File Record)
(0×08) — Диагностика (Diagnostic)
(0×0B) — Чтение счетчика событий (Get Com Event Counter)
(0×0C) — Чтение журнала событий (Get Com Event Log)
(0×11) — Чтение информации об устройстве (Report Slave ID)
(0×2B) — Encapsulated Interface Transport
— User-Defined Function Codes (65–72, 100–110) — коды, которые могут использоваться компаниями для собственных функций, и не описаны в спецификации;
— Reserved Function Codes (9, 10, 13, 14, 41, 42, 43, 90, 91, 125, 126 и 127) — зарезервированы коды, которые не доступны для общего использования.
Обработка ошибок
Ведущий отправляет запрос к Ведомому, в котором в поле «код функции» указывает ему на необходимое действие.
Байты данных содержат информацию, необходимую для выполнения данной функции.
Ведомый, в случае удачного выполнения этой функции, повторяет код функции в ответе.
При возникновении ошибки, код функции в ответе модифицируется — старший бит выставляется в 1.
В байтах данных передается причина ошибки. Например при исполнении Ведомым функции 0×0F возникла ошибка, тогда он ответит Ведущему полем функции равным 0×8F.
В дополнении к изменению кода функции, Ведомый размещает в поле данных уникальный код, который указывает на тип и причину ошибки.
В спецификации Modbus определено два типа данных, один бит и 16 битное слово. Данные организованны в четыре таблицы с 16 битной адресацией ячеек, адресация в таблицах начинается с 0. Для доступа к данным из разных таблиц предназначены отдельные команды.
Discrete Inputs | 1 бит | только чтение |
Coils | 1 бит | чтение и запись |
Input Registers | 16 бит | только чтение |
Holding Registers | 16 бит | чтение и запись |
Стандарт предусматривает отдельную таблицу для каждого типа данных, но особенностью реализации в программе FLProg является то, что все регистры ведомого хранятся в одном массиве в виде перекрывающихся таблиц, соответственно все команды от ведущего будут обращаться к одно и той же области памяти. В реализации ведущего предусмотрена работа только с таблицей «Holding Registers».
Ну наверное на этом с теорией закончим, и посмотрим на конкретику и железо.
Для создания сетей на основе RS-485 выгодно применять вот такие преобразователи
Они стоят недорого, но достаточно надежны. Собраны на микросхеме MAX485.
Соеденение с Arduino проводятся по схеме
Для эмуляции ведущего и ведомого во время разработки реализации протокола я использовал две очень хорошие бесплатные программы.
QModBus — Симулятор ведущего
PeakHmiMBSerialSlave — Симулятор ведомого
Ну и напоследок видео урок по созданию ведущего и ведомого устройства в программе FLProg.
PS. Благодарю авторов представленных ниже статей, которые помогли мне разобраться с протоколом Modbus, и реализовать данный функционал.
Источники:
Modbus RTU для Чайников
Arduino & Modbus