Последние темы Поиск
Общие форумы
Форумы поддержки портала iXBT.com
Специализированные форумы
ПроцессорыРазгон и охлаждениеСистемные платыМодули памятиВидеосистемаКриптовалюты, майнинг, blockchain-технологии, NFTИскусственный интеллект: технологии, практика, развитиеTV- и FM-тюнеры, видеовход, видеовыходЦифровое видео: захват, монтаж, обработкаМониторы и другие устройства отображенияЦифровое фотоБеспилотные летательные аппаратыЦифровой звукProAudio: Профессиональное звуковое оборудованиеСтереосистемыДомашний кинотеатр: проигрыватели и источники сигналаДомашний кинотеатр: аудиосистемаДомашний кинотеатр: ТV и проекторыМагнитные и SSD накопителиОптические носители информацииСетевые носители информацииПериферияКорпуса, блоки питания, UPSСети, сетевые технологии, подключение к интернетуСистемное администрирование, безопасностьСерверыНоутбуки, нетбуки и ультрабукиПланшеты и электронные книгиМобильные телефоны, смартфоны, кпк, коммуникаторыМобильные гаджетыОператоры и технологии мобильной связиТелефония, телекоммуникации, офисные АТСБытовая техника
Программы
Игры
Авторские форумы
Прочие форумы
Архивы конференции
Архив "О Конференции"Архив "Процессоры"Архив "Разгон и охлаждение"Архив "Системные платы"Архив "Модули памяти"Архив "Видеосистема"Архив "Видеозахват"Архив "Мониторы и другие устройства отображения"Архив "Цифровое изображение"Архив "Цифровой звук"Архив "Периферия"Архив "Корпуса, блоки питания, UPS"Архив "Коммуникации: сети и сетевые технологии"Домашний интернет, модемы (архив)Архив "Системное администрирование, безопасность"Архив "Мобильная связь"Программы Microsoft: Windows, Office, Server, Windows LiveАрхив "OС и системное ПО"Архив "Программы: Интернет"Архив "Программирование"Форум прикладных программистовАрхив "Электронные устройства и компоненты"Архив "Околокомпьютерный Флейм & Общий"Архив "Полемика (Злобный Флейм)"Околоавтомобильный ФлеймФорум ремонтниковВопросы компании IntelФотокамеры SamsungФорум о магазине приложений RuStoreФорум по продукции компании Huawei
Справка и сервисы
Другие проекты iXBT.com
Страницы:Кликните, чтобы указать произвольную страницу123далее
Reanimator++: Modbus
Reanimator++
Member
Автор темы
1487/2167 ответов
22 года на iXBT, с марта 2002
11 фото на iXBT.photo
Чаще пишет в "Эл. устройства" (68%)
Россия, Волгоград
Инфо Ответить
R
Reanimator++ MemberАвтор темы
8 лет назад / 21 июля 2017 12:20
Поскольку протокол пользуется завидной популярностью предлагаю обсуждать нюансы реализации здесь.

Возникла у нас задача перевести ряд девайсов на Modbus RTU с самопальных протоколов.
Основной камень - PIC32. Интерфейс - RS-232, RS-485.

Выбрана была библиотека FreeModbus. Поскольку порта по PIC32 не было, он был написан.
Основной функционал работает, далее полезли в нюансы.

Вопросов пока два:

1. Как корректно работать с данными при ошибке ILLEGAL DATA ADDRESS при групповом запросе на запись?
Т.е. допустим, мастер подал команду на запись группы регистров, одного либо нескольких из которых не существует.
Будет возвращена ошибка ILLEGAL DATA ADDRESS.
Корректно ли произвести запись тех данных из пакета, регистры для которых существуют или нет?
(мы пока склоняемся что нет)

2. В каком случае должна появиться ошибка ILLEGAL DATA VALUE ?
Мы по первости влупили туда проверку валидности значения, потом поняли что это неверно (нарушает иерархию протокол/приложение).
Сейчас высказывается предположение, что данная ошибка должна быть выведена при попытке неполной записи групп регистров.
Например, мы обзываем некоторые пары регистров float-ами или некоторые четверки double-ами.
Попытка частичной записи этой пары или четверки должна привести к ошибке ILLEGAL DATA VALUE.

Цитата из RFC:

02
ILLEGAL DATA ADDRESS
The data address received in the query is not an
allowable address for the server (or slave). More
specifically, the combination of reference number
and transfer length is invalid. For a controller with
100 registers, the PDU addresses the first
register as 0, and the last one as 99. If a request
is submitted with a starting register address of 96
and a quantity of registers of 4, then this request
will successfully operate (address-wise at least)
on registers 96, 97, 98, 99. If a request is
submitted with a starting register address of 96
and a quantity of registers of 5, then this request
will fail with Exception Code 0x02 “Illegal Data
Address” since it attempts to operate on registers
96, 97, 98, 99 and 100, and there is no register
with address 100.
03
ILLEGAL DATA VALUE
A value contained in the query data field is not an
allowable value for server (or slave). This
indicates a fault in the structure of the remainder
of a complex request, such as that the implied
length is incorrect. It specifically does NOT mean
that a data item submitted
for storage in a register
has a value outside the expectation of the
application program, since the MODBUS protocol
is unaware of the significance of any particular
value of any particular register.
niXto
Best Engineer 2013
9268/10529 ответов
15 лет на iXBT, с июня 2009
Чаще пишет в "Эл. устройства" (89%)
Беларусь
Инфо Ответить
n
niXto Best Engineer 2013
8 лет назад / 21 июля 2017 18:19
1 отклонять пакет, т.к. это глюк Мастера, потому что правильно работающий Мастер в принципе не может подать такую команду

2 если значения выходят за пределы мин-макс регистра (если установлено), и отклонять весь пакет
KaVc
Best Engineer 2016
916/940 ответов, #3 в рейтинге
14 лет на iXBT, с января 2011
4 фото на iXBT.photo
Чаще пишет в "Эл. устройства" (95%)
Россия, Реутов
Инфо Ответить
K
KaVc Best Engineer 2016
8 лет назад / 21 июля 2017 19:18
Reanimator++
Корректно ли произвести запись тех данных из пакета, регистры для которых существуют
Нет, хотя бы из соображений безопасности и дуракоустойчивости.

По второму пункту склоняюсь к интерпретации о неверной размерности содержимого.
Dismon
Member
3254/3724 ответов, #16 в рейтинге
23 года на iXBT, с марта 2001
Чаще пишет в "Эл. устройства" (90%)
Россия, Волгодонск
Инфо Ответить
D
Dismon Member
8 лет назад / 21 июля 2017 19:19
Reanimator++
Корректно ли произвести запись тех данных из пакета, регистры для которых существуют или нет?
(мы пока склоняемся что нет)

Вопрос интересный. Но предварительно замечание (не в смысле замечания, которое исправить, а примечание, которое стоит обдумать). Регистр может не только отсутствовать, он может быть предназначен только для чтения. Относить ли эту ошибку к "неверному адресу регистра" или же "подчинённый не смог выполнить команду"? Касательно же неверного адреса... Если рассуждать
логически: пакет пришел - если адрес слэйва правильный - если КС правильна - если команда "запись группы регистров - если параметры команды корректны - выполнить команду - сформировать ответ - отослать ответ. Т.е. по логике если команда содержит некорректные параметры в виде несуществующего регистра - надо выдавать ошибку адреса.


Мы по первости влупили туда проверку валидности значения
[i]потом поняли что это неверно (нарушает иерархию протокол/приложение).

Хм... а каким это образом? Просто интересно.

Сейчас высказывается предположение, что данная ошибка должна быть выведена при попытке неполной записи групп регистров. Например, мы обзываем некоторые пары регистров float-ами или некоторые четверки double-ами.
Опять же, рассуждая логически - формат кадра модбаса (скажем, РТУ) расписан в стандарте. Это адрес, команда, данные (они же параметры команды), КС. Причём данные - 16бит двоичные числа, в порядке старший-младший. Никаких флоатов и даблов. Протокол MODBUS не знает о представлении какого-либо значения конкретного регистра. Превращение потока двоичных данных в флоат, дабл и любой другой тип - вопрос сугубо интерпретации слэйва или мастера. Вот например, есть некая переменная, пусть флоат, 4 байта. Считая её за регистр, когда приходит команда "прочитать регистр", в ответ ожидается два байта данных, а переменная занимает 4. Иными словами, происходит несовпадение длины ожидаемых данных с длиной фактической посылки. Об этом же прямо говорится и в стандарте: "such as that the implied length is incorrect. It specifically does NOT mean that a data item submitted for storage in a register has a value outside the expectation of the application programm".

Таким образом, утверждение
Попытка частичной записи этой пары или четверки должна привести к ошибке ILLEGAL DATA VALUE.
Не совсем корректно, так как попытки записи не должны предприниматься, и данная ошибка должна формироваться ещё ДО попытки. И тем более, никаких частичных записей.

Добавление от 21.07.2017 19:26:

niXto
1 отклонять пакет, т.к. это глюк Мастера, потому что правильно работающий Мастер в принципе не может подать такую команду
Отклонять пакет, адресованный этому конкретно слэйву если КС совпадает - нельзя, нарушение стандарта - любой правильно переданный пакет требует ответа.

если значения выходят за пределы мин-макс регистра (если установлено)
Глупости. В стандарте ясно сказано: "It specifically does NOT mean that a data item submitted
for storage in a register has a value outside the expectation of the application program, since the MODBUS protocol is unaware of the significance of any particular value of any particular register. ", что означает "Это НЕ означает, что элемент данных, представленный для хранения в регистре, имеет значение вне ожиданий прикладной программы, поскольку протокол MODBUS не знает о значении какого-либо конкретного значения какого-либо конкретного регистра."
Reanimator++
Member
Автор темы
1488/2168 ответов
22 года на iXBT, с марта 2002
11 фото на iXBT.photo
Чаще пишет в "Эл. устройства" (68%)
Россия, Волгоград
Инфо Ответить
R
Reanimator++ MemberАвтор темы
8 лет назад / 21 июля 2017 20:46
Dismon
Благодарю вас, а также остальных за развернутый ответ, по 1 пункту считаем мнение единогласным - писать нельзя.
Действительно, из соображений дуракоустойчивости.

По 2 пункту попробуем развернуться.
Расскажу как пришли.

ПО стараемся выполнять модульно, в стиле многозадачности, хотя и используется суперцикл (по сути кооперативная многозадачность).
Т.е. каждая задача выполняет исключительно свою работу и хранит свои переменные по возможности внутри себя.
Взаимодействие между задачами осуществляется через так называемые public переменные (программируя на С придерживаемся архитектуры ООП). У задачи есть доступная извне структура (аналог класса), в которой находится большинство ее public данных.

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


Далее к сути вопроса.
По ошибке ILLEGAL DATA VALUE я смог нагуглить следующие варианты возникновения:
- ответ на запрос с длиной посылки равной 0 либо более 254 (?) байт
- ответ на попытку записи если девайс находится в locked mode (ну или какой либо другой вариант режима работы устройства когда куда-то писать нельзя)

По объединению данных в пары и четверки я соглашусь что это нарушает первооснову протокола, и это не совсем транспортный уровень.
Однако, данная ошибка предполагает ссылку на особенности Slave-а и как раз в данном случае ее можно было бы применить (на мой взгляд).
Т.е. Slave считает что данная группа регистров должна писаться/читаться только кучкой (во избежание) и накладывает таким образом ограничение на работу с ними.
Корректно?
Dismon
Member
3255/3725 ответов, #16 в рейтинге
23 года на iXBT, с марта 2001
Чаще пишет в "Эл. устройства" (90%)
Россия, Волгодонск
Инфо Ответить
D
Dismon Member
8 лет назад / 22 июля 2017 10:39
Reanimator++
По ошибке ILLEGAL DATA VALUE я смог нагуглить следующие варианты возникновения:
- ответ на запрос с длиной посылки равной 0 либо более 254 (?) байт


Ну, это как раз несоответствие длины, про которое говорится в стандарте. 254 наверное потому что данные (ну, для модбас рту) = 16 бит. адрес слэйва + команда = 16 бит, КС = 16 бит. Словом всё кратно 2 байтам.

- ответ на попытку записи если девайс находится в locked mode (ну или какой либо другой вариант режима работы устройства когда куда-то писать нельзя)
А вот с этим совершенно не согласен. Допустим у слэйва 10 регистров. Запрос слэйву пришел. Кадр правильный, КС совпадает. В кадре команда 3 - чтение регистра 5 (чисто для примера), число регистров - 1. Т.е. запрос абсолютно корректен, дошел без искажений, а слэйв ему в ответ "неверное значение данных"? Бред же явный. Для таких ситуаций существуют другие ошибки, и в данном случае, как мне кажется, уместней 0х06 - SLAVE DEVICE BUSY, если слэйв выполняет ранее отданную команду и не готов принять новую, либо 0х04 - FAILURE IN ASSOCIATED DEVICE.

Вообще же есть такой документ "MODBUS APPLICATION PROTOCOL SPECIFICATION V1.1b" (может быть есть и новее версия, но мне этой хватает ), там всё подробно расписано, даже приведены блок-схемы алгоритмов работы, как в общем виде:
595x623, 48,4Kb
так и для всех функций, вот например для функции 0х03:
652x646, 57,1Kb

Сразу ясно, что, куда и зачем.
К сообщению приложены файлы:
Reanimator++
Member
Автор темы
1489/2169 ответов
22 года на iXBT, с марта 2002
11 фото на iXBT.photo
Чаще пишет в "Эл. устройства" (68%)
Россия, Волгоград
Инфо Ответить
R
Reanimator++ MemberАвтор темы
8 лет назад / 22 июля 2017 15:18
Это называется - если ничего не получается, прочитайте наконец инструкцию!

В стандарте данный код ошибки предполагает неверную длину, и непонятные проверки того что двухбайтное целое не меньше 0 и не больше FFFF (зачем они это писали?).

Кстати выдавать 03-ILLEGAL DATA VALUE по запрету записи придумал не я а Шнайдер -
http://www.schneider-electric.com/en/faqs/FA211952/
Нагуглилось оно...

Ну да ладно, можно сделать по стандарту и положить на 03 ошибку только неверную длину пакета.


Но тем не менее, работать с группами регистров хочется. (float, double, long long, и т.п.)

Разрешать писать float порегистрово? - непонятно когда считать запись завершенной. Плюс атомарность процесса нарушается. Надо будет где-то хранить все незавершенные записи перед тем как передавать принятое значение в Application.

Еще есть риск что будет записано вообще не float (есть запрещенные комбинации) и можно здорово подвесить обработчик.

Можно таки запретить неатомарную запись групп и более корректно ошибку 04 туда ткнуть?
Или есть еще варианты?
Как решаете?
alexey_public
Member
17414/17693 ответов, #4 в рейтинге
21 год на iXBT, с марта 2004
121 фото на iXBT.photo
Чаще пишет в "Эл. устройства" (98%)
Беларусь, Минский район
Инфо Ответить
alexey_public Member
8 лет назад / 22 июля 2017 16:25
Reanimator++
Или есть еще варианты?
Я бы воткнул после записи float еще один регистр - в него можно CRC16 закинуть, запись туда будет подтверждением что пришли все 6 байт, а содержимое 5-гои 6-го байта - контролем верности принятых первых 4 байт данных.
Reanimator++
Member
Автор темы
1490/2170 ответов
22 года на iXBT, с марта 2002
11 фото на iXBT.photo
Чаще пишет в "Эл. устройства" (68%)
Россия, Волгоград
Инфо Ответить
R
Reanimator++ MemberАвтор темы
8 лет назад / 22 июля 2017 21:24
alexey_public
Ну это можно делать если клиент и сервер самопальные. Тогда да, добавляй что угодно.
Возьмем тот же Modbus Poll.
Выбираем регистры, выбираем тип float, жмем запись. Никаких дополнительных расчетов CRC он делать не будет, просто вкинет группу регистров.
Нужно чтобы устройством можно было воспользоваться путем применения стандартных программных средств.
Вопрос больше в правильной интерпретации протокола и умолчаний стандарта, которые де факто применяются.
alexey_public
Member
17416/17695 ответов, #4 в рейтинге
21 год на iXBT, с марта 2004
121 фото на iXBT.photo
Чаще пишет в "Эл. устройства" (98%)
Беларусь, Минский район
Инфо Ответить
alexey_public Member
8 лет назад / 23 июля 2017 00:14
Reanimator++
Ну это можно делать если клиент и сервер самопальные. Тогда да, добавляй что угодно.
А они в любом случае самопальные. Если ты хочешь чтобы что-то писало куда-то писало именно тебе, то ему нужно знать не только протокол Modbus, но и много чего еще для записи того же float - например порядок байт, т.к. в самом modbus такого типа нет и порядок байт для него не фиксирован. Одним словом если тебе кто-то посылает float - то он уже является чем-то нестандартным, а значит добавить CRC вполне реально.
В случае когда используется библиотека modbus для обмена - то ей просто скармливают байты float и говорят - мол эти 4 байта по такому-то адресу, никто не мешает добавить к ним еще 2 байта CRC и попросить отослать 6 байт по этому адресу.
Dismon
Member
3258/3728 ответов, #16 в рейтинге
23 года на iXBT, с марта 2001
Чаще пишет в "Эл. устройства" (90%)
Россия, Волгодонск
Инфо Ответить
D
Dismon Member
8 лет назад / 23 июля 2017 01:41
Reanimator++
Кстати выдавать 03-ILLEGAL DATA VALUE по запрету записи придумал не я а Шнайдер
Не стоит путать "Modbus plus" от Шнайдера с "исконным" модбасом. От Шнайдера появился позже, когда они купили фирму - разработчика. Тем не менее, стандартом стал "исконный" , а не улучшенный Шнайдером.

Но тем не менее, работать с группами регистров хочется. (float, double, long long, и т.п.)
Есть такое понятие "команды пользователя". В них можно писать что угодно, как угодно, естественно оставаясь в рамках формата кадра и его максимальной длины. Однако следует помнить, что нет никаких гарантий, что другие устройства не будут использовать тот же самый код команды для выполнения другой функции.

Разрешать писать float порегистрово? - непонятно когда считать запись завершенной.
Как когда? Тогда и только тогда, когда запишешь или прочитаешь указанное в запросе число 16-битных регистров. В очередной раз повторяю - модбас оперирует только с регистрами 16-бит, т.е числами от 0x0000 до 0хFFFF. Других типов данных он просто не знает.

alexey_public
Я бы воткнул после записи float еще один регистр - в него можно CRC16 закинуть, запись туда будет подтверждением что пришли все 6 байт, а содержимое 5-гои 6-го байта - контролем верности принятых первых 4 байт данных.
А это уже будет что угодно, но только не модбас.

ЗЫ: Ви таки не понимаете, что есть модбас. А модбас есть очень старый протокол опубликованный аж в 1979г, предназначенный для передачи сообщений между ПЛК. И естественно, он сделан с учётом возможностей того времени. Собственно, как я понимаю, ребята выпускавшие ПЛК разработали протокол для связи своих устройств между собой, и не собирались делать его общим стандартом. Просто он оказался простой, надёжный (по требованиям того времени), и самое главное - за его использование не просили денег. Но потому что он разрабатывался под определённые устройства конкретной архитектуры ему свойственно "странное" расположение байт данных - старший-младший - просто в такой нотации хранились данные в вычислителе ПЛК (чисто предположение). И вся "обработка" сводилась к копированию данных последовательно из буфера приёма в область памяти переменных или наоборот (однобитовые значения флагов и входов упаковывались в те-же 16 бит).
Иными словами, модбас просто передаёт область памяти переменных определённой длины с определённого адреса. Из этого же и общей "древности" вытекают и остальные его недостатки: ограничения по типам передаваемых данных, ручная индивидуальная настройка перед включением в сеть (назначение сетевых адресов и т.п.), работа только в режиме запрос-ответ с каждым устройством индивидуально (т.е. слэйв не может сам по своей инициативе отправить мастеру сообщение), ограничение в длине кадра, данные (регистры) должны быть расположены последовательно, слэйв никогда не узнает, что связь потеряна, он будет тупо и бесконечно ждать запроса... В общем недостатков море. Но это увы стандарт.

Как решаете?
Я лично обёртываю переменные и "регистры модбас" (массив байт) в юнион, примерно так:
01typedef struct                    // описание структуры "уставок"
02{
03  unsigned int DeviceCmd;         // 0x0000 команда извещателю
04  unsigned int DeviceStatus;      // 0x0001 состояние извещателя
05  unsigned int SelfTestInterval;  // 0x0002 интервал самотестирования, минут
06  unsigned int AlarmPeriod;       // 0x0003 длительность анализируемого периода для тревог, секеунд
07  unsigned int DeviceAdress;      // 0x0004 адрес устройства в сетях модбас
08  float koef0;                          // 0х0005, 0х0006 - коэффициент фильтрации
09  unsigned int AlarmCountUV;      // 0x0007 предел счётчика УФ-тревог, превышение - тревога
10} Tset;
11  
12typedef struct                    // описание структуры глобальных переменных
13{
14  unsigned char AlarmCountUV;     // счётчик тревог по УФ каналу
15  unsigned char AlarmPeriod;      // период тревог
16} Tvar;
17  
18typedef union                     // обёртываем структуры юнионом и асоциируем с массивом байт
19{
20  struct
21  {
22    Tset set;
23    Tvar var;
24  };
25  
26  unsigned char bytes[sizeof(Tset)];        // массив байт
27  
28} TData;
29  
30volatile TData  Data;                                      // системные переменные
В программе имеется набор переменных (set), в которых хранятся уставки, настройки и т.п. Эти переменные - изменяемые, а значит их значения должны читаться и записываться через модбас.
Так же в программе есть просто глобальные переменные var (контроллер 8 бит потому они char). Область set в юнионе асоциируется с массивом байт, которые условно можно обозвать таблицей регистров модбас. Естественно, должно соблюдаться правило кратности размера set двум байтам.
Хотим записать уставку AlarmPeriod, скажем 5. Формируем запрос : 01 06 00 03 00 05 хх хх, где хххх - КС. Слэйв принимает запрос (полагаем что адрес и КС правильные), и выполняет его, копируя два байта из буфера в область памяти, условно запишем:

Data.bytes[3*2]=buferUART[4];
Data.bytes[3*2+1]=buferUART[5];

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

Точно так же меняется значение koef0, например хотим записать в него 0, запрос 01 10 00 05 00 02 04 00 00 00 00 хх хх, и, соответственно слэйв возьмёт из буфера 4 байта, и последовательно разместит их с адреса Data.bytes[5*2], тем самым приравняв переменную флоат к нулю.

Кроме модбаса такая обёртка удобна при записи уставок в епром, пишем условно eeprom_read(&Data.bytes[0], sizeof(Tset)); И можем спокойно добавлять-удалять переменные уставки, не заморачиваясь изменениями числа байт, записываемых в еепром.

Добавление от 23.07.2017 01:56:

alexey_public
никто не мешает добавить к ним еще 2 байта CRC и попросить отослать 6 байт по этому адресу.
И, в соответствии со стандартом, слэйв запишет 6 байт в память, приняв число тип флоат и "загадив" следующую за ним переменную, хоть и специально выделенную под "загаживание" КС. Ну вот объясни, ЗАЧЕМ пихать ещё одну КС, если есть КС всего пакета? Причём не простая КС, тупое сложение, а вполне себе полином? При этом ты предлагаешь "записать 3 регистра с адреса ХХ", вместо "записать 2 регистра с адреса ХХ". Какой в этом смысл?

Исправлено: Dismon, 23.07.2017 02:05

alexey_public
Member
17418/17697 ответов, #4 в рейтинге
21 год на iXBT, с марта 2004
121 фото на iXBT.photo
Чаще пишет в "Эл. устройства" (98%)
Беларусь, Минский район
Инфо Ответить
alexey_public Member
8 лет назад / 23 июля 2017 05:39
Dismon
Ну вот объясни, ЗАЧЕМ пихать ещё одну КС, если есть КС всего пакета?
Потому что это совсем разные вещи. Речь идет про float на 4 байта, которого в стандарте нет, а не про пакет Modbus, это уже уровень выше. И если мы примем только 3 байта из 4 - причем по какой-то причине придут именно 3 байта, то вот тут нам и нужна защита, нужна гарантия что будут записаны все 4 байта и записаны верно.
Т.е. сама КС float - это уже не modbus, это протокол для передачи float над modbus. Он просто передаст 6 байт на уровень modbus и попросит их отправить. А там как сложится.
Dismon
Member
3260/3730 ответов, #16 в рейтинге
23 года на iXBT, с марта 2001
Чаще пишет в "Эл. устройства" (90%)
Россия, Волгодонск
Инфо Ответить
D
Dismon Member
8 лет назад / 23 июля 2017 07:31
alexey_public
Потому что это совсем разные вещи.
Мдя... как не хватает среди смайлов фэйспалма... Ладно. Попробуем иначе.

Речь идет про float на 4 байта
Чем отличается одно флоат от от четырёх чаров на осциллограмме при передаче в линии связи (обвязку данных в виде адреса и прочей информации пока не трогаем)?

И если мы примем только 3 байта из 4 - причем по какой-то причине придут именно 3 байта,
Ка-ра-шо. Мастер посылает запрос 01 10 00 05 00 02 04 00 00 00 00 хх хх. По какой-то причине вместо 4х байт данных (флоат, да) 00 00 00 00 приходят именно 3. Вопрос: совпадёт ли принятая контрольная сумма с той, что получится у слэйва, когда он её посчитает?
alexey_public
Member
17420/17699 ответов, #4 в рейтинге
21 год на iXBT, с марта 2004
121 фото на iXBT.photo
Чаще пишет в "Эл. устройства" (98%)
Беларусь, Минский район
Инфо Ответить
alexey_public Member
8 лет назад / 23 июля 2017 11:06
Dismon
По какой-то причине вместо 4х байт данных (флоат, да) 00 00 00 00 приходят именно 3. Вопрос: совпадёт ли принятая контрольная сумма с той, что получится у слэйва, когда он её посчитает?
Не совпадет, запишутся 3 байта к примеру, хотя в терминах modbus правильнее сказать - 2 байта, это будет верно. 3 байта - ошибка.
Пусть пришло только 2 байта из 4. После чего modbus отправляет их наверх, наверху сравнивают 4 байта, 2 принятых, 2 старых, и еще 2 старых байта КС - не сходится. Откидываем.

alexey_public
сама КС float - это уже не modbus, это протокол для передачи float над modbus.
Dismon
Member
3262/3732 ответов, #16 в рейтинге
23 года на iXBT, с марта 2001
Чаще пишет в "Эл. устройства" (90%)
Россия, Волгодонск
Инфо Ответить
D
Dismon Member
8 лет назад / 23 июля 2017 14:13
alexey_public
сама КС float - это уже не modbus, это протокол для передачи float над modbus.
И? Опять цитирую себя:
Dismon
А это уже будет что угодно, но только не модбас

Вопрос-то не в том, модбас или не он. Я спрашиваю, накуя пихать в кадр ещё одну КС для передаваемых данных.

Но будем последовательны. Итак, если что-то случилось, КС пакета не совпадут (кстати кадры модбас вполне могут быть нечётными, под длину кадра в байтах отводится 1 байт, а не 2, как на остальные данные, в том числе на число регистров ), передаваемая группа из 4 байт, не принята, никакие переменные слэйва не поменялись. Если ничего не случилось, кадр принят без ошибок, что засвидетельствует совпавшая КС. Весь принятый кадр лежит в буфере приёма, и начинается его анализ:
01 - адрес слэйва
10 - код команды "записать группу регистров"
00 05 - номер регистра, с которого писать, и этот номер 5
00 02 - писать 2 регистра
04 - данные занимают 4 байта
00 00 00 00 - собственно 4 байта передаваемых данных, они же должны превратиться во флоат koef0.

Проверяем адрес - адрес слэйва, значит надо отвечать. Поверяем код команды - поддерживаем такой код, проверяем, что стартовый регистр №5 у слэйва есть, что два регистра (№5 и №6) есть, проверяем, что эти регистры не рид-онли, берём длину данных в байтах (4) в счётчик и переносим указанное количество байт (4) в область памяти начиная с адреса Data.bytes[5*2]. И вот тут вдруг оказывается, что мы передали слэйву вещественное значение koef0, и переменная приняла нужное значение.

Ты же зачем-то предлагаешь помимо самого числа koef0, которое хранится в памяти в виде последовательности из 4х байт, добавить ещё переменную, в которой которой за каким-то огородным растением хранится КС этих 4х байт. Потом по модбасу отправить 6 байт слэйву.

Т.е. ты предлагаешь посылать слэйву пакет
01 10 00 05 00 03 06 00 00 00 00 УУ УУ хх хх
вместо
01 10 00 05 00 02 04 00 00 00 00 хх хх

где УУ УУ - контрольная сумма передаваемого числа, и предлагаешь использовать КС этих 4х байт (УУ УУ) для контроля правильности их передачи. Повторяю вопрос: Зачем? Правильность их приёма (то что именно эти значения и послали) проверена контрольной суммой хх хх всего пакета, куда эти данные входят.
Reanimator++
Member
Автор темы
1491/2171 ответов
22 года на iXBT, с марта 2002
11 фото на iXBT.photo
Чаще пишет в "Эл. устройства" (68%)
Россия, Волгоград
Инфо Ответить
R
Reanimator++ MemberАвтор темы
8 лет назад / 23 июля 2017 14:57
Dismon
Давайте немного шире отнесемся к представлениям чисел более регистра.
Поскольку стандарт древний, то в нем это не описано.
Но поскольку он применяется, и людям надо, то они расширяют это представление так как сочтут нужным, и эти нарушения де факто становятся стандартом.
Суть топика в том чтобы сориентироваться в данной ситуации и применить то что сейчас "на волне".

Применение float и других объединенных типов де факто производится всеми, я ориентируюсь на самый популярный отладчик Modbus Poll, который без лишних вопросов поддерживает эти типы (см скриншот).

371x636, 99.3Kb

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

Когда вы читаете/пишете float одним пакетом никаких вопросов не возникает, и все работает без проблем.

Проблемы будут когда вы попытаетесь сделать это порегистрово.
Ситуация для чтения - вы читаете первый регистр, затем второй регистр, а за время между чтениями число немного изменяется (достаточно чтобы перескочить между разрядами в половинках).
Ситуация для записи - вы пишите первый регистр, девайс считает что записан весь float, проверяет значение на допустимость, видит что записано слишком большое число, обрезает его до максимально допустимого в данном регистре, и затем вы пишите вторую половинку float-а...
Данный момент называется атомарность.
Как будет вести себя ваш код, если я попытаюсь писать float половинками?

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

Алексей же предложил добавить байт который будет означать что операция записи завершена. Для чтения это не сработает.
Решение считаю из ряда вон выходящим и предлагаю на нем не останавливаться.
alexey_public
Member
17421/17700 ответов, #4 в рейтинге
21 год на iXBT, с марта 2004
121 фото на iXBT.photo
Чаще пишет в "Эл. устройства" (98%)
Беларусь, Минский район
Инфо Ответить
alexey_public Member
8 лет назад / 23 июля 2017 18:57
Dismon
Повторяю вопрос: Зачем?
Reanimator++
Данный момент называется атомарность.

Для чтения тоже можно продумать подобное. Но опять таки -
Modbus Poll, который без лишних вопросов поддерживает эти типы
Они их фактически не поддерживают, а просто позволяют безконтрольно пересылать. Одним словом - нужен протокол для обмена такими данными.

Не хочется CRC - ладно, ввести еще один регистр контроля операции.
Например, есть регистры для float - штук 5, после записи всех регистров пишем в контрольный не CRC - раз его сложно считать, а код операции высокого уровня - мол все данные обновлены и их можно считать корректными.
Решение простое, суть та же. Возможна работа опять таки при помощи стандартных отладчиков Modbus.
Минус такого решения - нет алгоритма защиты данных, мастер может передать мол данные в порядке, хотя на самом деле это не так. CRC всех данных вместе или одного значения за раз - позволил бы убедиться в корректности данных.
Но других простых способов наверное не будет.
Хотя... Еще как вариант - использовать два регистра подтверждения - для ручной работы и для автоматической. Для ручной передавать простой код, для автоматической - CRC атомарной операции.
Это позволит использовать как ручную работу с регистрами, так и более надежный защищенный вариант.
Ваш ответ:

Нет значка Нет значка Вот тут! Лампочка Восклицание Вопрос Класс! Улыбка Злость Огорчение Поговорим? Краснею Подмигивание Ругаю ОдобряюBIUdelSxsupxsuboffsp spoilerqurlimgvideo• list1. list1 codeprecenter-hr-rusQWE→ЙЦУ
файлыочистить
Ваше имя: Авторизуйтесь Предпросмотр В полную форму
вставить выделенную цитату в окно ответа
Если Вы считаете это сообщение ценным для дискуссии (не обязательно с ним соглашаться), Вы можете поблагодарить его автора, а также перечислить ему на счет некоторую сумму со своего баланса (при отзыве благодарности перечисленная сумма не будет вам возвращена).
Также вы можете оценить сообщение как неудачное.
В течение суток можно 20 раз оценить сообщения разных участников (купите Premium-аккаунт, либо оплачивайте оценки сверх лимита).
Если Вы считаете это сообщение ценным для дискуссии (не обязательно с ним соглашаться), Вы можете поблагодарить его автора, а также перечислить ему на счет некоторую сумму со своего баланса (при отзыве благодарности перечисленная сумма не будет вам возвращена).
Также вы можете оценить сообщение как неудачное.
В течение суток можно 20 раз оценить сообщения разных участников (купите Premium-аккаунт, либо оплачивайте оценки сверх лимита).
Страницы:Кликните, чтобы указать произвольную страницу123далее