Вход

Просмотр полной версии : Не могу подружить 2 устройства через modbus.lib



Атаман
03.03.2017, 10:33
На столе ПЛК100+расходомер взлет + ОВЕН мк110.8дн.4р

Тестовая программа:



(*Устанавливаем настройки COM-порта*)
IF port_opened=0 THEN
Settings.Port:=com_num; (*номер COM-порта*)
Settings.dwBaudRate:= 115200; (*скорость*)
Settings.byParity:=0;
Settings.dwTimeout:=0;
Settings.byStopBits:=0;
Settings.dwBufferSize:=0;
Settings.dwScan:=0;
END_IF

COM_SERVICE1(Enable:=(port_opened=0) , Settings:=Settings , Task:=OPEN_TSK );
(*Если COM-порт открыт, то переходим к приему и передачи данных *)
IF COM_SERVICE1.ready THEN
port_opened:=2;
END_IF

IF port_opened=2 THEN (*Удачно проинициализировали*)

CASE master1 OF

0:
get1_modbus(
Enable:=Enable:= NOT get1_modbus.Complete, (* разрешение работы блока *)
Mode:=MB_RTU, (*режим передачи*)
DevAddr:=8 , (*адрес*)
FirstAddr:=2 , (*номер регистра*)
Quantity:=1, (*количество регистров*)
ComHandle:=Settings.Port , (*номер COM-порта*)
TimeOut:=TimeOut , (*Таймаут T#50ms*)
Buffer:=Buffer_out, (* буфер данных *)
Complete=>cmpl , (* скопировать признак завершения операции *)
Exception=>err , (* скопировать регистр ошибок *)
ByteCnt=>DataSize ); (*кол-во считанных байтов *)
(*если установлен признак завершения операции, то *)
IF cmpl THEN
IF err=0 THEN (*Если нет ошибок, то получаем данные из буфера типа INT*)
x:=BYTE_TO_WORD(BUFFER_out[1]) OR SHL(BYTE_TO_WORD(BUFFER_out[0]),8);
ELSE
errcount:=errcount +1;
END_IF
master1 := 3;
END_IF


2: get1_modbus(
Enable:= NOT get1_modbus.Complete , (* разрешение работы блока *)
Mode:=MB_RTU, (*режим передачи*)
DevAddr:=48 , (*адрес*)
FirstAddr:=50 , (*номер регистра*)
Quantity:=1, (*количество регистров*)
ComHandle:=Settings.Port , (*номер COM-порта*)
TimeOut:=TimeOut , (*Таймаут T#50ms*)
Buffer:=Buffer_out, (* буфер данных *)
Complete=>cmpl , (* скопировать признак завершения операции *)
Exception=>err , (* скопировать регистр ошибок *)
ByteCnt=>DataSize ); (*кол-во считанных байтов *)
(*если установлен признак завершения операции, то *)
IF cmpl THEN
IF err=0 THEN (*Если нет ошибок, то получаем данные из буфера типа INT*)
x:=BYTE_TO_WORD(BUFFER_out[1]) OR SHL(BYTE_TO_WORD(BUFFER_out[0]),8);
ELSE
errcount:=errcount +1;
END_IF
master1 := 3;
END_IF


3:
TimeOut2(IN :=TRUE,PT:=T#50ms);
TimeOut2;
IF TimeOut2.Q THEN
g:=g+1;
master1 := 0;
(*IF g/2 = TRUNC(g/2) THEN
master1 := 2;
END_IF*)
TimeOut2.IN := FALSE;
TimeOut;
END_IF

END_CASE

END_IF



В таком виде программа работает, опрашивается Взлет, ошибок 0. Убираю комментирование в 3м кейсе (подключаю второй модуль ОВЕН) и у Взлета каждая вторая ошибка 255. Что я делаю не так? Через конфигуратор оба работают нормально с редкими ошибками.

capzap
03.03.2017, 10:40
поправить надо бибку модбасовскую, есть там проблемы с буфферным массивом

Атаман
03.03.2017, 10:44
Как здесь (http://www.owen.ru/forum/showthread.php?t=25120&p=219530&viewfull=1#post219530) написано? Не помогло.

capzap
03.03.2017, 10:57
а этим http://www.owen.ru/forum/showthread.php?t=6805&p=143448&viewfull=1#post143448

Атаман
03.03.2017, 11:27
а этим http://www.owen.ru/forum/showthread.php?t=6805&p=143448&viewfull=1#post143448

Поменял MB_RD_HOLD_REGS из моей программы на READ_MULTIPLE_REGISTERS из примера. ПЛК сразу ушел в перезагрузку.

capzap
03.03.2017, 11:33
всмысле, при компиляции не на что не ругалась, обе бибки добавлены?

Атаман
03.03.2017, 11:45
(*Устанавливаем настройки COM-порта*)
IF port_opened=0 THEN
Settings.Port:=com_num; (*номер COM-порта*)
Settings.dwBaudRate:= 115200; (*скорость*)
Settings.byParity:=0;
Settings.dwTimeout:=0;
Settings.byStopBits:=0;
Settings.dwBufferSize:=0;
Settings.dwScan:=0;
END_IF

COM_SERVICE1(Enable:=(port_opened=0) , Settings:=Settings , Task:=OPEN_TSK );
(*Если COM-порт открыт, то переходим к приему и передачи данных *)
IF COM_SERVICE1.ready THEN
port_opened:=2;
Buffer_out := ADR(Buffer1);
END_IF

IF port_opened=2 THEN (*Удачно проинициализировали*)

CASE master1 OF

0: (* функция 03 инт - ФБ считывает значение параметра типа int из прибора с адресом162 в регистр с номером 48 по протоколу Modbus-RTU*)

get1_modbus(
Enable:= NOT get1_modbus.Complite, (* разрешение работы блока *)
UnitID:=8 , (*адрес*)
REF:=2 , (*номер регистра*)
Count:=1, (*количество регистров*)
Handle:=Settings.Port , (*номер COM-порта*)
Delay:=TimeOut , (*Таймаут T#50ms*)
PNTFF:=Buffer_out, (* буфер данных *)
Complite=>cmpl , (* скопировать признак завершения операции *)
ErrCode=>err , (* скопировать регистр ошибок *)
); (*кол-во считанных байтов *)
(*если установлен признак завершения операции, то *)
IF cmpl THEN
IF err=0 THEN (*Если нет ошибок, то получаем данные из буфера типа INT*)
n:=n+1;
(*x:=BYTE_TO_WORD(BUFFER_out[1]) OR SHL(BYTE_TO_WORD(BUFFER_out[0]),8);*)
ELSE
errcount:=errcount +1;
END_IF
master1 := 3;
END_IF


2: get1_modbus(
Enable:= NOT get1_modbus.Complite, (*разрешение работы блока *)
UnitID:=48 , (*адрес*)
REF:=50 , (*номер регистра*)
Count:=1, (*количество регистров*)
Handle:=Settings.Port , (*номер COM-порта*)
DELAY:=TimeOut , (*Таймаут T#50ms*)
PNTFF:=Buffer_out, (* буфер данных *)
Complite=>cmpl , (* скопировать признак завершения операции *)
ErrCode=>err , (* скопировать регистр ошибок *)
); (*кол-во считанных байтов *)
(*если установлен признак завершения операции, то *)
IF cmpl THEN
IF err=0 THEN (*Если нет ошибок, то получаем данные из буфера типа INT*)
n:=n+1;
(* x:=BYTE_TO_WORD(BUFFER_out[1]) OR SHL(BYTE_TO_WORD(BUFFER_out[0]),8);*)
ELSE
errcount:=errcount +1;
END_IF
master1 := 3;
END_IF


3:
TimeOut2(IN :=TRUE,PT:=T#100ms);
TimeOut2;
IF TimeOut2.Q THEN
g:=g+1;
master1 := 0;
(*IF g/2 = TRUNC(g/2) THEN
master1 := 2;
END_IF *)
TimeOut2.IN := FALSE;
TimeOut;
END_IF

END_CASE

END_IF


Буфер инициализировал, ошибка 60 теперь какая то постоянно. Modbus RTU в бибке? Переключателя не увидел.

Атаман
03.03.2017, 12:01
Ставлю точки останова на строки после IF err=0 THEN ... и вручную переключаю между запросами кнопкой f5 - всё работает, 0 ошибок. Что за ерунда?

capzap
03.03.2017, 12:15
TimeOut2(IN :=TRUE,PT:=T#100ms);
TimeOut2;
IF TimeOut2.Q THEN
g:=g+1;
master1 := 0;
(*IF g/2 = TRUNC(g/2) THEN
master1 := 2;
END_IF *)
TimeOut2.IN := FALSE;
TimeOut;
END_IF
я бы переписал на такое

TimeOut2(IN :=TRUE,PT:=T#100ms);
IF TimeOut2.Q THEN
g:=g+1;
master1 := 0;
TimeOut2(IN := FALSE);
END_IF
а то лишний код добавляет и лишние ошибки, типа отсутствие двойки на конце переменной
Если с точками останова всё работает, значит мал таймаут в опросе

Атаман
03.03.2017, 12:24
Если с точками останова всё работает, значит мал период опроса

Чот вообще не пойму, что происходит.

После IF complete добавил вызов get1_modbus c Enable := FAlse; Ошибок таймаута теперь нет,но значение регистра (переменная x) во взлете неправильное, 2051, хотя на самом деле 2

capzap
03.03.2017, 12:58
а в других регистрах тоже не верная инфа? Поднять скорость хотя бы до 38400 нельзя?

Атаман
03.03.2017, 13:55
Во всех регистрах 2051, ошибок 0. Как только возвращаю коммент в 3м кейсе, то есть оставляю один модуль Взлет, то он дает правильные регистры. Скорость 115200.

И еще по поводу Enable в модбас функциях. Читал на этом форуме, что нужно взводить на один цикл. Функции записи так работают, а функции чтения нет - complete в них остается False. Как же правильно?

capzap
03.03.2017, 14:05
но судя по примеру, по адресу 2 двойка должна означать скорость 2400, хотя я открывал первый попавшийся документ по взлету
по Enable я тоже подавал импульс, вконце концов бибка открыта можно самому убедится что она сама ловит фронт

Атаман
03.03.2017, 15:11
Это Rs.dl, а не скорость в этом влете.

Что может быть, если работают в бибке по одному нормально и оба в конфигураторе тоже нормально, а оба в бибке не хотят, причем косячит Взлет?

capzap
03.03.2017, 15:24
паузу ставить побольше между запросами, попробуйте четыре кейса и разное регулируемое время у таймеров после взлета и модуля, начиная с больших значений уменьшайте пока не появятся ошибки по таймауту

Атаман
03.03.2017, 17:35
ЁКЛМН!!!

В последней строчке должен быть TimeOut2, а не TimeOut.

capzap, спасибо за участие!