Modbus ASCII

Nikitaz
Offline
Зарегистрирован: 10.09.2021

Приветствую всех читающих. Хотел организовать связь Arduino UNO (Master) по rs-485. Отправка пакета осуществляется ASCII символами в 16-м виде.

Пример пакета :010600000057A2CRLF. Если правильно понял, то по таблице ASCII символов нужно переделать каждый символ в 16-й вид, получится 3A 3031 3036 3030 3030 3030 3537 4132 0D 0A. Это все разбить в массив и отправить в устройство.

На GitHub нашел библиотеку, с помощью которой вроде можно осуществить отправку (https://github.com/4-20ma/ModbusMaster/blob/master/examples/RS485_HalfDu...), но не понимаю, где в коде вставлять массив с элементами пакета и как его объявлять.

rkit
Offline
Зарегистрирован: 23.11.2016

Бессмыслицу какую-то написал. Прочитай документацию modbus.

b707
Offline
Зарегистрирован: 26.05.2017

Nikitaz пишет:

 Отправка пакета осуществляется ASCII символами в 16-м виде.

Высказывание, изобличающее вас как самого зеленого новичка, причем даже не в программировании, а в элементраной компьютерной грамотности.

Запомните, компьютеру абсолютно все равно, в каком виде вы запишите в своем скетче ASCII символы - как символы или как коды -  в десятичном, двоичном или шестнадцатиричном виде... Ничего специально преобразовывать не нужно, записи '0', 0x30 и 48 - абсолютно эквивалентны.

 

Цитата:
На GitHub нашел библиотеку,, но не понимаю, где в коде вставлять массив с элементами пакета и как его объявлять.

нигде

Если вы работаете через библиотеку - вам не нужно формировать пакеты Модбас самому, вы задаете только данные. Разберитесь, как работает тот пример, который вы цитируете

SergeiL
SergeiL аватар
Offline
Зарегистрирован: 05.11.2018

Nikitaz пишет:
На GitHub нашел библиотеку, с помощью которой вроде можно осуществить отправку (https://github.com/4-20ma/ModbusMaster/blob/master/examples/RS485_HalfDuplex/RS485_HalfDuplex.ino), но не понимаю, где в коде вставлять массив с элементами пакета и как его объявлять.

Эта библиотека под Modbus RTU.

"This is an Arduino library for communicating with Modbus slaves over RS232/485 (via RTU protocol)."

Причем она с блокировкой с момента начала передачи, до получения ответа или окончания таймаута ожидания приема. Таймаут по умолчанию 2 сек!!!   

Если вам нужен Modbus ASCII нужно искать другую библиотеку. 

Nikitaz
Offline
Зарегистрирован: 10.09.2021

b707 пишет:

Nikitaz пишет:

 Отправка пакета осуществляется ASCII символами в 16-м виде.

Высказывание, изобличающее вас как самого зеленого новичка, причем даже не в программировании, а в элементраной компьютерной грамотности.

Запомните, компьютеру абсолютно все равно, в каком виде вы запишите в своем скетче ASCII символы - как символы или как коды -  в десятичном, двоичном или шестнадцатиричном виде... Ничего специально преобразовывать не нужно, записи '0', 0x30 и 48 - абсолютно эквивалентны.

Может я неправильно выразился, но вот полный текст из спецификации:

"Пример отправки пакета с требованием установить мощность 87% на устройстве с 01 адресом. Выбор адреса осуществляется перемычками на корпусе устройства в соответствии с таблицей.
:010600000057A2CRLF

(значение необходимо передавать в шестнадцатеричном виде стандартными ASCII символами, т. е. значению 0x57 (один байт информации) придется два символа 5 и 7 (4 байта информации) и будет соответствовать мощность 87%. Для мощности 100% необходимо отправить значение 0x64"

Значит ли это, что мне нужно отправлять данные в таком виде? 0x01 0x06 0x00 0x00 0x00 0x57 0xA2?
Или после подсчета контрольной суммы преобразовать сформированный запрос в Char?

 

b707
Offline
Зарегистрирован: 26.05.2017

этого не знаю, я ориентировался на процитированную библиотеку, там никакие строчки в HEX не требуются

sadman41
Offline
Зарегистрирован: 19.10.2016

Нужна библиотека, которая не в MODBUS RTU шлёт пакет, а в MODBUS ASCII. Например: https://github.com/pepsilla/Arduino/tree/master/MODBUS/ASCII/ASCII_RTU

 

SergeiL
SergeiL аватар
Offline
Зарегистрирован: 05.11.2018

Nikitaz пишет:
Значит ли это, что мне нужно отправлять данные в таком виде? 0x01 0x06 0x00 0x00 0x00 0x57 0xA2?

Или после подсчета контрольной суммы преобразовать сформированный запрос в Char?

Нужно сначала посчитать LCR а потом формировать пакет для отправки.

LCR считается по данным до перевода в ASCII и без начального ":".

0x01 0x06 0x00 0x00 0x00 0x57 - это данные для расчета LCR, LCR = 0xA2. 

Потом пакет переводится в ASCII, включая контрольную сумму.

Первым идет признак начала пакета символ ":" (0x3A), заканчивается пакет двумя байтами 0x0D,0x0A.

Но пакет и контрольную сумму, по идее, должна сформировать библиотека. Подсказать какую использовать - не смогу, не использовал Modbus ASCII на мастере. Я сейчас дорабатываю библиотеку Modbus RTU master под себя. 

nik182
Offline
Зарегистрирован: 04.05.2015

Nikitaz пишет:

Пример пакета :010600000057A2CRLF. Если правильно понял, то по таблице ASCII символов нужно переделать каждый символ в 16-й вид, получится 3A 3031 3036 3030 3030 3030 3537 4132 0D 0A. Это все разбить в массив и отправить в устройство...

Не надо ничего переделывать. Достаточно строку :010600000057A2CRLF отправить через Serial.print(":010600000057A2CRLF"); если конечно ответа не надо.

SergeiL
SergeiL аватар
Offline
Зарегистрирован: 05.11.2018

nik182 пишет:

Nikitaz пишет:

Пример пакета :010600000057A2CRLF. Если правильно понял, то по таблице ASCII символов нужно переделать каждый символ в 16-й вид, получится 3A 3031 3036 3030 3030 3030 3537 4132 0D 0A. Это все разбить в массив и отправить в устройство...

Не надо ничего переделывать. Достаточно строку :010600000057A2CRLF отправить через Serial.print(":010600000057A2CRLF"); если конечно ответа не надо.

Признак конца пакета "CRLF" должен быть байтами 0x0D, 0x0A (2 байта) а не символами 'C','R','L','F' (4 байта)

 

nik182
Offline
Зарегистрирован: 04.05.2015

Serial.println(":010600000057A2"); Так лучше?

SergeiL
SergeiL аватар
Offline
Зарегистрирован: 05.11.2018

nik182 пишет:

Serial.println(":010600000057A2"); Так лучше?

Да, так пакет будет корректным. 

Но если передавать готовый пакет, с заранее посчитанной контрольной суммой, наверное будет правильней:

Serial.print(":010600000057A2\r\n");

А для произвольных значений все равно придется считать контрольную сумму, поэтому придется пакет собирать.

 

rkit
Offline
Зарегистрирован: 23.11.2016

Nikitaz пишет:

Может я неправильно выразился, но вот полный текст из спецификации:

А теперь покажи,  где в спецификации присутствутет слово "MODBUS"

Nikitaz
Offline
Зарегистрирован: 10.09.2021

В спецификации нет слов MODBUS, но есть схема, на которой указана связь по RS-485

Nikitaz
Offline
Зарегистрирован: 10.09.2021

sadman41 пишет:

Нужна библиотека, которая не в MODBUS RTU шлёт пакет, а в MODBUS ASCII. Например: https://github.com/pepsilla/Arduino/tree/master/MODBUS/ASCII/ASCII_RTU

 

 

Спасибо за пример. Но автор удалил библиотеку, на которую ссылается в примерах программы, а именно SerialCommand. В общем, скетч не запускается. 

nik182
Offline
Зарегистрирован: 04.05.2015

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

Nikitaz
Offline
Зарегистрирован: 10.09.2021

nik182 пишет:

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

Также тут заданы параметры передачи.

Управление передано блоку RS485. Изменение параметров производится отправкой команд с ПК или ПЛК в виде ASCII символов. Модуль после получения команды модуль отправляет ответ.
Параметры передачи:
Скорость передачи — 9600
Data bits 8
Stop bits 1
Parity — none

Какие по-вашему мнению могут быть другие способы отправки пакета?

SergeiL
SergeiL аватар
Offline
Зарегистрирован: 05.11.2018

Nikitaz пишет:
Может я неправильно выразился, но вот полный текст из спецификации:

"Пример отправки пакета с требованием установить мощность 87% на устройстве с 01 адресом. Выбор адреса осуществляется перемычками на корпусе устройства в соответствии с таблицей.
:010600000057A2CRLF

(значение необходимо передавать в шестнадцатеричном виде стандартными ASCII символами, т. е. значению 0x57 (один байт информации) придется два символа 5 и 7 (4 байта информации) и будет соответствовать мощность 87%. Для мощности 100% необходимо отправить значение 0x64"

Ну а это то откуда вы взяли?

Если из документации к устройству, протокол  - Modbus ASCII over RS485.

SergeiL
SergeiL аватар
Offline
Зарегистрирован: 05.11.2018

sadman41 пишет:

Нужна библиотека, которая не в MODBUS RTU шлёт пакет, а в MODBUS ASCII. Например: https://github.com/pepsilla/Arduino/tree/master/MODBUS/ASCII/ASCII_RTU

Посмотрел библиотеку, основа та же, что и в  https://github.com/jecrespo/simple-modbus

Но от  jecrespo чуть постарше, и в ней только RTU. Видимо pepsilla дописывал ASCII к ней.

Я сейчас под себя правлю эту библиотеку (SimpleModbusMaster от jecrespo).

В принципе она норм, без блокировок, написана с использованием конечного автомата.

SAB
Offline
Зарегистрирован: 27.12.2016

Nikitaz пишет:

Какие по-вашему мнению могут быть другие способы отправки пакета?

Передача данного кода 010600000057A2CRLF выглядит так :

Serial.write(0x30);Serial.write(0x31);Serial.write(0x30);Serial.write(0x36);Serial.write(0x30);Serial.write(0x30);Serial.write(0x30);Serial.write(0x30);Serial.write(0x30);Serial.write(0x30);Serial.write(0x35);Serial.write(0x37);Serial.write(0x41);Serial.write(0x32);Serial.write(0x43);Serial.write(0x52);Serial.write(0x4С);Serial.write(0x46);

Копируй, вставляй в свой код, и получай в обратку результат.

 

nik182
Offline
Зарегистрирован: 04.05.2015

Nikitaz пишет:

nik182 пишет:

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

Также тут заданы параметры передачи.

Управление передано блоку RS485. Изменение параметров производится отправкой команд с ПК или ПЛК в виде ASCII символов. Модуль после получения команды модуль отправляет ответ.
Параметры передачи:
Скорость передачи — 9600
Data bits 8
Stop bits 1
Parity — none

Какие по-вашему мнению могут быть другие способы отправки пакета?


Вот не надо путать тёплое с мягком. Протоколов общения много и они могут работать over 485. При этом есть похожие по содержанию на MODBUS. Если есть в документации точная ссылка на MODBUS, то это одно. А ещё бывает просто частный протокол общения, описанный в документации на устройство. А вот параметры сериальной передачи ни как не могут характеризовать протокол.

sadman41
Offline
Зарегистрирован: 19.10.2016

SAB, Serial.print("\x30\x31 .... \x0D\x0A");

SAB
Offline
Зарегистрирован: 27.12.2016

Согласен, можно и так, но я для топикстартера   чтобы понятнее было написал :)