Tools


«Сименс» в России

«Сименс» в России

Доступ по hart сразу ко всем PV, SV, TV, FV переменным

Промышленные Логические Контроллеры SIMATIC S7-300/-400, SIMATIC S7-1500, C7, WinAC, S5, станции распределенной периферии ET 200

Модераторы: gulenok_andrey, Кухаренко Сергей, pavel_puchkov

tvpvtu
Сообщения: 3
Зарегистрирован: 28 окт 2020, 16:35

Сообщение tvpvtu » 16 ноя 2020, 10:55

Добрый день. Для AI HART модулей 300-й серии в Hardware Config доступно для конфигурирования только восемь HART-переменных. Поэтому можно вытянуть либо по четыре переменные с двух датчиков, либо по две переменных с четырех датчиков итд…
Подскажите возможно-ли вытащить все переменные со всех датчиков?

Бронислав
Сообщения: 16
Зарегистрирован: 17 мар 2019, 20:14

Сообщение Бронислав » 16 ноя 2020, 17:09

Добрый день.
С помощью системных функций SFC 58/59 возможно получить все четыре переменные, подробнее https://support.industry.siemens.com/cs ... n&lc=ru-RU глава 7. Записываете в соответствующую DataRecord HART-команду на чтение переменных, затем считываете результат. Но это не совсем стандартное решение и оно создает дополнительную коммуникационную нагрузку, злоупотреблять им не стоит.

tvpvtu
Сообщения: 3
Зарегистрирован: 28 окт 2020, 16:35

Сообщение tvpvtu » 19 ноя 2020, 09:53

А есть пример работающего кода для считывания переменных по HART?

Traceep
Сообщения: 2
Зарегистрирован: 08 май 2018, 22:38
Откуда: Panama
Контактная информация:

Сообщение Traceep » 23 ноя 2020, 22:33

Делал когда-то давно, вот. Далеко не образец идеального кода, но работает.

Код: Выделить всё

FUNCTION_BLOCK AI_HART
// Block Parameters
VAR_INPUT
// Input Parameters
EN0 : BOOL; 
LADDR : INT;
cmd { 
S7_link:='false'; 
S7_string_0:= 'ident'; 
S7_string_1:= 'prim_var';
S7_string_3:= 'cur_var'
} : INT :=0; //Select CMD

Sh_Freim : BOOL; // 1-short freim, 0-long freim
Res_ID : BOOL; // обнулить адрес (широковещ.посылка)
N_CHAN : INT:=0; // input N chanel(0,1,...)
AI_TYPE { S7_string_0:= 'AI_2Ch'; 
S7_string_1:= 'AI_8Ch'}: BOOL:=0; //Select AI(2 or 8 chanel) 
Delay : INT; // Задержка, ms*OBxx 
END_VAR
VAR_IN_OUT
point : INT;
END_VAR
VAR_OUTPUT
// Output Parameters
out : BYTE;
Sbusy : BOOL;
Rbusy : BOOL; 
Ic : REAL;
PV1 : REAL;
PV2 : REAL;
PV3 : REAL;
END_VAR
VAR
// Output Parameters
i,WR,RD,timeout : INT;
SND_BUF: ARRAY[0..11] OF BYTE;
RCV_BUF: ARRAY[0..50] OF BYTE;
Ident: ARRAY[0..4] OF BYTE;
CRC : BYTE;
req : BOOL;
AI_ID: WORD;
init : BOOL;
RECNUM: INT;
db_num : WORD;
END_VAR
VAR_TEMP
TempPointer: ANY; // Artificial variable 
AnyPointer AT TempPointer: STRUCT 
BYTE0 :BYTE; // Byte 0 
TYP :BYTE; // Byte 1 Data/Type of parameter 
ANZ :WORD; // Byte 2+3 Length of the variables 
DBNR :WORD; // Byte 4+5 DB-Number 
BZ :DWORD; // Byte 6 to 10 Area pointers 
END_STRUCT; 
END_VAR

// Instruction Section
IF EN0 THEN 
IF NOT(init) THEN // Инициализации блока
TempPointer := db_num; // Узнаем номер instanse DB 
db_num := AnyPointer.DBNR; // и сохранаем его в переменной
init := true;
END_IF;

IF NOT(AI_TYPE)THEN 
RECNUM:=10+N_CHAN*40; // AI_2ch 
ELSE
RECNUM:=80+N_CHAN*2; // AI_8ch
END_IF; 

IF Res_ID THEN 
Res_ID:=false;
FOR i:=0 TO 4 BY 1 DO
ident[i]:= 16#00;
END_FOR; 
END_IF;
IF point = 0 THEN 
IF NOT REQ THEN point :=1; 
ELSIF REQ AND NOT(Sbusy) THEN point :=2; timeout:=0; 
ELSIF REQ AND timeout > 10 THEN point :=1; REQ := false; timeout:=0;
ELSE timeout := timeout+1; END_IF; 
END_IF;
AI_ID := INT_TO_WORD(LADDR);
IF point = 1 THEN // SEND DATA 
IF Sh_Freim THEN // ФОРМАТ КОРОТКОГО ФРЕЙМА
SND_BUF [0]:=16#40; //Const value
SND_BUF [1]:=INT_TO_BYTE(CMD); //Command
SND_BUF [2]:=16#00; //Num BYTE
ELSE // ФОРМАТ ДЛИННОГО ФРЕЙМА
SND_BUF [0]:=16#00; //Const value 
SND_BUF [1]:=16#05; //Num byte in Preambyle
SND_BUF [2]:=82; //Long Freim from Master
SND_BUF [3]:=16#80 OR ident[0]; //Address
SND_BUF [4]:=ident[1]; //Address
SND_BUF [5]:=ident[2]; //Address
SND_BUF [6]:=ident[3]; //Address
SND_BUF [7]:=ident[4]; //Address
SND_BUF [8]:=INT_TO_BYTE(CMD); //Command
SND_BUF [9]:=16#00; //Num byte
SND_BUF [10]:=SND_BUF[2]; // CRC 
FOR i := 3 TO 9 BY 1 DO
SND_BUF [10]:= SND_BUF [10] XOR SND_BUF [i];
END_FOR; 
END_IF;
REQ := true;
WR := WR_REC(REQ := REQ // IN: BOOL
,IOID := B#16#54 // IN: BYTE
,LADDR := AI_ID // IN: WORD
,RECNUM := INT_TO_BYTE(RECNUM) // IN: BYTE
,RECORD := SND_BUF // IN: ANY
,BUSY := Sbusy // OUT: BOOL
); // INT
point := 0; 
// Enable := 2;
END_IF;

Ухтыжка, здесь ограничение на количество символов. Продолжение будет дальше

Traceep
Сообщения: 2
Зарегистрирован: 08 май 2018, 22:38
Откуда: Panama
Контактная информация:

Сообщение Traceep » 23 ноя 2020, 22:34

Код: Выделить всё

IF point = 2 THEN // READ DATA
RD := RD_REC(REQ := true // IN: BOOL
,IOID := B#16#54 // IN: BYTE
,LADDR := AI_ID // IN: WORD
,RECNUM := INT_TO_BYTE(RECNUM+2) // IN: BYTE
,BUSY := Rbusy // OUT: BOOL
,RECORD := RCV_BUF // OUT: ANY
); // INT


IF NOT(Rbusy)AND REQ THEN point :=3; REQ := false; 
ELSIF timeout > 10 THEN point :=4; REQ := false; timeout:=0;
ELSE timeout := timeout+1; END_IF; 
END_IF;

IF point = 3 THEN // DATA ANALYSIS

CASE cmd OF
0: // Read identifier
Ident[0]:= WORD_TO_BLOCK_DB(db_num).db[66];
Ident[1]:= WORD_TO_BLOCK_DB(db_num).db[67];
Ident[2]:= WORD_TO_BLOCK_DB(db_num).db[74];
Ident[3]:= WORD_TO_BLOCK_DB(db_num).db[75];
Ident[4]:= WORD_TO_BLOCK_DB(db_num).db[76];

1: // Read primary var
IF Sh_Freim THEN PV1 := DWORD_TO_REAL(WORD_TO_BLOCK_DB(db_num).dbd66);
out := RCV_BUF [7];
ELSE PV1 := DWORD_TO_REAL(WORD_TO_BLOCK_DB(db_num).dbd66);
END_IF;
3: // Read current and var's
IF Sh_Freim THEN out := RCV_BUF[7];
Ic := DWORD_TO_REAL(WORD_TO_BLOCK_DB(db_num).dbd65);
PV1 := DWORD_TO_REAL(WORD_TO_BLOCK_DB(db_num).dbd70);
PV2 := DWORD_TO_REAL(WORD_TO_BLOCK_DB(db_num).dbd75);
PV3 := DWORD_TO_REAL(WORD_TO_BLOCK_DB(db_num).dbd80);
ELSE
Ic := DWORD_TO_REAL(WORD_TO_BLOCK_DB(db_num).dbd65);
PV1 := DWORD_TO_REAL(WORD_TO_BLOCK_DB(db_num).dbd70);
PV2 := DWORD_TO_REAL(WORD_TO_BLOCK_DB(db_num).dbd75);
PV3 := DWORD_TO_REAL(WORD_TO_BLOCK_DB(db_num).dbd80);
END_IF; 
END_CASE;
point := 4; timeout := 0;
END_IF; 
IF point = 4 THEN // Delay
timeout := timeout+1;
IF timeout > Delay THEN timeout:=0; point:=5; END_IF;
END_IF; 
IF point = 5 THEN 
FOR i := 0 TO 50 DO RCV_BUF [i] := 0; END_FOR; 
FOR i := 0 TO 10 DO SND_BUF [i] := 0; END_FOR; 
point := 0; 
END_IF;
END_IF; //EN0 
END_FUNCTION_BLOCK

кактотак

cron