Просмотр полной версии : Ошибка таймаута при записи в модули по ModBus-RTU.
В соседней теме уже задавал данный вопрос ПЛК73 + МК110-220.4К.4Р + МК110-224.8ДН.4Р опрос по ModBus (https://owen.ru/forum/showthread.php?t=32317) но так и не получил ответа.
На складе нашел еще 2 модуля МВ110-ДН и МУ110-16Р переписал для них программу.
С МВ110-ДН нет проблем все замечательно читается, отсоединяю от него RS-485 появляется ошибка таймаута. А вот с МУ110-16Р проблемы, отправляю маску выходов, на модуле загораются выхода и вместе с признаком завершения операции приходит ошибка 255 (Ошибка таймаута)!
Как с этим бороться?
Если мне не изменяет память, то в МУ110 параметр "максимальный сетевой тайм-аут" отвечает за то, через какое время блок падает в аварию. В ваших настройках оно нулевое.
Если мне не изменяет память, то в МУ110 параметр "максимальный сетевой тайм-аут" отвечает за то, через какое время блок падает в аварию. В ваших настройках оно нулевое.
Это относится к модулю, через сколько он уйдет в аварию и выхода установятся согласно аварийной маске если есть такое. 0 - отключено. У меня же авария появляется в контроллере после отправки выходной маски.
Почему у меня такого не бывает?
Ну и хотелось бы увидеть всю программу, по крайней мере, POU работы с МОДБАС, по скриншоту есть подозрение, что нет работы процедуры записи.
Почему у меня такого не бывает?
Ну и хотелось бы увидеть всю программу, по крайней мере, POU работы с МОДБАС, по скриншоту есть подозрение, что нет работы процедуры записи.
И при записи буфер не нужно "трогать" до тех пор, пока Complete не будет равно 1 и не будет выдержана пауза.
Я так делаю (по Вашему, кстати, ASo, примеру):
VAR
HPause : TON;
ES : BOOL;
DataReady : BOOL;
EndSendStored : BOOL;
MBTimeOut : TIME := T#350ms; //например
PTimeOut : : TIME := T#1ms; //например
END_VAR
IF NOT DataReady THEN
...//кладем в Buffer данные
DataReady := TRUE;
ES := TRUE;
END_IF
SendModbus(
Enable := ES,
Mode := MB_RTU,
DevAddr := 1, //например
FirstAddr := 1, //например
Quantity := 1, //например
ComHandle := Settings.Port,
TimeOut := MBTimeOut,//со значением этой переменной можно "поиграться", чтобы сократить время обмена и добиться устойчивой связи
Buffer := Buffer);
ES := FALSE;
IF SendModbus.Complete THEN //можно еще добавить проверку на Exception
...//тут Ваши условия/инструкции по необходимости
EndSendStored := TRUE;
END_IF
HPause(IN := EndSendStored, PT := PTimeOut) //со значением PTimeOut тоже "поиграться", чтобы сократить время обмена и добиться устойчивой связи
IF HPause.Q THEN
...//тут Ваши условия/инструкции по необходимости
EndSendStored := FALSE;
DataReady := FALSE;
END_IF
ошибка бывает только при функции записи, не так ли. Просто не обращайте на неё внимание так же как на порт инвалид
некоторое время назад я разбирал исходники почему это может быть
Это точно не вариант! Так как данный контролер должен управлять паровой котельной, а отвал или зависание модуля может привести к печальным последствиям.
Почему у меня такого не бывает?
Ну и хотелось бы увидеть всю программу, по крайней мере, POU работы с МОДБАС, по скриншоту есть подозрение, что нет работы процедуры записи.
Ну так во вложениях есть Опрос_модулей_16.pro
И при записи буфер не нужно "трогать" до тех пор, пока Complete не будет равно 1 и не будет выдержана пауза.
В вашем примере как то все нагромождено, могу предположить что вы опрашиваете модули в основном цикле программы, по этому используете задержки. У меня же опрос модулей выполняется отдельной подпрограммой которая запускается по задержке. И я уже писал что когда Complete = 1 то Exception = 255 смотри миниатюры остановка когда Complete = 1.
ну значит берите бибку и правте проблемный участок кода, чтоб этой ошибки не было
Править библиотеку? Я кое как научился отправлять, принимать данные с их помощью и это уже около 50 строк кода. А там 8 функций 9 функциональных блоков.
Пытался создавать копии FB. С копией MB_WR_REGS → MY_WR_REGS программа еще работает, но в ней есть обращение к MB_UNI_IO → MY_UNI_IO и если я делаю ее копию и из MY_WR_REGS обращаюсь к MY_UNI_IO то программа зависает. Ошибка ка раз формируется в MB_UNI_IO.
Так что я пока в тупике.
ну тогда чередуйте функции чтения и записи, даже если это не нужно, но зато вроде ошибка не появляется
Так у меня в примере и так сначала читается из МВ110-ДН и записывается в МУ110-16Р или вы предлагаете сначала считать битовою маску состояния выходов учитывая ошибки, и потом записать битовою маску состояния выходов игнорируя ошибку? Если так это конечно оригинально но в корни не правильно!
Если Вы слабо себя чувствуете в кодинге, то зачем перешли на библиотеку, у Вас из объектов две битовые маски, мастер конфигуратора с этим должен справиться без всяких проблем
Мая твая не понимай. Попробуйте объяснить доступными выражениями или примером.
Да с ST столкнулся впервые.
В библиотеку полез чтобы понять почему при правленой отправке битовой маски значений выходов модуля, а не ПЛК операция хоть и выполняется (выхода на МУ110-16Р включаются по маске) но завершается с ошибкой (EXC_TO: BYTE := 16#FF; (* TIMEOUT ERROR *)).
Например потому, что Вы не даете POU работать, вызывая его постоянно с триггером Enable=TRUE. Т.е. POU постоянно шлет пакет в очередь передачи, не ожидая приема ответа (не считывает очередь приема). Это типичная ошибка пользователей данной бибки, идущая от ошибок примера в руководстве.
смущает таймаут выставленный 5мс
Это минимальный таймаут при котором без ошибок происходить чтение из МВ110-ДН если меньше появляются ошибки. Я увеличивал его до 1 секунды, результата нет.
3ms тоже менял не помогает.
50016
Я так и не понял.
Где у меня в коде хоть как то при записи используется буфер до тех пор, пока Complete не будет равно 1
3:
Buffer[1] := DINT_TO_BYTE(out_5);(* Записываем данные в буфер*)
Buffer[0] := DINT_TO_BYTE( SHR(out_5,8));
set5(
Enable:= TRUE, (* Разрешение работы блока *)
Mode:=MB_RTU , (* Режим передачи ASCII/ RTU *)
DevAddr:=5 , (* Адрес ведомого устройства *)
FirstAddr:= 50, (* Номер первого регистра для чтения *)
Quantity:= 1, (* Количество записываемых регистров *)
ComHandle:=Settings.Port , (* Номер COM-порта *)
TimeOut:=TimeOut , (* Таймаут T#ХХХms *)
Buffer:=Buffer , (* Буфер данных *)
Complete=>cmpl , (* Скопировать признак завершения операции *)
Exception=>Error); (* Скопировать регистр ошибок *)
IF cmpl THEN (* Если завершено *)
master := 1;
set5(
Enable:=FALSE , (* Завершаем работу блока *)
Mode:=MB_RTU , (* Режим передачи ASCII/ RTU *)
DevAddr:=5 , (* Адрес ведомого устройства *)
FirstAddr:= 50, (* Номер первого регистра для чтения *)
Quantity:= 1, (* Количество записываемых регистров *)
ComHandle:=Settings.Port , (* Номер COM-порта *)
TimeOut:=TimeOut , (* Таймаут T#ХХХms *)
Buffer:=Buffer); (* Буфер данных *)
END_IF
первые две строчки кейса, пока в нем находимся, всегда перезаписываются
Powered by vBulletin® Version 4.2.3 Copyright © 2025 vBulletin Solutions, Inc. All rights reserved. Перевод: zCarot