PDA

Просмотр полной версии : ПЛК63 + МВ110-8АС + МУ110-8И + МК110-8ДН-4Р опрос по modbus



Егор_Егор
25.07.2018, 15:34
Здравствуйте! Прошу помощи в опросе МВ110-8АС с ПЛК63 по модбус. Связь с модулями есть - лампочки RS-485 мигают. из кучи примеров найденных на форуме слепил это, но никак не могу разобраться с указателями и буфером МВ110-8АС и МУ110-8И. С дискретными входами/выходами МК110 разобрался - все работает, но никак не удается получить значения с аналоговых входов.


VAR
get1_modbus: MB_RD_HOLD_REGS; (*МВ110.8АС*) (*функция 04 - чтение параметров float*)
send2_modbus: MB_WR_REGS; (*МУ110.8И*) (*функция 16 - запись параметров float*)
get3_modbus: MB_RD_HOLD_REGS; (*МК110.8ДН.4Р*) (*функция 04 - чтение параметров типа int*)
send4_modbus: MB_WR_REGS; (*МК110.8ДН.4Р*) (*функция 16 - запись параметров int*)
Buffer: ARRAY[0..255] OF BYTE; (* байтовый буфер данных *)




cmpl: BOOL;
port_opened: BYTE := 0;
Init: BOOL; (* признак инициализации пользовательской программы *)
Settings:COMSETTINGS; (* настройки последовательного порта *)
com_num: PORTS:=0; (*0 - RS-485, 1 - RS-232*)
enabl: BOOL; (*состояние работы блока*)
err: INT; (*номер ошибки*)
TimeOut: TIME:=T#50ms; (*таймаут*)
Exception: BYTE;
DataSize: WORD;
master1: BYTE:= 1;

COM_SERVICE1: COM_SERVICE;
ptr_D:POINTER TO BYTE;


(* Каналы модуля МВ110 8АС *)
i : BYTE;
pAI : POINTER TO BYTE;
pDiag : POINTER TO BYTE;
x: ARRAY[1..8] OF REAL;
ReciveBuffer : ARRAY[0..255] OF BYTE; (* Буфер ответов*)
SendBuffer : ARRAY[0..255] OF BYTE; (* Буфер посылок *)
AI : ARRAY[1..8] OF INT; (* Данные с каналов модуля*)
Diag : ARRAY[1..8] OF INT; (* Диагностические данные с каналов модуля*)


(* Каналы модуля МУ110 8И *)
pAO : POINTER TO BYTE;
y: ARRAY[1..8] OF REAL;

(* Каналы модуля МК110.8ДН.4Р *)
dwDI : WORD; (* Данные с входов модуля в формате word*)
DI : ARRAY[1..8] OF BOOL; (* Данные с входов модуля*)
DICntr : ARRAY[1..16] OF WORD; (* Счетчики входов модуля *)
pData : POINTER TO BYTE;
END_VAR


(*Устанавливаем настройки 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:=enabl , (* разрешение работы блока *)
Mode:=MB_RTU , (*режим передачи*)
DevAddr:=adr1 , (*адрес*)
FirstAddr:=100 , (*номер регистра*)
Quantity:=1, (*количество регистров*)
ComHandle:=Settings.Port ,(*номер COM-порта*)
TimeOut:=TimeOut , (*Таймаут T#50ms*)
Buffer:=Buffer , (* буфер данных *)
Complete=>cmpl , (* скопировать признак завершения операции *)
Exception=>err , (* скопировать регистр ошибок *)
ByteCnt=>DataSize ); (*кол-во считанных байтов *)
(*если установлен признак завершения операции, то *)
IF cmpl THEN
master1:=1;(*переходим к выполнению следующего ФБ*)
IF err=0 THEN (*Если нет ошибок, то получаем данные из буфера типа FLOAT*)
FOR i := 1 TO 8 DO
pAI := ADR(AI[i]);
pAI^ := Buffer[(i-1)*4 + 1];
pAI := pAI + 1;
pAI^ := Buffer[(i-1)*4];

pDiag := ADR(Diag[i]);
pDiag^ := ReciveBuffer[(i-1)*2 + 33];
pDiag := pDiag + 1;
pDiag^ := ReciveBuffer[(i-1)*2 + 32];
END_FOR;
END_IF
END_IF

1:
(*запись в буффер параметра типа Float*)
pAO:=ADR(y);
buffer[5] := pAO^;
pAO:=pAO+1;
buffer[4] := pAO^;
pAO:=pAO+1;
buffer[7] := pAO^;
pAO:=pAO+1;
buffer[6] := pAO^;

send2_modbus(
Enable:= enabl, (* разрешение работы блока *)
Mode:=MB_RTU , (*режим передачи*)
DevAddr:=adr2 , (*адрес*)
FirstAddr:= 0, (*номер регистра*)
Quantity:= 6, (*количество записываемых регистров*)
ComHandle:=Settings.Port ,(*номер сом-порта*)
TimeOut:=TimeOut , (*таймаут T#50ms*)
Buffer:=Buffer , (* буфер данных *)
Complete=>cmpl , (* скопировать признак завершения операции *)
Exception=>err , (* скопировать регистр ошибок *)
RegCnt=> DataSize); (*кол-во считанных байтов *)
(*если установлен признак завершения операции, то *)
IF cmpl THEN
master1:=2;(*переходим к выполнению следующего блока*)
END_IF


2:

get3_modbus(
Enable:= enabl, (* разрешение работы блока *)
Mode:=MB_RTU , (*режим передачи*)
DevAddr:=adr3 , (*адрес*)
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*)
dwDI:=BYTE_TO_WORD(BUFFER[1]) OR SHL(BYTE_TO_WORD(BUFFER[0]),8);
END_IF
master1:=3;
END_IF

3:

(*Пишем в буфер отправки битовую маску*)
ptr_D:=ADR(mk_mask_in);
Buffer[1]:=ptr_D^;
ptr_D:=ptr_D+1;
Buffer[0]:=ptr_D^;
(*Выполняем отправку*)
send4_modbus(
Enable:= enabl, (* разрешение работы блока *)
Mode:=MB_RTU , (*режим передачи*)
DevAddr:=adr3 , (*адрес*)
FirstAddr:=50 , (*номер регистра*)
Quantity:=1 , (*количество регистров*)
ComHandle:= Settings.Port,(*номер COM-порта*)
TimeOut:=TimeOut , (*Таймаут T#50ms*)
Buffer:=Buffer , (* буфер данных *)
Complete=>cmpl , (* скопировать признак завершения операции *)
Exception=>err , (* скопировать регистр ошибок *)
RegCnt=> DataSize); (*кол-во считанных байтов *)
(*если установлен признак завершения операции, то *)
IF cmpl THEN
master1:=0;(*переходим к выполнению следующего блока*)
END_IF
END_CASE

IF enabl = FALSE THEN
enabl := TRUE;
END_IF

IF err <> 0 THEN
enabl := FALSE;
END_IF
(*Разбираем битовую маску входов МК110.8ДН.4Р*)
A4_in1:=dwDI.0;
A4_in2:=dwDI.1;
A4_in3:=dwDI.2;
A4_in4:=dwDI.3;
A4_in5:=dwDI.4;
A4_in6:=dwDI.5;
A4_in7:=dwDI.6;
A4_in8:=dwDI.7;
END_IF

Трофимов Артем
25.07.2018, 16:13
(* Каналы модуля МУ110 8И *)
pAO : POINTER TO BYTE;
y: ARRAY[1..8] OF REAL;

зачем это? у модуля 8И регистры типа WORD
сделайте y: ARRAY[1..8] OF WORD; подайте значение от 0 до 1000 (0,0.. 100.0%)

Quantity:= 8 (8 же каналов а не 6), (*количество записываемых регистров*)
Buffer:=ADR(y) ,

и будете записывать. не представляю что Вы в модуль записываете. у Вас скорей всего err не равен 0 , т.е. ошибка какая то происходит.
cml выставится и при наличии ошибки

Егор_Егор
27.07.2018, 10:01
Спасибо, с записью вроде понял, но проверить сейчас нет возможности. А как быть с чтением с МВ1108АС? в примерах есть опрос одного регистра, но мне надо считывать значения со всех 8 входов.

Трофимов Артем
27.07.2018, 10:26
сразу и не заметил. у Вас ошибка в адресе регистра 8АС. в РЭ стоит 0х100 , а у Вас просто 100...
приставка 0х говорит о том , что число в шестнадцатеричной системе исчисления, а не десятеричной , поэтому либо переводите в десятеричну , т.е адрес окажется 256м, либо в кодесис пишите 16#100 (в кодесис директива 16# указана согласно МЭК стандартам языка и она эквивалентна общепринятым в других стандартах 0х).
в количестве регистров укажите 8 а не 1, будете читать все 8 каналов. учтите, данных придёт в 8 раз больше и надо будет их парсить, как у Вас в коде для одного канала, также для всех( просто сдвигая индескы буфера)

Егор_Егор
27.07.2018, 14:04
да, ошибку в адресе регистра я тоже нашел. Но судя по РЭ МВ110-8АС измеренное значение 1го канала это 0х120, 0х121, 0х122, или 288, 289, 290 регистры, 2го канала это 0х123, 0х124, 0х125, или 291, 292, 293 регистры и т.д. Как понимаю мне надо считать значения с 288, 291, 294... регистров. Но как это сделать не пойму. подредактировал код, но значения, конечно, не считываются.

учтите, данных придёт в 8 раз больше и надо будет их парсить, как у Вас в коде для одного канала, также для всех( просто сдвигая индескы буфера)
как это реализовать?
VAR
i : BYTE;
pAI : POINTER TO BYTE;
AI : ARRAY[1..8] OF REAL; (* Данные с каналов модуля*)
Buffer: ARRAY[0..255] OF BYTE; (*байтовый буфер данных*)
END_VAR

и отрывок кода:

get1_modbus(
Enable:=enabl , (* разрешение работы блока *)
Mode:=MB_RTU , (*режим передачи*)
DevAddr:=32 , (*адрес*)
FirstAddr:=288 , (*номер регистра*)
Quantity:=8, (*количество регистров*)
ComHandle:=Settings.Port ,(*номер COM-порта*)
TimeOut:=TimeOut , (*Таймаут T#50ms*)
Buffer:=Buffer , (*буфер данных*)
Complete=>cmpl , (* скопировать признак завершения операции *)
Exception=>err , (* скопировать регистр ошибок *)
ByteCnt=>DataSize ); (*кол-во считанных байтов *)
(*если установлен признак завершения операции, то *)
IF cmpl THEN
master1:=1;(*переходим к выполнению следующего ФБ*)
IF err=0 THEN (*Если нет ошибок, то получаем данные из буфера типа FLOAT*)
FOR i := 1 TO 8 DO
pAI := ADR(AI);
pAI^:=Buffer[1];
pAI:=pAI+1;
pAI^:=Buffer[0];
pAI:=pAI+1;
pAI^:=Buffer[3];
pAI:=pAI+1;
pAI^:=Buffer[2];

END_FOR;
END_IF
END_IF

Трофимов Артем
27.07.2018, 15:25
с адресом регистра верно.
1 вход занимает 3 регистра (2 регистра данные + метка времени) если метка не нужна то
Quantity:=24, (*количество регистров*)

парсинг :
pAI := ADR(AI[1]);
pAI^:=Buffer[1];
pAI:=pAI+1;
pAI^:=Buffer[0];
pAI:=pAI+1;
pAI^:=Buffer[3];
pAI:=pAI+1;
pAI^:=Buffer[2];

pAI := ADR(AI[2]);
pAI^:=Buffer[7];
pAI:=pAI+1;
pAI^:=Buffer[6];
pAI:=pAI+1;
pAI^:=Buffer[9];
pAI:=pAI+1;
pAI^:=Buffer[8];


pAI := ADR(AI[2]);
pAI^:=Buffer[13];
pAI:=pAI+1;
pAI^:=Buffer[12];
pAI:=pAI+1;
pAI^:=Buffer[15];
pAI:=pAI+1;
pAI^:=Buffer[14];


и так далее

Егор_Егор
27.07.2018, 16:23
Что-то не хочет работать:(

Егор_Егор
30.07.2018, 15:06
Поделитесь, люди добрые, кодом опроса всех входов модуля МВ110-8АС. по кривому примеру с ошибками не получается никак

Мастеренко Иван
30.07.2018, 18:06
Здравствуйте.

38190
Проверьте порт, сетевые настройки и адрес модуля

Spawn
31.07.2018, 03:28
Здравствуйте! Нужна помощь в организации опроса модулей ввода - вывода аналоговых сигналов с ПЛК 63. Связь с модулями настроить удалось, лампочки RS-485 мигают, но данные не считываются. Примеры с диска перепробовал. для опроса мв110-8АС использую функцию 0х03 Read Holding Registers, для МУ110-8И 0х10 Write Multiple registers.


VAR
get1_modbus: MB_RD_HOLD_REGS; (*МВ110.8АС*) (*функция 04 - чтение параметров float*)
send2_modbus: MB_WR_REGS; (*МУ110.8И*) (*функция 16 - запись параметров float*)

cmpl: BOOL;
port_opened: BYTE := 0;
Settings:COMSETTINGS; (* настройки последовательного порта *)
com_num: PORTS:=0; (*0 - RS-485, 1 - RS-232*)
enabl: BOOL; (*состояние работы блока*)
err: INT; (*номер ошибки*)
TimeOut: TIME:=T#100ms; (*таймаут*)
DataSize: WORD;
master1: BYTE:= 1;
COM_SERVICE1: COM_SERVICE;
ptr_D:POINTER TO BYTE;

(* Каналы модуля МВ110 8АС *)
pAI : POINTER TO BYTE;
Buffer: ARRAY[0..255] OF BYTE; (* байтовый буфер данных *)

(* Каналы модуля МУ110 8И *)
pAO : POINTER TO BYTE;
y: ARRAY[1..8] OF WORD;

END_VAR
VAR_INPUT
y1:WORD; (*Записываемый параметр типа WORD*)
y2:WORD; (*Записываемый параметр типа WORD*)
y3:WORD; (*Записываемый параметр типа WORD*)
y4:WORD; (*Записываемый параметр типа WORD*)
y5:WORD; (*Записываемый параметр типа WORD*)
y6:WORD; (*Записываемый параметр типа WORD*)
y7:WORD; (*Записываемый параметр типа WORD*)
y8:WORD; (*Записываемый параметр типа WORD*)
END_VAR
VAR_OUTPUT
x1:REAL; (*Принятый результат*)
x2:REAL; (*МВ110.8АС*)
x3:REAL;
x4:REAL;
x5:REAL;
x6:REAL;
x7:REAL;
x8:REAL;
END_VAR
(*Устанавливаем настройки 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:=enabl , (* разрешение работы блока *)
Mode:=MB_RTU , (*режим передачи*)
DevAddr:=32 , (*адрес*)
FirstAddr:=288 , (*номер регистра*)
Quantity:=24, (*количество регистров*)
ComHandle:=Settings.Port ,(*номер COM-порта*)
TimeOut:=TimeOut , (*Таймаут T#50ms*)
Buffer:=Buffer , (* буфер данных *)
Complete=>cmpl , (* скопировать признак завершения операции *)
Exception=>err , (* скопировать регистр ошибок *)
ByteCnt=>DataSize ); (*кол-во считанных байтов *)
(*если установлен признак завершения операции, то *)
IF cmpl THEN
master1:=1;(*переходим к выполнению следующего ФБ*)
IF err=0 THEN (*Если нет ошибок, то получаем данные из буфера типа FLOAT*)


pAI := ADR(x1);
pAI^:=Buffer[1];
pAI:=pAI+1;
pAI^:=Buffer[0];
pAI:=pAI+1;
pAI^:=Buffer[3];
pAI:=pAI+1;
pAI^:=Buffer[2];

pAI := ADR(x2);
pAI^:=Buffer[7];
pAI:=pAI+1;
pAI^:=Buffer[6];
pAI:=pAI+1;
pAI^:=Buffer[9];
pAI:=pAI+1;
pAI^:=Buffer[8];


pAI := ADR(x3);
pAI^:=Buffer[13];
pAI:=pAI+1;
pAI^:=Buffer[12];
pAI:=pAI+1;
pAI^:=Buffer[15];
pAI:=pAI+1;
pAI^:=Buffer[14];


pAI := ADR(x4);
pAI^:=Buffer[19];
pAI:=pAI+1;
pAI^:=Buffer[18];
pAI:=pAI+1;
pAI^:=Buffer[21];
pAI:=pAI+1;
pAI^:=Buffer[20];


pAI := ADR(x5);
pAI^:=Buffer[25];
pAI:=pAI+1;
pAI^:=Buffer[24];
pAI:=pAI+1;
pAI^:=Buffer[27];
pAI:=pAI+1;
pAI^:=Buffer[26];


pAI := ADR(x6);
pAI^:=Buffer[31];
pAI:=pAI+1;
pAI^:=Buffer[30];
pAI:=pAI+1;
pAI^:=Buffer[33];
pAI:=pAI+1;
pAI^:=Buffer[32];


pAI := ADR(x7);
pAI^:=Buffer[37];
pAI:=pAI+1;
pAI^:=Buffer[36];
pAI:=pAI+1;
pAI^:=Buffer[39];
pAI:=pAI+1;
pAI^:=Buffer[38];


pAI := ADR(x8);
pAI^:=Buffer[43];
pAI:=pAI+1;
pAI^:=Buffer[42];
pAI:=pAI+1;
pAI^:=Buffer[45];
pAI:=pAI+1;
pAI^:=Buffer[44];



END_IF
END_IF

1:
(*запись в буффер параметра типа Float*)
pAO:=ADR(y1);
buffer[5] := pAO^;
pAO:=pAO+1;
buffer[4] := pAO^;
pAO:=pAO+1;
buffer[7] := pAO^;
pAO:=pAO+1;
buffer[6] := pAO^;

pAO:=ADR(y2);
buffer[11] := pAO^;
pAO:=pAO+1;
buffer[10] := pAO^;
pAO:=pAO+1;
buffer[13] := pAO^;
pAO:=pAO+1;
buffer[12] := pAO^;

pAO:=ADR(y3);
buffer[17] := pAO^;
pAO:=pAO+1;
buffer[16] := pAO^;
pAO:=pAO+1;
buffer[19] := pAO^;
pAO:=pAO+1;
buffer[18] := pAO^;

pAO:=ADR(y4);
buffer[23] := pAO^;
pAO:=pAO+1;
buffer[22] := pAO^;
pAO:=pAO+1;
buffer[25] := pAO^;
pAO:=pAO+1;
buffer[24] := pAO^;

send2_modbus(
Enable:= enabl, (* разрешение работы блока *)
Mode:=MB_RTU , (*режим передачи*)
DevAddr:=48 , (*адрес*)
FirstAddr:= 0, (*номер регистра*)
Quantity:= 8, (*количество записываемых регистров*)
ComHandle:=Settings.Port ,(*номер сом-порта*)
TimeOut:=TimeOut , (*таймаут T#50ms*)
Buffer:=Buffer , (* буфер данных *)
Complete=>cmpl , (* скопировать признак завершения операции *)
Exception=>err , (* скопировать регистр ошибок *)
RegCnt=> DataSize); (*кол-во считанных байтов *)
(*если установлен признак завершения операции, то *)
IF cmpl THEN
master1:=2;(*переходим к выполнению следующего блока*)
END_IF

Попробуйте поменять местами порядок байт получаемых данных с модуля 8АС, на такой:
pAI := ADR(x1);
pAI^:=Buffer[3];
pAI:=pAI+1;
pAI^:=Buffer[2];
pAI:=pAI+1;
pAI^:=Buffer[1];
pAI:=pAI+1;
pAI^:=Buffer[0];

Егор_Егор
31.07.2018, 09:27
Спасибо, заработало)

Егор_Егор
31.07.2018, 12:02
Что-то рано я обрадовался. Происходит нечто непонятно: при загрузке в ПЛК Вашего примера все считывается, хотя ошибки прибавляются, но при копировании кода в мой проект данные прекращают считываться. В чем может быть причина?

Мастеренко Иван
01.08.2018, 09:34
приложите проект со скопированным кодом

Spawn
01.08.2018, 11:25
Я пользуюсь таким алгоритмом чтения:


PROGRAM GET_MB
VAR
(*TON*)
HavePause :TON;

(*FB*)
GetModbus : MB_RD_HOLD_REGS;
ComService : COM_SERVICE;

(*BOOL*)
ES : BOOL := TRUE;
EndSendStored : BOOL;

(*BYTE*)
ComPortState : BYTE := 0;
Addr : BYTE := 2;
RegQuant : BYTE := 24;

(*INT*)
MB110_8AC_1CH_STS : INT;
MB110_8AC_2CH_STS : INT;
MB110_8AC_3CH_STS : INT;
MB110_8AC_4CH_STS : INT;
MB110_8AC_5CH_STS : INT;
MB110_8AC_6CH_STS : INT;
MB110_8AC_7CH_STS : INT;
MB110_8AC_8CH_STS : INT;

(*WORD*)
DataSize : WORD;
RegAddr : WORD := 280;

(*REAL*)
MB110_8AC_1CH_VAL : REAL;
MB110_8AC_2CH_VAL : REAL;
MB110_8AC_3CH_VAL : REAL;
MB110_8AC_4CH_VAL : REAL;
MB110_8AC_5CH_VAL : REAL;
MB110_8AC_6CH_VAL : REAL;
MB110_8AC_7CH_VAL : REAL;
MB110_8AC_8CH_VAL : REAL;

(*TIME*)
TimeOut1 : TIME := T#50ms;
TimeOut2 : TIME := T#250ms;

(*STRUCT*)
Settings : COMSETTINGS;

(*TYPES*)
ComNum : PORTS := 0;

(*ARRAY*)
Buffer : ARRAY [0..255] OF BYTE;

(*POINTER*)
Ptb : POINTER TO BYTE;

END_VAR

(*Настройки COM-порта*)
IF ComPortState=0 THEN
Settings.Port:=ComNum; (*номер COM-порта*)
Settings.dwBaudRate:=115200; (*скорость*)
Settings.byParity:=0;
Settings.dwTimeout:=0;
Settings.byStopBits:=1;
Settings.dwBufferSize:=0;
Settings.dwScan:=0;
END_IF
(*________________________________________________ _______________*)

(*Открываем COM-порт*)
ComService(ENABLE := ComPortState = 0, SETTINGS := Settings, TASK := OPEN_TSK);
(*________________________________________________ _______________*)

(*Готовность COM-порта к обмену данными*)
IF ComService.Ready THEN
ComPortState := 2;
END_IF
(*________________________________________________ _______________*)

(*Если COM-порт открыт, то запускаем обмен данными*)
IF ComPortState=2 THEN
GetModbus(
Enable := ES,
Mode := MB_RTU,
DevAddr := Addr,
FirstAddr := RegAddr,
Quantity := RegQuant,
ComHandle := Settings.Port,
TimeOut := TimeOut1,
Buffer := Buffer,
ByteCnt => DataSize);
ES := FALSE;
(*Если прием данных завершен*)
IF GetModbus.Complete THEN
(*и без ошибок,*)
IF GetModbus.Exception = 0 THEN
(*то читаем их из Buffer в соответствующие переменные*)
(*Статусы результатов измерений модулей MB110 8AC*)
(*Первый канал*)
Ptb := ADR(MB110_8AC_1CH_STS);
Ptb^ := Buffer[1];
Ptb := Ptb + 1;
Ptb^ := Buffer[0];
(*Второй канал*)
Ptb := ADR(MB110_8AC_2CH_STS);
Ptb^ := Buffer[3];
Ptb := Ptb + 1;
Ptb^ := Buffer[2];
(*Третий канал*)
Ptb := ADR(MB110_8AC_3CH_STS);
Ptb^ := Buffer[5];
Ptb := Ptb + 1;
Ptb^ := Buffer[4];
(*Четвертый канал*)
Ptb := ADR(MB110_8AC_4CH_STS);
Ptb^ := Buffer[7];
Ptb := Ptb + 1;
Ptb^ := Buffer[6];
(*Пятый канал*)
Ptb := ADR(MB110_8AC_5CH_STS);
Ptb^ := Buffer[9];
Ptb := Ptb + 1;
Ptb^ := Buffer[8];
(*Шестой канал*)
Ptb := ADR(MB110_8AC_6CH_STS);
Ptb^ := Buffer[11];
Ptb := Ptb + 1;
Ptb^ := Buffer[10];
(*Седьмой канал*)
Ptb := ADR(MB110_8AC_7CH_STS);
Ptb^ := Buffer[13];
Ptb := Ptb + 1;
Ptb^ := Buffer[12];
(*Восьмой канал*)
Ptb := ADR(MB110_8AC_8CH_STS);
Ptb^ := Buffer[15];
Ptb := Ptb + 1;
Ptb^ := Buffer[14];
(*Измеренные значения модуля MB110 8AC*)
(*Первый канал*)
Ptb := ADR(MB110_8AC_1CH_VAL);
Ptb^ := Buffer[19];
Ptb := Ptb + 1;
Ptb^ := Buffer[18];
Ptb := Ptb + 1;
Ptb^ := Buffer[17];
Ptb := Ptb + 1;
Ptb^ := Buffer[16];
(*Второй канал*)
Ptb := ADR(MB110_8AC_2CH_VAL);
Ptb^ := Buffer[25];
Ptb := Ptb + 1;
Ptb^ := Buffer[24];
Ptb := Ptb + 1;
Ptb^ := Buffer[23];
Ptb := Ptb + 1;
Ptb^ := Buffer[22];
(*Третий канал*)
Ptb := ADR(MB110_8AC_3CH_VAL);
Ptb^ := Buffer[31];
Ptb := Ptb + 1;
Ptb^ := Buffer[30];
Ptb := Ptb + 1;
Ptb^ := Buffer[29];
Ptb := Ptb + 1;
Ptb^ := Buffer[28];
(*Четвертый канал*)
Ptb := ADR(MB110_8AC_4CH_VAL);
Ptb^ := Buffer[37];
Ptb := Ptb + 1;
Ptb^ := Buffer[36];
Ptb := Ptb + 1;
Ptb^ := Buffer[35];
Ptb := Ptb + 1;
Ptb^ := Buffer[34];
(*Пятый канал*)
Ptb := ADR(MB110_8AC_5CH_VAL);
Ptb^ := Buffer[43];
Ptb := Ptb + 1;
Ptb^ := Buffer[42];
Ptb := Ptb + 1;
Ptb^ := Buffer[41];
Ptb := Ptb + 1;
Ptb^ := Buffer[40];
(*Шестой канал*)
Ptb := ADR(MB110_8AC_6CH_VAL);
Ptb^ := Buffer[49];
Ptb := Ptb + 1;
Ptb^ := Buffer[48];
Ptb := Ptb + 1;
Ptb^ := Buffer[47];
Ptb := Ptb + 1;
Ptb^ := Buffer[46];
(*Седьмой канал*)
Ptb := ADR(MB110_8AC_7CH_VAL);
Ptb^ := Buffer[55];
Ptb := Ptb + 1;
Ptb^ := Buffer[54];
Ptb := Ptb + 1;
Ptb^ := Buffer[53];
Ptb := Ptb + 1;
Ptb^ := Buffer[52];
(*Восьмой канал*)
Ptb := ADR(MB110_8AC_8CH_VAL);
Ptb^ := Buffer[61];
Ptb := Ptb + 1;
Ptb^ := Buffer[60];
Ptb := Ptb + 1;
Ptb^ := Buffer[59];
Ptb := Ptb + 1;
Ptb^ := Buffer[58];
END_IF
EndSendStored := TRUE;
END_IF
(*Временная задержка*)
HavePause(IN := EndSendStored, PT := TimeOut2);
IF HavePause.Q THEN
ES := TRUE;
EndSendStored := FALSE;
END_IF
END_IF

Можно "поиграться" с таймаутами. Никаких ошибок, при условии правильной настройки мастера и слэйва.

Валенок
01.08.2018, 13:55
Я пользуюсь таким алгоритмом чтения:....
Массивы/структуры не ?

Егор_Егор
01.08.2018, 13:59
Всем спасибо, с записью проблема решилась переписыванием кода в новый пустой проект, видимо в конфигурации ПЛК что-то накрутил ненужного) Теперь пытаюсь разобраться с записью значений в МУ110-8И. Подскажите, где посмотреть порядок и номера байт для записи в модуль? или их высчитывать нужно? вот сам код опроса/записи:


FUNCTION_BLOCK mudb
VAR_INPUT
(*&#199;&#237;&#224;&#247;&#229;&#237;&#232;&#255; &#228;&#235;&#255; &#231;&#224;&#239;&#232;&#241;&#232; &#226; &#204;&#211;110-8&#200; &#192;3*)
y1:WORD; (*&#199;&#224;&#239;&#232;&#241;&#251;&#226;&#224;&#229;&#236;&#251;&#233; &#239;&#224;&#240;&#224;&#236;&#229;&#242;&#240; &#242;&#232;&#239;&#224; WORD*)
y2:WORD; (*&#199;&#224;&#239;&#232;&#241;&#251;&#226;&#224;&#229;&#236;&#251;&#233; &#239;&#224;&#240;&#224;&#236;&#229;&#242;&#240; &#242;&#232;&#239;&#224; WORD*)
y3:WORD; (*&#199;&#224;&#239;&#232;&#241;&#251;&#226;&#224;&#229;&#236;&#251;&#233; &#239;&#224;&#240;&#224;&#236;&#229;&#242;&#240; &#242;&#232;&#239;&#224; WORD*)
y4:WORD; (*&#199;&#224;&#239;&#232;&#241;&#251;&#226;&#224;&#229;&#236;&#251;&#233; &#239;&#224;&#240;&#224;&#236;&#229;&#242;&#240; &#242;&#232;&#239;&#224; WORD*)
y5:WORD; (*&#199;&#224;&#239;&#232;&#241;&#251;&#226;&#224;&#229;&#236;&#251;&#233; &#239;&#224;&#240;&#224;&#236;&#229;&#242;&#240; &#242;&#232;&#239;&#224; WORD*)
y6:WORD; (*&#199;&#224;&#239;&#232;&#241;&#251;&#226;&#224;&#229;&#236;&#251;&#233; &#239;&#224;&#240;&#224;&#236;&#229;&#242;&#240; &#242;&#232;&#239;&#224; WORD*)



(*&#193;&#232;&#242;&#238;&#226;&#224;&#255; &#236;&#224;&#241;&#234;&#224; &#226;&#251;&#245;&#238;&#228;&#238;&#226; &#236;&#238;&#228;&#243;&#235;&#255; &#204;&#202;1108&#196;&#205;*)
mk_mask_in:WORD;
END_VAR
VAR_OUTPUT

(*&#241;&#247;&#232;&#242;&#224;&#237;&#237;&#238;&#229; &#231;&#237;&#224;&#247;&#229;&#237;&#232;&#229; &#241; &#204;&#194;110-8&#192;&#209; &#192;2*)
real1: REAL;
real2: REAL;
real3: REAL;
real4: REAL;
real5: REAL;
real6: REAL;
real7: REAL;
real8: REAL;

(*&#194;&#245;&#238;&#228;&#251; &#236;&#238;&#228;&#243;&#235;&#255; &#204;&#202;1108&#196;&#205;*)
A4_in1: BOOL;
A4_in2: BOOL;
A4_in3: BOOL;
A4_in4: BOOL;
A4_in5: BOOL;
A4_in6: BOOL;
A4_in7: BOOL;
A4_in8: BOOL;

END_VAR
VAR
get3_modbus: MB_RD_HOLD_REGS; (*&#244;&#243;&#237;&#234;&#246;&#232;&#255; 03 - &#247;&#242;&#229;&#237;&#232;&#229; &#239;&#224;&#240;&#224;&#236;&#229;&#242;&#240;&#224; &#242;&#232;&#239;&#224; INT*)

send2_modbus: MB_WR_REGS; (*&#204;&#211;110.8&#200;*) (*&#244;&#243;&#237;&#234;&#246;&#232;&#255; 16 - &#231;&#224;&#239;&#232;&#241;&#252; &#239;&#224;&#240;&#224;&#236;&#229;&#242;&#240;&#238;&#226; float*)

Buffer: ARRAY[0..255] OF BYTE; (* &#225;&#224;&#233;&#242;&#238;&#226;&#251;&#233; &#225;&#243;&#244;&#229;&#240; &#228;&#224;&#237;&#237;&#251;&#245; *)

cmpl: BOOL; (*&#239;&#240;&#232;&#231;&#237;&#224;&#234; &#231;&#224;&#226;&#229;&#240;&#248;&#229;&#237;&#237;&#238;&#241;&#242;&#232; &#240;&#224;&#225;&#238;&#242;&#251; &#244;&#243;&#237;&#234;&#246;&#232;&#232;*)
port_opened: BYTE := 0; (*&#240;&#229;&#231;&#243;&#235;&#252;&#242;&#224;&#242; &#238;&#242;&#234;&#240;&#251;&#242;&#232;&#255; &#239;&#238;&#240;&#242;&#224;*)
Settings:COMSETTINGS; (* &#237;&#224;&#241;&#242;&#240;&#238;&#233;&#234;&#232; &#239;&#238;&#241;&#235;&#229;&#228;&#238;&#226;&#224;&#242;&#229;&#235;&#252;&#237;&#238;&#227;&#238; &#239;&#238;&#240;&#242;&#224; *)
com_num: PORTS:=0; (*0 - RS-485, 1 - RS-232*)
enable: BOOL; (*&#241;&#238;&#241;&#242;&#238;&#255;&#237;&#232;&#229; &#240;&#224;&#225;&#238;&#242;&#251; &#225;&#235;&#238;&#234;&#224;*)
err: INT; (*&#237;&#238;&#236;&#229;&#240; &#238;&#248;&#232;&#225;&#234;&#232;*)
TimeOut: TIME:=T#100ms; (*&#242;&#224;&#233;&#236;&#224;&#243;&#242;*)

DataSize: WORD; (*&#234;&#238;&#235;-&#226;&#238; &#241;&#247;&#232;&#242;&#224;&#237;&#237;&#251;&#245; &#225;&#224;&#233;&#242;&#238;&#226; *)
ptr_byte:POINTER TO BYTE; (*&#243;&#234;&#224;&#231;&#224;&#242;&#229;&#235;&#252; &#237;&#224; &#242;&#232;&#239; byte*)
COM_SERVICE1: COM_SERVICE;
state: WORD := 0; (*&#241;&#238;&#241;&#242;&#238;&#255;&#237;&#232;&#229;*)

i: WORD := 0; (*&#228;&#238;&#239;. &#239;&#229;&#240;&#229;&#236;&#229;&#237;&#237;&#224;&#255;*)
t:WORD; (*&#247;&#232;&#241;&#235;&#238; &#238;&#248;&#232;&#225;&#238;&#234;*)

dwDI : WORD; (* &#193;&#232;&#242;&#238;&#226;&#224;&#255; &#236;&#224;&#241;&#234;&#224; &#226;&#245;&#238;&#228;&#238;&#226; &#236;&#238;&#228;&#243;&#235;&#255; &#192;4*)
END_VAR

(*&#211;&#241;&#242;&#224;&#237;&#224;&#226;&#235;&#232;&#226;&#224;&#229;&#236; &#237;&#224;&#241;&#242;&#240;&#238;&#233;&#234;&#232; COM-&#239;&#238;&#240;&#242;&#224;*)
IF port_opened=0 THEN
Settings.Port:=com_num; (*&#237;&#238;&#236;&#229;&#240; COM-&#239;&#238;&#240;&#242;&#224;*)
Settings.dwBaudRate:=115200; (*&#241;&#234;&#238;&#240;&#238;&#241;&#242;&#252;*)
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 );
(*&#197;&#241;&#235;&#232; COM-&#239;&#238;&#240;&#242; &#238;&#242;&#234;&#240;&#251;&#242;, &#242;&#238; &#239;&#229;&#240;&#229;&#245;&#238;&#228;&#232;&#236; &#234; &#239;&#240;&#232;&#229;&#236;&#243; &#232; &#239;&#229;&#240;&#229;&#228;&#224;&#247;&#232; &#228;&#224;&#237;&#237;&#251;&#245; *)
IF COM_SERVICE1.ready THEN
port_opened:=2;
END_IF


CASE state OF
0:
enable:=1;
IF port_opened=2 THEN (*&#211;&#228;&#224;&#247;&#237;&#238; &#239;&#240;&#238;&#232;&#237;&#232;&#246;&#232;&#224;&#235;&#232;&#231;&#232;&#240;&#238;&#226;&#224;&#235;&#232;*)
(* &#244;&#243;&#237;&#234;&#246;&#232;&#255; 03 &#244;&#235;&#238;&#224;&#242; - &#212;&#193; &#241;&#247;&#232;&#242;&#251;&#226;&#224;&#229;&#242; &#231;&#237;&#224;&#247;&#229;&#237;&#232;&#229; &#239;&#224;&#240;&#224;&#236;&#229;&#242;&#240;&#224; &#242;&#232;&#239;&#224; int16 &#232;&#231; &#239;&#240;&#232;&#225;&#238;&#240;&#224; &#241; &#224;&#228;&#240;&#229;&#241;&#238;&#236; 22 c &#240;&#229;&#227;&#232;&#241;&#242;&#240;&#224; &#241; &#237;&#238;&#236;&#224;&#240;&#238;&#236; 0dec &#239;&#238; &#239;&#240;&#238;&#242;&#238;&#234;&#238;&#235;&#243; Modbus-RTU*)
get3_modbus(
Enable:=enable, (* &#240;&#224;&#231;&#240;&#229;&#248;&#229;&#237;&#232;&#229; &#240;&#224;&#225;&#238;&#242;&#251; &#225;&#235;&#238;&#234;&#224; *)
Mode:=MB_RTU , (*&#240;&#229;&#230;&#232;&#236; &#239;&#229;&#240;&#229;&#228;&#224;&#247;&#232;*)
DevAddr:=32 , (*&#224;&#228;&#240;&#229;&#241;*)
FirstAddr:=288 , (*&#237;&#238;&#236;&#229;&#240; &#240;&#229;&#227;&#232;&#241;&#242;&#240;&#224;*)
Quantity:=24, (*&#234;&#238;&#235;&#232;&#247;&#229;&#241;&#242;&#226;&#238; &#240;&#229;&#227;&#232;&#241;&#242;&#240;&#238;&#226;*)
ComHandle:=Settings.Port ,(*&#237;&#238;&#236;&#229;&#240; COM-&#239;&#238;&#240;&#242;&#224;*)
TimeOut:=TimeOut , (*&#210;&#224;&#233;&#236;&#224;&#243;&#242; T#50ms*)
Buffer:=Buffer , (* &#225;&#243;&#244;&#229;&#240; &#228;&#224;&#237;&#237;&#251;&#245; *)
Complete=>cmpl , (* &#241;&#234;&#238;&#239;&#232;&#240;&#238;&#226;&#224;&#242;&#252; &#239;&#240;&#232;&#231;&#237;&#224;&#234; &#231;&#224;&#226;&#229;&#240;&#248;&#229;&#237;&#232;&#255; &#238;&#239;&#229;&#240;&#224;&#246;&#232;&#232; *)
Exception=>err , (* &#241;&#234;&#238;&#239;&#232;&#240;&#238;&#226;&#224;&#242;&#252; &#240;&#229;&#227;&#232;&#241;&#242;&#240; &#238;&#248;&#232;&#225;&#238;&#234; *)
ByteCnt=>DataSize ); (*&#234;&#238;&#235;-&#226;&#238; &#241;&#247;&#232;&#242;&#224;&#237;&#237;&#251;&#245; &#225;&#224;&#233;&#242;&#238;&#226; *)
(*&#229;&#241;&#235;&#232; &#243;&#241;&#242;&#224;&#237;&#238;&#226;&#235;&#229;&#237; &#239;&#240;&#232;&#231;&#237;&#224;&#234; &#231;&#224;&#226;&#229;&#240;&#248;&#229;&#237;&#232;&#255; &#238;&#239;&#229;&#240;&#224;&#246;&#232;&#232;, &#242;&#238; *)


IF cmpl THEN
IF err=0 THEN (*&#197;&#241;&#235;&#232; &#237;&#229;&#242; &#238;&#248;&#232;&#225;&#238;&#234;, &#242;&#238; &#239;&#238;&#235;&#243;&#247;&#224;&#229;&#236; &#228;&#224;&#237;&#237;&#251;&#229; &#232;&#231; &#225;&#243;&#244;&#229;&#240;&#224;, &#244;&#238;&#240;&#236;&#232;&#240;&#243;&#229;&#236; &#239;&#229;&#240;&#229;&#236;&#229;&#237;&#237;&#251;&#229;*)
(*&#236;&#238;&#228;&#243;&#235;&#252; &#239;&#229;&#240;&#229;&#228;&#224;&#229;&#242; &#231;&#237;&#224;&#247;&#229;&#237;&#232;&#255; &#241;&#242;&#224;&#240;&#248;&#232;&#236; &#241;&#235;&#238;&#226;&#238;&#236; &#226;&#239;&#229;&#240;&#229;&#228; &#228;&#235;&#255; Float32 &#232; &#241;&#242;&#224;&#240;&#248;&#232;&#236; &#225;&#224;&#233;&#242;&#238;&#236; &#226;&#239;&#229;&#240;&#229;&#228; &#228;&#235;&#255; Int16*)
(*&#239;&#238;&#253;&#242;&#238;&#236;&#243; &#239;&#229;&#240;&#229;&#236;&#229;&#237;&#237;&#251;&#229; &#241;&#238;&#225;&#232;&#240;&#224;&#229;&#236; "&#241;&#239;&#240;&#224;&#226;&#224;-&#237;&#224;&#235;&#229;&#226;&#238;" *)
(*&#226;&#245;&#238;&#228;1*)
ptr_byte:=ADR(real1);
ptr_byte^:=buffer[3];
ptr_byte:=ptr_byte+1;
ptr_byte^:=buffer[2];
ptr_byte:=ptr_byte+1;
ptr_byte^:=buffer[1];
ptr_byte:=ptr_byte+1;
ptr_byte^:=buffer[0];

ptr_byte:=ADR(real2);
ptr_byte^:=buffer[9];
ptr_byte:=ptr_byte+1;
ptr_byte^:=buffer[8];
ptr_byte:=ptr_byte+1;
ptr_byte^:=buffer[7];
ptr_byte:=ptr_byte+1;
ptr_byte^:=buffer[6];

ptr_byte:=ADR(real3);
ptr_byte^:=buffer[15];
ptr_byte:=ptr_byte+1;
ptr_byte^:=buffer[14];
ptr_byte:=ptr_byte+1;
ptr_byte^:=buffer[13];
ptr_byte:=ptr_byte+1;
ptr_byte^:=buffer[12];

ptr_byte:=ADR(real4);
ptr_byte^:=buffer[21];
ptr_byte:=ptr_byte+1;
ptr_byte^:=buffer[20];
ptr_byte:=ptr_byte+1;
ptr_byte^:=buffer[19];
ptr_byte:=ptr_byte+1;
ptr_byte^:=buffer[18];

ptr_byte:=ADR(real5);
ptr_byte^:=buffer[27];
ptr_byte:=ptr_byte+1;
ptr_byte^:=buffer[26];
ptr_byte:=ptr_byte+1;
ptr_byte^:=buffer[25];
ptr_byte:=ptr_byte+1;
ptr_byte^:=buffer[24];


ptr_byte:=ADR(real6);
ptr_byte^:=buffer[33];
ptr_byte:=ptr_byte+1;
ptr_byte^:=buffer[32];
ptr_byte:=ptr_byte+1;
ptr_byte^:=buffer[31];
ptr_byte:=ptr_byte+1;
ptr_byte^:=buffer[30];

ptr_byte:=ADR(real7);
ptr_byte^:=buffer[39];
ptr_byte:=ptr_byte+1;
ptr_byte^:=buffer[38];
ptr_byte:=ptr_byte+1;
ptr_byte^:=buffer[37];
ptr_byte:=ptr_byte+1;
ptr_byte^:=buffer[36];

ptr_byte:=ADR(real8);
ptr_byte^:=buffer[45];
ptr_byte:=ptr_byte+1;
ptr_byte^:=buffer[44];
ptr_byte:=ptr_byte+1;
ptr_byte^:=buffer[43];
ptr_byte:=ptr_byte+1;
ptr_byte^:=buffer[42];

state:=1;
enable:=0;
ELSE t:=t+1;
state:=1;
END_IF
END_IF
END_IF

1: (*&#228;&#224;&#235;&#252;&#237;&#229;&#233;&#248;&#229;&#229; &#231;&#224;&#226;&#232;&#241;&#232;&#242; &#238;&#242; &#239;&#238;&#235;&#252;&#231;&#238;&#226;&#224;&#242;&#229;&#235;&#255;*)
(*&#238;&#247;&#232;&#241;&#242;&#232;&#236; &#225;&#243;&#244;&#229;&#240;*)

FOR i:=0 TO 255 DO
buffer[i]:=0;
END_FOR
(*&#226;&#229;&#240;&#237;&#229;&#236;&#241;&#255; &#238;&#239;&#255;&#242;&#252; &#226; &#241;&#238;&#241;&#242;&#238;&#255;&#237;&#232;&#229; 0*)
state:=2;

2:

(*&#231;&#224;&#239;&#232;&#241;&#252; &#226; &#225;&#243;&#244;&#244;&#229;&#240; &#239;&#224;&#240;&#224;&#236;&#229;&#242;&#240;&#224; &#242;&#232;&#239;&#224; Float*)

enable:=1;
ptr_byte:=ADR(y1);
buffer[5] := ptr_byte^;
ptr_byte:=ptr_byte+1;
buffer[4] := ptr_byte^;
ptr_byte:=ptr_byte+1;
buffer[7] := ptr_byte^;
ptr_byte:=ptr_byte+1;
buffer[6] := ptr_byte^;



send2_modbus(
Enable:= enable, (* &#240;&#224;&#231;&#240;&#229;&#248;&#229;&#237;&#232;&#229; &#240;&#224;&#225;&#238;&#242;&#251; &#225;&#235;&#238;&#234;&#224; *)
Mode:=MB_RTU , (*&#240;&#229;&#230;&#232;&#236; &#239;&#229;&#240;&#229;&#228;&#224;&#247;&#232;*)
DevAddr:=48 , (*&#224;&#228;&#240;&#229;&#241;*)
FirstAddr:= 0, (*&#237;&#238;&#236;&#229;&#240; &#240;&#229;&#227;&#232;&#241;&#242;&#240;&#224;*)
Quantity:= 8, (*&#234;&#238;&#235;&#232;&#247;&#229;&#241;&#242;&#226;&#238; &#231;&#224;&#239;&#232;&#241;&#251;&#226;&#224;&#229;&#236;&#251;&#245; &#240;&#229;&#227;&#232;&#241;&#242;&#240;&#238;&#226;*)
ComHandle:=Settings.Port ,(*&#237;&#238;&#236;&#229;&#240; &#241;&#238;&#236;-&#239;&#238;&#240;&#242;&#224;*)
TimeOut:=TimeOut , (*&#242;&#224;&#233;&#236;&#224;&#243;&#242; T#50ms*)
Buffer:=buffer , (* &#225;&#243;&#244;&#229;&#240; &#228;&#224;&#237;&#237;&#251;&#245; *)
Complete=>cmpl , (* &#241;&#234;&#238;&#239;&#232;&#240;&#238;&#226;&#224;&#242;&#252; &#239;&#240;&#232;&#231;&#237;&#224;&#234; &#231;&#224;&#226;&#229;&#240;&#248;&#229;&#237;&#232;&#255; &#238;&#239;&#229;&#240;&#224;&#246;&#232;&#232; *)
Exception=>err , (* &#241;&#234;&#238;&#239;&#232;&#240;&#238;&#226;&#224;&#242;&#252; &#240;&#229;&#227;&#232;&#241;&#242;&#240; &#238;&#248;&#232;&#225;&#238;&#234; *)
RegCnt=> DataSize); (*&#234;&#238;&#235;-&#226;&#238; &#241;&#247;&#232;&#242;&#224;&#237;&#237;&#251;&#245; &#225;&#224;&#233;&#242;&#238;&#226; *)
(*&#229;&#241;&#235;&#232; &#243;&#241;&#242;&#224;&#237;&#238;&#226;&#235;&#229;&#237; &#239;&#240;&#232;&#231;&#237;&#224;&#234; &#231;&#224;&#226;&#229;&#240;&#248;&#229;&#237;&#232;&#255; &#238;&#239;&#229;&#240;&#224;&#246;&#232;&#232;, &#242;&#238; *)
IF cmpl THEN
state:=3;(*&#239;&#229;&#240;&#229;&#245;&#238;&#228;&#232;&#236; &#234; &#226;&#251;&#239;&#238;&#235;&#237;&#229;&#237;&#232;&#254; &#241;&#235;&#229;&#228;&#243;&#254;&#249;&#229;&#227;&#238; &#225;&#235;&#238;&#234;&#224;*)
END_IF

3:

FOR i:=0 TO 255 DO
buffer[i]:=0;
END_FOR
(*&#226;&#229;&#240;&#237;&#229;&#236;&#241;&#255; &#238;&#239;&#255;&#242;&#252; &#226; &#241;&#238;&#241;&#242;&#238;&#255;&#237;&#232;&#229; 0*)
state:=4;
enable:=0;


4:

enable:=1;
IF port_opened=2 THEN (*&#211;&#228;&#224;&#247;&#237;&#238; &#239;&#240;&#238;&#232;&#237;&#232;&#246;&#232;&#224;&#235;&#232;&#231;&#232;&#240;&#238;&#226;&#224;&#235;&#232;*)
get3_modbus(
Enable:= enable, (* &#240;&#224;&#231;&#240;&#229;&#248;&#229;&#237;&#232;&#229; &#240;&#224;&#225;&#238;&#242;&#251; &#225;&#235;&#238;&#234;&#224; *)
Mode:=MB_RTU , (*&#240;&#229;&#230;&#232;&#236; &#239;&#229;&#240;&#229;&#228;&#224;&#247;&#232;*)
DevAddr:=64 , (*&#224;&#228;&#240;&#229;&#241;*)
FirstAddr:=51 , (*&#237;&#238;&#236;&#229;&#240; &#240;&#229;&#227;&#232;&#241;&#242;&#240;&#224;*)
Quantity:=1 , (*&#234;&#238;&#235;&#232;&#247;&#229;&#241;&#242;&#226;&#238; &#240;&#229;&#227;&#232;&#241;&#242;&#240;&#238;&#226;*)
ComHandle:= Settings.Port,(*&#237;&#238;&#236;&#229;&#240; COM-&#239;&#238;&#240;&#242;&#224;*)
TimeOut:=TimeOut , (*&#210;&#224;&#233;&#236;&#224;&#243;&#242; T#50ms*)
Buffer:=buffer , (* &#225;&#243;&#244;&#229;&#240; &#228;&#224;&#237;&#237;&#251;&#245; *)
Complete=>cmpl , (* &#241;&#234;&#238;&#239;&#232;&#240;&#238;&#226;&#224;&#242;&#252; &#239;&#240;&#232;&#231;&#237;&#224;&#234; &#231;&#224;&#226;&#229;&#240;&#248;&#229;&#237;&#232;&#255; &#238;&#239;&#229;&#240;&#224;&#246;&#232;&#232; *)
Exception=>err , (* &#241;&#234;&#238;&#239;&#232;&#240;&#238;&#226;&#224;&#242;&#252; &#240;&#229;&#227;&#232;&#241;&#242;&#240; &#238;&#248;&#232;&#225;&#238;&#234; *)
ByteCnt=> DataSize); (*&#234;&#238;&#235;-&#226;&#238; &#241;&#247;&#232;&#242;&#224;&#237;&#237;&#251;&#245; &#225;&#224;&#233;&#242;&#238;&#226; *)
(*&#229;&#241;&#235;&#232; &#243;&#241;&#242;&#224;&#237;&#238;&#226;&#235;&#229;&#237; &#239;&#240;&#232;&#231;&#237;&#224;&#234; &#231;&#224;&#226;&#229;&#240;&#248;&#229;&#237;&#232;&#255; &#238;&#239;&#229;&#240;&#224;&#246;&#232;&#232;, &#242;&#238; *)

IF cmpl THEN
IF err=0 THEN (*&#197;&#241;&#235;&#232; &#237;&#229;&#242; &#238;&#248;&#232;&#225;&#238;&#234;, &#242;&#238; &#239;&#238;&#235;&#243;&#247;&#224;&#229;&#236; &#228;&#224;&#237;&#237;&#251;&#229; &#232;&#231; &#225;&#243;&#244;&#229;&#240;&#224; &#242;&#232;&#239;&#224; INT*)
dwDI:=BYTE_TO_WORD(buffer[1]) OR SHL(BYTE_TO_WORD(buffer[0]),8);
END_IF
state:=5;
END_IF
END_IF
5:

FOR i:=0 TO 255 DO
buffer[i]:=0;
END_FOR
(*&#226;&#229;&#240;&#237;&#229;&#236;&#241;&#255; &#238;&#239;&#255;&#242;&#252; &#226; &#241;&#238;&#241;&#242;&#238;&#255;&#237;&#232;&#229; 0*)
state:=6;
enable:=0;


6:
enable:=1;
(*&#207;&#232;&#248;&#229;&#236; &#226; &#225;&#243;&#244;&#229;&#240; &#238;&#242;&#239;&#240;&#224;&#226;&#234;&#232; &#225;&#232;&#242;&#238;&#226;&#243;&#254; &#236;&#224;&#241;&#234;&#243;*)
ptr_byte:=ADR(mk_mask_in);
buffer[1]:=ptr_byte^;
ptr_byte:=ptr_byte+1;
buffer[0]:=ptr_byte^;
(*&#194;&#251;&#239;&#238;&#235;&#237;&#255;&#229;&#236; &#238;&#242;&#239;&#240;&#224;&#226;&#234;&#243;*)
send2_modbus(
Enable:= enable, (* &#240;&#224;&#231;&#240;&#229;&#248;&#229;&#237;&#232;&#229; &#240;&#224;&#225;&#238;&#242;&#251; &#225;&#235;&#238;&#234;&#224; *)
Mode:=MB_RTU , (*&#240;&#229;&#230;&#232;&#236; &#239;&#229;&#240;&#229;&#228;&#224;&#247;&#232;*)
DevAddr:=64 , (*&#224;&#228;&#240;&#229;&#241;*)
FirstAddr:=50 , (*&#237;&#238;&#236;&#229;&#240; &#240;&#229;&#227;&#232;&#241;&#242;&#240;&#224;*)
Quantity:=1 , (*&#234;&#238;&#235;&#232;&#247;&#229;&#241;&#242;&#226;&#238; &#240;&#229;&#227;&#232;&#241;&#242;&#240;&#238;&#226;*)
ComHandle:= Settings.Port,(*&#237;&#238;&#236;&#229;&#240; COM-&#239;&#238;&#240;&#242;&#224;*)
TimeOut:=TimeOut , (*&#210;&#224;&#233;&#236;&#224;&#243;&#242; T#50ms*)
Buffer:=buffer , (* &#225;&#243;&#244;&#229;&#240; &#228;&#224;&#237;&#237;&#251;&#245; *)
Complete=>cmpl , (* &#241;&#234;&#238;&#239;&#232;&#240;&#238;&#226;&#224;&#242;&#252; &#239;&#240;&#232;&#231;&#237;&#224;&#234; &#231;&#224;&#226;&#229;&#240;&#248;&#229;&#237;&#232;&#255; &#238;&#239;&#229;&#240;&#224;&#246;&#232;&#232; *)
Exception=>err , (* &#241;&#234;&#238;&#239;&#232;&#240;&#238;&#226;&#224;&#242;&#252; &#240;&#229;&#227;&#232;&#241;&#242;&#240; &#238;&#248;&#232;&#225;&#238;&#234; *)
RegCnt=> DataSize); (*&#234;&#238;&#235;-&#226;&#238; &#241;&#247;&#232;&#242;&#224;&#237;&#237;&#251;&#245; &#225;&#224;&#233;&#242;&#238;&#226; *)
(*&#229;&#241;&#235;&#232; &#243;&#241;&#242;&#224;&#237;&#238;&#226;&#235;&#229;&#237; &#239;&#240;&#232;&#231;&#237;&#224;&#234; &#231;&#224;&#226;&#229;&#240;&#248;&#229;&#237;&#232;&#255; &#238;&#239;&#229;&#240;&#224;&#246;&#232;&#232;, &#242;&#238; *)
IF cmpl THEN
state:=7;(*&#239;&#229;&#240;&#229;&#245;&#238;&#228;&#232;&#236; &#234; &#226;&#251;&#239;&#238;&#235;&#237;&#229;&#237;&#232;&#254; &#241;&#235;&#229;&#228;&#243;&#254;&#249;&#229;&#227;&#238; &#225;&#235;&#238;&#234;&#224;*)
END_IF

IF enable = FALSE THEN
enable := TRUE;
END_IF

IF err <> 0 THEN
enable := FALSE;
END_IF
(*&#208;&#224;&#231;&#225;&#232;&#240;&#224;&#229;&#236; &#225;&#232;&#242;&#238;&#226;&#243;&#254; &#236;&#224;&#241;&#234;&#243; &#226;&#245;&#238;&#228;&#238;&#226; &#204;&#202;110.8&#196;&#205;.4&#208;*)
A4_in1:=dwDI.0;
A4_in2:=dwDI.1;
A4_in3:=dwDI.2;
A4_in4:=dwDI.3;
A4_in5:=dwDI.4;
A4_in6:=dwDI.5;
A4_in7:=dwDI.6;
A4_in8:=dwDI.7;

7:
FOR i:=0 TO 255 DO
buffer[i]:=0;
END_FOR
(*&#226;&#229;&#240;&#237;&#229;&#236;&#241;&#255; &#238;&#239;&#255;&#242;&#252; &#226; &#241;&#238;&#241;&#242;&#238;&#255;&#237;&#232;&#229; 0*)
state:=0;

END_CASE

Дискретные входы/выходы и считываются и записываются нормально

Валенок
01.08.2018, 14:53
Ой, пля.. Сначала немного теории:

Нюанс модбаса
В модбас сетевой порядок байт в словах (регистрах) отличается порядка байт в словах (вордах) на местном плк. На плк порядок байт 12, сетевой 21.
Важно ! Та биб-ка (модбас.либ) нифига не удосуживается приводить данные из/в сетевого порядка.

Отсюда - что при отправке, что при чтении данные нужно приводить самому.
(Местный релиз ntohw/htonw сводится к единой функции перестановки байтов попарно)

При чтении, после приведения порядка, данные повторяют таблицу регистров приведенную в РЭ для модулей.
При записи, данные повторяющие таблицу регистров нужно привести в сетевой порядок и спокойно отправлять.

Общий нюанс всех модулей Овен :
Все 32-битное на модулях (дворды, реалы) имеет другой порядок расположения слов. На плк байты 1234, там 3412
Т.е. при чтении сначала приводим из сетевого, после этого для всех 32-х битных меняем порядок слов.
При записи сначала (если есть 32-битное) приводит дабл-слова к порядку модуля, после - полученное приводим в сетевой порядок.

Теперь ньюанс конкретно 8АС/2AC
Автор таблицы регистров был пьян, поэтому реализовал таблицу кривом виде совершенно не учитывая невозможность обращения к 32-битному значению с адреса некратного 4-ем байтам. Автор не подозревает что данные можно читать все за раз.
Но это, так сказать, родовая болезнь овен-реализаторов.


fblock mu8i
var_input
out : array[1..8] of real; //например для 0..100%
end_var
var_in_out
buf : array[0..255] of byte; //отправлять на регистр 0, 8 регистров
end_var
var
p : pointer to array[1..8] of word;
---------------------------------------------
p := adr(buf);
for i := 1 to 8 do
p^[i] := real_to_word(limit(0, out[i] * 10, 1000)); // !! 0..100%
end_for
ntohw(adr(buf),sizeof(p^)); //несложная функция для самостоятельного релиза


Теперь 8ac. Читать - так все.


//не поленится описать типы, чтоб после не писать тупых коментов в коде.

enum ai_status(
status_ok := 0,
status_unready := 16#f006,
status_off := 16#f007,
status_break := 16#f00d,
...
);

struct ai_struct(
status : ai_status := status_unready,
cyclic : word;
value : real;
);


fblock mv8ac
var_in_out
buf : array[0..255] of byte; //читать с регистра 16#118, 32 регистра
end_var
var_output
ai : array[1..8] of struct_ai;
end_var
var
srd : pointer to array[1..8] of word;
read : pointer to array[1..8, 1..3] of word;
p : pointer to array[1..2] of word;
end_var
------------------------------
ntohw(adr(buf),sizeof(ai)); //все та же несложная функция для самостоятельного релиза
srd := adr(buf);
read := adr(buf) + sizeof(srd^);
for i := 1 to 8 do
p := adr(ai[i].value);
ai[i].status := srd^[i];
ai[i].cyclic := read^[i,3];
p^[1] := read^[i,2];
p^[2] := read^[i,1];
end_for

Spawn
02.08.2018, 11:17
Массивы/структуры не ?

Не, мне пока и так нравится. Вполне себе рабочий алгоритм. Да он не похож на Ваш, но как по мне, он и не обязан быть похожим - сколько людей столько и мнений. Вы пользуетесь своими методами/алгоритмами, кто-то другой может пользоваться своими методами/алгоритмами.

На счет
//не поленится описать типы, чтоб после не писать тупых коментов в коде.. Комментарий - он прежде всего комментарий, а уже потом все остальное. Если Ваши исходники ни кто не читает, то это не значит, что у всех остальных будет такая же ситуация. Как говорит мой знакомый, цитирую "Инструкция должна быть написана для обезьяны. Чтобы обезьяна читала и понимала что, где и как.", поэтому дополнительный комментарий, на мой взгляд, в теле кода лишним не будет (если, конечно, это не анекдот, хотя и он может быть полезен - поспособствует кратковременному "снижению температуры мозга"), даже с учетом использования типов, структур и массивов.

Валенок
02.08.2018, 17:35
Никто же не говорит что индуский код не работает. Работает. И ему да - обязательно нужны коменты )))
Я привел общее решение для приведения модбасных данных. Причем не только для Овена.
Кто как делает - мне побоку.
Жду очередной плач на форуме что никак не видно данных, например из 2A

Spawn
03.08.2018, 00:01
Я привел общее решение для приведения модбасных данных. Причем не только для Овена.

За пример, от меня лично, спасибо. Реальная помощь с Вашей стороны.


Никто же не говорит что индуский код не работает. Работает. И ему да - обязательно нужны коменты )))

А вот сарказм и грубость, товарищ Валенок, здесь неуместны, и к делу никакого отношения не имеют.


Жду очередной плач на форуме что никак не видно данных, например из 2A

Так Вы возьмите и помогите нуждающимся, если есть возможность и желание, вместо того чтобы оскорблять. Начинающие (и не только) пользователи продукции ОВЕН могут не иметь глубоких познаний всех тонкостей и нюансов ее работы, поэтому каждый раз, всё снова и снова, через неопределенные (а может и нет) временные интервалы, в тех или иных ветках форума, будут появляться всё те же вопросы, нуждающиеся во всё тех же ответах.

Егор_Егор
03.08.2018, 10:03
Всем откликнувшимся большое спасибо! Все работает, пускай и на индуском коде:)