PDA

Просмотр полной версии : ПЛК304 + ModBus.compiled-library



Jumo
02.12.2011, 06:01
Здравствуйте господа и дамы, прошу поделится рабочим примером работы с библиотекой ModBus. Пытаюсь осуществить связь с ТРМ201 по протоколу ModBusRtu. Первый раз мне повезло и соединение было установлено, но затем снова появилась ошибка 255, увеличение таймаута не помогло. Может быть кто-нибудь укажет мне на ошибку, которую я найти не могу.
Код программы следующий:

PROGRAM PLC_PRG
VAR
GetTemp: ModBus.MB_RD_HOLD_REGS; (*функция 03 - чтение параметра типа INT*)
Connection1: ComConn; (*Функциональные блок открытия порта*)
Buffer: ARRAY[0..255] OF BYTE; (*байтовый буфер данных *)
ConnectionClose: ComClose; (*Функциональный блок закрытия последовательного порта*)
cmpl: BOOL;
DataSize: WORD;
x: WORD;
TimeOut: ModBus.SysCom.COM_Timeout;
Err: INT;
Timer1:ton;
b:BOOL;
name: DWORD;
h: SysFile.RTS_IEC_RESULT;
FileHandle : SysFile.RTS_IEC_HANDLE;
TextTest: STRING:='';
TextTest1: STRING:='/mnt/usb1/';
TextTest2: STRING:='ar1';
t: INT:=1;
END_VAR
VAR_INPUT
END_VAR


//Если порт закрыт, то откроем его
IF Connection1.done = FALSE THEN
Connection1(enable:=TRUE, PortNum:=2);
//Открываем первый физический порт
//Все остальные настройки порта оставляем по умолчанию
IF Connection1.Done=TRUE THEN
ModBus.SysCom.SysComPurge (Connection1.Handle); //очищаем буфер порта
TimeOut:=0; // Время для функций read write
END_IF
END_IF

//blinker.TIMEHIGH:=T#5S;
//blinker.TIMELOW:=T#1S;
//blinker(ENABLE:=TRUE);

//rtrig(CLK:=blinker.OUT);

IF (Connection1.Done=TRUE) THEN
GetTemp(
Enable:=1 , (*разрешение работы блока *)
Mode:=MB_RTU , (*режим передачи*)
DevAddr:=1 , (*адрес*)
FirstAddr:=1 , (*номер регистра*)
Quantity:=1, (*количество регистров*)
ComHandle:=Connection1.Handle, (*номер COM-порта*)
TimeOut:=T#50MS , (*Таймаут T#50ms*)
Buffer:=Buffer , (*буфер данных *)
Complete=>cmpl , (*скопировать признак завершения операции *)
Exception=>err , (*скопировать регистр ошибок *)
ByteCnt=>DataSize ); (*кол-во считанных байтов *)
END_IF;

//если установлен признак завершения операции, то
IF cmpl THEN
IF err=0 THEN (*Если нет ошибок, то получаем данные из буфера типа INT*)
x:=BYTE_TO_WORD(BUFFER[1]) OR SHL(BYTE_TO_WORD(BUFFER[0]),8);
test:=x/INT_TO_REAL(10);
END_IF
END_IF

Функциональный блок ComConn:
FUNCTION_BLOCK ComConn
VAR_INPUT
Enable: BOOL; (*Разрешение работы блока*)
PortNum: ModBus.SysCom.COM_Ports:=2; (*Номер порта на ПЛК, на ПЛК 304 это порт 2*)
PortBaudrate: ModBus.SysCom.COM_Baudrate:=19200; (*Скорость работы порта, по умолчанию 19.2 кбод*)
PortParity: ModBus.SysCom.COM_Parity:=0; (*Режим проверки на четнось: 0-нет; 1- нечет; 2- чет,
по умолчанию нет проверки на четность*)
PortStopBits: ModBus.SysCom.COM_StopBits:=0; (*Количество стоп-бит: 1- 1 бит; 2- 1.5 бита; 3- 2 бита,
по умолчанию 1 стоп-бит*)
PortByteSyze: BYTE:=8; (*Размер посылки в байтах*)
END_VAR
VAR_OUTPUT
Handle: ModBus.SysCom.RTS_IEC_HANDLE; (*Идентификатор открытого порта, если ошибка, то все F*)
Done: BOOL:=FALSE; (*Флаг завершения операции*)
ErrCode: ModBus.SysCom.RTS_IEC_RESULT; (*Код ошибок*)
END_VAR
VAR
Settings: ModBus.SysCom.COM_Settings; (*Настройки порта*)
SettingsEX: Modbus.SysCom.COM_SettingsEx; (*Расширенные настройки порта*)
Result: ModBus.SysCom.RTS_IEC_RESULT; (**)
Rtrig: ModBus.R_TRIG;
Trig: rs;
END_VAR

Rtrig(clk:=(Enable AND NOT done));
Trig(set:=Rtrig.q, RESET1:=FALSE);
IF Trig.Q1 THEN
Settings.sPort:= PortNum; (*Инициализируем номер порта*)
Settings.ulBaudrate:= PortBaudrate; (*Инициализируем скорость работы порта*)
Settings.byParity:= PortParity; (*Настройка проверки четности порта*)
Settings.ulTimeout:=0;
Settings.byParity:= PortStopBits; (*Настройка количества стоп-бит*)
Settings.ulBufferSize:= 0; (*Размер буфера*)
SettingsEx.byByteSize:= PortByteSyze; (*Размер посылки данных*)
SettingsEx.bBinary := TRUE;
SettingsEx.bDtrControl := FALSE;
SettingsEx.bRtsControl := FALSE;
SettingsEx.bOutxCtsFlow := FALSE;
SettingsEx.bOutxDsrFlow := FALSE;
SettingsEx.bDsrSensitivity := FALSE;
//Переходим непосредственно к открытию порта
Handle:=ModBus.SysCom.SysComOpen2(ADR(Settings),AD R(SettingsEx),ADR(ErrCode));

//Если порт открыт, то переходим к приему передачи данных
IF (Handle<>16#FFFFFFFF) THEN
//Если условие не выполняется, то порт занят
Done:= TRUE;
Trig(RESET1:=TRUE);
ELSE
Done:=FALSE;
END_IF
END_IF

P.S. Пример, приложенный на диске с контроллером, не работает :(.

Александр123456
02.12.2011, 06:59
Как я тебя понимаю!!!!!! Тоже уже два дня сижу, а результата ноль!!! ПОМОГИТЕ КТО ЗНАЕТ!!!

Александр123456
02.12.2011, 07:08
У меня такая прога:

PROGRAM PLC_PRG
VAR
get1_modbus: MB_RD_HOLD_REGS; (*функция 03 - чтение параметра типа INT*)
get2_modbus: MB_RD_INP_REGS; (*функция 04 - чтение трех параметров типа INT*)

Buffer: ARRAY[0..255] OF BYTE; (* байтовый буфер данных *)
cmpl: BOOL;
port_opened: BYTE := 0;
Init: BOOL; (* признак инициализации пользовательской программы *)
Settings:modbus.SysCom.COM_Settings;(* настройки последовательного порта *)
com_num: modbus.SysCom.COM_Ports:=2; (*2 - RS-485, 3,4,5 - RS-232*)
enabl: BOOL; (*состояние работы блока*)
err: INT; (*номер ошибки*)
TimeOut: TIME:=T#100mS;(*таймаут*)
Exception: BYTE;
DataSize: WORD;
master1: BYTE:= 1;


x:WORD; (*считанное значение*)
x1: WORD; (*считанное значение*)
x2: WORD; (*считанное значение*)
x3: WORD; (*считанное значение*)


COM_SERVICE1: COM_SERVICE;

END_VAR

(*Устанавливаем настройки COM-порта*)
IF port_opened=0 THEN
Settings.sPort:=com_num; (*номер COM-порта*)
Settings.ulBaudrate:=9600; (*скорость*)
Settings.byParity:=0;
Settings.ulTimeout:=0;
Settings.byStopBits:=1;
Settings.ulBufferSize:=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: (* функция 03 инт - ФБ считывает значение параметра типа int из прибора с адресом 2 в регистр с номером 8 по протоколу Modbus-ASCII*)
get1_modbus(
Enable:=enabl , (* разрешение работы блока *)
Mode:=MB_RTU , (*режим передачи*)
DevAddr:=1 , (*адрес*)
FirstAddr:=1 , (*номер регистра*)
Quantity:=1, (*количество регистров*)
ComHandle:=Settings.sPort ,(*номер COM-порта*)
TimeOut:=TimeOut , (*Таймаут T#50ms*)
Buffer:=Buffer , (* буфер данных *)
Complete=>cmpl , (* скопировать признак завершения операции *)
Exception=>err , (* скопировать регистр ошибок *)
ByteCnt=>DataSize ); (*кол-во считанных байтов *)
(*если установлен признак завершения операции, то *)
IF cmpl THEN
IF err=0 THEN (*Если нет ошибок, то получаем данные из буфера типа INT*)
x:=BYTE_TO_WORD(BUFFER[1]) OR SHL(BYTE_TO_WORD(BUFFER[0]),8);
END_IF
master1:=1; (*переходим к выполнению следующего ФБ*)
END_IF

1: (* функция 04 инт - ФБ считывает значения трех параметров типа Int из прибора с адресом 2 начиная с регистра с номeром 12*)
get2_modbus(
Enable:= enabl, (* разрешение работы блока *)
Mode:=MB_RTU , (*режим передачи*)
DevAddr:=1 , (*адрес*)
FirstAddr:=0 , (*номер регистра*)
Quantity:=3 , (*количество регистров*)
ComHandle:= Settings.sPort,(*номер 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);
x2:=BYTE_TO_WORD(BUFFER[5]) OR SHL(BYTE_TO_WORD(BUFFER[4]),8);
x3:=BYTE_TO_WORD(BUFFER[9]) OR SHL(BYTE_TO_WORD(BUFFER[8]),8);
END_IF
master1:=0;(*переходим к выполнению следующего ФБ*)
END_IF
END_CASE

IF enabl = FALSE THEN
enabl := TRUE;
END_IF

IF err <> 0 THEN
enabl := FALSE;
END_IF

END_IF

Александр123456
02.12.2011, 07:10
А если указываю порт Р2,Р3,Р4 то библиотека вообще перестает работать!!

Jumo
02.12.2011, 07:28
ComHandle:= Settings.sPort,(*номер COM-порта*)

Здесь у них ошибка, это не номер порта, это его идентификатор.
Один раз у меня библиотека заработала, затем перестала. Пока еще не выяснил причину.

Александр123456
02.12.2011, 07:29
Подключаю к ПЛК110 по RS485 либо по RS232 никакого результата, АС4-м читаю без проблем.

Jumo
02.12.2011, 07:29
COM_SERVICE1(Enable:=(port_opened=0) , Settings:=Settings , Task:=OPEN_TSK );
При использовании этого блока, порт у меня открывался не с первого раза, поэтому я от него отказался.

Jumo
02.12.2011, 07:31
Подождем ответа модератора, может быть скажет что-нибудь вразумительное. Есть подозрения что библиотека для работы с modbus глючная.

Александр123456
02.12.2011, 07:33
Порты у меня открываются без проблем, но дальше ничего.

Jumo
02.12.2011, 07:33
Повезло, мне пришлось ручками все делать. А внутри функционального блока modbus попробуй исправить номер порта на его идентификатор, возможно поможет, у меня в первый раз все заработало, но после сброса контроллера обмен данными прекратился.

Jumo
02.12.2011, 08:06
Ну отзовитесь же кто-нибудь, ведь этот контроллер заточен под работу с этим интерфейсом, расскажите как его оживить??!!!!!

Малышев Олег
02.12.2011, 09:39
нужно найти адаптер 485 и посмотреть что идет в порты - возможно прибор идут искажения в линии нужно поставить терминаторы (если на столе то не нужно)

Jumo
02.12.2011, 10:02
Проблема в том, что до определенного момента все работало на этом кабеле, так что вариант с распиновкой не проходит.

Александр123456
02.12.2011, 10:03
Итак
1) Проблема может быть совсем не в программе - вполне возможно это проблема в соединении. Если у вас ПЛК304-M01 то схема 485 в руководстве неверна. Нужно переобжать кабель - если повернуть разъем RJ-45, который устанавливается в ПЛК контактами к себе а кабелем вниз, перенумеровать контакты слева направо, то для 485 А(+)=8 контакт Б(-)=6 контакт.
2) Опять таки для 304 - М01 если Вы установили JP1 (или JP4) в ON после загрузки ПЛК порты все равно остаются в 232 режиме. Следует перезагрузится.
3) Адаптер 485 нужно найти и посмотреть что идет в порты - возможно прибор идут искажения в линии нужно поставить терминаторы (если на столе то не нужно)

Да, версия М01. А теперь можно поподробнее о том как должны стоять джемпера для работы того или иного интерфейса.

Александр123456
02.12.2011, 11:27
нужно найти адаптер 485 и посмотреть что идет в порты - возможно прибор идут искажения в линии нужно поставить терминаторы (если на столе то не нужно)

Распиновку поменял, A-8 B-6, джемпера все отключены. В порт ничего не идет!!!

Jumo
02.12.2011, 11:55
Наличие сигнала лучше всего проверить осциллографом. У меня возникает другая проблема, запрос посылается, но ответа не приходит.

Евгений Сергеевич
02.12.2011, 12:05
Здравствуйте.
На счет ПЛК 304 М01 это Олег погорячился(
Этот прибор следующая итерация и он не продается так что распиновку менять не надо.

Смотрели ли вы пример на сайте по опросу модуля МВА8?

http://www.owen.ru/catalog/44162596
http://www.kipshop.ru/CoDeSys3.0/Video/codesys-3.0-video-1.zip
http://kipshop.ru/CoDeSys3.0/Sample/ip_codesys_plc304_opros_moduley.zip

полномодемный порт второй согласно описанию.

джамперы
все вверх - off - 485
все вниз - on - 232

Jumo
02.12.2011, 12:42
Эти примеры я смотрел, хотелось бы увидеть что-нибудь более универсальное на языке st, пожалуйста покажите рабочий пример для работы с библиотекой modbus.

P.S. Набор устройств работающий по шине rs-485 не ограничивается модулями ОВЕН.

Евгений Сергеевич
02.12.2011, 13:19
библиотека открытая. надо что-то другое открыли изменили адреса регистров и их количество, переименовали и все. сама же библиотека и есть пример работы с библиотекой модбас.

Jumo
02.12.2011, 13:28
Понял, посмотрю в случае успеха отпишусь.
Но все таки возникает вопрос: почему на диске совершенно левый пример.

Евгений Сергеевич
02.12.2011, 13:30
пример опроса ТРМ202

Открыть File / Project Archive / Extraxt Archive...