PDA

Просмотр полной версии : Modbus.lib портиться команда при таймауте



Ovtia
01.12.2021, 07:39
Здравствуйте! Помогите, пожалуйста, разобраться в проблеме.
ПЛК150-220.У.М
Версия таргета: 2.12
Использую библиотеку Modbus.lib для организации Modbus мастера на порту RS-485. Набросал программу на основе примеров с форума. Столкнулся с такой непонятной проблемой: если устройство не успело ответить до таймаута, то следующая Modbus-посылка от мастера будет испорчена: вместо команды от мастера будет выслана часть ответа слейв устройства с прикрепленной к ней чек суммой.
И даже не важно какой ФБ будет вызываться дальше, например: таймаут вышел на блоке MB_RD_HOLD_REGS, а следующим в программе будет запускаться блок MB_WR_REGS, все равно его посылка будет представлять часть предыдущего ответа.
Прикладываю тестовую программу, скриншот программы, скриншот Serial Port Monitor когда проблема возникает и когда нет (если увеличить размер таймаута). В высланной программе проблема проявляется, но вырезано все лишнее и используется только один MB блок.
И еще вопрос, нужно ли делать блоку Enable := FALSE после выполнения? Его наличие или отсутствие никак не влияет на проблему.

Ovtia
01.12.2021, 10:16
50ms
Это не опечатка, это сделано, чтобы сымитировать таймаут на короткой линии на тестовом стенде. В реальности в сети будет 4 ПЛК-слейвов и 1 ПР, расстояние м/у каждым метров по сто, читаться с каждого пара десятков регистров и писаться по несколько. В то же время очень важно иметь минимальный таймаут, т.к. часть оборудования может быть выключена. Хотя на объекте я его конечно подниму. Скорее всего на объекте и 15 мс будет мало и тогда я получу ту же проблему? Может быть я как-то неправильно использую Modbus.lib?


нет

Спасибо понял.

kondor3000
01.12.2021, 11:27
Это не опечатка, это сделано, чтобы сымитировать таймаут на короткой линии на тестовом стенде. В реальности в сети будет 4 ПЛК-слейвов и 1 ПР, расстояние м/у каждым метров по сто, читаться с каждого пара десятков регистров и писаться по несколько. В то же время очень важно иметь минимальный таймаут, т.к. часть оборудования может быть выключена. Хотя на объекте я его конечно подниму. Скорее всего на объекте и 15 мс будет мало и тогда я получу ту же проблему? Может быть я как-то неправильно использую Modbus.lib?


Вы думаете от 100 метров или 5 метров что-то зависит? Во всех примерах стоит 50 мс, и всё работает даже с тысячами переменных. Тут всё от программиста зависит.

Вот вы пишите 4 ПЛК слейвы и 1 ПР. ПР мастером будет? И какой ПР вы хотите мастером сделать?

Ovtia
01.12.2021, 12:07
Вы думаете от 100 метров или 5 метров что-то зависит? Во всех примерах стоит 50 мс, и всё работает даже с тысячами переменных. Тут всё от программиста зависит.

Вот вы пишите 4 ПЛК слейвы и 1 ПР. ПР мастером будет? И какой ПР вы хотите мастером сделать?

Нет, мастером будет именно ПЛК150, на шине еще 4 ПЛК150 и ПР - они слейвы. Их у меня физически нет для тестирования modbus обмена использую МВА8. Здесь я просто демонстрирую проблему с библиотекой Modbus.lib. Я не понимаю, или я упускаю какое-то действие (например очистки буфера), либо с библиотекой какая-то проблема. Неужели это нормально, если ответ пришел вне периода тайм аута, то следующий вызов этого ФБ в библиотеке будет некорректным. Все показано на скриншотах. Дело не в неправильно подобранном периоде тайм аута. Он намеренно выставлен низким, дело в том как обмен рушится, если один из ответов пришел поздно. Если это так и работает, то я просил бы поделиться опытом, как с этим работать, если это зависит только от программиста.

Ovtia
01.12.2021, 12:35
если задача стоит в том чтобы со слейвов прочитать пачкой примерно одинаковый набор данных, то лучше создать фиксированный набор байт, повторяющий пакет запроса модбас и слать его в установленное время в порт, а потом разбирать пришедшие данные без всяких библиотек

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

Ovtia
01.12.2021, 12:58
Начнём с того, что для вашей задачи вообще не нужны библиотеки, освойте сначала конфигурацию. Для ускорения обмена, сгруппируйте подряд регистры.
Разнесите чтение и запись в отдельные UMD (универсал модбас девайс), чтение сделайте циклически, а запись по изменению. Время опроса 10 мс вместо 100.
Ещё для ускорения обмена почитайте пост # 396 petera https://owen.ru/forum/showthread.php?t=22915&page=180
а по поводу опроса МВА8 почитайте тут и мой пост тоже https://owen.ru/forum/showthread.php?t=35094

А по поводу библиотеки, примите за аксиому 50 мс и всё! Что касается ускорения обмена, группировка регистров и чтение циклически, запись по событию. Берёте пример, корректируете регистры и не парьте себе мозг!

Использую библиотеку именно по тому, что не устраивает обмен через конфигурацию: смотрел Serial Port Monitor'ом как работает через конфигурацию: отдельный запрос на каждый регистр - это категорически не устраивает, потому что любой из ПЛК-слейвов может быть отключен, и это не должно сильно влиять на систему в целом, если регистры запрашиваются по одному, то и таймаута ждать от каждого.
Спасибо, советами воспользуюсь, 50 мс не должно быть критично, если для каждого девайса я делаю одну групповую запись и один групповой запрос. Но хотелось бы все-таки услышать мнение по поводу поведения библиотеки modbus.lib.

Ovtia
01.12.2021, 15:41
И у меня не опечатка про "dp1MVA8". МВ8A - 50мс. Таймаут - индивидуальная настройка конкретного девайса. Некоторым 0*мс нормуль.
*У меня другое от этой либы трактование таймаута.
Я согласен. Но, учитывая специфику задачи, хотелось бы во-первых выставить таймауты как можно меньшие, а во-вторых таймаут ответа - величина случайная и легко может может изредка превышать даже установленные с большим запасом пределы, и тогда при использовании этой библиотеки мы получаем вот что. Или это я делаю что-то не так. Мне никто так и не может пояснить. А какое у вас трактование таймаута в этой библиотеке?


Либа позволит легко изменить цикличность "обнаруживающих" запросов.
Т.е. я в программе могу по обнаружению ошибки 255 MB блока уменьшить частоту опроса этим блоком? Да это удобно.


Она ведет себя хорошо и моет руки перед едой. Но как-то раз попросил её сходить за пивом. Отвратительно повела себя - пришла без водки.
Поведение программного компонента описана в документации к библиотеке modbus.lib и порождает ожидания своего поведения исходя из входных и выходных данных своих блоков. Увидеть поведение, описанное мной, программист не ожидает.

Sergey666
01.12.2021, 18:09
Я согласен. Но, учитывая специфику задачи, хотелось бы во-первых выставить таймауты как можно меньшие, а во-вторых таймаут ответа - величина случайная и легко может может изредка превышать даже установленные с большим запасом пределы, и тогда при использовании этой библиотеки мы получаем вот что. Или это я делаю что-то не так. Мне никто так и не может пояснить.

А что объяснять? Устройство "тормоз" отвечает не немедленно, а...когда сможет, а мастер "резкий" уже следующую команду шлет, вот хрень какая-то и получается на шине.

Ovtia
02.12.2021, 04:27
А что объяснять?


Что ожидаете то ?

Объяснить нормально ли такое поведение, как избежать этого, какие практические приемы позволяют избежать такого поведения. Пока я вижу, что ответ сводится к выставлению таймингов с запасом - это очевидный вариант, но неужели никто не копал глубже? Я ожидаю, что при отправке ФБ перезапишет свой буфер ввода-выводы на основе моих данных на своих входах и отправит его в порт, я не ожидаю, что ФБ возьмет кусок (по величине равный корректной команде) запоздалого ответа, рассчитает для него чек сумму и отправит в порт.


Прочитал РЭ на молоток. Согласно ему ожидаю забитые гвозди, но почему-то сильно болит палец. Видимо неправильный молоток.

Или неправильно пользуетесь молотком. Именно так мой вопрос и звучал. Например в РЭ на молоток не было написано, что первые удары по гвоздю нельзя производить с размаха, именно по этому палец и болит. А в общем виде РЭ на молоток правильно описывает процедуру использования, но забыли указать важный нюанс для новичка в забивании гвоздей.


Но либа - отличная, авторам - респект. Хотя я ее не юзаю, есть другие.

А какие еще есть? Не поделитесь вариантами?

ferret_maybe
02.12.2021, 10:30
Объяснить нормально ли такое поведение, как избежать этого, какие практические приемы позволяют избежать такого поведения. Пока я вижу, что ответ сводится к выставлению таймингов с запасом - это очевидный вариант, но неужели никто не копал глубже? Я ожидаю, что при отправке ФБ перезапишет свой буфер ввода-выводы на основе моих данных на своих входах и отправит его в порт, я не ожидаю, что ФБ возьмет кусок (по величине равный корректной команде) запоздалого ответа, рассчитает для него чек сумму и отправит в порт.

А чего вы ожидаете от асинхронного обмена в полудуплексном режиме?
Алгоритм простой:
Шаг 1. Открыл порт
Шаг 2. Послал команду запрос и ждешь ответа или конца времени разрешенной работы, если пришел ответ Шаг 3. Если не пришел и прошло время Шаг 4.
Шаг 3. Обработка вашего ответа
Шаг 4. Опрос нового устройства шаги 2 и 3 повторяем для нового (создаем шаги новые) или запуск таймера задержки опросов и шаг 2.

Цикл выполнения программы насколько меньше 5мс?

Ovtia
02.12.2021, 10:52
А чего вы ожидаете от асинхронного обмена в полудуплексном режиме?
Шаг 2. Послал команду запрос и ждешь ответа или конца времени разрешенной работы, если пришел ответ Шаг 3. Если не пришел и прошло время Шаг 4.
Шаг 4. Опрос нового устройства шаги 2 и 3 повторяем для нового (создаем шаги новые) или запуск таймера задержки опросов и шаг 2.

Цикл выполнения программы насколько меньше 5мс?
Вот именно так это и не работает. Все на скриншотах.
Для этой тестовой программы сильно меньше. Еще раз: 5 мс - это не принципиальный момент. Я мог поставить 15 мс и для конкретно МВА8, этого бы тоже не хватило. Я здесь просто продемонстрировал то, как ведет себя библиотека. И задал вопросы.

Спорягин Кирилл
02.12.2021, 11:15
Не вдавался в детали обсуждения, но может быть проблема в этом:
https://owen.ru/forum/showthread.php?t=21940&page=14&p=219033&viewfull=1#post219033 ?
В части 2 данного поста.

Ovtia
02.12.2021, 12:53
Не вдавался в детали обсуждения, но может быть проблема в этом:
https://owen.ru/forum/showthread.php?t=21940&page=14&p=219033&viewfull=1#post219033 ?
В части 2 данного поста.

В моем примере проблема воспроизводится и с MB_RD_HOLD_REGS и с MB_WR_REGS, в общем с любым ФБ использующим буфер. Для чтения не нужно даже готовить буфер, его готовит ФБ чтения (если я все правильно понимаю), но и он портится как я описал. Но спасибо за ссылку, узнал еще кое-что нового об этой библиотеке.

ferret_maybe
02.12.2021, 17:24
Второй раз можете попробовать вызывать ФБ MB_RD_HOLD_REGS2 без указания выходных и INPUT_OUTPUT параметров, например:
MB_RD_HOLD_REGS2(Enable:= FALSE);
Создается ощущение, что пишите в эти переменные(в том числе и буфер) по нескольку раз в коде программы.
Может быть проверить работу кода, ниже:

IF NOT rs485_opened THEN
rs485_settings.Port := 0;
rs485_settings.dwBaudRate := 115200;
rs485_settings.byStopBits := 1;
rs485_settings.byParity := 0;
rs485_settings.dwTimeout := 0;
rs485_settings.dwBufferSize := 0;
rs485_settings.dwScan := 0;
rs485_COM_SERVICE(Enable:= NOT(rs485_opened), Settings:= rs485_settings, Task:= OPEN_TSK, Ready=> rs485_opened);
END_IF

IF rs485_opened THEN
CASE step OF
0:
IF mb_complete AND mb_exception = 0 THEN
step:=1;
END_IF
IF mb_complete AND mb_exception <> 0 THEN
step:=2;
END_IF
1:
(* &#240;&#224;&#231;&#225;&#238;&#240; &#228;&#224;&#237;&#237;&#251;&#245; *)
dp1MVA8 := SHL(BYTE_TO_WORD(mb_buffer[0]), 8) OR BYTE_TO_WORD(mb_buffer[1]);
int1MVA8 := SHL(BYTE_TO_WORD(mb_buffer[2]), 8) OR BYTE_TO_WORD(mb_buffer[3]);
step:=2;
2:
IF TONDelay.Q THEN
step := 0;
END_IF
END_CASE

MB_RD_HOLD_REGS2(
Enable:= (step=0), (* &#194;&#251;&#239;&#238;&#235;&#237;&#229;&#237;&#232;&#229; &#239;&#240;&#232; 0 &#248;&#224;&#227;&#229; *)
Mode:= MB_RTU,
DevAddr:= 2,
FirstAddr:= 0,
Quantity:= 48,
ComHandle:= rs485_settings.Port,
TimeOut:= response_timeout,
Buffer:= mb_buffer,
Complete=> mb_complete,
Exception=> mb_exception,
ByteCnt=> mb_bytesReturn);
TONDelay(IN:= (step=2), PT:= PollDelay);
END_IF

Ovtia
03.12.2021, 04:23
Ну и долго эти стоны будут продолжаться ?
Если нечего сказать, то можно просто промолчать. Здесь идет дискуссия, я задал вопрос, форумчане дают комментарии (спасибо им за это), я отвечаю на них.

Откройте либу, разберите код и найдете сами все проблемные моменты (ессно они есть).
Код библиотеки закрыт.


Еще раз - я её не использую хотя авторам огромное спасибо. Но даже когда юзал хватало мозгов выяснять индивидуальные особенности девайсов, учитывать их и не заниматься хренью в виде 'а давай заместо доски бревно сунем'.
Несмотря на эльфийские хотелки никуда не уйдете от индивидуальных таймаутов.
Или из тех кому нужно прописывать что горячий кофий не нужно лить на себя ?
А может вести разговор по теме дискуссии. Или из тех, кому нужно выглядеть самым умным, по факту таким не являясь?

Ovtia
03.12.2021, 04:28
Второй раз можете попробовать вызывать ФБ MB_RD_HOLD_REGS2 без указания выходных и INPUT_OUTPUT параметров, например:
MB_RD_HOLD_REGS2(Enable:= FALSE);
Создается ощущение, что пишите в эти переменные(в том числе и буфер) по нескольку раз в коде программы.
Может быть проверить работу кода, ниже:
Да, я пробовал вызывать его и без параметров и вообще не вызывать его с Enable:= FALSE.
В данном примере в параметры передаю только константы, в буфер вообще не пишу, только читаю, да и если даже убрать чтение из буфера, поведение блока (то что он шлет в порт) не поменяется.
Мне нравится ваше решение, но к сожалению, результат в порте тот же.

ferret_maybe
03.12.2021, 07:00
Начнем сначала... Волновое сопротивление в линии передачи стоит?
Если что без обид все пытаются помочь со своего взгляда, себе вы можете помочь только сами. Форумчане не видят полной картины, что у вас там происходит.

Немного лирики из личного опыта: коллега занимался настройкой передачи данных "в поле" и на верхнем уровне(настраивал конфигурацию ПЛК) сидел другой человек. При договоре о параметрах передачи по телефону:
- Параметры передачи как обычно?
- Да.
Затем долго нет возможности подключиться к ведомому со стороны мастера, хотя с использованием ноутбука все по шлейфу от ведущего и ведомого работает, данные о правильности формирования запроса формируются при прослушивании канала. В общем непонятно, мастер шлет... слейв отвечает, но мастер не получает. Проблема была в том, что при настройке параметров передачи на мастере было указано EVEN - контроль четности, а на ведомом отключен контроль четности. Работа двух человек...

Спорягин Кирилл
03.12.2021, 10:28
Если нечего сказать, то можно просто промолчать. Здесь идет дискуссия, я задал вопрос, форумчане дают комментарии (спасибо им за это), я отвечаю на них.
Код библиотеки закрыт.
А может вести разговор по теме дискуссии. Или из тех, кому нужно выглядеть самым умным, по факту таким не являясь?

Ovtia, Вы по-аккуратнее с корефеями)))

Код библиотеки Modbus.lib открыт. Нужно просто снять галочки в кодесисе (потыкайтесь).

Ну, и уж раз Вы решили использовать библиотеку, то можете ознакомиться с универсальным диспетчером:
https://owen.ru/forum/showthread.php?t=25112&highlight=%F3%ED%E8%E2%E5%F0%F1%E0%EB%FC%ED%FB%E9+ %E4%E8%F1%EF%E5%F2%F7%E5%F0

Ovtia
03.12.2021, 10:32
Начнем сначала... Волновое сопротивление в линии передачи стоит?
Нет не стоит. Линия передачи меньше метра, все у меня на столе.

Если что без обид все пытаются помочь со своего взгляда, себе вы можете помочь только сами. Форумчане не видят полной картины, что у вас там происходит.
Понимаете, это даже скорее не проблема у меня, возможно все будет прекрасно на объекте, когда я выставлю тайм ауты с запасом. Я показал то, как я работаю с этой библиотекой (почерпнув знания из примеров на форуме и документации) на примере тестовой программы (ту которую я выложил сюда), показал то, что она шлет в порт (я думаю неважно какая линия и даже интерфейс, любой может эту программу запустить на своем ПЛК и получить тот же результат). И задал вопрос: это нормально? Если нет, что в моем примере не так? Если это особенность работы библиотеки, то как коллеги борются с этим проявлением, ведь кто-нибудь наверняка наблюдал такое же поведение? Очевидный ответ: поднять тайм ауты, но мне хотелось бы узнать, может кто-нибудь раскурил тему и делает какие-нибудь действия в своей программе, если вышел тайм аут.
Вообще если поразмышлять проблема довольно серьезная. Ну например, у меня один из слейвов, по какой-то причине начал конкретно отставать с ответом, а после него у меня всегда идет запись в другой слейв - это у меня так и будет, поскольку мастер передает состояния своих дискретных входов слейвам (да все сложно, но повлиять я на это не могу). Слейв не среагирует на событие и тогда все будет не очень весело.

Ovtia
03.12.2021, 10:44
Код библиотеки Modbus.lib открыт. Нужно просто снять галочки в кодесисе (потыкайтесь).

Ну, и уж раз Вы решили использовать библиотеку, то можете ознакомиться с универсальным диспетчером:
https://owen.ru/forum/showthread.php?t=25112&highlight=%F3%ED%E8%E2%E5%F0%F1%E0%EB%FC%ED%FB%E9+ %E4%E8%F1%EF%E5%F2%F7%E5%F0
Спасибо за наводку. Посмотрю вашу библиотеку, покопаюсь в codesys.

Spawn
04.12.2021, 00:35
Работаю с библиотекой давно и проблем (у меня) с ней не было.


VAR
SendModbus : MB_WR_REGS;
ES : BOOL := FALSE;
DataReady : BOOL;
MBTimeOut : TIME := T#150ms; //например
Buffer : ARRAY[0..255] OF BYTE;
END_VAR

IF NOT DataReady THEN
...//кладем в Buffer данные
DataReady := TRUE;
ES := TRUE;
END_IF

//настраиваем и открываем порт

//по готовности порта, "работаем" с ним
SendModbus(
Enable := ES,
Mode := MB_RTU,
DevAddr := 1, //например
FirstAddr := 1, //например
Quantity := 2, //например
ComHandle := Settings.Port,
TimeOut := MBTimeOut,
Buffer := Buffer);
ES := FALSE;

IF SendModbus.Complete THEN //можно еще добавить проверку на Exception
...//тут Ваши условия/инструкции по необходимости
ES := TRUE;
DataReady := FALSE;
END_IF

Пользуюсь кодом (когда-то позаимствованным из поста ASo и немного измененным по совету Валенка), указанным выше (пример записи в устройство, чтение аналогичное с небольшими изменениями). Полет нормальный.

Ovtia
09.12.2021, 07:34
Работаю с библиотекой давно и проблем (у меня) с ней не было.
Спасибо за Ваш вариант. К сожалению он работает так же.
Вообще, почитав исходники библиотеки, прихожу к выводу, что никакими манипуляциями вызова FB библиотеки поменять это поведение не получится. Т. к. в FB MB_UNI_IO (вызывается любым FB чтения/записи Modbus.lib) первым делом читается порт, и если там что-то есть, оно попадает в, подготовленный вами или другим FB библиотеки, буфер. Модифицировать библиотеку ни времени ни желания нет, отладка изменений займет слишком много времени, которого уже не хватает на проект в целом.
Альтернатив выставлению таймингов с большим запасом я не вижу, но имхо такое поведение - это баг.