Yegor, а вы капитально разбираетесь в контроллерах). Сейчас понимаю что мне много еще что познать надо... А может вы мне подскажете по библиотеке NetVar для кдс 2 если вы в ней копались основательно.
Вид для печати
Yegor, а вы капитально разбираетесь в контроллерах). Сейчас понимаю что мне много еще что познать надо... А может вы мне подскажете по библиотеке NetVar для кдс 2 если вы в ней копались основательно.
Тоже столкнулся с продукцией данной компании, только с датчиком момента и скорости. Естественно, тоже уперся в то, что они называют Модбасом. И что самое удивительное - это действительно Модбас. В протоколе действительно зарезервированы номера функций 101-110 и 66-69 (могу ошибаться в диапазоне) для расширений производителя. А раз так, то нас может выручить блок MB_UNI_IO из Modbus.lib. Но он не выручает, потому как при попытке заменить им блоки MB_RD_* (MB_WR_*) компилятор ругается на конфликт типов данных в ComHandle.
Выяснилось, что за каким-то лядом все входные переменные в блоке были сделаны VAR_IN_OUT, что и приводило к ошибкам компиляции. Пришлось вскрывать Modbus.lib и править объявление на такое:
После этого пример из библиотеки заработал, как это ни странно, с минимальными переделками:Код:FUNCTION_BLOCK MB_UNI_IO
VAR_INPUT
Mode: MB_MODE; (* Serial Transmission Mode of MODBUS networks *)
ComHandle:DWORD; (* äåñêðèïòîð ïîñëåäîâàòåëüíîãî ïîðòà áèáëèîòåêè SysLibCom *)
TimeOut: TIME; (* âðåìÿ òàéì-àóòà [ìñ] - ìàêñ. çàäåðæêà íà îáðàáîòêó çàïðîñà *)
END_VAR
VAR_IN_OUT
Complete: BOOL; (* åñëè = TRUE, òî îáìåí çàâåðøåí *)
Exception: BYTE; (* èñêëþ÷åíèÿ ïðîòîêîëà MODBUS *)
DataBuf: ARRAY[0..255] OF BYTE; (* áóôåð äàííûõ êàäðà *)
DataSize: BYTE; (* ðàçìåð êàäðà áåç êîíòðîëüíîé ñóììû *)
END_VAR
Код:PROGRAM PLC_PRG
VAR
(*Ïðèìåð ðàáîòû ñ ÷àñòîòíûì ïðèâîäîì ÎÂÅÍ Ï× ïî RS-485*)
com_num1: PORTS; (*Íîìåð ïîðòà íà êîòîðûé ïîäêëþ÷åíî îáîðóäîâàíèå*)
com_hndl: DWORD;
Settings1: COMSETTINGS; (*Ïàðàìåòðû ïîðòà *)
COM_SERVICE1: COM_SERVICE; (*Áëîê îòêðûòèÿ è íàñòðîéêè ïîðòà *)
com_ready1: BOOL; (*Ñòàòóñ ïîðòà - îòêðûò/çàêðûò*)
UNI:MB_UNI_IO;
i: BYTE;
command_word:WORD:=16#847C;
RT: R_TRIG;
t_zad:TIME:=T#20ms;
buffer: ARRAY[0..255] OF BYTE;
result: ARRAY[0..255] OF BYTE;
id: ARRAY[0..255] OF BYTE;
mode: MB_MODE := MB_RTU;
data_size: BYTE := 17;
compl: BOOL;
except: BYTE;
port_opened: BOOL;
mtype: INT;
crc: WORD;
crc1: WORD;
END_VAR
В принципе, в Тилкомовской документации приводятся примеры посылаемых команд даже с контрольной суммой, но я посчитал, что будет правильнее считать её. В коде специально оставил закомментированной контрольную сумму из документации.Код:(*****************************************************
Ïðèìåð ðàáîòû ñ áèáëèîòåêîé SysLibCom
ôîðìèðîâàíèå êîìàíäû â äâîè÷íîì âèäå
*****************************************************)
(*******************************************************
Îòêðûâàåì ïîðò
*******************************************************)
(*Îòêðûâàåì ïåðâûé ïîðò*)
IF NOT com_ready1 THEN
(*
Íîìåð ïîðòà (com_number):
0 - RS-485
1 - RS-232
4 - RS-232 DEBUG
*)
com_num1 := 0;
(*
Íàñòðîéêè ïîðòà (com_settings):
byParity - Ðåæèì ïðîâåðêè ÷åòíîñòè 0 = íåò, 1 = íå÷åò, 2 = ÷åò
byStopBits - Êîë-âî ñòîïîâûõ áèò 0 =îäèí, 1=ïîëòîðà , 2=äâà
dwBaudRate - Ñêîðîñòü îáìåíà 4800, 9600, 19200, 38400, 57600, 115200 áèò/ñ.
dwBufferSize - Íå èñïîëüçóåòñÿ äîëæíî áûòü =0
dwScan - Íå èñïîëüçóåòñÿ äîëæíî áûòü =0
dwTimeout - Íå èñïîëüçóåòñÿ äîëæíî áûòü =0
Port - Íîìåð ïîðòà â ôîðìàòå ïåðå÷èñëåíèÿ PORTS (com_number)
*)
Settings1.Port:=com_num1;
Settings1.dwBaudRate:=115200;
Settings1.byParity:=0;
Settings1.dwTimeout:=0;
Settings1.byStopBits:=0;
Settings1.dwBufferSize:=0;
Settings1.dwScan:=0;
(*
Íàñòðîéêà è îòêðûòèå ïîðòà (COM_SERVICE)
Ïîêà íà âûõîäå Ready íå áóäåò ñèãíàë TRUE, ñòó÷èìñÿ â ïîðò
Ïîðò îòêðûâàåòñÿ ñ íàñòðîéêàìè, óêàçàííûìè â com_settings,
à íà âõîä Task ïîäàþòñÿ ñëåäóþùèå çíà÷åíèÿ:
0 - Îòêðûòèå è íàñòðîéêà ïîðòà â ñîîòâåòñòâèè ñ íàñòðîéêàìè â ñòðóêòóðå Settings
1 - Èçìåíåíèå íàñòðîåê óæå îòêðûòîãî ïîðòà íà íàñòðîéêè óêàçàííûå â Settings
2 - Çàêðûòèå ïîðòà, íîìåð ïîðòà áåðåòñÿ èç Settings.Port
*)
COM_SERVICE1(Enable:=TRUE , Settings:=Settings1 , Task:=OPEN_TSK );
IF COM_SERVICE1.Ready THEN
COM_SERVICE1.Enable := FALSE;
com_ready1:=TRUE;
END_IF
END_IF
(*******************************************************
Ðàáîòà ñ ïîðòîì
*******************************************************)
IF (com_ready1=TRUE )THEN
CASE mtype OF
0:
IF NOT UNI.Active THEN
buffer[0] := 1;
buffer[1] := 101;
buffer[2] := 12;
buffer[3] := 0;
buffer[4] := 1;
buffer[5] := 0;
buffer[6] := 0;
buffer[7] := 0;
buffer[8] := 0;
buffer[9] := 0;
buffer[10] := 16#F4;
buffer[11] := 16#1;
buffer[12] := 0;
buffer[13] := 0;
buffer[14] := 0;
crc := MB_CRC(ADR(buffer[0]), 15);
SysMemCpy(ADR(buffer[15]), ADR(crc), 2);
(* buffer[15] := 145;
buffer[16] := 185; *)
data_size := 17;
END_IF
UNI(
Mode:=mode ,
ComHandle:=com_num1,
TimeOut:=t_zad,
DataBuf := buffer,
DataSize := data_size,
Complete := compl,
Exception := except
);
RT(CLK:=compl);
IF rt.Q THEN
MB_MOVED(ADR(result[0]), ADR(buffer[0]), data_size+2);
IF result[3] = 0 THEN
mtype :=1;
END_IF
END_IF
1:
IF NOT UNI.Active THEN
buffer[0] := 1;
buffer[1] := 16#67;
buffer[2] := 0;
crc1 := MB_CRC(ADR(buffer[0]), 3);
SysMemCpy(ADR(buffer[3]), ADR(crc1), 2);
(* buffer[15] := 145;
buffer[16] := 185; *)
data_size := 5;
END_IF
UNI(
Mode:=mode ,
ComHandle:=com_num1,
TimeOut:=t_zad,
DataBuf := buffer,
DataSize := data_size,
Complete := compl,
Exception := except
);
RT(CLK:=compl);
IF rt.Q THEN
MB_MOVED(ADR(id[0]), ADR(buffer[0]), data_size+2);
mtype :=2;
END_IF
2:
IF NOT UNI.Active THEN
buffer[0] := 1;
buffer[1] := 16#6B;
buffer[2] := 0;
crc := MB_CRC(ADR(buffer[0]), 3);
SysMemCpy(ADR(buffer[3]), ADR(crc), 2);
(* buffer[3] := 16#0A;
buffer[4] := 16#30;*)
data_size := 5;
END_IF
UNI(
Mode:=mode ,
ComHandle:=com_num1,
TimeOut:=t_zad,
DataBuf := buffer,
DataSize := data_size,
Complete := compl,
Exception := except
);
RT(CLK:=compl);
IF rt.Q THEN
MB_MOVED(ADR(result[0]), ADR(buffer[0]), data_size+2);
SysMemCpy(ADR(Torque), ADR(result[11]), 4);
SysMemCpy(ADR(Speed), ADR(result[19]), 4);
SysMemCpy(ADR(Temper), ADR(result[15]), 4);
ELSE
IF except <> 0 THEN
Torque := 0;
Speed := 0;
Temper := 0;
END_IF
END_IF
END_CASE
END_IF
Когда все стандартные вещи реализуются через расширения это уже сложно назвать модбасом. Как бы ни было, отличная находка, спасибо.Цитата:
В протоколе действительно зарезервированы номера функций 101-110 и 66-69 (могу ошибаться в диапазоне) для расширений производителя.
madiggo а вы не могли бы код выложить, чтобы коменты на русском были ? :)
На всякий случай, тут расшифровщик: https://www.artlebedev.ru/tools/decoder/
Код:FUNCTION_BLOCK MB_UNI_IO
VAR_INPUT
Mode: MB_MODE; (* Serial Transmission Mode of MODBUS networks *)
ComHandle:DWORD; (* дескриптор последовательного порта библиотеки SysLibCom *)
TimeOut: TIME; (* время тайм-аута [мс] - макс. задержка на обработку запроса *)
END_VAR
VAR_IN_OUT
Complete: BOOL; (* если = TRUE, то обмен завершен *)
Exception: BYTE; (* исключения протокола MODBUS *)
DataBuf: ARRAY[0..255] OF BYTE; (* буфер данных кадра *)
DataSize: BYTE; (* размер кадра без контрольной суммы *)
END_VAR
Код:PROGRAM PLC_PRG
VAR
(*Пример работы с частотным приводом ОВЕН ПЧВ по RS-485*)
com_num1: PORTS; (*Номер порта на который подключено оборудование*)
com_hndl: DWORD;
Settings1: COMSETTINGS; (*Параметры порта *)
COM_SERVICE1: COM_SERVICE; (*Блок открытия и настройки порта *)
com_ready1: BOOL; (*Статус порта - открыт/закрыт*)
UNI:MB_UNI_IO;
i: BYTE;
command_word:WORD:=16#847C;
RT: R_TRIG;
t_zad:TIME:=T#20ms;
buffer: ARRAY[0..255] OF BYTE;
result: ARRAY[0..255] OF BYTE;
id: ARRAY[0..255] OF BYTE;
mode: MB_MODE := MB_RTU;
data_size: BYTE := 17;
compl: BOOL;
except: BYTE;
port_opened: BOOL;
mtype: INT;
crc: WORD;
crc1: WORD;
END_VAR
Код:(*****************************************************
Пример работы с библиотекой SysLibCom
формирование команды в двоичном виде
*****************************************************)
(*******************************************************
Открываем порт
*******************************************************)
(*Открываем первый порт*)
IF NOT com_ready1 THEN
(*
Номер порта (com_number):
0 - RS-485
1 - RS-232
4 - RS-232 DEBUG
*)
com_num1 := 0;
(*
Настройки порта (com_settings):
byParity - Режим проверки четности 0 = нет, 1 = нечет, 2 = чет
byStopBits - Кол-во стоповых бит 0 =один, 1=полтора , 2=два
dwBaudRate - Скорость обмена 4800, 9600, 19200, 38400, 57600, 115200 бит/с.
dwBufferSize - Не используется должно быть =0
dwScan - Не используется должно быть =0
dwTimeout - Не используется должно быть =0
Port - Номер порта в формате перечисления PORTS (com_number)
*)
Settings1.Port:=com_num1;
Settings1.dwBaudRate:=115200;
Settings1.byParity:=0;
Settings1.dwTimeout:=0;
Settings1.byStopBits:=0;
Settings1.dwBufferSize:=0;
Settings1.dwScan:=0;
(*
Настройка и открытие порта (COM_SERVICE)
Пока на выходе Ready не будет сигнал TRUE, стучимся в порт
Порт открывается с настройками, указанными в com_settings,
а на вход Task подаются следующие значения:
0 - Открытие и настройка порта в соответствии с настройками в структуре Settings
1 - Изменение настроек уже открытого порта на настройки указанные в Settings
2 - Закрытие порта, номер порта берется из Settings.Port
*)
COM_SERVICE1(Enable:=TRUE , Settings:=Settings1 , Task:=OPEN_TSK );
IF COM_SERVICE1.Ready THEN
COM_SERVICE1.Enable := FALSE;
com_ready1:=TRUE;
END_IF
END_IF
(*******************************************************
Работа с портом
*******************************************************)
IF (com_ready1=TRUE )THEN
CASE mtype OF
0:
IF NOT UNI.Active THEN
buffer[0] := 1;
buffer[1] := 101;
buffer[2] := 12;
buffer[3] := 0;
buffer[4] := 1;
buffer[5] := 0;
buffer[6] := 0;
buffer[7] := 0;
buffer[8] := 0;
buffer[9] := 0;
buffer[10] := 16#F4;
buffer[11] := 16#1;
buffer[12] := 0;
buffer[13] := 0;
buffer[14] := 0;
crc := MB_CRC(ADR(buffer[0]), 15);
SysMemCpy(ADR(buffer[15]), ADR(crc), 2);
(* buffer[15] := 145;
buffer[16] := 185; *)
data_size := 17;
END_IF
UNI(
Mode:=mode ,
ComHandle:=com_num1,
TimeOut:=t_zad,
DataBuf := buffer,
DataSize := data_size,
Complete := compl,
Exception := except
);
RT(CLK:=compl);
IF rt.Q THEN
MB_MOVED(ADR(result[0]), ADR(buffer[0]), data_size+2);
IF result[3] = 0 THEN
mtype :=1;
END_IF
END_IF
1:
IF NOT UNI.Active THEN
buffer[0] := 1;
buffer[1] := 16#67;
buffer[2] := 0;
crc1 := MB_CRC(ADR(buffer[0]), 3);
SysMemCpy(ADR(buffer[3]), ADR(crc1), 2);
(* buffer[15] := 145;
buffer[16] := 185; *)
data_size := 5;
END_IF
UNI(
Mode:=mode ,
ComHandle:=com_num1,
TimeOut:=t_zad,
DataBuf := buffer,
DataSize := data_size,
Complete := compl,
Exception := except
);
RT(CLK:=compl);
IF rt.Q THEN
MB_MOVED(ADR(id[0]), ADR(buffer[0]), data_size+2);
mtype :=2;
END_IF
2:
IF NOT UNI.Active THEN
buffer[0] := 1;
buffer[1] := 16#6B;
buffer[2] := 0;
crc := MB_CRC(ADR(buffer[0]), 3);
SysMemCpy(ADR(buffer[3]), ADR(crc), 2);
(* buffer[3] := 16#0A;
buffer[4] := 16#30;*)
data_size := 5;
END_IF
UNI(
Mode:=mode ,
ComHandle:=com_num1,
TimeOut:=t_zad,
DataBuf := buffer,
DataSize := data_size,
Complete := compl,
Exception := except
);
RT(CLK:=compl);
IF rt.Q THEN
MB_MOVED(ADR(result[0]), ADR(buffer[0]), data_size+2);
SysMemCpy(ADR(Torque), ADR(result[11]), 4);
SysMemCpy(ADR(Speed), ADR(result[19]), 4);
SysMemCpy(ADR(Temper), ADR(result[15]), 4);
ELSE
IF except <> 0 THEN
Torque := 0;
Speed := 0;
Temper := 0;
END_IF
END_IF
END_CASE
END_IF
Отличная ссылка, спасибо.
Отличная статья, спасибо Yegor
Всем доброго дня и с наступающим праздником! спасибо автору действительно отличная статья, но к сожалению в моем случае немного не подходит, не сталкивался ли кто с аналогичной проблемой при использовании СПК? есть ли кого примеры использования библиотеки CAA SerialCom?
У меня стоит задача подключение стороннего цифрового датчика с протоколом обмена UAI к СПК107, датчик кстати отечественный, однако заводом предусмотрено подключение только к ПК с помощью специального преобразователя, как поделилась тех поддержка производителя обмен происходит по RS232 и в качестве примера выслал несколько команд, меня собственно тоже интересует открытие порта в момент включения и съем показаний пока не снимется питание.
Командами 37 — чтение и 38 — запись
пример чтения параметров
запрос «:01;37;00001E;41405»
ответ «!1;01;44032»
Буду очень признателен за любую информацию по теме.
Добрый день. См. документацию:
http://ftp.owen.ru/index.html/CoDeSy...cols_v.1.0.pdf
Спасибо, этот документ читал, но к сожалению, ввиду малого опыта, многое моменты остались непонятны. Может есть живой пример на CFC?