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
Последний раз редактировалось madiggo; 23.06.2016 в 14:32.
Когда все стандартные вещи реализуются через расширения это уже сложно назвать модбасом. Как бы ни было, отличная находка, спасибо.В протоколе действительно зарезервированы номера функций 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
Связь со мной: telegram: @JuneSmellsLikeBlood | e-mail: e.kislov@owen.ru (личка на форуме - не подходит)
Раздел CDS V3.5 на сайте | Основные темы по CDS V3.5 на форуме: Вопросы и ответы | Визуализация | Настройка обмена с другими устройствами
Repository Archive V3.5 SP4 (необходим для СПК207/СПК1хх без Eth/ПЛК3xx)
oscat.ru | Как обратиться в техподдержку? | Как отлаживать ошибки | Отладка проектов в CODESYS V3.5 | Проблема XY | Как правильно задавать вопросы | AnyDesk
Спасибо, этот документ читал, но к сожалению, ввиду малого опыта, многое моменты остались непонятны. Может есть живой пример на CFC?