Просмотр полной версии : ПЛК 110-32М смена скорости порта
Papagun78
31.08.2015, 11:49
Здравствуйте.
В сети RS-485 есть множество устройств, часть из них работает на скорости 115200 (модули ввода/вывода) и часть на скорости 19200 (частотники, сторонние контроллеры). В мастер сеть все теги не влазят, поэтому приходится вести обмен данными вручную через библиотеки.
Собственно трудность: на одной скорости чтение и запись по RS не представляет сложности, но вот перейти на другую скорость обмена у меня не получается. Прошу помощи опытных специалистов, как лучше и правильнее менять скорость порта?
Я пытаюсь это делать путём закрытия порта и открытия его с новыми настройками. Однако данный манёвр приводит к полному отсутствию связи с каким-либо устройством.
Программа выгляди так:
IF port_opened=0 THEN
Settings.Port:=0;
Settings.dwBaudRate:=115200;
Settings.byParity:=0;
Settings.dwTimeout:=0;
Settings.byStopBits:=1;
Settings.dwBufferSize:=0;
Settings.dwScan:=0;
END_IF
COM_SERVICE1(Enable:=(port_opened=0) , Settings:=Settings , Task:=OPEN_TSK );
IF COM_SERVICE1.ready THEN
port_opened:=2;
END_IF
IF port_opened=2 THEN
CASE master1 OF
0:
get1_modbus(
Enable:=enabl ,
Mode:=MB_RTU ,
DevAddr:=150 ,
FirstAddr:=520 ,
Quantity:=1,
ComHandle:=Settings.Port ,
TimeOut:=TimeOut ,
Buffer:=Buffer ,
Complete=>cmpl ,
Exception=>err ,
ByteCnt=>DataSize );
IF cmpl THEN
IF err=0 THEN
x1:=BYTE_TO_WORD(BUFFER[1]) OR SHL(BYTE_TO_WORD(BUFFER[0]),8);
END_IF
master1:=0;
END_IF
Как правильно перенастроить или переоткрыть порт с новыми настройками?
не увидел в коде, а где Вы закрываете порт, может ошибка где то в этом кроется
во вторых считаю что это плохая затея, прибор видя что идут данные на другой скорости может в линию отправлять мусор, что помешает принять качественный ответ от опрашиваемого прибора
Papagun78
31.08.2015, 13:03
не увидел в коде, а где Вы закрываете порт, может ошибка где то в этом кроется
во вторых считаю что это плохая затея, прибор видя что идут данные на другой скорости может в линию отправлять мусор, что помешает принять качественный ответ от опрашиваемого прибора
Закрывать пытаюсь вот так:
COM_SERVICE1(Enable:=(port1_opened=2) , Settings:=Settings , Task:=CLOSE_TSK );
IF COM_SERVICE1.ready=0 THEN
port1_opened:=0;
Чисто интуитивно поменял условия (обозначил красным), но думаю, что всё должно быть как-то по другому, но вот не знаю как.
Затем меняю настройки порта
Settings.Port:=0;
Settings.dwBaudRate:=19200;
Settings.byParity:=0;
Settings.dwTimeout:=0;
Settings.byStopBits:=1;
Settings.dwBufferSize:=0;
Settings.dwScan:=0;
и снова открываю его с новыми настройками
COM_SERVICE1(Enable:=(port2_opened=0) , Settings:=Settings , Task:=OPEN_TSK );
IF COM_SERVICE1.ready THEN
port2_opened:=2;
END_IF
Насчёт плохой затеи - это вынужденная мера, так как настроить все устройства на одну высокую скорость нереально, единственное можно настроить все на минимально возможную 19200, но это приведёт к замедлению процесса обмена, а устройств 17 штук, на каждое ожидание в 50 мс в идеале, а то и более если несколько запросов делать, и того до секунды цикл опроса вырастает.
Думаю нужно просто грамотно переоткрыть порт или сменить скорость в открытом. Вопрос КАК?
мне кажется должно пройти некоторое время(несмотря на деление по модулю), пока сам физический порт закроется, чтоб его можно использовать повторно, это в Вашем случае
А если посмотрите исходник блока http://www.owen.ru/forum/showthread.php?t=16787&p=131822&viewfull=1#post131822 то можно увидеть что RESET_TSK пытается применить новые настройки, сам лично не пробовал, но автор же не зря так написал
Papagun78
31.08.2015, 14:40
Да, судя по всему RESET_TASK помогает, код программы такой, полный код:
t:=t+1;
IF (t MOD 1000)=0 THEN
A := A + 1;
t := 0;
IF A > 999 THEN
A := 0;
END_IF
END_IF
(*Óñòàíàâëèâàåì íàñòðîéêè COM-ïîðòà*)
IF port1_opened =0 THEN
Settings.Port:=0; (*íîìåð COM-ïîðòà*)
Settings.dwBaudRate:=115200; (*ñêîðîñòü*)
Settings.byParity:=0;
Settings.dwTimeout:=0;
Settings.byStopBits:=1;
Settings.dwBufferSize:=0;
Settings.dwScan:=0;
END_IF
COM_SERVICE1(Enable:=(port1_opened=0) , Settings:=Settings , Task:=OPEN_TSK );
(*Åñëè COM-ïîðò îòêðûò, òî ïåðåõîäèì ê ïðèåìó è ïåðåäà÷è äàííûõ *)
IF COM_SERVICE1.ready THEN
port1_opened:=2;
END_IF
IF port1_opened=2 THEN (*Óäà÷íî ïðîèíèöèàëèçèðîâàëè*)
CASE master1 OF
0: (* ôóíêöèÿ 03 èíò - ÔÁ ñ÷èòûâàåò çíà÷åíèå ïàðàìåòðà òèïà int èç ïðèáîðà ñ àäðåñîì 10 èç ðåãèñòðà ñ íîìåðîì 51 ïî ïðîòîêîëó Modbus-RTU*)
get1_modbus(
Enable:=enabl , (* ðàçðåøåíèå ðàáîòû áëîêà *)
Mode:=MB_RTU , (*ðåæèì ïåðåäà÷è*)
DevAddr:=150 , (*àäðåñ*)
FirstAddr:=520 , (*íîìåð ðåãèñòðà*)
Quantity:=1, (*êîëè÷åñòâî ðåãèñòðîâ*)
ComHandle:=Settings.Port , (*íîìåð COM-ïîðòà*)
TimeOut:=TimeOut , (*Òàéìàóò T#50ms*)
Buffer:=Buffer , (* áóôåð äàííûõ *)
Complete=>cmpl , (* ñêîïèðîâàòü ïðèçíàê çàâåðøåíèÿ îïåðàöèè *)
Exception=>err , (* ñêîïèðîâàòü ðåãèñòð îøèáîê *)
ByteCnt=>DataSize ); (*êîë-âî ñ÷èòàííûõ áàéòîâ *)
(*åñëè óñòàíîâëåí ïðèçíàê çàâåðøåíèÿ îïåðàöèè, òî *)
IF cmpl THEN
IF err=0 THEN (*Åñëè íåò îøèáîê, òî ïîëó÷àåì äàííûå èç áóôåðà òèïà INT*)
x1:=BYTE_TO_WORD(BUFFER[1]) OR SHL(BYTE_TO_WORD(BUFFER[0]),8);
END_IF
master1:=1; (*ïåðåõîäèì ê âûïîëíåíèþ ñëåäóþùåãî ÔÁ*)
END_IF
1: (* ôóíêöèÿ 16 - çàïèñü ïàðàìåòðîâ òèïà Int (ðåãèñòð 4) è Real (ðåãèñòð 6) â ïðèáîð ñ àäðåñîì 2 *)
(*çàïèñü â áóôôåð ïàðàìåòðà òèïà INT*)
Buffer[1] := DINT_TO_BYTE(A);
Buffer[0] := DINT_TO_BYTE( SHR(A,8));
Buffer[3] := DINT_TO_BYTE( SHR(A,16));
Buffer[2] := DINT_TO_BYTE( SHR(A,24));
send2_modbus(
Enable:= enabl, (* ðàçðåøåíèå ðàáîòû áëîêà *)
Mode:=MB_RTU , (*ðåæèì ïåðåäà÷è*)
DevAddr:=150 , (*àäðåñ*)
FirstAddr:= 520, (*íîìåð ðåãèñòðà*)
Quantity:= 1, (*êîëè÷åñòâî çàïèñûâàåìûõ ðåãèñòðîâ*)
ComHandle:=Settings.Port ,(*íîìåð ñîì-ïîðòà*)
TimeOut:=TimeOut , (*òàéìàóò T#50ms*)
Buffer:=Buffer , (* áóôåð äàííûõ *)
Complete=>cmpl , (* ñêîïèðîâàòü ïðèçíàê çàâåðøåíèÿ îïåðàöèè *)
Exception=>err , (* ñêîïèðîâàòü ðåãèñòð îøèáîê *)
RegCnt=> DataSize); (*êîë-âî ñ÷èòàííûõ áàéòîâ *)
(*åñëè óñòàíîâëåí ïðèçíàê çàâåðøåíèÿ îïåðàöèè, òî *)
IF cmpl THEN
master1:=2;(*ïåðåõîäèì ê âûïîëíåíèþ ñëåäóþùåãî áëîêà*)
END_IF
2:
Settings.Port:=0; (*íîìåð COM-ïîðòà*)
Settings.dwBaudRate:=19200; (*ñêîðîñòü*)
Settings.byParity:=0;
Settings.dwTimeout:=0;
Settings.byStopBits:=1;
Settings.dwBufferSize:=0;
Settings.dwScan:=0;
port1_opened:=0;
COM_SERVICE1(Enable:=(port1_opened=0) , Settings:=Settings , Task:=RESET_TSK );
(*Åñëè COM-ïîðò îòêðûò, òî ïåðåõîäèì ê ïðèåìó è ïåðåäà÷è äàííûõ *)
IF COM_SERVICE1.ready THEN
port1_opened:=2;
END_IF
get1_modbus(
Enable:=enabl , (* ðàçðåøåíèå ðàáîòû áëîêà *)
Mode:=MB_RTU , (*ðåæèì ïåðåäà÷è*)
DevAddr:=10 , (*àäðåñ*)
FirstAddr:=51 , (*íîìåð ðåãèñòðà*)
Quantity:=1, (*êîëè÷åñòâî ðåãèñòðîâ*)
ComHandle:=Settings.Port , (*íîìåð COM-ïîðòà*)
TimeOut:=TimeOut , (*Òàéìàóò T#50ms*)
Buffer:=Buffer , (* áóôåð äàííûõ *)
Complete=>cmpl , (* ñêîïèðîâàòü ïðèçíàê çàâåðøåíèÿ îïåðàöèè *)
Exception=>err , (* ñêîïèðîâàòü ðåãèñòð îøèáîê *)
ByteCnt=>DataSize ); (*êîë-âî ñ÷èòàííûõ áàéòîâ *)
(*åñëè óñòàíîâëåí ïðèçíàê çàâåðøåíèÿ îïåðàöèè, òî *)
IF cmpl THEN
IF err=0 THEN (*Åñëè íåò îøèáîê, òî ïîëó÷àåì äàííûå èç áóôåðà òèïà INT*)
x2:=BYTE_TO_WORD(BUFFER[1]) OR SHL(BYTE_TO_WORD(BUFFER[0]),8);
END_IF
master1:=3; (*ïåðåõîäèì ê âûïîëíåíèþ ñëåäóþùåãî ÔÁ*)
END_IF
IF enabl = FALSE THEN
enabl := TRUE;
END_IF
IF err <> 0 THEN
enabl := FALSE;
END_IF
3:
port1_opened:=0;
master1:=0;
END_CASE
IF enabl = FALSE THEN
enabl := TRUE;
END_IF
IF err <> 0 THEN
enabl := FALSE;
END_IF
END_IF
но работает нестабильно, опрос модуля на 19200 стабилен, а запись и чтения модуля на 115200 проходит один раз в несколько десятков секунд. Не могу понять в чём причина, вроде везде есть подтверждение включения порта и только потом работа с ним, явные задержки времени не требуются, но не работает стабильно.
Дмитрий Артюховский
31.08.2015, 14:48
COM_SERVICE все делает ну очень медленно (почему то, до 100 циклов ПЛК тратит на функцию!) ну ее нафиг, в SysLibCom вполне достаточно. Обмен на библиотеках тем и хорош что все происходит быстрее таймаутов по 50 мс - получили ответ -> начинаем новый сеанс.
А используя разную скорость вы догружаете периферийные устройства анализом посылок, которые они гарантированно не поймут, а возможно и поймут неправильно и попытаются ответить не вовремя.
Papagun78
31.08.2015, 14:52
COM_SERVICE все делает ну очень медленно (почему то, до 100 циклов ПЛК тратит на функцию!) ну ее нафиг, в SysLibCom вполне достаточно. Обмен на библиотеках тем и хорош что все происходит быстрее таймаутов по 50 мс - получили ответ -> начинаем новый сеанс.
А используя разную скорость вы догружаете периферийные устройства анализом посылок, которые они гарантированно не поймут, а возможно и поймут неправильно и попытаются ответить не вовремя.
Дайте, пожалуйста, пример реализации обмена данными через SysLibCom.
Дмитрий Артюховский
31.08.2015, 16:58
IF NOT port_opened_scan THEN (* если порт не открыт *)
com_handle_scan := SysComOpen( com_num_scan ); (* открываем его *)
IF com_handle_scan <> 16#FFFFFFFF THEN (* если порт открыт удачно - ставим флаг *)
port_init_scan := TRUE;
ELSE
SysComClose( com_num_scan ); (* иначе закрываем порт *)
com_handle_scan := SysComOpen( com_num_scan ); (* и открываем его повторно *)
port_init_scan := TRUE; (* ставим флаг открытия *)
END_IF
(* настраиваем порт *)
com_set_scan.Port := com_num_scan;
com_set_scan.dwBaudRate := 19200; (* 9600; 38400; 57600 *)
com_set_scan.byParity := 0;
com_set_scan.dwTimeout := 0;
com_set_scan.byStopBits := 0;
com_set_scan.dwBufferSize := 1024;
com_set_scan.dwScan := 0;
res_scan := SysComSetSettings( com_num_scan, ADR( com_set_scan ) ); (* применить настройки порта *)
IF NOT res_scan THEN
port_opened_scan := TRUE; (* порт успешно открыт *)
END_IF
SCANTIME := T#45MS;
END_IF
COM_SERVICE внутри себя ведет счетчик циклов ПЛК и собственно выполняется на сотом, зачем это сделано совершенно не понятно, а учитывая, что у многих цикл ПЛК выставлен много больше 1 мс -> порты открываются (и закрываются) минутами!!
Powered by vBulletin® Version 4.2.3 Copyright © 2025 vBulletin Solutions, Inc. All rights reserved. Перевод: zCarot