- Modbus, краткое введение
- Описание протокола modbus rtu
- Accessport
- Modbus rtu для чайников / блог им. khomin / сообщество
- Modscan32/64
- Scada система masterscada – лидер российского рынка
- Двухслойная структура проекта
- Какие бывают ошибки запроса modbus?
- Наладка систем автоматизации, использующих modbus устройства
- Общие сведения о modbus сети
- Тестирование устройств с поддержкой modbus rtu в рамках процесса разработки
- Типы данных modbus
- Функции modbus
- Как послать команду modbus rtu на чтение дискретного вывода? команда 0×01
Modbus, краткое введение
Modbus является довольно распространённым протоколом в системах автоматизации на среднем и нижнем (полевом) уровнях. Средний — это уровень контроллеров — устройств, осуществляющих сбор данных и управление технологическим процессом. Нижний или полевой — это уровень взаимодействия датчиков и контроллеров или датчиков напрямую с сервером. Более подробно об уровнях в системах автоматизации можно посмотреть здесь.
Как правило, структура типовой системы автоматизации, использующей в качестве базового протокола Modbus, выглядит так как показано на рисунке в начале статьи. В качестве ”среды” для протокола Modbus может выступать либо RS-485/422/232 (подробно про RS-485 можно прочитать здесь и здесь), поверх него работает Modbus RTU или Modbus ASCII, либо транспортный протокол TCP в TCP/IP сетях, такая версия носит название Modbus TCP. В данной статье будет рассмотрен Modbus RTU.
Протокол Modbus предполагает наличие одного ведущего устройства в сети (оно называется Master или Client) и от 1 до 247 ведомых (они называются Slave или Server). Полное описание можно найти на официальном сайте или в вики.
Master периодически взаимодействует со Slave-устройствами, считывая или записывая в них какую-либо информацию. Этот процесс осуществляется в форме запрос-ответ. Запрос представляет собой последовательность байт, называемую кадром, в котором время между байтами стандартизировано и зависит от скорости передачи данных (напомним, что речь идет о Modbus RTU) и составляет не более длительности интервала, в течение которого может быть передано 1,5 байта данных. Время между кадрами должно быть не меньше времени передачи 3,5 байт.
Формат запроса имеет следующий вид:
ID — адрес устройства (1 байт),FN — Modbus функция (1 байт),[args] — аргументы функции (N байт, зависит от функции),CRC — контрольная сумма CRC-16 (2 байта).
Ответ имеет схожий формат:
Почти все поля ответного кадра аналогичны кадру запроса, за исключением поля DATA, оно имеет различное наполнение, в зависимости от функции.
Если устройством не поддерживается запрашиваемая функция или аргументы в поле [args] запроса являются некорректными для данного Slave-устройства, то в ответе, в поле FN старший бит будет выставлен в 1 (т.е. на FN наложится маска 0x80), а в поле DATA будет помещена дополнительная информация об ошибке.
Каждое Slave-устройство может иметь определенные области данных и содержать дополнительную специфическую информацию.Возможные области данных представлены в таблице ниже:
За более подробной информацией следует обратиться к полному описанию Modbus RTU, доступному в виде спецификации.
Описание протокола modbus rtu
Modbus —коммуникационный протокол, основан на архитектуре ведущий-ведомый (master-slave). Использует для передачи данных интерфейсы RS-485, RS-422, RS-232, а также Ethernet сети TCP/IP (протокол Modbus TCP).
Сообщение Modbus RTU состоит из адреса устройства SlaveID, кода функции, специальных данных в зависимости от кода функции и CRC контрольной суммы.
| SlaveID | Код функции | Специальные данные | CRC |
Если отбросить SlaveID адрес и CRC контрольную сумму, то получится PDU, Protocol Data Unit.
SlaveID – это адрес устройства, может принимать значение от 0 до 247, адреса с 248 до 255 зарезервированы.
Данные в модуле хранятся в 4 таблицах.
Две таблицы доступны только для чтения и две для чтения-записи.
В каждой таблице помещается 9999 значений.
В сообщении Modbus используется адрес регистра.
Например, первый регистр AO Holding Register, имеет номер 40001, но его адрес равен 0000.
Разница между этими двумя величинами есть смещение offset.
Каждая таблица имеет свое смещение, соответственно: 1, 10001, 30001 и 40001.
Ниже приведен пример запроса Modbus RTU для получения значения AO аналогового выхода (holding registers) из регистров от #40108 до 40110 с адресом устройства 17.
11 03 006B 0003 7687
| 11 | Адрес устройства SlaveID (17 = 11 hex) |
| 03 | Функциональный код Function Code (читаем Analog Output Holding Registers) |
| 006B | Адрес первого регистра (40108-40001 = 107 =6B hex) |
| 0003 | Количество требуемых регистров (чтение 3-х регистров с 40108 по 40110) |
| 7687 | Контрольная сумма CRC |
В ответе от Modbus RTU Slave устройства мы получим:
11 03 06 AE41 5652 4340 49AD
Где:
| 11 | Адрес устройства (17 = 11 hex) | SlaveID |
| 03 | Функциональный код | Function Code |
| 06 | Количество байт далее (6 байтов идут следом) | Byte Count |
| AE | Значение старшего разряда регистра (AE hex) | Register value Hi (AO0) |
| 41 | Значение младшего разряда регистра (41 hex) | Register value Lo (AO0) |
| 56 | Значение старшего разряда регистра (56 hex) | Register value Hi (AO1) |
| 52 | Значение младшего разряда регистра (52 hex) | Register value Lo (AO1) |
| 43 | Значение старшего разряда регистра (43 hex) | Register value Hi (AO2) |
| 40 | Значение младшего разряда регистра (40 hex) | Register value Lo (AO2) |
| 49 | Контрольная сумма | CRC value Lo |
| AD | Контрольная сумма | CRC value Hi |
Регистр аналогового выхода AO0 имеет значение AE 41 HEX или 44609 в десятичной системе.
Регистр аналогового выхода AO1 имеет значение 56 52 HEX или 22098 в десятичной системе.
Регистр аналогового выхода AO2 имеет значение 43 40 HEX или 17216 в десятичной системе.
Значение AE 41 HEX — это 16 бит 1010 1110 0100 0001, может принимать различное значение, в зависимости от типа представления.
Значение регистра 40108 при комбинации с регистром 40109 дает 32 бит значение.
Пример представления.
| Тип представления | Диапазон значений | Пример в HEX | Будет в десятичной форме |
|---|---|---|---|
| 16-bit unsigned integer | 0 до 65535 | AE41 | 44,609 |
| 16-bit signed integer | -32768 до 32767 | AE41 | -20,927 |
| two character ASCII string | 2 знака | AE41 | ® A |
| discrete on/off value | 0 и 1 | 0001 | 0001 |
| 32-bit unsigned integer | 0 до 4,294,967,295 | AE41 5652 | 2,923,517,522 |
| 32-bit signed integer | -2,147,483,648 до 2,147,483,647 | AE41 5652 | -1,371,449,774 |
| 32-bit single precision IEEE floating point number | 1,2·10−38 до 3,4×10 38 | AE41 5652 | -4.395978 E-11 |
| four character ASCII string | 4 знака | AE41 5652 | ® A V R |
Accessport
Программа из разряда “чистых” терминалов. Она не поддерживает Modbus, поэтому при её использовании будьте готовы считать CRC для ваших кадров самостоятельно. Несомненным плюсом является то, что в неё встроен сниффер последовательного порта.
Достоинства: наличие сниффера порта, ПО бесплатное, настраиваемое представление данных, возможность передачи файлов.
Недостатки: не поддерживает Modbus вообще, нет возможность создавать профили, в режиме авто-опрос можно работать только с одним устройством, в настоящее время ПО не развивается.
В заключение хотелось бы добавить, что в сети достаточно большое количество программ для работы с последовательным портом, но если есть необходимость работать именно с Modbus протоколом, то его поддержка в таком ПО крайне желательна. Одна из основных причин — это расчет CRC, в ручную это делать накладно, также важно, чтобы программа могла уметь разделять кадры, иначе все превращается в сплошную мешанину байтов, ну и если есть авто-опрос, то это сильно упрощает жизнь.
Хочется дополнить список ПО и библиотек для работы с Modbus, тем, что было переставлено в комментариях.SCADAFreeSCADAModbus TCP/RTUAdvanced TCP/IP Data LoggerArdsoft Эмулятор ModbusPortMonMODBUS FOR WINDOWSPeakHMIModpoll Modbus Master SimulatorQModMastermodbus_tkpymodbuslibmodbus
Благодарю всех, кто помог улучшить статью!
Спасибо за внимание!
Modbus rtu для чайников / блог им. khomin / сообщество
Modbus— протокол, работающий по принципу «клиент-сервер».
Широко применяется в промышленности.
Modbus
может использоваться для передачи данных через последовательные линии связи RS-485, RS-422, RS-232, а также сети TCP/IP.
В этой статье рассмотрим на примере линии RS-485.
И так, в основе интерфейса RS-485 лежит принцип дифференциальной (балансной) передачи данных. Суть его заключается в передаче одного сигнала по двум проводам. Причем по одному проводу (условно A) идет оригинальный сигнал, а по другому (условно B) — его инверсная копия. Другими словами, если на одном проводе «1», то на другом «0» и наоборот. Таким образом, между двумя проводами витой пары всегда есть разность потенциалов: при «1» она положительна, при «0» — отрицательна.
Именно этой разностью потенциалов и передается сигнал. Такой способ передачи обеспечивает высокую устойчивость к синфазной помехе. Синфазной называют помеху, действующую на оба провода линии одинаково. К примеру, электромагнитная волна, проходя через участок линии связи, наводит в обоих проводах потенциал. Если сигнал передается потенциалом в одном проводе относительно общего, как в RS-232, то наводка на этот провод может исказить сигнал относительно хорошо поглощающего наводки общего («земли»). Кроме того, на сопротивлении длинного общего провода будет падать разность потенциалов земель — дополнительный источник искажений. А при дифференциальной передаче искажения не происходит. В самом деле, если два провода пролегают близко друг к другу, да еще перевиты, то наводка на оба провода одинакова. Потенциал в обоих одинаково нагруженных проводах изменяется одинаково, при этом информативная разность потенциалов остается без изменений.
Воплощение
Есть несколько вариантов.
— Подешевле на известной MAX-ADM485.
Без изоляции, развязки, изолированного источника питания. Зато стоит не более 25 рублей.
— Подороже, сюда можно отнести монстра ADM2587, ADM2483 и пр.
Разводить пп желательно очень вдумчиво.
Узел RS-485 хорошо вынести подальше от точных и измерительных цепей, узлов и т.п.
На обычную сигнальную линию проложенную вдоль силовых установок и мощных потребителей, воздействует огромное количество наводок и помех.
В некоторых случаях, их потенциал может достигнуть нескольких тысяч вольт!
Так выглядит типичная посылка, от Ведущего — Ведомому.
Так выглядит ответ Ведомого — Ведущему
ID — Адрес ведомого устройства. Он может иметь значения от 1 до 247. Адрес 0 используется для широковещательной передачи, его распознаёт каждое устройство, адреса в диапазоне 248…255 — зарезервированы.
Команда(код функции):
в данном примере одна, на чтение 0x03.
Но в действительности их намного больше.
Все коды функций делятся на:
— Публичные коды, описанные в стандарте MODBUS-IDA. Их список включает уже назначенные и используемые коды, а также коды для будущего использования;
— User-Defined Function Codes (65-72, 100-110) — коды, которые могут использоваться компаниями для собственных функций, и не описаны в спецификации;
— Reserved Function Codes (9, 10, 13, 14, 41, 42, 43, 90, 91, 125, 126 и 127) — зарезервированы коды, которые не доступны для общего использования.
(0x02) — чтение значений из нескольких дискретных входов (Read Discrete Inputs).
(0x03) — чтение значений из нескольких регистров хранения (Read Holding Registers).
(0x04) — чтение значений из нескольких регистров ввода (Read Input Registers).
(0x05) — запись значения одного флага (Force Single Coil).
(0x06) — запись значения в один регистр хранения (Preset Single Register).
(0x07) — Чтение сигналов состояния (Read Exception Status)
(0x0F) — запись значений в несколько регистров флагов (Force Multiple Coils)
(0x10) — запись значений в несколько регистров хранения (Preset Multiple Registers)
(0x16) — запись в один регистр хранения с использованием маски «И» и маски «ИЛИ» (Mask Write Register).
(0x18) — Чтение данных из очереди (Read FIFO Queue)
(0x14) — Чтение из файла (Read File Record)
(0x15) — Запись в файл (Write File Record)
(0x08) — Диагностика (Diagnostic)
(0x0B) — Чтение счетчика событий (Get Com Event Counter)
(0x0C) — Чтение журнала событий (Get Com Event Log)
(0x11) — Чтение информации об устройстве (Report Slave ID)
(0x2B) — Encapsulated Interface Transport
Обработка ошибок
Ведущий отправляет запрос к Ведомому, в котором в поле «код функции» указывает ему на необходимое действие.
Байты данных содержат информацию, необходимую для выполнения данной функции.
Ведомый, в случае удачного выполнения этой функции, повторяет код функции в ответе.
При возникновении ошибки, код функции в ответе модифицируется — старший бит выставляется в 1.
В байтах данных передается причина ошибки. Например при исполнении Ведомым функции 0x0F возникла ошибка, тогда он ответит Ведущему полем функции равным 0x8F.
В дополнении к изменению кода функции, Ведомый размещает в поле данных уникальный код, который указывает на тип и причину ошибки.
CRC-16, циклически избыточный код.
Полином:
Для расчета есть два метода:
Простой
uint16_t GetCRC16(byte *buf, uint8_t len)
{
uint16_t crc;
crc = 0xFFFF;
while(len--)
{
crc = crctable[((crc>>8)^*buf )&0xFF] ^ (crc<<8);
}
crc ^= 0xFFFF;
return crc;
}и
Табличный
const uint8_t auchCRCHi[256]=
{
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81,
0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01,
0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81,
0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01,
0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81,
0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01,
0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81,
0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01,
0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81,
0x40
};
const uint8_t auchCRCLo[256]=
{
0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06, 0x07, 0xC7, 0x05, 0xC5, 0xC4,
0x04, 0xCC, 0x0C, 0x0D, 0xCD, 0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09,
0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A, 0x1E, 0xDE, 0xDF, 0x1F, 0xDD,
0x1D, 0x1C, 0xDC, 0x14, 0xD4, 0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3,
0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3, 0xF2, 0x32, 0x36, 0xF6, 0xF7,
0x37, 0xF5, 0x35, 0x34, 0xF4, 0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A,
0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 0x28, 0xE8, 0xE9, 0x29, 0xEB, 0x2B, 0x2A, 0xEA, 0xEE,
0x2E, 0x2F, 0xEF, 0x2D, 0xED, 0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26,
0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60, 0x61, 0xA1, 0x63, 0xA3, 0xA2,
0x62, 0x66, 0xA6, 0xA7, 0x67, 0xA5, 0x65, 0x64, 0xA4, 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F,
0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68, 0x78, 0xB8, 0xB9, 0x79, 0xBB,
0x7B, 0x7A, 0xBA, 0xBE, 0x7E, 0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5,
0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71, 0x70, 0xB0, 0x50, 0x90, 0x91,
0x51, 0x93, 0x53, 0x52, 0x92, 0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C,
0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 0x5A, 0x9A, 0x9B, 0x5B, 0x99, 0x59, 0x58, 0x98, 0x88,
0x48, 0x49, 0x89, 0x4B, 0x8B, 0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C,
0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42, 0x43, 0x83, 0x41, 0x81, 0x80,
0x40
};
uint16_t CRC16(uint8_t *p, uint16_t len)
{
uint8_t crc_hi;
uint8_t crc_lo;
uint8_t n;
if (len>256U)
{
return (0);
}
n = (uint8_t)len;
crc_hi = 0xFF; // high byte of CRC initialized
crc_lo = 0xFF; // low byte of CRC initialized
do
{
uint8_t i = crc_hi ^ *p ; // will index into CRC lookup table
crc_hi = crc_lo ^ (uint8_t)(&auchCRCHi[i]); // calculate the CRC
crc_lo = (uint8_t)(&auchCRCLo[i]);
}
while (--n); // pass through message buffer (max 256 items)
return ((crc_hi << 8) | crc_lo);
}
Использование табличной функции
unsigned char mess[3] = {1,108,8};
volatile unsigned short res1 = CRC16(&mess,3);
res1 будет равен 0x0СС6 при подстановке в конце команды менять местами
старший и младший байты не надо. Эта функция при занесении значения в
res1 автоматически меняет местами старший и младший байты.

Как указано в даташите на ADM485, для работы на прием выводы RE-DE-DI должны быть в 0,
тогда на выводе RO появляются принятые данные.
Для работы на передачу — все противоположно, но данные следует слать на DI.
Простая функция приема
void USART1_IRQHandler(void)
{ uint16_t temp;
if((Modbus_Progress_Status == M_STAT_REC_ON)|| (Modbus_Progress_Status == M_STAT_CLEAR))
{
Modbus_Data[Modbus_Count_Byte] = USART1->DR;
Modbus_Count_Byte ;
if(Modbus_Count_Byte >= LENGTH_PACK)
{
if(Modbus_Data[0] == MY_ID)
{
temp = Modbus_Data[7];
temp = temp<<8;
temp |= Modbus_Data[6];
if(CRC_calc(Modbus_Data,9)==temp)
{
Modbus_Progress_Status = M_STAT_TRAN_ON;
Modbus_Count_Byte =0;
USART1->CR1 &=~ USART_CR1_RE;
USART1->CR1 &=~ USART_CR1_RXNEIE;
Modbus_Send();
};
}}}}
Ответ выглядит примерно так
void Modbus_Send(void)
{
uint16_t crc;
uint8_t i;
USART1->CR1 &=~ USART_CR1_RE;
USART1->CR1 &=~ USART_CR1_RXNEIE;
Modbus_DataTX[0]= ID;
Modbus_DataTX[1]= COMMAND_READ;
Modbus_DataTX[2]= LENGTH_REDE;
Modbus_DataTX[3]= Param1L;
Modbus_DataTX[4]= Param1H;
Modbus_DataTX[5]= Param2L;
Modbus_DataTX[6]= Param1H;
....
Modbus_DataTX[21]= Param21L;
Modbus_DataTX[22]= Param21H;
crc = CRC(Modbus_DataTX, 23);
Modbus_DataTX[23]= (crc & 0x00FF);
Modbus_DataTX[24]= (crc >>8);
Modbus_Transmit_Select();
for(i=0; i<LENGTH_PACK_REDE; i )
{
USART_Transmit(Modbus_DataTX[i]);
}
USART1->CR1 &=~ USART_CR1_TE;
Modbus_Receive_Select();
// Тут очищаем флаги если есть
Modbus_Data_TransLength = 0;
Modbus_Progress_Status = M_STAT_CLEAR;
Modbus_Progress_Status = 0;
Modbus_Count_Byte = 0;
Modbus_Count_TransByte =0;
USART1->CR1 |= USART_CR1_RE;
USART1->CR1 |= USART_CR1_RXNEIE;
}
Все интервалы организованы на прерываниях.
Сообщение должно начинаться и заканчиваться интервалом тишины, длительностью не менее 3,5 символов.
Во время передачи сообщения не должно быть пауз длительностью более 1,5 символов.
Для скоростей более 19200 бод допускается использовать интервалы 1,75 и 0,75 мс, соответственно.
Для отладки удобно использовать что-то вроде Modbus_Poll.
К сожалению он не бесплатный, триальная версия работает 25 дней, ограничивает работу 10 минутами и всячески достает сообщениями…
Файл логанализатора, с общением по Modbus Яндекс диск
Рекомендуется к прочтению:
Спецификация Modbus Link
RS-485 для чайников — Link
Modbus в Википедии Link
Modbus протокол Link
Отдельное спасибо товарищу Papandopala, за функцию табличного расчета CRC.
Modscan32/64
Следующим ПО в нашем обзоре будет Modscan от WinTECH. Внешне эта программа очень похожа на Modbus Poll, но функционалом она обладает значительно меньшим.
У Modscan есть одна уникальная особенность для программ данного типа — это возможность создания форм (своего рода мнемосхем). Пока ее функционалу далеко до реальных SCADA-систем, но наличие такого бонуса радует. На сегодняшний день это достаточно скудный, по своим возможностям инструмент (имеется ввиду редактор форм), но будем надеяться, что со временем, разработчики доведут его до хорошего уровня.
Достоинства: возможность создания собственных форм для просмотра данных, поддержка MMI & OLE Automation.
Недостатки: цена (одна лицензия $ 84.95), нет поддержки нестандартного Modbus, нет профилей для быстрого переключения портов, ненастраиваемая система логирования, малое количество поддерживаемых Modbus-функций.
Scada система masterscada – лидер российского рынка
MasterSCADA – система для создания АСУТП, MES, решения задач учета и диспетчеризации объектов промышленности, ЖКХ и автоматизации зданий.
MasterSCADA™ — самый современный, инновационный мощный и удобный инструмент для быстрой и качественной разработки систем. В нем воплощен двадцатилетний опыт разработчиков в области создания программных продуктов для систем автоматизации самых разных объектов.
MasterSCADA™ — это не просто один из современных SCADA- и SoftLogic-пакетов, это принципиально новый инструмент разработки систем управления и диспетчеризации. В нем реализованы средства и методы разработки проектов, обеспечивающие резкое сокращение трудозатрат и повышение надежности создаваемой системы.
Популярность и надежность MasterSCADA подтверждается не только числом проданных лицензий, а так же серьезностью организаций, использующих ее, и проектов, реализованных на ней. Сегодня нашу SCADA используют такие компании, как:
Газпром
Роснефть
Лукойл
Иркутскэнерго
Калининская АЭС
И многие другие.
Общее число внедрений Master SCADA системы составляет десятки тысяч практически во всех отраслях промышленности в России, ближнем и дальнем зарубежье.
В 2021 г. MasterSCADA была включена в Единый Реестр российских программ для электронных вычислительных машин и баз данных. В соответствии с приказом Минкомсвязи России от 08.11.2021 №538, Приложение 2, №пп. 17, ей был присвоен реестровый № 2201.
Внесение ПО в Единый Реестр российских программ дало MasterSCADA немаловажное преимущество – возможность ее использования государственными организациями в системах управления любыми объектами, включая самые технологически сложные и важные для нашего государства.
Двухслойная структура проекта
В MasterSCADA проект разделен на два слоя:
- Слой описания аппаратной структуры проекта. Здесь описываются рабочие станции, контроллеры и модули ввода-вывода, входящие в проект. Задаются их свойства и настраиваются связи между ними;
- Слой описания логики проекта. Здесь описывается логическая структура проекта: какие технологические объекты автоматизаруются в данном проекте, их свойства, параметры, алгоритмы управления и мнемосхемы. Кроме того, здесь разрабатываются отчеты, настраиваются журналы и параметры информационной безопасности системы.
Такой подход дает возможность:
- разрабатывать эти структуры параллельно;
- независимо работать специалистам различных профилей;
- решить проблему перехода от одной технической структуры системы к другой (например, реализовать тот же проект на базе других контроллеров).
Какие бывают ошибки запроса modbus?
Если устройство получило запрос, но запрос не может быть обработан, то устройство ответит кодом ошибки.
Ответ будет содержать измененный Функциональный код, старший бит будет равен 1.
Пример:
Пример запроса и ответ с ошибкой:
Расшифровка кодов ошибок
| 01 | Принятый код функции не может быть обработан. |
| 02 | Адрес данных, указанный в запросе, недоступен. |
| 03 | Значение, содержащееся в поле данных запроса, является недопустимой величиной. |
| 04 | Невосстанавливаемая ошибка имела место, пока ведомое устройство пыталось выполнить затребованное действие. |
| 05 | Ведомое устройство приняло запрос и обрабатывает его, но это требует много времени. Этот ответ предохраняет ведущее устройство от генерации ошибки тайм-аута. |
| 06 | Ведомое устройство занято обработкой команды. Ведущее устройство должно повторить сообщение позже, когда ведомое освободится. |
| 07 | Ведомое устройство не может выполнить программную функцию, заданную в запросе. Этот код возвращается для неуспешного программного запроса, использующего функции с номерами 13 или 14. Ведущее устройство должно запросить диагностическую информацию или информацию об ошибках от ведомого. |
| 08 | Ведомое устройство при чтении расширенной памяти обнаружило ошибку паритета. Ведущее устройство может повторить запрос, но обычно в таких случаях требуется ремонт. |
Наладка систем автоматизации, использующих modbus устройства
Людей, занимающихся наладкой систем автоматизации и просто пытающихся “подружиться” с каким-либо устройством, на борту которого находится Modbus, в разы больше чем, тех, кто эти устройства разрабатывает. Исходя из специфики задачи, требования к соответствующему ПО будут немного отличаться.
Если необходимо соединить контроллер и одиночное Slave-устройство, то прежде всего, нужно установить с ним связь с помощью преобразователя интерфейсов RS-485/USB, ПК и специализированного программного обеспечения либо терминала. В таком случае, логика работы и набор инструментов ничем не отличается от тех, что применяются при разработке Slave-устройства на стадии тестирования. На этом этапе не требуется длительное тестирование с последующим анализом большого количества лог-файлов.
В случае, когда у вас уже есть готовая сеть устройств, можно выделить следующие задачи:
В этом случае, понадобится либо терминал с возможностью создания списка запросов, либо специализированный инструмент типа Modbus Poll, который позволяет опрашивать несколько устройств в рамках одного проекта.
Modbus-устройства могут иметь определенные настройки интерфейса RS-485: количество бит данных, четность и количество стоп бит. Устройства с различными настройками не могут работать в одной сети с одним и тем же мастером. Тестирование и конфигурирование таких устройств удобно проводить, применяя терминальные программы, имеющие возможность быстрого переключения между предустановленными профилями настроек портов или работающие с несколькими линиями одновременно.
Реже возникает задача организации обмена данными с устройством, протокол которого отличается от стандартной спецификации Modbus RTU. Нам приходилось встречаться с ситуацией, когда протокол Slave-устройства логически повторяет Modbus (структура пакета, таймауты и т.п.), но использует функции вне стандарта.
В таком случаем возможна работа с использованием Modbus Poll, он позволяет строить произвольные запросы, или терминала, обладающего сходным функционалом. Стандартная SCADA-система, обычно, в такой ситуации бессильна, и работа с подобным оборудованием осуществляется через специальный OPC сервер.
Общие сведения о modbus сети
ModBus сеть объединяет одно ведущее (мастер) и несколько ведомых (слейвов). Обмен данными в сети происходит по инициативе мастера. Он может отправить запрос одному из подчинённых устройств или широковещательное сообщение сразу всем ведомым устройствам сети.
После отправки запроса мастер ожидает ответ в течение заданного времени («время таймаута»). Если в течение этого времени ответ не получен, мастер считает, что связь с ведомым отсутствует. На широковещательное сообщение ответ не предусмотрен.
Слейвы (ведомые устройства) не могут самостоятельно инициировать передачу данных. Они могут передать данные только после запроса мастера (и только те данные, которые мастер запросит).
Существует три разновидности протокола:
- ModBus ASCII — разновидность протокола, в которой сообщения кодируются с помощью ASCII-символов. Сообщения разделяются символами «:» и CR/LF. Не очень удобен, в России используется крайне редко.
- ModBus RTU — разновидность протокола, в которой сообщения кодируются «как есть» (числами). Между собой сообщения разделяются временной паузой в 3,5 символа при заданной скорости передачи.
- ModBus TCP — разновидность протокола для работы поверх TCP/IP стека, требуется при соединении устройств по Ethernet.
Тестирование устройств с поддержкой modbus rtu в рамках процесса разработки
Как при разработке, так и при наладке устройств с поддержкой протокола Modbus RTU, вам необходимо иметь специализированное программное обеспечение и технические средства. Из технических средств наиболее простой вариант — это преобразователь RS-485/USB, из всех устройств такого типа, по нашему мнению, наилучшим выбором является MOXA UPORT 1130/UPORT 1150, цена вопроса которого составит 5000 — 6000 руб.
Существуют различные отечественные решения, например, преобразователи фирмы Fractal или ОВЕН. Конструкция этих устройств достаточно проста, и при определенной сноровке такой преобразователь можно собрать самостоятельно. Более сложными являются решения типа Ethernet/RS-485 (например, NPORT от MOXA).
При разработке устройств с поддержкой Modbus RTU, чаще всего требуется реализовать функцию Slave, так как в основном это различные датчики, управляемые реле, модули ввода/вывода и т.п., Master-устройства создаются реже. В сетях автоматизации в качестве мастера, обычно выступает контроллер, а он, как правило, уже имеет реализацию Modbus-стека, либо OPC Server/SCADA система, укомплектованные Modbus-драйвером.
Вопрос разработки непосредственно Modbus-стека мы не будем рассматривать в этой статье. Единственное, стоит отметить библиотеку FreeMODBUS, на базе которой достаточно просто построить устройство с поддержкой функций Modbus Slave. Пример реализации описан в статье на Хабре.
Вторым важным моментом при разработке Modbus-устройств является тестирование. Здесь всё зависит от стадии разработки и цели тестирования.
На начальных этапах полезным инструментом является Modbus-терминал. С помощью него мы можем вручную сконструировать запрос, послать его и проанализировать ответ. Существуют терминалы в чистом виде, например, SmartTerminal, Access Port, терминалы с поддержкой Modbus RTU — Termite от S2-Team или Pic18 Terminal от Fractal (не обновлялась с 2006 года) и т.п.
В процессе разработки нередко возникает ситуация, когда устройство принимает запрос и отвечает на него (это можно понять либо по светодиодам приема/передачи пакетов, если вы их предусмотрели в конструкции, либо через отладчик, поставив breakpoint в нужном месте), а в терминале или какой-то другой специализированной программе, данные не отображаются.
В таком случае вам пригодится сниффер для последовательного порта, желательно, с поддержкой протокола Modbus. В качестве примера можно привести Free Serial Analyzer, COM Port Toolkit. Последний в настоящее время, похоже, прекратил свое развитие.
В дальнейшем, требуется не только проверять работает ли устройство в принципе (т.е. корректно отвечает на запросы), но и определять наработку на отказ с помощью длительного тестирования. Важными аспектами здесь являются поддержка авто-опроса с изменяемой нагрузкой (количество запросов в секунду) и наличие функции логирования.
Следует учитывать, что собранные логи нужно будет анализировать, то есть определять количество запросов, на которые устройство не ответило, обнаруживать сбои, например, самопроизвольное изменение данных в ячейках и т.п. Конечно, можно использовать полноценную SCADA-систему, либо самому разработать и написать систему анализа и визуализации логов.
Как вариант, рекомендуем обратить внимание на MasterSCADA от Insat. Она имеет встроенный Modbus-драйвер и версия до 32 точек является бесплатной, довольно проста в освоении (на сайте производителя есть хорошая документация и видео уроки).
В конце данной статьи мы определим список функций “идеального” инструмента для тестирования и наладки устройств/систем на базе протокола Modbus, а также сделаем небольшой обзор существующих инструментов.
Типы данных modbus
Любой узел сети ModBus — это интеллектуальное устройство (контроллер, регулятор, датчик и др.). Согласно спецификации узел сети может иметь следующие структуры данных:
- Discrete Inputs — состояния дискретных входов устройства, их можно только прочитать. Однобитовый тип данных.
- Coils — состояния дискретных выходов устройства, их можно прочитать и изменить (записать новое состояние). Однобитовый тип.
- Input Registers — 16-битные регистры, доступные только для чтения.
- Holding Registers — 16-битные регистры свободного назначения, доступны для чтения и записи.
Указанные типы данных необязательны для всех устройств, поддерживающих ModBus. Например, Discrete Inputs и Coils характерны больше для ПЛК.
Производитель устройства сам решает, какой тип данных сделать доступным для чтения и записи по ModBus, и об этом написано в руководстве устройства. В большинстве случае пользуются типом Holding Registers, поскольку он самый универсальный.
Функции modbus
Номер функции определяет тип запрашиваемых данных и что с ними нужно сделать (прочитать/записать).
Функций ModBus достаточно много и они разделены на три категории:
- стандартные — функции, описанные в стандарте протокола. Среди них много устаревших и неиспользуемых.
- пользовательские — диапазон номеров функций (с 65 по 72 и с 100 по 110), которые может использовать любой производитель устройств для реализации своих специфичных функций. При этом вполне возможно, что у устройств различных производителей под одинаковыми номерами будут разные по смыслу функции.
- зарезервированные — функции, не описанные в базовом стандарте, но реализованные в устройствах различных производителей. При этом гарантируется, что данные производители зарезервировали эти номера для себя и другие производители не могут ими воспользоваться.
Однако, это всё лирика… На практике в большинстве случаев используются всего несколько функций, мы подробно поговорим о них в отдельной статье, а в этой будем рассматривать всё на примере функции Read Holding Registers (чтение регистров общего назначения).
Функция Read Holding Registers (0x03)
Функция под номером 3 — одна из самых употребимых функций, предназначена для чтения регистров общего назначения устройства.
В запросе указывается количество регистров, которые нужно прочитать и адрес первого из них.
Ответ содержит количество байт (количество регистров умноженное на 2) и значения запрошенных регистров.
Как послать команду modbus rtu на чтение дискретного вывода? команда 0×01
Эта команда используется для чтения значений дискретных выходов DO.
В запросе PDU задается начальный адрес первого регистра DO и последующее количество необходимых значений DO. В PDU значения DO адресуются, начиная с нуля.
Значения DO в ответе находятся в одном байте и соответствуют значению битов.
Значения битов определяются как 1 = ON и 0 = OFF.
Младший бит первого байта данных содержит значение DO адрес которого указывался в запросе. Остальные значения DO следуют по нарастающей к старшему значению байта. Т.е. справа на лево.
Если запрашивалось меньше восьми значений DO, то оставшиеся биты в ответе будут заполнены нулями (в направлении от младшего к старшему байту). Поле Byte Count Количество байт далее указывает количество полных байтов данных в ответе.
Пример запроса DO с 20 по 56 для SlaveID адреса устройства 17. Адрес первого регистра будет 0013 hex = 19, т.к. счет ведется с 0 адреса (0014 hex = 20, -1 смещение нуля = получаем 0013 hex = 19).
Состояния выходов DO 27-20 показаны как значения байта CD hex, или в двоичной системе 1100 1101.
В регистре DO 56-52 5 битов справа были запрошены, а остальные биты заполнены нулями до полного байта (0001 1011).
| Каналы | — | — | — | DO 56 | DO 55 | DO 54 | DO 53 | DO 52 |
|---|---|---|---|---|---|---|---|---|
| Биты | 0 | 0 | 0 | 1 | 1 | 0 | 1 | 1 |
| Hex | 1B | |||||||
