Tagessicherung

This commit is contained in:
maier_s
2021-03-30 08:27:31 +02:00
parent 9b9c5cf7a7
commit 07d225369a
154 changed files with 2 additions and 31818 deletions

3
.gitignore vendored
View File

@@ -1,4 +1,5 @@
prj.backup/
prj.backup/*
/prj.backup
/prj/*.info

View File

@@ -1,53 +0,0 @@
FUNCTION "Any.Create" : Void
{ S7_Optimized_Access := 'FALSE' }
VERSION : 0.1
VAR_INPUT
I_DataType : Byte; // Code für den Datentyp (16#01=BOOL, 16#02=BYTE, 16#03=CHAR, 16#04=WORD, 16#05=INT, 16#06=DWORD, 16#07=DINT, 16#08=REAL, 16#09=DATE, 16#0A=TOD, 16#0B=TIME, 16#0C=S5TIME, 16#0E=DT, 16#13=STRING)
I_DataCount : Int; // Wiederholfaktor
I_DB_Number : Int; // Nummer für Datenbaustein
I_MemoryArea : Byte; // Speicherbereich (16#81=Input area (I), 16#82=Output area (O), 16#83=Bit memory area (M), 16#84=Shared Data Block (DB), 16#85=Instance Data Block (DI), 16#86=Local data (L stack), 16#87=Previous local data (V))
I_Byte : Int; // Zeiger für Byteadresse
I_Bit : Int; // Zeiger für Bitadresse
END_VAR
VAR_OUTPUT
O_Any : Any; // Any Out
pDataAny AT O_Any : "Any.T_AnyPoint";
END_VAR
VAR_TEMP
pData : Any; // Pointer Eingangs Daten
flt : Int; // Fehler Blkmov
END_VAR
BEGIN
(*#################################################################################################
Copyright (c) Fondium Singen GmbH
### Änderungshistorie ###
Datum: Version: Bearbeiter: Beschreibung:
18.02.2021 0.0 St. Maier Neuerstellung
16.03.2021 0.0 St. Maier div. Anpassungen
#################################################################################################*)
(*#################################################################################################
Beschreibung:
Mit der Funktion kann ein Any-Pointer zusammen gestellt werden - dieser wird dann am
Ausgang O_Any bereitgestllt.
#################################################################################################*)
#pDataAny.SyntaxId := 16#10;
#pDataAny.DataType := #I_DataType;
#pDataAny.DataCount := #I_DataCount;
#pDataAny.DB_Number := INT_TO_WORD(#I_DB_Number);
#pDataAny.BytePointer := SHL(IN := BYTE_TO_DWORD(#I_MemoryArea), N := 24) OR SHL(IN := WORD_TO_DWORD(INT_TO_WORD(#I_Byte)), N := 3) OR WORD_TO_DWORD(INT_TO_WORD(#I_Bit));
END_FUNCTION

View File

@@ -1,65 +0,0 @@
FUNCTION "Any.GetEndAdr" : Int
{ S7_Optimized_Access := 'FALSE' }
VERSION : 0.1
VAR_INPUT
I_Any : Any; // Eingangs-Any
END_VAR
VAR_TEMP
pData : Any; // Pointer Eingangs Daten
pDataAny AT pData : "Any.T_AnyPoint"; // Pointer Eingangs Daten Detail
adrOffSet : Int; // Adress-Offset
END_VAR
BEGIN
(*#################################################################################################
Copyright (c) Fondium Singen GmbH
### Änderungshistorie ###
Datum: Version: Bearbeiter: Beschreibung:
06.03.2021 0.0 St. Maier Neuerstellung
#################################################################################################*)
(*#################################################################################################
Beschreibung:
Die Funktion gibt die End-Adresse eines Any-Pointers zurück.
#################################################################################################*)
// Any initialisieren
#pData := #I_Any;
// Offset bestimmen
#adrOffSet := "Any.GetOffset"(#pData);
CASE CHAR_TO_INT(BYTE_TO_CHAR(#pDataAny.DataType)) OF
1: // BOOL
#"Any.GetEndAdr" := 8 * #pDataAny.DataCount + #adrOffSet - 2; // Boolean
2, 3: // Byte, Char
#"Any.GetEndAdr" := #pDataAny.DataCount + #adrOffSet - 2; // 1 Byte, Adress-Offset addieren und 2 Byte abziehen
4, 5, 9, 12: // Word, Int, Date, S5Time
#"Any.GetEndAdr" := #pDataAny.DataCount * 2 + #adrOffSet - 2; // 2 Byte, mit 2 Byte multiplizieren und Adress-Offset addieren und 2 Byte abziehen
6..8, 10, 11: // DWord, DInt, Reak, TOD, Time
#"Any.GetEndAdr" := #pDataAny.DataCount * 4 + #adrOffSet - 2; // 4 Byte, mit 4 Byte multiplizieren und Adress-Offset addieren und 2 Byte abziehen
14: // DT
#"Any.GetEndAdr" := #pDataAny.DataCount * 8 + #adrOffSet - 2; // 8 Byte, mit 8 Byte multiplizieren und Adress-Offset addieren und 2 Byte abziehen
ELSE:
#"Any.GetEndAdr" := 0;
END_CASE;
END_FUNCTION

View File

@@ -1,40 +0,0 @@
FUNCTION "Any.GetOffset" : Int
{ S7_Optimized_Access := 'FALSE' }
VERSION : 0.1
VAR_INPUT
I_Any : Any; // Eingangs-Any
END_VAR
VAR_TEMP
pData : Any; // Pointer Eingangs Daten
pDataAny AT pData : "Any.T_AnyPoint"; // Pointer Eingangs Daten Detail
END_VAR
BEGIN
(*#################################################################################################
Copyright (c) Fondium Singen GmbH
### Änderungshistorie ###
Datum: Version: Bearbeiter: Beschreibung:
06.03.2021 0.0 St. Maier Neuerstellung
#################################################################################################*)
(*#################################################################################################
Beschreibung:
Die Funktion gibt die Offset-Adresse eines Any-Pointers zurück.
#################################################################################################*)
// Any initialisieren
#pData := #I_Any;
// Adress-Offset berechnen
#"Any.GetOffset" := DWORD_TO_INT(SHR(IN := SHL(IN := #pDataAny.BytePointer, N := 16), N := 19));
END_FUNCTION

View File

@@ -1,129 +0,0 @@
FUNCTION "Any.Lng" : Word
{ S7_Optimized_Access := 'FALSE' }
AUTHOR : FSI
VERSION : 0.3
VAR_INPUT
I_StartBitAndRange : Any; // Definierter ANY-Pointer
END_VAR
VAR_OUTPUT
O_Lng : DInt; // ermittelte Länge
END_VAR
VAR_TEMP
buffer : "Any.T_AnyPoint"; // Variable "buffer" vom Typ UDT: "T_AnyPoint"
tmpAny AT buffer : Any; // Temp. Variable zum Zugriff auf dem Buffer (UDT)
bitCnt : DInt; // Bit-Zähler
err : Word; // Fehler-Rückgabewert
END_VAR
BEGIN
(*#################################################################################################
Copyright (c) Fondium Singen GmbH
### Änderungshistorie ###
Datum: Version: Bearbeiter: Beschreibung:
26.09.2019 0.0 St. Maier Neuerstellung
10.10.2019 0.1 St. Maier Abhänigkeiten aus Baustein Beschreibung entfernt
10.10.2019 0.2 St. Maier O_Buffer entfernt - zukünftig für jedes Element einen
seperaten Baustein
11.10.2019 0.3 St. Maier Überarbeitung Kopf damit TIA kompatibel
17.10.2019 0.4 St. Maier Variablen Kommentare eingefügt - wurden bei der
Portierung nach TIA nicht übernommen
24.10.2019 0.5 St. Maier Datentypen erweitert
#################################################################################################*)
(*################################### Baustein Beschreibung #######################################
Abhängigkeiten (von anderen Fuktionen und Quellen):
-
Inputs:
- StartBitAndRange: Definierter ANY-Pointer
Outputs:
- Lng: ermittelte Länge
In-\Outputs:
-
Return-Value:
- AnyLng: Fehlermeldung für die Bausteinausgabe
Funktionsbeschreibung:
Der Baustein gibt die Länge eines Any-Pointer zurück.
#################################################################################################*)
(* Datentypen
Hex Dez Datentyp
00 0 NIL
01 1 Bool
02 2 Byte
03 3 Char
04 4 WORD
05 5 INT
06 6 DWORD
07 7 DINT
08 8 REAL
09 9 Date
0A 10 Time of day (TOD)
0B 11 Time
0C 12 S5Time
0D 13 String
0E 14 Date and Time (DT)
*)
#err := 0; // Rücksetze err-Variable
#tmpAny := #I_StartBitAndRange; // Hier werden die Daten aus der Eingangsvariable "StartBitAndRange" (ANY-
// Pointer) der temporären Variable "tmpAny" (ANY-Pointer mit Zugriff auf
// die Buffer-Variable vom Typ UDT "tAnyPoint") übergeben. Somit ist das Lesen
// und Schreiben der Daten in den Buffer möglich, um den Zeiger zu bilden.
CASE CHAR_TO_INT(BYTE_TO_CHAR(#buffer.DataType)) OF
1:
#bitCnt := 8 * #buffer.DataCount; // Boolean
2:
#bitCnt := #buffer.DataCount; // BYTE, dann multipliziere mit 8
3:
#bitCnt := #buffer.DataCount; // CHAR, dann multipliziere mit 8
4:
#bitCnt := #buffer.DataCount / 2; // WORD, dann multipliziere mit 16
5:
#bitCnt := #buffer.DataCount / 2; // INT, dann multipliziere mit 16
6:
#bitCnt := #buffer.DataCount / 4; // DWORD, dann multipliziere mit 32
7:
#bitCnt := #buffer.DataCount / 4; // DINT, dann multipliziere mit 32
8:
#bitCnt := #buffer.DataCount / 4; // REAL, dann multipliziere mit 32
9:
#bitCnt := #buffer.DataCount / 2; // Date, dann multipliziere mit 16
10:
#bitCnt := #buffer.DataCount / 4; // Time of day (TOD), dann multipliziere mit 32
11:
#bitCnt := #buffer.DataCount / 4; // Time, dann multipliziere mit 32
12:
#bitCnt := #buffer.DataCount / 2; // S5Time, dann multipliziere mit 16
14:
#bitCnt := #buffer.DataCount / 8; // Date and Time (DT), dann multipliziere mit 16
ELSE: // Andere Typen vom ANY-Pointer, werden nicht unterstützt!
#err := W#16#8001; // Typ vom ANY-Pointer wird nicht unterstützt
END_CASE;
#O_Lng := #bitCnt; // Länge ausgeben
#"Any.Lng" := #err; // Fehlermeldung für die Bausteinausgabe
END_FUNCTION

View File

@@ -1,65 +0,0 @@
FUNCTION "Any.NoOfBytes" : Int
{ S7_Optimized_Access := 'FALSE' }
VERSION : 0.1
VAR_INPUT
I_Any : Any; // Eingangs-Any
END_VAR
VAR_TEMP
pData : Any; // Pointer Eingangs Daten
pDataAny AT pData : "Any.T_AnyPoint"; // Pointer Eingangs Daten Detail
adrOffSet : Int; // Adress-Offset
END_VAR
BEGIN
(*#################################################################################################
Copyright (c) Fondium Singen GmbH
### Änderungshistorie ###
Datum: Version: Bearbeiter: Beschreibung:
06.03.2021 0.0 St. Maier Neuerstellung
#################################################################################################*)
(*#################################################################################################
Beschreibung:
Die Funktion gibt die Anzahl der Bytes eines Any-Pointers zurück.
#################################################################################################*)
// Any initialisieren
#pData := #I_Any;
// Offset bestimmen
#adrOffSet := "Any.GetOffset"(#pData);
CASE CHAR_TO_INT(BYTE_TO_CHAR(#pDataAny.DataType)) OF
1: // BOOL
#"Any.NoOfBytes" := #pDataAny.DataCount; // Boolean
2, 3: // Byte, Char
#"Any.NoOfBytes" := #pDataAny.DataCount; // 1 Byte
4, 5, 9, 12: // Word, Int, Date, S5Time
#"Any.NoOfBytes" := #pDataAny.DataCount * 2; // 2 Byte, mit 2 Byte multiplizieren
6..8, 10, 11: // DWord, DInt, Reak, TOD, Time
#"Any.NoOfBytes" := #pDataAny.DataCount * 4; // 4 Byte, mit 4 Byte multiplizieren
14: // DT
#"Any.NoOfBytes" := #pDataAny.DataCount * 8; // 8 Byte, mit 8 Byte multiplizieren
ELSE:
#"Any.NoOfBytes" := 0;
END_CASE;
END_FUNCTION

View File

@@ -1,81 +0,0 @@
FUNCTION "Any.Struct" : Word
{ S7_Optimized_Access := 'FALSE' }
AUTHOR : FSI
VERSION : 0.1
VAR_INPUT
I_UDT : Any; // UDT
I_StartBitAndRange : Any; // Definierter ANY-Pointer
END_VAR
VAR_OUTPUT
O_DataCount : DInt; // ermittelte Anzahl Elemente
END_VAR
VAR_TEMP
lngUdt : DInt; // ermittelte Länge des UDT
lngStruct : DInt; // Länge des ANY-Pointers
err : Word; // Fehler-Rückgabewert
END_VAR
BEGIN
(*#################################################################################################
Copyright (c) Fondium Singen GmbH
### Änderungshistorie ###
Datum: Version: Bearbeiter: Beschreibung:
11.10.2019 0.0 St. Maier Neuerstellung
11.10.2019 0.1 St. Maier Überarbeitung Kopf damit TIA kompatibel
18.10.2019 0.2 St. Maier Variablen Kommentare eingefügt - wurden bei der
Portierung nach TIA nicht übernommen
#################################################################################################*)
(*################################### Baustein Beschreibung #######################################
Abhängigkeiten (von anderen Fuktionen und Quellen):
- AnyLng
Inputs:
- I_UDT: Referenz UDT
- StartBitAndRange: Definierter ANY-Pointer
Outputs:
- O_DataCount: ermittelte Länge/Anzahl der Elemente eines UDT Arrays
In-\Outputs:
-
Return-Value:
- AnyLng: Fehlermeldung für die Bausteinausgabe
Funktionsbeschreibung:
Der Baustein gibt die Länge/Anzahl der Elemente eines UDT Arrays zurück.
#################################################################################################*)
#err := 0 ; // Rücksetze err-Variable
// Länge des UDT bestimmen
#err := "Any.Lng"( I_StartBitAndRange := #I_UDT // IN: ANY
,O_Lng => #lngUdt // OUT: DINT
); // WORD
// Länge des ANY-Pointers bestimmen
#err := "Any.Lng"( I_StartBitAndRange := #I_StartBitAndRange // IN: ANY
,O_Lng => #lngStruct // OUT: INT
); // WORD
#O_DataCount := #lngStruct / #lngUdt; // Anzahl Elemente ausgeben
#"Any.Struct" := #err; // Fehlermeldung für die Bausteinausgabe
END_FUNCTION

View File

@@ -1,14 +0,0 @@
TYPE "Any.T_AnyCreate"
AUTHOR : FSI
VERSION : 0.0
STRUCT
DataType : Byte; // Code für den Datentyp (16#01=BOOL, 16#02=BYTE, 16#03=CHAR, 16#04=WORD, 16#05=INT, 16#06=DWORD, 16#07=DINT, 16#08=REAL, 16#09=DATE, 16#0A=TOD, 16#0B=TIME, 16#0C=S5TIME, 16#0E=DT, 16#13=STRING)
DataCount : Int; // Wiederholfaktor
DB_Number : Int; // Nummer für Datenbaustein
MemoryArea : Byte; // Speicherbereich (16#81=Input area (I), 16#82=Output area (O), 16#83=Bit memory area (M), 16#84=Shared Data Block (DB), 16#85=Instance Data Block (DI), 16#86=Local data (L stack), 16#87=Previous local data (V))
BytePointer : Int; // Zeiger für Byteadresse
BitPointer : Int; // Zeiger für Bitadresse
END_STRUCT;
END_TYPE

View File

@@ -1,13 +0,0 @@
TYPE "Any.T_AnyPoint"
AUTHOR : FSI
VERSION : 0.0
STRUCT
SyntaxId : Byte; // Angabe der Syntax-ID
DataType : Byte; // Code für den Datentyp (16#01=BOOL, 16#02=BYTE, 16#03=CHAR, 16#04=WORD, 16#05=INT, 16#06=DWORD, 16#07=DINT, 16#08=REAL, 16#09=DATE, 16#0A=TOD, 16#0B=TIME, 16#0C=S5TIME, 16#0E=DT, 16#13=STRING)
DataCount : Int; // Wiederholfaktor
DB_Number : Word; // Nummer für Datenbaustein
BytePointer : DWord; // Zeiger für Byte- und Bitadresse
END_STRUCT;
END_TYPE

View File

@@ -1,14 +0,0 @@
TYPE "Any.T_AnyPointDtl"
VERSION : 0.1
STRUCT
SyntaxId : Byte := 16#0; // Angabe der Syntax-ID
DataType : Byte := 16#0; // Code für den Datentyp (16#01=BOOL, 16#02=BYTE, 16#03=CHAR, 16#04=WORD, 16#05=INT, 16#06=DWORD, 16#07=DINT, 16#08=REAL, 16#09=DATE, 16#0A=TOD, 16#0B=TIME, 16#0C=S5TIME, 16#0E=DT, 16#13=STRING)
DataCount : Int := 0; // Wiederholfaktor
DB_Number : Word := 16#0; // Nummer für Datenbaustein
MemoryArea : Byte; // Speicherbereich (16#81=Input area (I), 16#82=Output area (O), 16#83=Bit memory area (M), 16#84=Shared Data Block (DB), 16#85=Instance Data Block (DI), 16#86=Local data (L stack), 16#87=Previous local data (V))
ByteAddressMSB : Byte; // Speicherbereich MSB
ByteAddressLSB : Word; // Speicherbereich LSB
END_STRUCT;
END_TYPE

View File

@@ -1,95 +0,0 @@
FUNCTION "BufClr" : Void
{ S7_Optimized_Access := 'FALSE' }
VERSION : 0.1
VAR_INPUT
I_Data : Any; // Eingangswert
END_VAR
VAR_TEMP
pData : Any; // Pointer Eingangs Daten
pDataAny AT pData : "Any.T_AnyPoint"; // Pointer Eingangs Daten Detail
pDataTrg : Any; // Pointer Eingangs Daten
pDataTrgAny AT pDataTrg : "Any.T_AnyPoint"; // Pointer Eingangs Daten Detail
step : Int; // Schrittweite für die Adressen
adrAct : Int; // Aktuelle Adresse
adrEnd : Int; // End Adresse
bitCnt : Int; // Bit-Zähler
tmpDWord : DWord; // tmp Var
adrOffSet : Int; // Adress-Offset
flt : Int; // Fehler Blkmov
END_VAR
VAR CONSTANT
LEN_DW : Int := 4; // Doppelwort
LEN_W : Int := 2; // Wort
END_VAR
BEGIN
(*#################################################################################################
Copyright (c) Fondium Singen GmbH
### Änderungshistorie ###
Datum: Version: Bearbeiter: Beschreibung:
05.03.2021 0.0 St. Maier Neuerstellung
17.03.2021 0.0 St. Maier Var für End-Adress Bestimmung angepasst
#################################################################################################*)
(*#################################################################################################
Beschreibung:
Die Funktion initialisiert ein beliebiges Array mit 0. Beim Aufruf wird der Funktion ein
Pointer auf das zu initialisierende Array übergeben. Das durch den Pointer angegebene Array
wird direkt im Speicher manipuliert.
#################################################################################################*)
// Pointer initizialisieren
#pData := #I_Data;
#pDataTrg := #pData;
// Byte-Offset berechnen
#adrOffSet := "Any.GetOffset"(#pData);
#adrAct := #adrOffSet;
// End-Adress berechnen
#adrEnd := "Any.GetEndAdr"(#pDataTrg);
// Schrittweiten berechnen
IF #pDataAny.DataCount / #LEN_DW > real#1.0 THEN
#step := #LEN_DW;
ELSE
#step := #LEN_W;
END_IF;
WHILE (#adrAct <= #adrEnd) DO
#tmpDWord := DW#16#00000000;
// Daten zum Kopieren zusammenstellen
IF #step = #LEN_DW THEN // Doppelwort
#pDataTrgAny.DataType := B#16#06; // Doppelwort
ELSE // Wort
#pDataTrgAny.DataType := B#16#04; // Wort
END_IF;
#pDataTrgAny.BytePointer := dw#16#84000000 OR SHL(IN := WORD_TO_DWORD(INT_TO_WORD(#adrAct)), N := 3); // Byte-Adresse in Pointer laden
#pDataTrgAny.DataCount := 1; // Länge
#flt := BLKMOV(SRCBLK := #tmpDWord, DSTBLK => #pDataTrg); // Eingangs-Daten kopieren
// Schrittweite am Ende des Datenbereichs bestimmen
IF #adrEnd - #adrAct < #LEN_DW THEN
#step := #LEN_W;
END_IF;
// Adressen inkrementieren
#adrAct := #adrAct + #step;
END_WHILE;
END_FUNCTION

View File

@@ -1,73 +0,0 @@
FUNCTION_BLOCK "CpuPrgChanged"
{ S7_Optimized_Access := 'FALSE' }
VERSION : 0.1
VAR_OUTPUT
O_PrgChanged : Bool; // Anwenderprogramm wurde geändert
O_HwChanged : Bool; // Hardware wurd geändert
END_VAR
VAR
"SFC51" : Struct
OUT_RET_VAL : Int;
OUT_BUSY : Bool;
OUT_SZL_HEADER : Struct
LENTHDR : Word;
N_DR : Word;
END_STRUCT;
OUT_DR : Struct
INDEX : Word; // Index-Informationen des Teilauszugs
sch_schal : Word; // Durch Betriebsartenschalter eingestellte
sch_par : Word; // parametrierte Schutzstufe
sch_rel : Word; // gültige Schutzstufe der CPU
bart_sch : Word; // Stellung des Betriebsartenschalters
anl_sch : Word; // Stellung des Anlaufartenschalters
ken_f : Word; // Reserviert
ken_rel : Word; // Kennung der Gültigkeit der vier folgendenPrüfsummen
ken_ver1_hw : Word; // Prüfsumme 1 der Hardwarekonfiguration
ken_ver2_hw : Word; // Prüfsumme 2 der Hardwarekonfiguration
ken_ver1_awp : Word; // Prüfsumme 1 des Anwenderprogramms
ken_ver2_awp : Word; // Prüfsumme 2 des Anwenderprogramms
res : Array[0..7] of Word;
END_STRUCT;
END_STRUCT;
checksumHw : Word;
checksumAwp : Word;
END_VAR
VAR_TEMP
hvVar : Bool;
END_VAR
BEGIN
(*#################################################################################################
Copyright (c) Fondium Singen GmbH
### Änderungshistorie ###
Datum: Version: Bearbeiter: Beschreibung:
01.12.2020 0.0 St. Maier Neuerstellung
#################################################################################################*)
// Aufruf SFC 51
#SFC51.OUT_RET_VAL := RDSYSST(REQ := true,
SZL_ID := W#16#232,
INDEX := W#16#4,
BUSY => #SFC51.OUT_BUSY,
SZL_HEADER => #SFC51.OUT_SZL_HEADER,
DR => #SFC51.OUT_DR
);
#hvVar := (#checksumAwp <> 0) AND NOT #SFC51.OUT_BUSY;
#O_HwChanged := (#SFC51.OUT_DR.ken_ver2_hw <> #checksumHw) AND #hvVar;
#O_PrgChanged := (#SFC51.OUT_DR.ken_ver2_awp <> #checksumAwp) AND #hvVar;
#checksumHw := #SFC51.OUT_DR.ken_ver2_hw;
#checksumAwp := #SFC51.OUT_DR.ken_ver2_awp;
END_FUNCTION_BLOCK

View File

@@ -1,58 +0,0 @@
FUNCTION "CpuRdZt" : Void
{ S7_Optimized_Access := 'FALSE' }
VERSION : 0.1
VAR_OUTPUT
O_DatUzt : Date_And_Time; // Datum und Uhrzeit
END_VAR
VAR_TEMP
retVal : Int; // Rückgabewert Systemzeitauslesen
tmpDatUzt : Date_And_Time;
END_VAR
BEGIN
(*#################################################################################################
Copyright (c) Fondium Singen GmbH
### Änderungshistorie ###
Datum: Version: Bearbeiter: Beschreibung:
16.10.2019 0.0 St. Maier Neuerstellung
#################################################################################################*)
(*################################### Baustein Beschreibung #######################################
Abhängigkeiten (von anderen Fuktionen und Quellen):
-
Inputs:
-
Outputs:
- O_DatUzt: Uhrzeit und Datum der CPU
In-\Outputs:
-
Return-Value:
-
Funktionsbeschreibung:
Baustein lies System Datum und Uhrzeit von der CPU aus.
#################################################################################################*)
// Systemzeit auslesen
#retVal := RD_SYS_T(#tmpDatUzt);
IF #retVal = 0 THEN
// aktuelles Datum und Uhrzeit ausgeben
#O_DatUzt := #tmpDatUzt;
END_IF;
END_FUNCTION

View File

@@ -1,65 +0,0 @@
FUNCTION "CpuZt" : DWord
{ S7_Optimized_Access := 'FALSE' }
AUTHOR : FSI
VERSION : 0.1
VAR_INPUT
"I_STIME.tx" : DWord; // Zeit
END_VAR
VAR CONSTANT
debug : Bool;
N : Int;
offset : Int;
offset_1 : DWord := 0;
END_VAR
BEGIN
(*#################################################################################################
Copyright (c) Fondium Singen GmbH
### Änderungshistorie ###
Datum: Version: Bearbeiter: Beschreibung:
23.09.2018 0.0 St. Maier Neuerstellung
11.10.2019 0.1 St. Maier Überarbeitung Kopf damit TIA kompatibel
17.10.2019 0.2 St. Maier I_STIME Eingefügt, damit keine Abhängigkeit zu einem
IDB besteht
18.10.2019 0.3 St. Maier Variablen Kommentare eingefügt - wurden bei der
Portierung nach TIA nicht übernommen
#################################################################################################*)
(*################################### Baustein Beschreibung #######################################
Abhängigkeiten (von anderen Fuktionen und Quellen):
- STIME, IDB_STIME
Inputs:
- I_STIME.tx
Outputs:
-
In-\Outputs:
-
Return-Value:
-
Funktionsbeschreibung:
#################################################################################################*)
#CpuZt := #"I_STIME.tx";
IF #debug THEN
#CpuZt := DINT_TO_DWORD((DWORD_TO_DINT(SHL(IN:=#CpuZt,N:=#N) OR SHL(IN:=DWORD#1,N:=#N))-1) + DWORD_TO_DINT(#offset_1));
END_IF;
END_FUNCTION

View File

@@ -1,65 +0,0 @@
FUNCTION "CpuZtUS" : DWord
{ S7_Optimized_Access := 'FALSE' }
AUTHOR : FSI
VERSION : 0.1
VAR_INPUT
"I_STIME.tx" : DWord; // Zeit
END_VAR
VAR CONSTANT
debug : Bool;
N : Int;
offset : Int;
offset_1 : DWord := 0;
END_VAR
BEGIN
(*#################################################################################################
Copyright (c) Fondium Singen GmbH
### Änderungshistorie ###
Datum: Version: Bearbeiter: Beschreibung:
23.09.2018 0.0 St. Maier Neuerstellung
11.10.2019 0.1 St. Maier Überarbeitung Kopf damit TIA kompatibel
17.10.2019 0.2 St. Maier I_STIME Eingefügt, damit keine Abhängigkeit zu einem
IDB besteht
18.10.2019 0.3 St. Maier Variablen Kommentare eingefügt - wurden bei der
Portierung nach TIA nicht übernommen
#################################################################################################*)
(*################################### Baustein Beschreibung #######################################
Abhängigkeiten (von anderen Fuktionen und Quellen):
- STIME, IDB_STIME
Inputs:
- I_STIME.tx
Outputs:
-
In-\Outputs:
-
Return-Value:
-
Funktionsbeschreibung:
#################################################################################################*)
#CpuZtUS := DINT_TO_DWORD(DWORD_TO_DINT(#"I_STIME.tx") * 1000);
IF #debug THEN
#CpuZtUS := DINT_TO_DWORD((DWORD_TO_DINT(SHL(IN:=#CpuZtUS,N:=#N) OR SHL(IN:=DWORD#1,N:=#N))-1) + DWORD_TO_DINT(#offset_1));
END_IF;
END_FUNCTION

View File

@@ -1,9 +0,0 @@
TYPE "CpuZylZt.T_ZylZt"
AUTHOR : FSI
VERSION : 0.0
STRUCT
Zt : Time;
END_STRUCT;
END_TYPE

View File

@@ -1,15 +0,0 @@
TYPE "CpuZylZt.T_ZylZtStat"
VERSION : 0.1
STRUCT
ZylZtMin : Time; // minimale gemessene Zykluszeit
ZylZtMax : Time; // maximal gemessene Zykluszeit
ZylZtAv : Time; // durschnittlich gemessene Zykluszeit
ZylZt : Time; // zuletzt gemessene Zykluszeit
SysZt : Time; // Laufzeit seit dem letzten Start
SysTg : Int; // Anzahl der Tage seit dem letzten Start
SysLfZt : "TimeDtl"; // Laufzeit seit dem letzten Start
Zyl : DWord; // Anzahl der Zyklen seit dem letzten Start
END_STRUCT;
END_TYPE

View File

@@ -1,231 +0,0 @@
FUNCTION_BLOCK "CpuZylZt"
{ S7_Optimized_Access := 'FALSE' }
AUTHOR : FSI
VERSION : 1.1
VAR_INPUT
I_Rst : Bool; // Reset
I_ZylZtSreg : Any; // Schieberegister für Zykluszeiten
"I_STIME.tx" : DWord; // Zeit
END_VAR
VAR_OUTPUT
O_ZylZtMin : Time := t#10h; // minimale gemessene Zykluszeit
O_ZylZtMax : Time := t#0ms; // maximal gemessene Zykluszeit
O_ZylZtAv : Time := t#0ms; // durschnittlich gemessene Zykluszeit
O_ZylZt : Time := t#0ms; // zuletzt gemessene Zykluszeit
O_SysZt : Time := t#0ms; // Laufzeit seit dem letzten Start
O_SysTg : Int := 0; // Anzahl der Tage seit dem letzten Start
O_Zyl : DWord := 0; // Anzahl der Zyklen seit dem letzten Start
END_VAR
VAR
zylZt : Time; // zuletzt gemessene Zykluszeit
tx : Time; // aktuelle Systemzeit
init : Bool; // Baustein inizialisiert
anyFlt : Word; // Infos des Schieberegisters
ZylZtSum : Time; // Fehler beim Bestimmen der Länge
i : Int; // ermittelte Länge des AnyPointers
i_init : Bool;
tmpUdt : "CpuZylZt.T_ZylZt"; // Summe der Zykluszeiten
oldVal : "CpuZylZt.T_ZylZt";
cyclNrs : DInt; // Laufvariable für Schieberegister
END_VAR
VAR_TEMP
TOP_SI : Struct
EV_CLASS : Byte;
EV_NUM : Byte;
PRIORITY : Byte;
NUM : Byte;
TYP2_3 : Byte;
TYP1 : Byte;
ZI1 : Word;
ZI2_3 : DWord;
END_STRUCT;
START_UP_SI : Struct
EV_CLASS : Byte;
EV_NUM : Byte;
PRIORITY : Byte;
NUM : Byte;
TYP2_3 : Byte;
TYP1 : Byte;
ZI1 : Word;
ZI2_3 : DWord;
END_STRUCT;
err : Int;
END_VAR
BEGIN
(*#################################################################################################
Copyright (c) Fondium Singen GmbH
### Änderungshistorie ###
Datum: Version: Bearbeiter: Beschreibung:
23.09.2019 0.0 St. Maier Neuerstellung
24.09.2019 0.1 St. Maier Durchschittsberechnung der Zykluszeit angepasst
24.09.2019 1.0 St. Maier Überarbeitung des Baustein, damit nicht Baustein für
Verlängerung des Schieberegisters angepasst werden muss
sondern nur der dazugehörige DB
11.10.2019 1.1 St. Maier Überarbeitung Kopf damit TIA kompatibel
15.10.2019 2.0 St. Maier Überarbeitung des Baustein, damit nicht Baustein für
Verlängerung des Schieberegisters oder Anpassung des
UDT angepasst werden muss.
17.10.2019 2.1 St. Maier I_STIME Eingefügt, damit keine Abhängigkeit zu einem
IDB besteht
18.10.2019 2.2 St. Maier Variablen Kommentare eingefügt - wurden bei der
Portierung nach TIA nicht übernommen
18.10.2019 2.3 St. Maier O_ZylZtMin Defaultwert auf t#10h gesetzt,ansonsten
wird min. Zykluszeit von 0 ms angezeigt
24.10.2019 3.0 St. Maier Überarbeitung Schieberegister
10.02.2021 3.1 St. Maier Probleme mit Zeitwert im negativen Bereich behoben
#################################################################################################*)
(*################################### Baustein Beschreibung #######################################
Abhängigkeiten (von anderen Fuktionen und Quellen):
- RD_SINFO
- CpuZeit
- Any.Lng
- Any.Struct
Inputs:
- I_Rst : Reset
- I_ZylZtShiftReg : Schieberegister für Zykluszeiten
Outputs:
- O_ZylZtMin: minimale gemessene Zykluszeit
- O_ZylZtMax: maximal gemessene Zykluszeit
- O_ZylZtAv : durschnittlich gemessene Zykluszeit
- O_ZylZt : zuletzt gemessene Zykluszeit
- O_SysZt : Laufzeit seit dem letzten Start
- O_SysTg : Anzahl der Tage seit dem letzten Start
- O_Zyl : Anzahl der Zyklen seit dem letzten Start
In-\Outputs:
-
Return-Value:
-
Funktionsbeschreibung:
Dies Funktion überacht die Zykluszeiten der SPS und stellt eine Reihe von Informationen über
Zykluszeiten und Laufzeiten zur Verfügung.
#################################################################################################*)
(* aktuelle Startinformationen auslesen *)
(* OB1_SCAN_1 BYTE - B#16#01: Abschluss des Neustarts (Warmstarts)
- B#16#02: Abschluss des Wiederanlaufs
- B#16#03: Abschluss des freien Zyklus
- B#16#04: Abschluss des Kaltstarts
- B#16#05: Erster OB 1-Zyklus der neuen Master-CPU nach
Master-Reserve-Umschaltung und STOP des
bisherigen Masters *)
#err := RD_SINFO(TOP_SI => #TOP_SI // OUT: STRUCT
, START_UP_SI => #START_UP_SI // OUT: STRUCT
); // INT
// Zurücksetzen der letzten Zykluszeit bei System start
IF #TOP_SI.EV_NUM <> 3 THEN
#zylZt := t#0ms;
END_IF;
// Infos wie Array-Länge von Schieberegiaster bestimmen
#anyFlt := "Any.Struct"(I_UDT := #tmpUdt
, I_StartBitAndRange := #I_ZylZtSreg
, O_DataCount => #cyclNrs
);
#tx := DINT_TO_TIME(DWORD_TO_DINT("CpuZt"("I_STIME.tx" := #"I_STIME.tx"))) - #zylZt;
IF #I_Rst THEN
#O_ZylZtMin := t#10h;
#O_ZylZtMax := t#0ms;
#O_ZylZtAv := t#0ms;
#ZylZtSum := t#0ms;
#O_Zyl := 0;
#i := 0;
#i_init := false;
RETURN;
ELSIF #zylZt <> t#0ms THEN
IF #tx < #O_ZylZtMin AND #tx > t#0ms THEN
#O_ZylZtMin := #tx;
ELSIF #tx > #O_ZylZtMax THEN
#O_ZylZtMax := #tx;
END_IF;
#O_ZylZt := #tx;
#tmpUdt.Zt := #tx;
END_IF;
IF #init THEN
#O_SysZt := #O_SysZt + #tx;
IF #O_SysZt >= t#1d THEN
#O_SysZt := #O_SysZt - t#1d;
#O_SysTg := #O_SysTg + 1;
END_IF;
END_IF;
// Zähler zum durchlaufen des Registers
IF #i >= DINT_TO_INT(#cyclNrs) - 1 THEN
#i := 0;
#i_init := true;
ELSE
#i := #i + 1;
END_IF;
// Daten aus Array abholen für Zykluszeitberechnung
"UdtAryGet"(I_SrcAry := #I_ZylZtSreg,
I_SrcIndex := #i,
I_DesUdt := #oldVal,
O_Ret => #err);
// "alte" Zykluszeit subtrahieren
IF #i_init = true THEN
#ZylZtSum := #ZylZtSum - #oldVal.Zt;
END_IF;
// Daten kopieren
"UdtArySet"(I_SrcUdt:=#tmpUdt,
I_DestIndex:= #i,
I_DestAry:=#I_ZylZtSreg,
O_Ret=>#err);
// Zykluszeiten addieren
#ZylZtSum := #ZylZtSum + #tmpUdt.Zt;
#init := TRUE;
#zylZt := #zylZt + #tx;
#O_Zyl := DINT_TO_DWORD(DWORD_TO_DINT(#O_Zyl) + 1);
// Durchschnitts-Zykluszeit berechnen
IF #i_init THEN
#O_ZylZtAv := #ZylZtSum / (#cyclNrs - 1);
ELSE
#O_ZylZtAv := #ZylZtSum / (#i);
END_IF;
END_FUNCTION_BLOCK

View File

@@ -1,124 +0,0 @@
FUNCTION_BLOCK "STIME"
{ S7_Optimized_Access := 'FALSE' }
AUTHOR : FSI
VERSION : 0.2
VAR_OUTPUT
tx : DWord;
at_tx { S7_HMI_Accessible := 'False'; S7_HMI_Visible := 'False'} AT tx : Array[0..31] of Bool;
END_VAR
VAR
last_time : DWord;
bit31 : Bool;
init : Bool := TRUE;
END_VAR
VAR_TEMP
TOP_SI : Struct
EV_CLASS : Byte;
EV_NUM : Byte;
PRIORITY : Byte;
NUM : Byte;
TYP2_3 : Byte;
TYP1 : Byte;
ZI1 : Word;
ZI2_3 : DWord;
END_STRUCT;
START_UP_SI : Struct
EV_CLASS : Byte;
EV_NUM : Byte;
PRIORITY : Byte;
NUM : Byte;
TYP2_3 : Byte;
TYP1 : Byte;
ZI1 : Word;
ZI2_3 : DWord;
END_STRUCT;
err : Int;
END_VAR
BEGIN
(*#################################################################################################
Copyright (c) Fondium Singen GmbH
### Änderungshistorie ###
Datum: Version: Bearbeiter: Beschreibung:
23.09.2019 0.0 St. Maier Neuerstellung
10.10.2019 0.1 St. Maier IDB Generierung eingefügt
11.10.2019 0.2 St. Maier Überarbeitung Kopf damit TIA kompatibel
#################################################################################################*)
(*################################### Baustein Beschreibung #######################################
Abhängigkeiten (von anderen Fuktionen und Quellen):
-
Inputs:
-
Outputs:
-
In-\Outputs:
-
Return-Value:
-
Funktionsbeschreibung:
Der Siemens Sps Timer zählt von 0 bis 2 ^ 31-1 und startet nach Überlauf bei 0.
Dies bedeutet, dass das Bit 31 (das höchste Bit) niemals verwendet wird und daher ein Problem
auftritt, wenn t2 - t1 geprüft wird.
t2 - t1 ist auch in einer Überlaufsituation immer gültig, in der die Zeit t1 sehr hoch und t2 sehr
niedrig ist. Das Ergebnis der Subtraktion t2 - t1 ist jedoch weiterhin gültig.
Diese Berechnung funktioniert bei Siemens nicht, da das höchste Bit nicht verwendet wird.
Dieses Modul speichert das höchste Bit, ändert das höchste Bit bei jedem Überlauf und gibt dieses aus.
#################################################################################################*)
(* aktuelle Startinformationen auslesen *)
(* OB1_SCAN_1 BYTE - B#16#01: Abschluss des Neustarts (Warmstarts)
- B#16#02: Abschluss des Wiederanlaufs
- B#16#03: Abschluss des freien Zyklus
- B#16#04: Abschluss des Kaltstarts
- B#16#05: Erster OB 1-Zyklus der neuen Master-CPU nach
Master-Reserve-Umschaltung und STOP des
bisherigen Masters *)
#err := RD_SINFO( TOP_SI => #TOP_SI // OUT: STRUCT
,START_UP_SI => #START_UP_SI // OUT: STRUCT
); // INT
// Zurücksetzen der letzten Zykluszeit bei System start
IF #TOP_SI.EV_NUM = 1 OR #TOP_SI.EV_NUM = 2 OR #TOP_SI.EV_NUM = 4 OR NOT #init THEN
#last_time := 0;
#bit31 := false;
#init := true;
END_IF;
// Systemzeit auslesen
#tx := DINT_TO_DWORD(TIME_TO_DINT(TIME_TCK()));
// Auf Überlauf überprüfen
IF DWORD_TO_DINT(#tx) < DWORD_TO_DINT(#last_time) THEN
// Wenn Überlauf, dann den Wert des höchsten Bits ändern
#bit31 := NOT #bit31;
END_IF;
// Höchste Bit in einen Time-Wert ädnern
#at_tx[7] := #bit31;
// Die letzte Systemzeit zum Überprüfen des nächsten Überlaufs merken
#last_time := #tx;
END_FUNCTION_BLOCK

View File

@@ -1,54 +0,0 @@
FUNCTION "BlockDbToAny" : Void
{ S7_Optimized_Access := 'FALSE' }
VERSION : 0.1
VAR_INPUT
I_BlockDb : Block_DB; // Block Datenbaustein
I_DataType : Byte; // Code für den Datentyp (16#01=BOOL, 16#02=BYTE, 16#03=CHAR, 16#04=WORD, 16#05=INT, 16#06=DWORD, 16#07=DINT, 16#08=REAL, 16#09=DATE, 16#0A=TOD, 16#0B=TIME, 16#0C=S5TIME, 16#0E=DT, 16#13=STRING)
I_DataCount : Int; // Wiederholfaktor
I_Byte : Int; // Zeiger für Byteadresse
I_Bit : Int; // Zeiger für Bitadresse
END_VAR
VAR_OUTPUT
O_Any : Any; // Any Out
END_VAR
VAR_TEMP
err : Int;
Temp_1 : Any;
pDataAny AT Temp_1 : "Any.T_AnyPoint";
END_VAR
BEGIN
(*#################################################################################################
Copyright (c) Fondium Singen GmbH
### Änderungshistorie ###
Datum: Version: Bearbeiter: Beschreibung:
16.03.2021 0.0 St. Maier Neuerstellung
#################################################################################################*)
(*#################################################################################################
Beschreibung:
Die Funktion erstellt aus einem Block_DB einen Any
#################################################################################################*)
#pDataAny.SyntaxId := 16#10;
#pDataAny.DataType := #I_DataType;
#pDataAny.DataCount := #I_DataCount;
#pDataAny.DB_Number := BLOCK_DB_TO_WORD(#I_BlockDb);
#pDataAny.BytePointer :=dw#16#84000000 OR SHL(IN := WORD_TO_DWORD(INT_TO_WORD(#I_Byte)), N := 3) OR WORD_TO_DWORD(INT_TO_WORD(#I_Bit));
#Temp_1 := #Temp_1;
#err := BLKMOV(SRCBLK := #Temp_1, DSTBLK => #O_Any);
END_FUNCTION

View File

@@ -1,39 +0,0 @@
FUNCTION "DbNoByName" : Int
{ S7_Optimized_Access := 'FALSE' }
VERSION : 0.1
VAR_INPUT
I_Db : Any; // DB
END_VAR
VAR_TEMP
buffer : Any; // DB address ANY pointer - used for accessing DB data
pBuffer AT buffer : Struct // Diassembled ANY pointer structure
S7Code : Byte; // Code for S7 (fixed at 16#10)
DataType : Byte; // Code for data type
Length : Int; // Repetition factor = Send/receive length
DBNumber : Int; // Data block Number
MemoryArea : Byte; // Specified memory area = 0x84 = data block
ByteAddressMSB : Byte; // Byte address most significant bits
ByteAddressLSB : Word; // Byte address least significant bits
END_STRUCT;
END_VAR
BEGIN
(*#################################################################################################
Copyright (c) Fondium Singen GmbH
### Änderungshistorie ###
Datum: Version: Bearbeiter: Beschreibung:
03.12.2020 0.0 St. Maier Neuerstellung
#################################################################################################*)
#buffer := #I_Db;
#DbNoByName := #pBuffer.DBNumber;
END_FUNCTION

View File

@@ -1,70 +0,0 @@
FUNCTION "UdtAryGet" : Void
{ S7_Optimized_Access := 'FALSE' }
VERSION : 0.1
VAR_INPUT
I_SrcAry : Any; // Quell Array
I_SrcIndex : Int; // Index der ausgelesen werden soll
I_DesUdt : Any; // Ziel UDT zur Bestimmg der Datenlänge etc
END_VAR
VAR_OUTPUT
O_Ret : Int;
END_VAR
VAR_TEMP
anySrc : Any;
p_anySrc AT anySrc : "Any.T_AnyPoint";
anyDest : Any;
p_anyDest AT anyDest : "Any.T_AnyPoint";
tmpPt : DWord;
END_VAR
BEGIN
(*#################################################################################################
Copyright (c) Fondium Singen GmbH
### Änderungshistorie ###
Datum: Version: Bearbeiter: Beschreibung:
24.10.2019 0.0 St. Maier Neuerstellung
#################################################################################################*)
(*################################### Baustein Beschreibung #######################################
Abhängigkeiten (von anderen Fuktionen und Quellen):
-
Inputs:
- I_SrcAry : Quell Array
- I_SrcIndex : Index der ausgelesen werden soll
- I_DesUdt : Ziel UDT zur Bestimmg der Datenlänge etc
Outputs:
- O_Ret
: Rückgabewert des Blockmoves
In-\Outputs:
-
Return-Value:
-
Funktionsbeschreibung:
Diese Funktion ließt Daten an einer Bestimmen Stelle aus einem Array aus.
#################################################################################################*)
#anySrc := #I_SrcAry;
#anyDest := #I_DesUdt;
#tmpPt := DINT_TO_DWORD(DWORD_TO_DINT(#p_anySrc.BytePointer AND DW#16#FFFFFF) + INT_TO_DINT(#p_anyDest.DataCount) * INT_TO_DINT(#I_SrcIndex) * 8);
#p_anySrc.BytePointer := (#p_anySrc.BytePointer AND DW#16#FF000000) OR #tmpPt;
#p_anySrc.DataCount := #p_anyDest.DataCount;
#O_Ret := BLKMOV(SRCBLK := #anySrc, DSTBLK => #anyDest); // SFC20
END_FUNCTION

View File

@@ -1,73 +0,0 @@
FUNCTION "UdtArySet" : Void
{ S7_Optimized_Access := 'FALSE' }
VERSION : 0.1
VAR_INPUT
I_SrcUdt : Any; // Quel UDT zur Bestimmg der Datenlänge etc
I_DestIndex : Int; // Index, in den geschrieben werden soll
I_DestAry : Any; // Ziel Array
END_VAR
VAR_OUTPUT
O_Ret : Int;
END_VAR
VAR_TEMP
anySrc : Any;
p_anySrc AT anySrc : "Any.T_AnyPoint";
anyDest : Any;
p_anyDest AT anyDest : "Any.T_AnyPoint";
tmpPt : DWord;
END_VAR
BEGIN
(*#################################################################################################
Copyright (c) Fondium Singen GmbH
### Änderungshistorie ###
Datum: Version: Bearbeiter: Beschreibung:
24.10.2019 0.0 St. Maier Neuerstellung
#################################################################################################*)
(*################################### Baustein Beschreibung #######################################
Abhängigkeiten (von anderen Fuktionen und Quellen):
-
Inputs:
- I_SrcUdt : Quel UDT zur Bestimmg der Datenlänge etc
- I_DestIndex : Index, in den geschrieben werden soll
- I_DestAry : Ziel Array
Outputs:
- O_Ret
: Rückgabewert des Blockmoves
In-\Outputs:
-
Return-Value:
-
Funktionsbeschreibung:
Die Funktion schreibt Daten an eine bestimmte Stelle in einem Array.
#################################################################################################*)
#anySrc := #I_SrcUdt;
#anyDest := #I_DestAry;
#tmpPt := DINT_TO_DWORD(DWORD_TO_DINT(#p_anyDest.BytePointer AND DW#16#FFFFFF) + INT_TO_DINT(#p_anySrc.DataCount) * INT_TO_DINT(#I_DestIndex) * 8);
#p_anyDest.BytePointer := (#p_anyDest.BytePointer AND DW#16#FF000000) OR #tmpPt;
#p_anyDest.DataCount := #p_anySrc.DataCount;
#O_Ret := BLKMOV(SRCBLK := #anySrc, DSTBLK => #anyDest); // SFC20
END_FUNCTION

View File

@@ -1,89 +0,0 @@
FUNCTION "UdtInAnyKop" : Void
{ S7_Optimized_Access := 'FALSE' }
VERSION : 0.1
VAR_INPUT
I_SrcUdtAry : Any;
I_DestUdtAry : Any;
I_DestIndex : Int;
END_VAR
VAR_OUTPUT
O_Ret : Int;
END_VAR
VAR_TEMP
anySrc : Any;
p_anySrc AT anySrc : "Any.T_AnyPoint";
anyDest : Any;
p_anyDest AT anyDest : "Any.T_AnyPoint";
tmpPt : DWord;
END_VAR
BEGIN
(*#################################################################################################
Copyright (c) Fondium Singen GmbH
### Änderungshistorie ###
Datum: Version: Bearbeiter: Beschreibung:
14.10.2019 0.0 St. Maier Neuerstellung
#################################################################################################*)
(*################################### Baustein Beschreibung #######################################
Abhängigkeiten (von anderen Fuktionen und Quellen):
-
Inputs:
- I_SrcUdtAry
- I_SrcIndex
- I_DestUdtAry
- I_DestIndex
Outputs:
- O_Ret
: Rückgabewert des Blockmoves
In-\Outputs:
-
Return-Value:
-
Funktionsbeschreibung:
Kopiert UDT's aus Arrays, die Datenlänge des UDT wird automatisch ermittelt.
Anpassungen der Datenlänge nach Änderungen an den UDT's entfällt somit.
Achtung Array bzw. Speichergrenzen werden nicht überprüft.
Gegebenenfalls, Indexangaben vorher auf Korrektheit prüfen bzw. limittieren!
Bei inkorrekten Indexangaben geht CPU in STOP.
Verwendung: Verwaltung von Datensätzen wie Rezepturen, Betriebsdaten,
Positionsdaten usw. in der Steuerung.
Kopiert wird von/zu: DB, statischen Lokaldaten im Instanz-DB
(Multinnstanzfähig, ohne zus. Adresskorrektur, da Step7 bei Verwendung von
Instanzdaten bei UDT's automatisch als Quelle [#84] DB und Nr. mit korrekter
Adress angibt statt nur DI [#85])
Nicht kopiert wrid von/zu lokalen Daten (TEMP), da vor- vorherige Lokaldaten
benötigt werden (S7 aber nur vorherige Lokaldaten unterstützt)
#################################################################################################*)
#anySrc := #I_SrcUdtAry;
#anyDest := #I_DestUdtAry;
#tmpPt := DINT_TO_DWORD(DWORD_TO_DINT(#p_anyDest.BytePointer AND DW#16#FFFFFF) + INT_TO_DINT(#p_anySrc.DataCount) * INT_TO_DINT(#I_DestIndex) * 8);
#p_anyDest.BytePointer := (#p_anyDest.BytePointer AND DW#16#FF000000) OR #tmpPt;
#p_anyDest.DataCount := #p_anySrc.DataCount;
#O_Ret := BLKMOV(SRCBLK := #anySrc, DSTBLK => #anyDest); // SFC20
END_FUNCTION

View File

@@ -1,101 +0,0 @@
FUNCTION "UdtInAnyUmkop" : Void
{ S7_Optimized_Access := 'FALSE' }
VERSION : 0.1
VAR_INPUT
I_SrcUdtAry : Any;
I_SrcIndex : Int;
I_DestUdtAry : Any;
I_DestIndex : Int;
END_VAR
VAR_OUTPUT
O_Ret : Int;
END_VAR
VAR_TEMP
anySrc : Any;
p_anySrc AT anySrc : "Any.T_AnyPoint";
anyDest : Any;
p_anyDest AT anyDest : "Any.T_AnyPoint";
tmpPt : DWord;
END_VAR
BEGIN
(*#################################################################################################
Copyright (c) Fondium Singen GmbH
### Änderungshistorie ###
Datum: Version: Bearbeiter: Beschreibung:
15.10.2019 0.0 St. Maier Neuerstellung
#################################################################################################*)
(*################################### Baustein Beschreibung #######################################
Abhängigkeiten (von anderen Fuktionen und Quellen):
-
Inputs:
- I_SrcUdtAry
- I_SrcIndex
- I_DestUdtAry
- I_DestIndex
Outputs:
- O_Ret
: Rückgabewert des Blockmoves
In-\Outputs:
-
Return-Value:
-
Funktionsbeschreibung:
Kopiert UDT's aus Arrays, die Datenlänge des UDT wird automatisch ermittelt.
Anpassungen der Datenlänge nach Änderungen an den UDT's entfällt somit.
Achtung Array bzw. Speichergrenzen werden nicht überprüft.
Gegebenenfalls, Indexangaben vorher auf Korrektheit prüfen bzw. limittieren!
Bei inkorrekten Indexangaben geht CPU in STOP.
Verwendung: Verwaltung von Datensätzen wie Rezepturen, Betriebsdaten,
Positionsdaten usw. in der Steuerung.
Kopiert wird von/zu: DB, statischen Lokaldaten im Instanz-DB
(Multinnstanzfähig, ohne zus. Adresskorrektur, da Step7 bei Verwendung von
Instanzdaten bei UDT's automatisch als Quelle [#84] DB und Nr. mit korrekter
Adress angibt statt nur DI [#85])
Nicht kopiert wrid von/zu lokalen Daten (TEMP), da vor- vorherige Lokaldaten
benötigt werden (S7 aber nur vorherige Lokaldaten unterstützt)
#################################################################################################*)
#anySrc := #I_SrcUdtAry;
#anyDest := #I_DestUdtAry;
#tmpPt := DINT_TO_DWORD(DWORD_TO_DINT(#p_anyDest.BytePointer AND DW#16#FFFFFF) + INT_TO_DINT(#p_anySrc.DataCount) * INT_TO_DINT(#I_SrcIndex) * 8);
#p_anySrc.BytePointer := (#p_anyDest.BytePointer AND DW#16#FF000000) OR #tmpPt;
#p_anySrc.DB_Number := #p_anyDest.DB_Number;
#tmpPt := DINT_TO_DWORD(DWORD_TO_DINT(#p_anyDest.BytePointer AND DW#16#FFFFFF) + INT_TO_DINT(#p_anySrc.DataCount) * INT_TO_DINT(#I_DestIndex) * 8);
#p_anyDest.BytePointer := (#p_anyDest.BytePointer AND DW#16#FF000000) OR #tmpPt;
#p_anyDest.DataCount := #p_anySrc.DataCount;
#O_Ret := BLKMOV(SRCBLK := #anySrc, DSTBLK => #anyDest); // SFC20
END_FUNCTION

View File

@@ -1,15 +0,0 @@
TYPE "START_UP_SI"
VERSION : 0.1
STRUCT
EV_CLASS : Byte;
EV_NUM : Byte;
PRIORITY : Byte;
NUM : Byte;
TYP2_3 : Byte;
TYP1 : Byte;
ZI1 : Word;
ZI2_3 : DWord;
END_STRUCT;
END_TYPE

View File

@@ -1,15 +0,0 @@
TYPE "TOP_SI"
VERSION : 0.1
STRUCT
EV_CLASS : Byte;
EV_NUM : Byte;
PRIORITY : Byte;
NUM : Byte;
TYP2_3 : Byte;
TYP1 : Byte;
ZI1 : Word;
ZI2_3 : DWord;
END_STRUCT;
END_TYPE

View File

@@ -1,112 +0,0 @@
FUNCTION "CalcLegHolidays" : Void
{ S7_Optimized_Access := 'FALSE' }
VERSION : 0.1
VAR_INPUT
I_Year : Int; // Jahr, für dass die Feiertage errechnet werden soll
END_VAR
VAR_OUTPUT
O_LegHolidays : "Dat.T_LegHoliday"; // Feiertage
END_VAR
VAR_TEMP
hvODay : Int; // Hilfsvariable zur Bestimmung des Ostersonntags
i : Int; // Schleifenzähler
END_VAR
VAR CONSTANT
MAX_HOLIDAYS : Int := 12; // max. Anzahl von Feiertagen, die errechnet werden sollen
END_VAR
BEGIN
(*#################################################################################################
Copyright (c) Fondium Singen GmbH
### Änderungshistorie ###
Datum: Version: Bearbeiter: Beschreibung:
12.01.2021 0.0 St. Maier Neuerstellung
Beschreibung:
Der Baustein berechnet die gesetzlichen Feiertage von BW Stand 2021.
#################################################################################################*)
FOR #i := 0 TO #MAX_HOLIDAYS - 1 DO
CASE #i OF
0: // Ostersonntag
#hvODay := (204 - 11 * (#I_Year MOD 19)) MOD 30;
IF #hvODay > 27 THEN
#hvODay := #hvODay - 1;
END_IF;
#hvODay := 28 + #hvODay - ((#I_Year + WORD_TO_INT(SHR(IN := INT_TO_WORD(#I_Year), N := 2)) + #hvODay - 13) MOD 7);
IF #hvODay > 33 THEN
#O_LegHolidays.holidays[#i]."date" := "SetDate"(I_Year := #I_Year, I_Month := 4, I_Day := #hvODay - 31);
ELSE
#O_LegHolidays.holidays[#i]."date" := "SetDate"(I_Year := #I_Year, I_Month := 3, I_Day := #hvODay);
END_IF;
#O_LegHolidays.holidays[#i]."desc" := 'Ostersonntag';
1: // Neujahr
#O_LegHolidays.holidays[#i]."date" := "SetDate"(I_Year := #I_Year, I_Month := 1, I_Day := 1);
#O_LegHolidays.holidays[#i]."desc" := 'Neujahr';
2: // Heilige Drei Könige
#O_LegHolidays.holidays[#i]."date" := "SetDate"(I_Year := #I_Year, I_Month := 1, I_Day := 6);
#O_LegHolidays.holidays[#i]."desc" :='Heilige Drei Könige';
3: // Karfreitag
#O_LegHolidays.holidays[#i]."date" := DINT_TO_DATE(DATE_TO_DINT(#O_LegHolidays.holidays[0]."date") - 2);
#O_LegHolidays.holidays[#i]."desc" := 'Karfreitag';
4: // Ostermontag
#O_LegHolidays.holidays[#i]."date" := DINT_TO_DATE(DATE_TO_DINT(#O_LegHolidays.holidays[0]."date") + 1);
#O_LegHolidays.holidays[#i]."desc" := 'Ostermontag';
5: // Tag der Arbeit
#O_LegHolidays.holidays[#i]."date" := "SetDate"(I_Year := #I_Year, I_Month := 5, I_Day := 1);
#O_LegHolidays.holidays[#i]."desc" := 'Tag der Arbeit';
6: // Pfingstsonntag
#O_LegHolidays.holidays[#i]."date" := DINT_TO_DATE(DATE_TO_DINT(#O_LegHolidays.holidays[0]."date") + 49);
#O_LegHolidays.holidays[#i]."desc" := 'Pfingstsonntag';
7: // Pfingstmontag
#O_LegHolidays.holidays[#i]."date" := DINT_TO_DATE(DATE_TO_DINT(#O_LegHolidays.holidays[0]."date") + 50);
#O_LegHolidays.holidays[#i]."desc" := 'Pfingstmontag';
8: // Tag der Deutschen Einheit
#O_LegHolidays.holidays[#i]."date" := "SetDate"(I_Year := #I_Year, I_Month := 10, I_Day := 3);
#O_LegHolidays.holidays[#i]."desc" := 'Tag der Deutschen Einheit';
9: // Allerheiligen
#O_LegHolidays.holidays[#i]."date" := "SetDate"(I_Year := #I_Year, I_Month := 11, I_Day := 1);
#O_LegHolidays.holidays[#i]."desc" := 'Allerheiligen';
10: // 1. Weihnachtsfeiertag
#O_LegHolidays.holidays[#i]."date" := "SetDate"(I_Year := #I_Year, I_Month := 21, I_Day := 25);
#O_LegHolidays.holidays[#i]."desc" := '1. Weihnachtsfeiertag';
11: // 2. Weihnachtsfeiertag
#O_LegHolidays.holidays[#i]."date" := "SetDate"(I_Year := #I_Year, I_Month := 21, I_Day := 26);
#O_LegHolidays.holidays[#i]."desc" := '2. Weihnachtsfeiertag';
ELSE
;
END_CASE;
END_FOR;
END_FUNCTION

View File

@@ -1,8 +0,0 @@
TYPE "Dat.Shift"
VERSION : 0.1
STRUCT
"Dat.ShiftDtl" : Array[0..4] of "Dat.ShiftDtl"; // Schichtdaten
END_STRUCT;
END_TYPE

View File

@@ -1,10 +0,0 @@
TYPE "Dat.ShiftDtl"
VERSION : 0.1
STRUCT
End : Date_And_Time; // Ende der Schicht
Strt : Date_And_Time; // Start der Schicht
Shift : Char; // Schicht
END_STRUCT;
END_TYPE

View File

@@ -1,11 +0,0 @@
TYPE "Dat.T_LegHoliday"
VERSION : 0.1
STRUCT
holidays : Array[0..11] of Struct // feste Feiertage
"date" : Date; // Datum des Feiertags
desc : String[35]; // Bezeichnung des Feiertags
END_STRUCT;
END_STRUCT;
END_TYPE

View File

@@ -1,81 +0,0 @@
FUNCTION "SetDate" : Date
{ S7_Optimized_Access := 'FALSE' }
VERSION : 0.1
VAR_INPUT
I_Year : Int;
I_Month : Int;
I_Day : Int;
END_VAR
VAR_TEMP
cnt : DWord;
MTH_OFS : DInt;
leap_year : Bool;
END_VAR
BEGIN
(*#################################################################################################
Copyright (c) Fondium Singen GmbH
### Änderungshistorie ###
Datum: Version: Bearbeiter: Beschreibung:
12.01.2021 0.0 St. Maier Neuerstellung
#################################################################################################*)
(* calculate the amount of days to 31.12. the year before *)
#cnt := DINT_TO_DWORD(DWORD_TO_DINT(SHR(IN := DINT_TO_DWORD(INT_TO_DINT(#I_Year) * 1461 - 2878173), N := 2)) + INT_TO_DINT(#I_Day));
(* add the days for the month of the year *)
CASE LIMIT(MN := 1, IN := #I_Month, MX := 12) OF
1:
#MTH_OFS := 0;
2:
#MTH_OFS := 31;
3:
#MTH_OFS := 59;
4:
#MTH_OFS := 90;
5:
#MTH_OFS := 120;
6:
#MTH_OFS := 151;
7:
#MTH_OFS := 181;
8:
#MTH_OFS := 212;
9:
#MTH_OFS := 243;
10:
#MTH_OFS := 273;
11:
#MTH_OFS := 304;
12:
#MTH_OFS := 334;
ELSE:
#MTH_OFS := 0;
END_CASE;
#cnt := DINT_TO_DWORD(DWORD_TO_DINT(#cnt) + #MTH_OFS);
(* for leap years and month > february then add one more day *)
IF #I_Year MOD 400 = 0 THEN
#leap_year := TRUE;
ELSIF #I_Year MOD 100 = 0 THEN
#leap_year := FALSE;
ELSIF #I_Year MOD 4 = 0 THEN
#leap_year := TRUE;
ELSE
#leap_year := FALSE;
END_IF;
IF #I_Month > 2 AND #leap_year THEN
#cnt := DINT_TO_DWORD(DWORD_TO_DINT(#cnt) + 1);
END_IF;
(* generate the date *)
#SetDate := DINT_TO_DATE(DWORD_TO_DINT(#cnt) - 7305);
END_FUNCTION

View File

@@ -1,23 +0,0 @@
TYPE "Dbg.E_Dbg"
VERSION : 0.1
STRUCT
Mod { S7_HMI_Visible := 'False'} : Struct // Modus
Strt { S7_HMI_Visible := 'False'} : Int := 1; // Start der Zeitmessung
ZwZt { S7_HMI_Visible := 'False'} : Int := 2; // Zwischenzeit erfassen
Stp { S7_HMI_Visible := 'False'} : Int := 3; // Stop der Zeitmessung
Rst { S7_HMI_Visible := 'False'} : Int := 4; // Messspeicher reseten/leeren
END_STRUCT;
St : Struct // Baustein Status
None : Word := 16#00; // kein Status
Strt : Word := 16#01; // gestartet und initialisiert
Stp : Word := 16#02; // gestoppt
END_STRUCT;
Err : Struct
NoErr : Word := 16#00; // kein Fehler
NoMessErr : Word := 16#01; // Anzahl der Messungen überschritten
FunktErr : Word := 16#FF; // Funktionsaufruf nicht vorhanden
END_STRUCT;
END_STRUCT;
END_TYPE

View File

@@ -1,9 +0,0 @@
TYPE "Dbg.T_GenCpuLst"
VERSION : 0.1
STRUCT
min : Int; // min. Cpu-Last
max : Int; // max. Cpu-Last
END_STRUCT;
END_TYPE

View File

@@ -1,8 +0,0 @@
TYPE "Dbg.T_Sreg"
VERSION : 0.1
STRUCT
Zt : Int; // gemessene Zeit [ms]
END_STRUCT;
END_TYPE

View File

@@ -1,77 +0,0 @@
FUNCTION_BLOCK "DbgGenCpuLst"
{ S7_Optimized_Access := 'FALSE' }
VERSION : 0.1
VAR_INPUT
I_MinVal : Int; // min. Zykluszeit in ms
I_MaxVal : Int; // max. Zykluszeit in ms
END_VAR
VAR
init : Bool;
oldVal : "STIME"; // alter Zeitwert
newVal : "STIME"; // aktueller Zeitwert
rdm : Int; // Zufallszahl, die auf den alten Zeitwert addiert wird
END_VAR
BEGIN
(*#################################################################################################
Copyright (c) Fondium Singen GmbH
### Änderungshistorie ###
Datum: Version: Bearbeiter: Beschreibung:
24.10.2019 0.0 St. Maier Neuerstellung
03.02.2020 0.1 St. Maier Init-Funktion eingefügt um Fehler beim Neustart zu
vermeiden.
#################################################################################################*)
(*################################### Baustein Beschreibung #######################################
Abhängigkeiten (von anderen Fuktionen und Quellen):
- IN: EingangswerZufallszahl zwischen LOW und HIGHt
Inputs:
-
Outputs:
-
In-\Outputs:
-
Return-Value:
- Nachkommateil von x
Funktionsbeschreibung:
Dieser Baustein Simuliert eine CPU-Last bzw.verlängert die Zykluszeit über einen
Zufallsgenerator. Über die Eingangsvariablen I_Min und I_Max können die Grenzen der Zyklus-
zeit bestimmt werden.
#################################################################################################*)
IF NOT #init THEN
#newVal();
#init := true;
END_IF;
#oldVal();
#rdm := "Rdm2"(
I_OldVal := #rdm
, I_MinVal := #I_MinVal
, I_MaxVal := #I_MaxVal
, "I_STIME.tx" := #oldVal.tx
);
WHILE DWORD_TO_DINT(#newVal.tx) < DWORD_TO_DINT(#oldVal.tx) + #rdm DO
#newVal();
END_WHILE;
END_FUNCTION_BLOCK

View File

@@ -1,17 +0,0 @@
TYPE "DbgTmr.T_Zt"
VERSION : 0.1
STRUCT
Zt : Int; // letzt gemessene Zeit [ms]
Min : Int := 32767; // Min. Wert [ms]
Max : Int; // Max. Wert [ms]
Av : Int; // Durchschnittswert [ms]
Sreg : Array[0..50] of "Dbg.T_Sreg"; // Schieberegister
HvAv : Struct // Hilfsvariablen zur Durchschnittsberechnung
Sum : Int; // Summe
Cnt : Int; // Zähler
CntInit : Bool;
END_STRUCT;
END_STRUCT;
END_TYPE

View File

@@ -1,275 +0,0 @@
FUNCTION_BLOCK "DbgTmr"
{ S7_Optimized_Access := 'FALSE' }
VERSION : 0.1
VAR_INPUT
I_E_Mod : Int; // Funktion die aufgerufen werden soll
I_SvDbgData : Any; // Array in den die Datengespeichert werden sollen
END_VAR
VAR_OUTPUT
O_St : Word; // Statusausgabe
O_Err : Word; // Fehlerausgabe
END_VAR
VAR
E_Dbg : "Dbg.E_Dbg"; // Enum
tmpT_Zt : "DbgTmr.T_Zt"; // temp. Struct
rstT_Zt : "DbgTmr.T_Zt"; // Zum reseten benötigt
tmpT_Sreg : "Dbg.T_Sreg"; // temp. Struct für Bestimmung Länge Schieberegister
tmpZt : DInt; // temp. Zeit
zwZtCnt : Int; // Zähler für Zwischenzeiten
zwZtLen : DInt; // Anzahl der Zwischenzeiten
avLen : DInt; // Länge desSchieberegisters für Durchschnittsberechnung
errCode : Word; // Error der aufgerufenen Funktion
retVal : Int; // Error der aufgerufenen Funktion
sTime : "STIME";
rstCnt : Int; // Zähler zum Reseten der Daten
flkStp : "Flnk"; // Flankenauswertung Stop-Status
hvStp : Bool; // HV Modus Stop
END_VAR
VAR CONSTANT
MOD_STRT : Int := 1; // Modus Start
MOD_ZW_ZT : Int := 2; // Modus Zwischenzeit
MOD_STP : Int := 3; // Modus Stop
MOD_RST : Int := 4; // Modus Reset
END_VAR
BEGIN
(*#################################################################################################
Copyright (c) Fondium Singen GmbH
### Änderungshistorie ###
Datum: Version: Bearbeiter: Beschreibung:
23.10.2019 0.0 St. Maier Neuerstellung
14.11.2019 1.0 St. Maier Erweiterung um Min.-, Max.- und Durchschnittswert-
berechnung
#################################################################################################*)
(*################################### Baustein Beschreibung #######################################
Funktionsbeschreibung:
Die Funktion errechnet die Laufzeit zwischen mehreren Aufrufen der gleichen Instanz in einem
Zyklus. Diese Funktion kann zum Bestimmen der Bearbeitungszeit einer anderen Funktion verwendet
werden.
Über den Eingang I_SvDbgData wird definiert, in welchen Speicherbereich die Daten gespeichert
werden sollen. Zur Erstellung des Speicherbereichs wird aus dem Datentyp DbgTmr.T_Zt ein Array
gebildet; dabei gibt die Array-Länge die Anzahl der Zwischenwerte vor.
Betriebsarten über den Eingang I_E_Mod anwählbar:
Start: Erstaufruf der Instanz
Zwischenzeit: Errechnung Zwischenzeiten inkl. Min.-, Max.- und Durchschnittszeiten
Stop: Stop der Funktion und Fehler zurücksetzen
Fehler-Codes:
- 0x01: Anzahl der Zwischenzeiten überschritten
- 0xFF: Funktionsaufruf nicht vorhanden
Status-Codes:
- 0x00: kein Status
- 0x01: Funktion gestartet
- 0x02: Funktion gestoppt
#################################################################################################*)
// ##############################################################################################
// ########## allgemeiner Teil
// ##############################################################################################
// Systemzeit auslesen
#sTime();
// ##############################################################################################
// ########## Modus/Funktionsaufrufe
// ##############################################################################################
CASE #I_E_Mod OF
#MOD_STRT: // Start-Funktionsaufruf
IF WORD_TO_INT(#O_St) <> WORD_TO_INT(#E_Dbg.St.Stp) THEN
GOTO Func_Strt;
END_IF;
RETURN;
#MOD_ZW_ZT: // Zwischenzeit-Funktionsaufruf
IF WORD_TO_INT(#O_St) = WORD_TO_INT(#E_Dbg.St.Strt) THEN
GOTO Func_ZwZt;
END_IF;
RETURN;
#MOD_STP: // Stop-Funktionsaufruf
IF WORD_TO_INT(#O_St) = WORD_TO_INT(#E_Dbg.St.Strt) THEN
GOTO Func_Stp;
END_IF;
RETURN;
#MOD_RST: // Reset-Funktionsaufruf
IF WORD_TO_INT(#O_St) = WORD_TO_INT(#E_Dbg.St.Stp) THEN
GOTO Func_Rst;
END_IF;
RETURN;
ELSE // Statement section ELSE
GOTO Err_FF;
RETURN;
END_CASE;
// ##############################################################################################
// ########## public Funktionen
// ##############################################################################################
// ########## Funktion Start ##########
Func_Strt:
#zwZtCnt := 0;
#tmpZt := DWORD_TO_DINT(#sTime.tx);
#O_St := #E_Dbg.St.Strt;
GOTO Func_ZwZtBer;
RETURN;
// ########## Funktion Zwischenzeit ##########
Func_ZwZt:
GOTO Func_ZwZtBer;
RETURN;
// ########## Funktion Stop ##########
Func_Stp:
#O_Err := #E_Dbg.Err.NoErr; // Fehler zurücksetzen
#O_St := #E_Dbg.St.Stp; // Status Stop setzen
GOTO Func_ZwZtBer; // Zwischenzeitberechnen
RETURN;
// ########## Funktion Reset ##########
Func_Rst:
#zwZtCnt := 0; // Zwischenzeitzähler zurücksetzen
#tmpZt := 0; // Zwischenzeit zurücksetzen
#O_St := #E_Dbg.St.None; // Status None setzen
// Anzahl der Zwischenzeiten bestimmen
#errCode := "Any.Struct"(I_UDT := #tmpT_Zt
, I_StartBitAndRange := #I_SvDbgData
, O_DataCount => #zwZtLen
);
// Den Array mit den Zwischenzeiten druchlaufen und Start-Werte setzen
FOR #rstCnt := 0 TO DINT_TO_INT(#zwZtLen) - 1 DO
// aktuelles Array-Element auf Start-Werte setzen
"UdtArySet"(I_SrcUdt := #rstT_Zt,
I_DestIndex := #rstCnt,
I_DestAry := #I_SvDbgData,
O_Ret => #retVal);
END_FOR;
RETURN;
// ##############################################################################################
// ########## private Funktionen
// ##############################################################################################
// ########## Zeitberechnung ##########
Func_ZwZtBer:
// Anzahl der Zwischenzeiten bestimmen
#errCode := "Any.Struct"(I_UDT := #tmpT_Zt
, I_StartBitAndRange := #I_SvDbgData
, O_DataCount => #zwZtLen
);
// Daten Zwischenzeit aus Array abholen und temp. zwischenspeichern zur weiteren Verarbeitung
"UdtAryGet"(I_SrcAry := #I_SvDbgData,
I_SrcIndex := #zwZtCnt,
I_DesUdt := #tmpT_Zt,
O_Ret => #retVal
);
// Zeit speichern zwischen Start bzw. der letzten Zwischenzeit bestimmen
#tmpT_Zt.Zt := DINT_TO_INT(DWORD_TO_DINT(#sTime.tx) - #tmpZt);
// Min. Zeit bestimmen
IF #tmpT_Zt.Zt < #tmpT_Zt.Min THEN
#tmpT_Zt.Min := #tmpT_Zt.Zt;
END_IF;
// Max. Zeit bestimmen
IF #tmpT_Zt.Zt > #tmpT_Zt.Max THEN
#tmpT_Zt.Max := #tmpT_Zt.Zt;
END_IF;
// Avs.Zeit Berechnen #####
// Zähler zum Durchlaufen des Schieberegisters
IF #tmpT_Zt.HvAv.Cnt >= DINT_TO_INT(#avLen) - 1 THEN
#tmpT_Zt.HvAv.Cnt := 0;
#tmpT_Zt.HvAv.CntInit := true;
ELSE
#tmpT_Zt.HvAv.Cnt := #tmpT_Zt.HvAv.Cnt + 1;
END_IF;
// Infos wie Array-Länge von Schieberegister bestimmen (Schieberegister für Durchschnittsberechnung)
#errCode := "Any.Struct"(I_UDT := #tmpT_Sreg
, I_StartBitAndRange := #tmpT_Zt.Sreg
, O_DataCount => #avLen
);
// alte Zeit von Summenzeit subtrahieren (alter Wert muss zuerst subtrahiert befor neu errechneter addiert werden kann)
#tmpT_Zt.HvAv.Sum := #tmpT_Zt.HvAv.Sum - #tmpT_Zt.Sreg[#tmpT_Zt.HvAv.Cnt].Zt;
// errechnete Zwischenzeit im Schieberegister speichern
#tmpT_Zt.Sreg[#tmpT_Zt.HvAv.Cnt].Zt := #tmpT_Zt.Zt;
// errechnete Zwischenzeit auf Summenzeit addieren
#tmpT_Zt.HvAv.Sum := #tmpT_Zt.HvAv.Sum + #tmpT_Zt.Zt;
// Durchschnitt berechnen
IF #tmpT_Zt.HvAv.CntInit THEN
#tmpT_Zt.Av := #tmpT_Zt.HvAv.Sum / (DINT_TO_INT(#avLen) - 1);
ELSE
#tmpT_Zt.Av := #tmpT_Zt.HvAv.Sum / #tmpT_Zt.HvAv.Cnt;
END_IF;
// temp. Daten der Zwischenzeit in Array kopieren
"UdtArySet"(I_SrcUdt := #tmpT_Zt,
I_DestIndex := #zwZtCnt,
I_DestAry := #I_SvDbgData,
O_Ret => #retVal);
GOTO Func_ZwZtCnt;
RETURN;
// ########## Funktion Zähler erhöhen und Grenzen überprüfen ##########
Func_ZwZtCnt:
// Zähler inkrementieren und Grenzenüberwachung
IF #zwZtCnt >= #zwZtLen THEN
GOTO ERR_01; // Fehlerausgabe wenn Anzahl Zwischenzeiten größer als Array
ELSE
#zwZtCnt := #zwZtCnt + 1; // Zähler inkrementieren
END_IF;
// Zeit auslesen
#tmpZt := DWORD_TO_DINT(#sTime.tx);
RETURN;
// ########## Fehlerausgabe ##########
ERR_01:
#O_Err := #E_Dbg.Err.NoMessErr; // Anzahl der Zwischenzeiten überschritten
RETURN;
Err_FF:
#O_Err := #E_Dbg.Err.FunktErr; // Funktionsaufruf nicht vorhanden
RETURN;
END_FUNCTION_BLOCK

View File

@@ -1,57 +0,0 @@
FUNCTION_BLOCK "PlcSimCheck"
{ S7_Optimized_Access := 'FALSE' }
VERSION : 0.1
VAR_OUTPUT
RUN_IN_PLCSIM : Bool;
END_VAR
VAR
RDSYSST : Struct
RET_WERT : Int;
REQ : Bool;
BUSY : Bool;
SZL_HEADER : Struct
LENTHDR : Word;
N_DR : Word;
END_STRUCT;
SZL_11C_5 : Struct
index : Word;
serialn : Array[0..23] of Char;
res : Array[1..4] of Word;
END_STRUCT;
END_STRUCT;
CPU_DATA : Struct
Index : Word;
CPUIdent : Array[1..34] of Byte;
Reserved : Word;
MajorVersion : Word;
MinorVersion_1 : Byte;
MinorVersion_2 : Byte;
END_STRUCT;
END_VAR
BEGIN
(*#################################################################################################
Copyright (c) Fondium Singen GmbH
### Änderungshistorie ###
Datum: Version: Bearbeiter: Beschreibung:
24.02.2020 0.0 St. Maier Neuerstellung
#################################################################################################*)
#RDSYSST.RET_WERT := RDSYSST( // SFC51 Module identification
REQ := true
, SZL_ID := W#16#11C // W#16#011C: a single identification data record
, INDEX := W#16#5 // W#16#0005: Serial number of the module
, BUSY => #RDSYSST.BUSY
, SZL_HEADER => #RDSYSST.SZL_HEADER
, DR => #CPU_DATA
);
#RUN_IN_PLCSIM:= #CPU_DATA.CPUIdent[1] = B#16#0;
END_FUNCTION_BLOCK

View File

@@ -1,65 +0,0 @@
FUNCTION "CpuZtUS" : DWord
{ S7_Optimized_Access := 'FALSE' }
AUTHOR : FSI
VERSION : 0.1
VAR_INPUT
"I_STIME.tx" : DWord; // Zeit
END_VAR
VAR CONSTANT
debug : Bool;
N : Int;
offset : Int;
offset_1 : DWord := 0;
END_VAR
BEGIN
(*#################################################################################################
Copyright (c) Fondium Singen GmbH
### Änderungshistorie ###
Datum: Version: Bearbeiter: Beschreibung:
23.09.2018 0.0 St. Maier Neuerstellung
11.10.2019 0.1 St. Maier Überarbeitung Kopf damit TIA kompatibel
17.10.2019 0.2 St. Maier I_STIME Eingefügt, damit keine Abhängigkeit zu einem
IDB besteht
18.10.2019 0.3 St. Maier Variablen Kommentare eingefügt - wurden bei der
Portierung nach TIA nicht übernommen
#################################################################################################*)
(*################################### Baustein Beschreibung #######################################
Abhängigkeiten (von anderen Fuktionen und Quellen):
- STIME, IDB_STIME
Inputs:
- I_STIME.tx
Outputs:
-
In-\Outputs:
-
Return-Value:
-
Funktionsbeschreibung:
#################################################################################################*)
#CpuZtUS := DINT_TO_DWORD(DWORD_TO_DINT(#"I_STIME.tx") * 1000);
IF #debug THEN
#CpuZtUS := DINT_TO_DWORD((DWORD_TO_DINT(SHL(IN:=#CpuZtUS,N:=#N) OR SHL(IN:=DWORD#1,N:=#N))-1) + DWORD_TO_DINT(#offset_1));
END_IF;
END_FUNCTION

View File

@@ -1,78 +0,0 @@
FUNCTION_BLOCK "FltMav"
{ S7_Optimized_Access := 'FALSE' }
VERSION : 0.1
VAR_INPUT
I_X : DInt; // Eingangswert
I_N : Int; // Anzahl der Mittelwerte
I_Rst : Bool; // asynchraner Reset Eingang
END_VAR
VAR_OUTPUT
O_Y : DInt; // gefilterter Wert
END_VAR
VAR
init : Bool;
buffer : Array[0..31] of DInt;
i : Int;
sum : DInt;
END_VAR
VAR_TEMP
tmp : Int;
tN : Int;
END_VAR
BEGIN
(*#################################################################################################
Copyright (c) Fondium Singen GmbH
### Änderungshistorie ###
Datum: Version: Bearbeiter: Beschreibung:
11.02.2021 0.0 St. Maier Neuerstellung
#################################################################################################*)
(*#################################################################################################
Beschreibung:
Die Funktion ist ein Filter mit gleitendem Mittelwert. Beim Filter mit
gleitendem Mittelwert (auch Moving Average Filter genannt) wird der Mit-
telwert von N aufeinander folgenden Messwerten als Mittelwert ausgege-
ben.
Y:= (X0 + X1 + … + Xn-1) / N
X0 ist der Wert X im momentanen Zyklus, X1 ist der Wert im Zyklus davor
usw. Die Anzahl der Werte über die der Mittelwert gebildet werden soll
wird am Eingang I_N spezifziert, der Wertebereich von I_N liegt zwischen 1
und 32.
#################################################################################################*)
(* limit N to size of buffer *)
#tN := MIN(IN1 := #I_N, IN2 := 32);
(* startup initialisation *)
IF NOT #init OR #I_Rst OR #tN = 0 THEN
#init := TRUE;
#tmp := #tN - 1;
FOR #i := 0 TO #tmp DO
#buffer[#i] := #I_X;
END_FOR;
#sum := #O_Y * #tN;
#O_Y := #I_X;
ELSE
#tmp := #tN;
#i := "Inc1"(I_X := #i,
I_N := #tmp);
#sum := #sum + #I_X - #buffer[#i];
#O_Y := #sum / #tN;
#buffer[#i] := #I_X;
END_IF;
END_FUNCTION_BLOCK

View File

@@ -1,77 +0,0 @@
FUNCTION_BLOCK "FltMav_Real"
{ S7_Optimized_Access := 'FALSE' }
VERSION : 0.1
VAR_INPUT
I_X : Real; // Eingangswert
I_N : Int; // Anzahl der Mittelwerte
I_Rst : Bool; // asynchraner Reset Eingang
END_VAR
VAR_OUTPUT
O_Y : Real; // gefilterter Wert
END_VAR
VAR
init : Bool;
buffer : Array[0..31] of Real;
i : Int;
sum : Real;
END_VAR
VAR_TEMP
tmp : Int;
tN : Int;
END_VAR
BEGIN
(*#################################################################################################
Copyright (c) Fondium Singen GmbH
### Änderungshistorie ###
Datum: Version: Bearbeiter: Beschreibung:
11.02.2021 0.0 St. Maier Neuerstellung
#################################################################################################*)
(*#################################################################################################
Beschreibung:
Die Funktion ist ein Filter mit gleitendem Mittelwert. Beim Filter mit
gleitendem Mittelwert (auch Moving Average Filter genannt) wird der Mit-
telwert von N aufeinander folgenden Messwerten als Mittelwert ausgege-
ben.
Y:= (X0 + X1 + … + Xn-1) / N
X0 ist der Wert X im momentanen Zyklus, X1 ist der Wert im Zyklus davor
usw. Die Anzahl der Werte über die der Mittelwert gebildet werden soll
wird am Eingang I_N spezifziert, der Wertebereich von I_N liegt zwischen 1
und 32.
#################################################################################################*)
(* limit N to size of buffer *)
#tN := MIN(IN1 := #I_N, IN2 := 32);
(* startup initialisation *)
IF NOT #init OR #I_Rst OR #tN = 0 THEN
#init := TRUE;
#tmp := #tN - 1;
FOR #i := 0 TO #tmp DO
#buffer[#i] := #I_X;
END_FOR;
#sum := #O_Y * #tN;
#O_Y := #I_X;
ELSE
#tmp := #tN;
#i := "Inc1"(I_X := #i,
I_N := #tmp);
#sum := #sum + #I_X - #buffer[#i];
#O_Y := #sum / #tN;
#buffer[#i] := #I_X;
END_IF;
END_FUNCTION_BLOCK

View File

@@ -1,98 +0,0 @@
FUNCTION_BLOCK "FltMedian"
{ S7_Optimized_Access := 'FALSE' }
VERSION : 0.1
VAR_INPUT
I_X : Int;
END_VAR
VAR_OUTPUT
O_Y : Int;
END_VAR
VAR
val : Array[0..10] of Int;
age : Array[0..10] of Int;
END_VAR
VAR_TEMP
bfrVal : Array[0..10] of Int;
bfrAge : Array[0..10] of Int;
bfrIdx : Int;
valIdx : Int;
tmpIdx : Int;
oldestDel : Bool;
oldestAge : Int;
oldestIdx : Int;
incomingValue : Bool;
medianIdx : Int;
END_VAR
VAR CONSTANT
FILTER_ELEMENTS : Int := 11;
END_VAR
BEGIN
(*#################################################################################################
Copyright (c) Fondium Singen GmbH
### Änderungshistorie ###
Datum: Version: Bearbeiter: Beschreibung:
11.02.2021 0.0 St. Maier Neuerstellung
#################################################################################################*)
#bfrIdx := 0; // Initialize Index
#valIdx := 0; // Initialize Index
#oldestDel := FALSE;
#oldestAge := -1;
#incomingValue := FALSE;
#medianIdx := (#FILTER_ELEMENTS / 2);
// Find oldest element (this will be removed from updated list)
FOR #tmpIdx := 0 TO #FILTER_ELEMENTS - 1 DO
IF #age[#tmpIdx] > #oldestAge THEN
#oldestAge := #age[#tmpIdx];
#oldestIdx := #tmpIdx;
END_IF;
END_FOR;
WHILE #bfrIdx < #FILTER_ELEMENTS DO
// If this is oldest element, then just skip over it so that it falls out of list.
IF #valIdx = #oldestIdx THEN
#valIdx := #valIdx + 1;
END_IF;
// If new value is smaller than current index value, then write incoming value to buffer
IF #incomingValue = FALSE AND #I_X <= #val[#valIdx] OR #valIdx > (#FILTER_ELEMENTS - 1) THEN
// Write incoming value and age to buffer
#bfrVal[#bfrIdx] := #I_X;
#bfrAge[#bfrIdx] := 0;
#bfrIdx := #bfrIdx + 1;
#incomingValue := TRUE;
END_IF;
// Write current value and incremented age to buffer
IF #bfrIdx < #FILTER_ELEMENTS THEN
#bfrVal[#bfrIdx] := #val[#valIdx];
#bfrAge[#bfrIdx] := #age[#valIdx] + 1;
#bfrIdx := #bfrIdx + 1;
#valIdx := #valIdx + 1;
END_IF;
END_WHILE;
// Write buffer to values/ages
FOR #tmpIdx := 0 TO (#FILTER_ELEMENTS - 1) DO
#val[#tmpIdx] := #bfrVal[#tmpIdx];
#age[#tmpIdx] := #bfrAge[#tmpIdx];
END_FOR;
// You've been waiting for it! Here it is...
// Return median of dataset (middle element)
#O_Y := #val[#medianIdx];
END_FUNCTION_BLOCK

View File

@@ -1,98 +0,0 @@
FUNCTION_BLOCK "FltMedian_Real"
{ S7_Optimized_Access := 'FALSE' }
VERSION : 0.1
VAR_INPUT
I_X : Real;
END_VAR
VAR_OUTPUT
O_Y : Real;
END_VAR
VAR
val : Array[0..10] of Real;
age : Array[0..10] of Int;
END_VAR
VAR_TEMP
bfrVal : Array[0..10] of Real;
bfrAge : Array[0..10] of Int;
bfrIdx : Int;
valIdx : Int;
tmpIdx : Int;
oldestDel : Bool;
oldestAge : Int;
oldestIdx : Int;
incomingValue : Bool;
medianIdx : Int;
END_VAR
VAR CONSTANT
FILTER_ELEMENTS : Int := 11;
END_VAR
BEGIN
(*#################################################################################################
Copyright (c) Fondium Singen GmbH
### Änderungshistorie ###
Datum: Version: Bearbeiter: Beschreibung:
19.02.2021 0.0 St. Maier Neuerstellung
#################################################################################################*)
#bfrIdx := 0; // Initialize Index
#valIdx := 0; // Initialize Index
#oldestDel := FALSE;
#oldestAge := -1;
#incomingValue := FALSE;
#medianIdx := (#FILTER_ELEMENTS / 2);
// Find oldest element (this will be removed from updated list)
FOR #tmpIdx := 0 TO #FILTER_ELEMENTS - 1 DO
IF #age[#tmpIdx] > #oldestAge THEN
#oldestAge := #age[#tmpIdx];
#oldestIdx := #tmpIdx;
END_IF;
END_FOR;
WHILE #bfrIdx < #FILTER_ELEMENTS DO
// If this is oldest element, then just skip over it so that it falls out of list.
IF #valIdx = #oldestIdx THEN
#valIdx := #valIdx + 1;
END_IF;
// If new value is smaller than current index value, then write incoming value to buffer
IF #incomingValue = FALSE AND #I_X <= #val[#valIdx] OR #valIdx > (#FILTER_ELEMENTS - 1) THEN
// Write incoming value and age to buffer
#bfrVal[#bfrIdx] := #I_X;
#bfrAge[#bfrIdx] := 0;
#bfrIdx := #bfrIdx + 1;
#incomingValue := TRUE;
END_IF;
// Write current value and incremented age to buffer
IF #bfrIdx < #FILTER_ELEMENTS THEN
#bfrVal[#bfrIdx] := #val[#valIdx];
#bfrAge[#bfrIdx] := #age[#valIdx] + 1;
#bfrIdx := #bfrIdx + 1;
#valIdx := #valIdx + 1;
END_IF;
END_WHILE;
// Write buffer to values/ages
FOR #tmpIdx := 0 TO (#FILTER_ELEMENTS - 1) DO
#val[#tmpIdx] := #bfrVal[#tmpIdx];
#age[#tmpIdx] := #bfrAge[#tmpIdx];
END_FOR;
// You've been waiting for it! Here it is...
// Return median of dataset (middle element)
#O_Y := #val[#medianIdx];
END_FUNCTION_BLOCK

View File

@@ -1,67 +0,0 @@
FUNCTION_BLOCK "FltPt1"
{ S7_Optimized_Access := 'FALSE' }
VERSION : 0.1
VAR_INPUT
I_Val : Real; // Eingangssignal
I_T : Time; // Zeitkonstante
I_K : Real := 1.0; // Multiplikator
"I_STIME.tx" : DWord; // Zeit
END_VAR
VAR_OUTPUT
O_Val : Real; // Aussgangssignal
END_VAR
VAR
last : DWord;
tx : DWord;
init : Bool;
END_VAR
BEGIN
(*#################################################################################################
Copyright (c) Fondium Singen GmbH
### Änderungshistorie ###
Datum: Version: Bearbeiter: Beschreibung:
03.02.2021 0.0 St. Maier Neuerstellung
#################################################################################################*)
(*#################################################################################################
Beschreibung:
Die Funktion ist ein LZI-Übertragungsglied mit einem proportionalen
Übertragungsverhalten 1. Ordnung, auch als Tiefpass Filter 1. Ordnung
bezeichnet. Der Multiplikator I_K legt den Verstärkungsfaktor (Multiplikator)
fest und I_T die Zeitkonstante.
Eine Änderung am Eingang wird am Ausgang gedämpft sichtbar. Das
Ausgangssignal steigt innerhalb von I_T auf 63% des Eingangswerts und
nach 3 * I_T auf 95% des Eingangswerts an. Somit ist nach einer
sprunghaften Änderung des Eingangssignals von 0 auf 10 der Ausgang
zum Zeitpunkt der Eingangsänderung 0, steigt nach 1 * I_T auf 6,3 an und
erreicht nach 3 * I_T 9,5 und nähert sich dann asymptotisch dem Wert 10
an. Beim ersten Aufruf wird der Ausgang O_VAL mit dem Eingangswert I_Val
initialisiert um ein defniertes Anlauf Verhalten zu gewährleisten. Falls der
Eingang I_T gleich T#0s ist entspricht der Ausgang O_VAL = I_K * I_Val.
#################################################################################################*)
#tx := "CpuZtUS"(#"I_STIME.tx");
IF NOT #init OR #I_T = t#0s THEN
#init := TRUE;
#O_Val := #I_K * #I_Val;
ELSE
#O_Val := #O_Val + (#I_Val * #I_K - #O_Val) * DINT_TO_REAL(DWORD_TO_DINT(#tx) - DWORD_TO_DINT(#last)) / DINT_TO_REAL(TIME_TO_DINT(#I_T)) * 1.0E-3;
IF ABS(#O_Val) < 1.0E-20 THEN
#O_Val := 0.0;
END_IF;
END_IF;
#last := #tx;
END_FUNCTION_BLOCK

View File

@@ -1,76 +0,0 @@
FUNCTION_BLOCK "FltPt2"
{ S7_Optimized_Access := 'FALSE' }
VERSION : 0.1
VAR_INPUT
I_Val : Real; // Eingangssignal
I_T : Time; // Zeitkonstante
I_D : Real; // Dämpfung
I_K : Real := 1.0; // Multiplikator
"I_STIME.tx" : DWord := 16#0; // Zeit
END_VAR
VAR_OUTPUT
O_Val : Real; // Ausgangssignal
END_VAR
VAR
init : Bool;
int1 : "Integrate";
int2 : "Integrate";
tn : Real;
I1 : Real;
I2 : Real;
tn2 : Real;
END_VAR
BEGIN
(*#################################################################################################
Copyright (c) Fondium Singen GmbH
### Änderungshistorie ###
Datum: Version: Bearbeiter: Beschreibung:
04.02.2021 0.0 St. Maier Neuerstellung
#################################################################################################*)
(*#################################################################################################
Beschreibung:
Die Funktion ist ein LZI-Übertragungsglied mit einem proportionalen Übertra-
gungsverhalten 2. Ordnung, auch als Tiefpass Filter 2. Ordnung bekannt.
Der Multiplikator I_K legt den Verstärkungsfaktor (Multiplikator) fest, I_T und
I_D die Zeitkonstante und die Dämpfung. Falls der Eingang I_T gleich T#0s ist
entspricht der Ausgang O_Vak = I_K * I_Val.
Die entsprechende Funktionalbeziehung in Zeitbereich ist folgende Dife-
renzialgleichung gegeben:
T² * OUT''(T) + 2 * D* T * OUT'(T) + OUT(T) = K * in(T).
#################################################################################################*)
// startup initialisation
IF NOT #init OR #I_T = T#0s THEN
#init := TRUE;
#O_Val := #I_K * #I_Val;
#I2 := #O_Val;
ELSE
#tn := DINT_TO_REAL(TIME_TO_DINT(#I_T)) * 1.0E-3;
#tn2 := #tn * #tn;
#int1(I_X := #I_Val * #I_K / #tn2 - #I1 * 0.5 * #I_D / #tn - #I2 / #tn2,
"I_STIME.tx":= #"I_STIME.tx",
O_Y => #I1
);
#int2(I_X := #I1,
"I_STIME.tx":= #"I_STIME.tx",
O_Y => #I2
);
#O_Val := #I2;
END_IF;
END_FUNCTION_BLOCK

View File

@@ -1,38 +0,0 @@
FUNCTION_BLOCK "LowPassFilter"
{ S7_Optimized_Access := 'FALSE' }
VERSION : 0.1
VAR_INPUT
I_Val : Real; // ungefilterte Eingangswert
I_Tau : Real; // Zeitinterval (in Sekunden) für Filterzyklus
END_VAR
VAR_OUTPUT
O_Val : Real; // gefilteter Ausgabewert nach Tiefpass
END_VAR
VAR
lastFltVal : Real; // letztes Filtervalue
END_VAR
VAR_TEMP
expRate : Real; // entspricht exp(-0.1 / I_Tau)
END_VAR
BEGIN
(*#################################################################################################
Copyright (c) Fondium Singen GmbH
### Änderungshistorie ###
Datum: Version: Bearbeiter: Beschreibung:
03.02.2021 0.0 St. Maier Neuerstellung
#################################################################################################*)
#expRate := EXP(-0.1 / #I_Tau);
#O_Val := #lastFltVal * #expRate + (#I_Val * (1 - #expRate)); // neuen Ausgangwert berechnen
#lastFltVal := #O_Val; // Ausgangwert für nächsten Zyklus speichern
END_FUNCTION_BLOCK

View File

@@ -1,46 +0,0 @@
FUNCTION "Pt1" : Void
{ S7_Optimized_Access := 'FALSE' }
VERSION : 0.1
VAR_INPUT
I_C : Real; // Tiefpasskonstante, z.B.: 0.01 = 99.8% Endwert nach ca. 1000 Zyklen. Max. 1.0
I_Val : Real; // ungefilterte Eingangswert
I_En : Bool; // Filterfunktion aktivieren
END_VAR
VAR_OUTPUT
O_Val : Real; // gefilteter Ausgabewert nach Tiefpass
END_VAR
VAR_TEMP
"const" : Real; // auf 1.0 begrenzte Konstante
END_VAR
BEGIN
(*#################################################################################################
Copyright (c) Fondium Singen GmbH
### Änderungshistorie ###
Datum: Version: Bearbeiter: Beschreibung:
02.02.2021 0.0 St. Maier Neuerstellung
#################################################################################################*)
#const := #I_C;
// Max. Wert Konstante = 1.0
IF #I_C > real#1.0 THEN
#const := real#1.0;
END_IF;
IF #I_En THEN // Filter eingeschalten
#O_Val := ((#I_Val - #O_Val) * #const) + #O_Val;
ELSE // Filter ausgeschalten
#O_Val := #I_Val;
END_IF;
END_FUNCTION

View File

@@ -1,78 +0,0 @@
FUNCTION_BLOCK "Flnk.NrVal"
{ S7_Optimized_Access := 'FALSE' }
AUTHOR : FSI
VERSION : 0.1
VAR_INPUT
I_Val : DInt;
END_VAR
VAR_OUTPUT
O_Flnk : Bool;
O_FlnkPos : Bool;
O_FlnkNeg : Bool;
END_VAR
VAR
flk : "Flnk";
flkPos : "Flnk";
flkNeg : "Flnk";
altVal : DInt;
END_VAR
BEGIN
(*#################################################################################################
Copyright (c) Fondium Singen GmbH
### Änderungshistorie ###
Datum: Version: Bearbeiter: Beschreibung:
10.10.2019 0.0 St. Maier Neuerstellung
11.10.2019 0.1 St. Maier Überarbeitung Kopf damit TIA kompatibel
#################################################################################################*)
(*################################### Baustein Beschreibung #######################################
Abhängigkeiten (von anderen Fuktionen und Quellen):
- keine
Inputs:
-
Outputs:
-
In-\Outputs:
-
Return-Value:
-
Funktionsbeschreibung:
Flankenauswertung eines numerischen Signals.
#################################################################################################*)
// positive Werteänderung
#flkPos(I_Val := #I_Val > #altVal // IN: BOOL
);
// negative Werteänderung
#flkNeg(I_Val := #I_Val < #altVal// IN: BOOL
);
// Ausgabe
#O_Flnk := #flkPos.O_FlnkPos OR #flkNeg.O_FlnkPos; // Impuls bei positiver und negativer Werteänderung
#O_FlnkPos := #flkPos.O_FlnkPos; // Impuls bei positiver Werteänderung
#O_FlnkNeg := #flkNeg.O_FlnkPos; // Impuls bei negativer Werteänderung
#altVal := #I_Val;
END_FUNCTION_BLOCK

View File

@@ -1,73 +0,0 @@
FUNCTION_BLOCK "Flnk"
{ S7_Optimized_Access := 'FALSE' }
AUTHOR : FSI
VERSION : 0.1
VAR_INPUT
I_Val : Bool;
END_VAR
VAR_OUTPUT
O_FlnkPos : Bool;
O_FlnkNeg : Bool;
O_FlnkPosNeg : Bool;
END_VAR
VAR
hvPos : Bool;
hvNeg : Bool;
hvPosNeg : Bool;
END_VAR
BEGIN
(*#################################################################################################
Copyright (c) Fondium Singen GmbH
### Änderungshistorie ###
Datum: Version: Bearbeiter: Beschreibung:
10.10.2019 0.0 St. Maier Neuerstellung
11.10.2019 0.1 St. Maier Überarbeitung Kopf damit TIA kompatibel
#################################################################################################*)
(*################################### Baustein Beschreibung #######################################
Abhängigkeiten (von anderen Fuktionen und Quellen):
- keine
Inputs:
-
Outputs:
-
In-\Outputs:
-
Return-Value:
-
Funktionsbeschreibung:
Flankenauswertung eines binären Signals. Es werden positive, negative und positive und negative
Flanke des Eingangssignals ausgewertet.
#################################################################################################*)
// Impuls bei Flanke 0->1
#O_FlnkPos := #I_Val AND NOT #hvPos;
#hvPos := #I_Val;
// Impuls bei Flanke 1->0
#O_FlnkNeg := NOT #I_Val AND #hvNeg;
#hvNeg := #I_Val;
// Impuls bei Flanke 0->1 & 1->0
#O_FlnkPosNeg := (#I_Val AND NOT #hvPosNeg) OR (NOT #I_Val AND #hvPosNeg);
#hvPosNeg := #I_Val;
END_FUNCTION_BLOCK

View File

@@ -1,10 +0,0 @@
TYPE "IbaSimDatFrmWrkSt.T_Cmd"
VERSION : 0.1
STRUCT
Frg : Bool; // Freigabe an PC zum Senden/Empfangen
PcSnd : Bool; // PC verbunden
NewDat : Bool; // neue Daten vorhanden
END_STRUCT;
END_TYPE

View File

@@ -1,9 +0,0 @@
TYPE "IbaSimDatFrmWrkSt.T_Data"
VERSION : 0.1
STRUCT
Cmd : "IbaSimDatFrmWrkSt.T_Cmd"; // Befehle
Data : Array[0..254] of Byte; // Daten
END_STRUCT;
END_TYPE

View File

@@ -1,67 +0,0 @@
FUNCTION_BLOCK "IbaSimDatFrmWrkSt"
{ S7_Optimized_Access := 'FALSE' }
VERSION : 0.1
VAR_INPUT
I_Data : Any; // Eingangsdaten
END_VAR
VAR_IN_OUT
IO_Cmd : "IbaSimDatFrmWrkSt.T_Cmd"; // Triggersignal
IO_Data { S7_HMI_Visible := 'False'} : Any; // Datenausgabe
END_VAR
VAR
adr : Int; // Adresszähler
END_VAR
VAR_TEMP
pTmpData : Any; // Pointer Tmp-Daten
pTmpDataAny AT pTmpData : "Any.T_AnyPoint"; // Pointer Tmp-Daten Detail
noElements : Int; // Anzahl der Elemente
flt : Int; // Fehler von Blkmov
adrOffSet : Int; // Adress-Offset
END_VAR
BEGIN
(*#################################################################################################
Copyright (c) Fondium Singen GmbH
### Änderungshistorie ###
Datum: Version: Bearbeiter: Beschreibung:
10.03.2021 0.0 St. Maier Neuerstellung
#################################################################################################*)
IF NOT #IO_Cmd.Frg OR NOT #IO_Cmd.PcSnd THEN
RETURN;
END_IF;
// Pointer initizialisieren
#pTmpData := #I_Data;
// Anzahl der Einzelelemente/Typen bestimmen
#noElements := "Any.NoOfBytes"(#I_Data) / "Any.NoOfBytes"(#IO_Data) - 1;
// // Adressgrenzen überwachen
// IF #adr >= #adrOffSet + #noElements * "Any.NoOfBytes"(#IO_Data) THEN
// #adr := #adrOffSet;
// END_IF;
// Byte-Offset berechnen
#adrOffSet := "Any.GetOffset"(#I_Data);
// Daten zum Kopieren zusammenstellen
#pTmpDataAny.BytePointer := #pTmpDataAny.BytePointer OR SHL(IN := WORD_TO_DWORD(INT_TO_WORD(#adrOffSet)), N := 3); // Byte-Adresse in Pointer laden
#pTmpDataAny.DataCount := "Any.NoOfBytes"(#IO_Data); // Länge
// Daten kopieren und am Ausgang bereitstellen
#flt := BLKMOV(SRCBLK := #pTmpData, DSTBLK => #IO_Data); // Eingangs-Daten kopieren
#IO_Cmd.NewDat := false;
END_FUNCTION_BLOCK

View File

@@ -1,21 +0,0 @@
DATA_BLOCK "IbaSimDatFrmWrkSt_"
{ S7_Optimized_Access := 'FALSE' }
VERSION : 0.1
STRUCT
GenCpuLst : "Dbg.T_GenCpuLst";
rcv : "IbaSimDatFrmWrkSt.T_Data"; // Daten von PC
abc_1 : Struct // Daten an PC
Cmd : Struct
Strt : Bool;
NewDat : Bool;
NewDatQuit : Bool;
END_STRUCT;
Data : Array[0..254] of Byte;
END_STRUCT;
END_STRUCT;
BEGIN
END_DATA_BLOCK

View File

@@ -1,10 +0,0 @@
TYPE "IbaSimDatMgt.E_IbaSimDatMgt"
VERSION : 0.1
STRUCT
Mod : Struct // Modus
EnzlStep : Int := 1; // Einzelschritt-Betrieb
END_STRUCT;
END_STRUCT;
END_TYPE

View File

@@ -1,118 +0,0 @@
FUNCTION_BLOCK "IbaSimDatMgt.Main"
{ S7_Optimized_Access := 'FALSE' }
VERSION : 0.1
VAR_INPUT
I_Trig : Bool := false; // Triggersignal
I_Data : Any; // Eingangsdaten
I_Mod : Int; // Modus
END_VAR
VAR_OUTPUT
O_Finished : Bool := false; // Durchlauf beendet
END_VAR
VAR_IN_OUT
IO_Data { S7_HMI_Visible := 'False'} : Any; // Datenausgabe
END_VAR
VAR
ibaSimDatMgt : "IbaSimDatMgt";
enzlStepFlnk : "Flnk";
END_VAR
VAR CONSTANT
MOD_ENZL_STEP : Int := 1; // Einzelschritt-Betrieb
MOD_ZYL_STEP : Int := 2; // Zyklusschritt-Betrieb
MOD_ONE_LOOP : Int := 3; // Schleifen-Betrieb
END_VAR
BEGIN
(*#################################################################################################
Copyright (c) Fondium Singen GmbH
### Änderungshistorie ###
Datum: Version: Bearbeiter: Beschreibung:
17.02.2021 0.0 St. Maier Neuerstellung
#################################################################################################*)
(*#################################################################################################
#### Modus/Funktionsaufrufe
#################################################################################################*)
CASE #I_Mod OF
#MOD_ENZL_STEP: // Einzelschritt-Betrieb
GOTO Func_EnzlStep;
#MOD_ZYL_STEP: // Zyklusschritt-Betrieb
GOTO Func_ZylStep;
#MOD_ONE_LOOP: // Schleifen-Betrieb
GOTO Func_OneLoop;
ELSE // Statement section ELSE
GOTO END;
END_CASE;
(*#################################################################################################
#### publilc Funktionen
#################################################################################################*)
// ### Funktion Einzelschritt-Betrieb
Func_EnzlStep:
// Flankenauswertung
#enzlStepFlnk(I_Val:=#I_Trig);
#ibaSimDatMgt(I_Trig:=#enzlStepFlnk.O_FlnkPos,
I_Data:=#I_Data,
O_Finished=>#O_Finished,
IO_Data:=#IO_Data
);
GOTO END;
// ### Funktion Zyklusschritt-Betrieb
Func_ZylStep:
#ibaSimDatMgt(I_Trig := #I_Trig,
I_Data := #I_Data,
IO_Data := #IO_Data
);
#O_Finished := #ibaSimDatMgt.O_AktAdr = #ibaSimDatMgt.O_MaxAdr;
GOTO END;
// ### Funktion Schleifen-Betrieb
Func_OneLoop:
#O_Finished := false;
REPEAT
#ibaSimDatMgt(I_Trig := true,
I_Data := #I_Data,
IO_Data := #IO_Data
);
UNTIL #ibaSimDatMgt.O_AktAdr <= #ibaSimDatMgt.O_MaxAdr END_REPEAT;
#O_Finished := true;
GOTO END;
// ### Funktion Ende
END:
;
END_FUNCTION_BLOCK

View File

@@ -1,86 +0,0 @@
FUNCTION_BLOCK "IbaSimDatMgt"
{ S7_Optimized_Access := 'FALSE' }
VERSION : 0.1
VAR_INPUT
I_Trig : Bool; // Triggersignal
I_Data : Any; // Eingangsdaten
END_VAR
VAR_OUTPUT
O_Finished : Bool; // Durchlauf beendet
O_AktAdr : Int; // aktuelle Adresse
O_MaxAdr : Int; // max. Adresse
END_VAR
VAR_IN_OUT
IO_Data { S7_HMI_Visible := 'False'} : Any; // Datenausgabe
END_VAR
VAR
adr : Int; // Adresszähler
END_VAR
VAR_TEMP
pTmpData : Any; // Pointer Tmp-Daten
pTmpDataAny AT pTmpData : "Any.T_AnyPoint"; // Pointer Tmp-Daten Detail
noElements : Int; // Anzahl der Elemente
flt : Int; // Fehler von Blkmov
adrOffSet : Int; // Adress-Offset
END_VAR
BEGIN
(*#################################################################################################
Copyright (c) Fondium Singen GmbH
### Änderungshistorie ###
Datum: Version: Bearbeiter: Beschreibung:
17.02.2021 0.0 St. Maier Neuerstellung
06.03.2021 1.0 St. Maier Optimierung Funktion
- Adress-Offset-Brechnung mit Funktion Any.GetOffset
- Anzahl Bytes bestimmen mit Funktion Any.NoOfBytes
- Tmp-Var opitimiert
#################################################################################################*)
#O_Finished := false;
IF NOT #I_Trig THEN
RETURN;
END_IF;
// Pointer initizialisieren
#pTmpData := #I_Data;
// Anzahl der Einzelelemente/Typen bestimmen
#noElements := "Any.NoOfBytes"(#I_Data) / "Any.NoOfBytes"(#IO_Data) - 1;
// Adressgrenzen überwachen
IF #adr >= #adrOffSet + #noElements * "Any.NoOfBytes"(#IO_Data) THEN
#adr := #adrOffSet;
END_IF;
// Byte-Offset berechnen
#adrOffSet := "Any.GetOffset"(#IO_Data);
// Daten zum Kopieren zusammenstellen
#pTmpDataAny.BytePointer := #pTmpDataAny.BytePointer OR SHL(IN := WORD_TO_DWORD(INT_TO_WORD(#adr)), N := 3); // Byte-Adresse in Pointer laden
#pTmpDataAny.DataCount := "Any.NoOfBytes"(#IO_Data); // Länge
// Daten kopieren und am Ausgang bereitstellen
#flt := BLKMOV(SRCBLK := #pTmpData, DSTBLK => #IO_Data); // Eingangs-Daten kopieren
// Adresse inkrementieren
IF #adr < #adrOffSet + (#noElements * "Any.NoOfBytes"(#IO_Data) - 1) THEN
#adr := #adr + "Any.NoOfBytes"(#IO_Data);
END_IF;
// Ausgänge schreiben
#O_Finished := true;
#O_AktAdr := #adr;
#O_MaxAdr := #adrOffSet + #noElements * "Any.NoOfBytes"(#IO_Data);
END_FUNCTION_BLOCK

View File

@@ -1,93 +0,0 @@
FUNCTION_BLOCK "ChckBwg"
{ S7_Optimized_Access := 'FALSE' }
VERSION : 0.1
VAR_INPUT
I_Frg : Bool; // Freigabe Eingang
I_X : DInt; // Messwert der zu überwachen ist
I_PosBwg : Bool := false; // positive Bewegungsrichtung
I_NegBwg : Bool := false; // negative Bewegungsrichtung
I_Rng : DInt; // zulässiger Bereich/Tolerantfeld, wenn keine Bewegung ausgeführt wird
I_MaxDeltaSprg : Int; // max. erlaubtes/r Delta/Sprung für Sprungüberwachung
I_Dly : Time := T#0ms; // Verzögerungszeit
END_VAR
VAR_OUTPUT
O_Flt : Bool; // Fehlerausgang
O_FltDtl : Word; // Fehler im Detail
END_VAR
VAR
checkBwgStop : "ChckBwgStop"; // Überwachung Stillstandsdrift
chckBwgRitg : "ChckBwgRitg"; // Überwachung Bewegungsrichtung
sprgKorMessWrt : "SprgKorMessWrt"; // Sprungüberwachung des Messwertes
END_VAR
BEGIN
(*#################################################################################################
Copyright (c) Fondium Singen GmbH
### Änderungshistorie ###
Datum: Version: Bearbeiter: Beschreibung:
03.03.2021 0.0 St. Maier Neuerstellung
#################################################################################################*)
(*#################################################################################################
Beschreibung:
Der Baustein überwacht eine Achse/Messsystem, ob dieses im Stillstand aus einem vor-
gegebenen Bereich I_Rng driftet, ob sich der Messwert zur Bewegungsrichtung ändert und ob
der Messwert Sprünge I_MaxDeltaSprg hat.
#################################################################################################*)
// Freigabe Eingang überwachen
IF NOT #I_Frg THEN
#O_Flt := false;
#O_FltDtl := w#16#00;
RETURN;
END_IF;
// Überprüfen ob Achse wegdriftet
#checkBwgStop(I_En := NOT #I_PosBwg AND NOT #I_NegBwg,
I_X := #I_X,
I_Rng := #I_Rng);
// Überprüfung der Bewegungsrichtung
#chckBwgRitg(I_X := #I_X,
I_Pos := #I_PosBwg,
I_Neg := #I_NegBwg,
I_Dly:=#I_Dly);
// Überprüfen des Messwertes auf Sprünge
#sprgKorMessWrt(I_En := #I_PosBwg OR #I_NegBwg,
I_MaxDelta := #I_MaxDeltaSprg,
I_Mode := 0,
IO_X := #I_X);
// Fehlerausgabe
#O_Flt := #checkBwgStop.O_Flt OR #chckBwgRitg.O_Flt OR #sprgKorMessWrt.O_Flt;
// Überwachung Stillstandsdrift angesprochen
IF #checkBwgStop.O_Flt THEN
#O_FltDtl := #O_FltDtl OR w#16#01;
END_IF;
// Überwachung Bewegungsrichtung angesprochen
IF #chckBwgRitg.O_Flt THEN
#O_FltDtl := #O_FltDtl OR w#16#02;
END_IF;
// Sprungüberwachung des Messwertes angesprochen
IF #sprgKorMessWrt.O_Flt THEN
#O_FltDtl := #O_FltDtl OR w#16#04;
END_IF;
END_FUNCTION_BLOCK

View File

@@ -1,142 +0,0 @@
FUNCTION_BLOCK "ChckBwgRitg"
{ S7_Optimized_Access := 'FALSE' }
VERSION : 0.1
VAR_INPUT
I_X : DInt; // Messwert der zu überwachen ist
I_Pos : Bool; // positive Bewegungsrichtung
I_Neg : Bool; // negative Bewegungsrichtung
I_Dly : Time; // Verzögerungszeit
END_VAR
VAR_OUTPUT
O_Flt : Bool := false; // Überwachung angeschlagen
END_VAR
VAR
init : Bool; // Buffer initialisiert
flnkPos : "Flnk"; // Flankenauswertung der Positionsrichtungen
flnkNeg : "Flnk"; // Flankenauswertung der Positionsrichtungen
dly {OriginalPartName := 'TON'; LibVersion := '1.0'} : TON;
delta : DInt; // Delta von x und x-1
oldVal : DInt;
buf : Array[0..#BUF_MAX] of DInt; // Buffer für Messwerte
bufX : Array[0..#BUF_MAX] of DInt; // Buffer für Messwerte
i : Int; // Zähler
ii : Int; // Zähler
cnt : Int; // Zähler für Überwachung Bewungsrichtung
END_VAR
VAR CONSTANT
BUF_MAX : Int := 10; // max. Bufferlänge
NO_MIN_BWG : Int := 3; // Anzahl Delta für Begungsrichtung i.O.
END_VAR
BEGIN
(*#################################################################################################
Copyright (c) Fondium Singen GmbH
### Änderungshistorie ###
Datum: Version: Bearbeiter: Beschreibung:
03.03.2021 0.0 St. Maier Neuerstellung
#################################################################################################*)
(*################################################################################################
Beschreibung:
Die Funktion überprüft, ob sich das Eingangssigal I_X zur Bewegungsrichtung ändert.
Bei postiver Bewegungsrichtung muss sich das Eingangssingal in positiver und bei
negativer Bewegungsrichtung in negative Richtung ändern. Ist die nicht der Fall liegt ein
Fehler vor und der Ausgang O_Flt wird auf true gesteuert.
#################################################################################################*)
// Flankenauswertung der Bewgungsrichtungen
#flnkPos(I_Val := #I_Pos);
#flnkNeg(I_Val := #I_Neg);
#dly(IN := #I_Pos OR #I_Neg,
PT := #I_Dly);
// Änderung der Bewegungsrichtung - Buffer zurücksetzen
IF #flnkPos.O_FlnkNeg OR #flnkNeg.O_FlnkNeg OR NOT #dly.Q THEN
#init := false;
#oldVal := 0;
#ii := 0;
//"BufClr"(#buf); // Buffer löschen
//"BufClr"(#bufX); // Buffer löschen
#O_Flt := false;
END_IF;
IF NOT #dly.Q THEN
RETURN;
END_IF;
// oldVal initialisieren
IF #oldVal = 0 THEN
#oldVal := #I_X;
END_IF;
// Delta zwischen alten und aktuellen Messwert bilden
#delta := #I_X - #oldVal;
// Delta in Buffer eintragen
#buf[#ii] := #delta;
#bufX[#ii] := #I_X;
// Zählervar. inkrementieren
#ii := #ii + 1;
// Zählervar. überwachen
IF #ii > #BUF_MAX THEN
#init := true;
#ii := 0;
END_IF;
// aktueller Messwert speichern
#oldVal := #I_X;
// Wenn Baustein nicht inizialisert, hier beenden
IF NOT #init THEN
RETURN;
END_IF;
// Buffer durchlaufen und Delta auswerten
#cnt := 0;
FOR #i := 0 TO #BUF_MAX DO
// Delta in Verbindung mit der Bewegungsrichtung überwachen
IF (#buf[#i] > 0 AND #I_Pos) OR (#buf[#i] < 0 AND #I_Neg) THEN
#cnt := #cnt + 1;
END_IF;// Überprüfen ob eine Bewegung angefordert ist
IF NOT #I_Pos AND NOT #I_Neg THEN
#init := false;
#oldVal := 0;
#ii := 0;
// "BufClr"(#buf); // Buffer löschen
// "BufClr"(#bufX); // Buffer löschen
#O_Flt := false;
RETURN;
END_IF;
END_FOR;
// Zählerstand Bewegungsrichtung auswerten
IF #cnt >= #NO_MIN_BWG OR (#I_Pos AND #bufX[#BUF_MAX - 1] - #bufX[0] > 0) OR (#I_Neg AND #bufX[0] - #bufX[#BUF_MAX - 1] > 0) THEN
;
#O_Flt := false;
ELSE
#O_Flt := true;
END_IF;
END_FUNCTION_BLOCK

View File

@@ -1,65 +0,0 @@
FUNCTION_BLOCK "ChckBwgStop"
{ S7_Optimized_Access := 'FALSE' }
VERSION : 0.1
VAR_INPUT
I_En : Bool; // Freigabe Eingang, Start Überwachung, Stillstand
I_X : DInt; // Messwert der zu überwachen ist
I_Rng : DInt; // zulässiger Bereich/Tolerantfeld
END_VAR
VAR_OUTPUT
O_Flt : Bool := false; // Überwachung angeschlagen
END_VAR
VAR
enFlnk : "Flnk"; // Flankenauswertung
x : DInt; // Stillstandsposition gespeichert
END_VAR
BEGIN
(*#################################################################################################
Copyright (c) Fondium Singen GmbH
### Änderungshistorie ###
Datum: Version: Bearbeiter: Beschreibung:
03.03.2021 0.0 St. Maier Neuerstellung
#################################################################################################*)
(*#################################################################################################
Beschreibung:
Die Funktions überwacht bei Stillstand einer Bewegung I_EN = true, ob das Eingangssignal I_X
aus dem vorgegebenen Range driftet. Ist dies der Fall, wird der Fehlerausgang O_Flt auf true
gesetzt.
#################################################################################################*)
// Flankenauswertung
#enFlnk(I_Val:=#I_En);
// Wenn keine Freigabe vorhanden.
IF NOT #I_En THEN
#O_Flt := FALSE;
RETURN;
END_IF;
// Stillstandposition speichern
IF #enFlnk.O_FlnkPos THEN
#x := #I_X;
END_IF;
// Bereichsüberwachung und Fehlerausgabe
IF REAL_TO_DINT(SQRT(SQR((DINT_TO_REAL(#I_X - #x))))) >= #I_Rng THEN
#O_Flt := true;
ELSE
#O_Flt := false;
END_IF;
END_FUNCTION_BLOCK

View File

@@ -1,69 +0,0 @@
FUNCTION_BLOCK "ImpToGeschDrehz"
{ S7_Optimized_Access := 'FALSE' }
VERSION : 0.1
VAR_INPUT
I_Imp : Bool; // Impulseingang (z.B. Drehzahlwächter)
I_Dmr : Int; // Durchmesser der Rolle [mm]
I_ImpProUmdr : Int; // Impulse pro Umdrehung
END_VAR
VAR_OUTPUT
O_Geschw : Real; // Errechnete Geschwindigkeit [m/sec]
O_Drehz : Real; // Errechnete Drehzahl [n/min]
END_VAR
VAR
stime : "STIME"; // Zeit
impCnt : Int; // Imulszähler
impFlnk : "Flnk";
startTime : DWord; // Startzeit bei erster positiver Flanke
END_VAR
VAR CONSTANT
PI : Real := 3.141593;
END_VAR
BEGIN
(*#################################################################################################
Copyright (c) Fondium Singen GmbH
### Änderungshistorie ###
Datum: Version: Bearbeiter: Beschreibung:
28.10.2019 0.0 St. Maier Neuerstellung
#################################################################################################*)
#stime();
// Flankenauswertung
#impFlnk(I_Val:=#I_Imp);
// positive Flanken zählen
IF #impFlnk.O_FlnkPos THEN
#impCnt := #impCnt + 1;
// Zeit bei erster positiven Flanke speichern
IF #impCnt = 1 THEN
#startTime := #stime.tx;
END_IF;
END_IF;
IF #impCnt > #I_ImpProUmdr THEN
// Drehzahl berechnen
#O_Drehz := 60000.0 / INT_TO_REAL(#impCnt - 1) / INT_TO_REAL(DWORD_TO_INT(#stime.tx) - DWORD_TO_INT(#startTime)) ;
// Geschwindigkeit berechnen
#O_Geschw := INT_TO_REAL(#I_Dmr) * #PI * #O_Drehz / 60 / 1000;
// Zähler zurücksetzen
#impCnt := 0;
END_IF;
END_FUNCTION_BLOCK

View File

@@ -1,115 +0,0 @@
FUNCTION_BLOCK "SprgKorMessWrt"
{ S7_Optimized_Access := 'FALSE' }
VERSION : 0.1
VAR_INPUT
I_En : Bool; // Freigabe Eingang
I_MaxDelta : Int; // max. erlaubtes/r Delta/Sprung
I_Mode : Int; // Modus 0 = keine Korrektur, 1 = Korrektur mit Delta x-1, 2 = Korrektur mit Trend-Delta
END_VAR
VAR_OUTPUT
O_Flt : Bool; // Überwachung angeschlagen
END_VAR
VAR_IN_OUT
IO_X : DInt; // korregierter Wert
END_VAR
VAR
init : Bool;
oldData : Struct // Altwerte von Zyklus n-1
x : DInt; // Messsignal
delta : DInt; // Sprunggröße
END_STRUCT;
trend : "TrendEx"; // Trend des Deltas
END_VAR
VAR_TEMP
korVal : DInt; // Korrekturwert
delta : DInt; // Delta von x und x-1
flt : Bool; // Fehler-Flag
END_VAR
BEGIN
(*#################################################################################################
Copyright (c) Fondium Singen GmbH
### Änderungshistorie ###
Datum: Version: Bearbeiter: Beschreibung:
28.02.2021 0.0 St. Maier Neuerstellung
#################################################################################################*)
(*#################################################################################################
Beschreibung:
Die Funktion überwacht, wenn der Eingang I_En = true ist, die Sprunghöhe/Delta des Eingangs-
signals IO_X. Ist das Delta größer/gleich dem am Eingang I_MaxDelta eingestellen Wertes wird
bei I_Mode = 0 der Eingangswert IO_X nicht korrigiert, sondern nur der Ausgang O_Flt für einen
Zyklus auf true gesetzt, bei I_Mode = 1 wird der Eingangswert IO_X mit dem Delta des Zyklus
davor korrigiert und bei I_Mode = 2 wird der Eingangswert IO_X mit dem Trend aus den letzten
x-Zyklen korrigiert.
#################################################################################################*)
IF NOT #init THEN
#init := true;
#oldData.x := #IO_X;
#oldData.delta := #delta;
END_IF;
// Freigabe überprüfen
IF NOT #I_En THEN
#init := false;
#O_Flt := false;
RETURN;
END_IF;
#delta := #IO_X - #oldData.x;
// Trend von Delta bestimmen
IF #I_Mode = 2 THEN
#trend(I_X := DINT_TO_REAL(#delta),
I_N := 5
);
END_IF;
// Sprung des Messsignals auswerten
IF ABS(#delta) >= INT_TO_DINT(#I_MaxDelta) THEN
CASE #I_Mode OF
1: // Korrektur mit Delta x-1
#IO_X := #oldData.x + #oldData.delta; // Messwert korrigieren;
2: // Korrektur mit Trend-Delta
#IO_X := #oldData.x + REAL_TO_DINT(#trend.O_Q.D); // Messwert korrigieren; ;
ELSE // Statement section ELSE
;
END_CASE;
#flt := true; // Fehler-Flag setzen
ELSE
#flt := false; // Fehler-Flag zurücksetzen
// Speichern der aktual Werte für nächsten Zyklus
#oldData.delta := #delta;
END_IF;
// Ausgänge beschreiben
#O_Flt := #flt;
// Speichern der aktual Werte für nächsten Zyklus
#oldData.x := #IO_X;
END_FUNCTION_BLOCK

View File

@@ -1,60 +0,0 @@
FUNCTION "BoolToReal" : Real
{ S7_Optimized_Access := 'FALSE' }
AUTHOR : FSI
VERSION : 0.2
VAR_INPUT
I_BoolVal : Bool;
END_VAR
BEGIN
(*#################################################################################################
Copyright (c) Fondium Singen GmbH
### Änderungshistorie ###
Datum: Version: Bearbeiter: Beschreibung:
29.07.2019 0.0 St. Maier Neuerstellung
15.08.2019 0.1 St. Maier Header angepasst und Beschreibung angepasst
11.10.2019 0.2 St. Maier Überarbeitung Kopf damit TIA kompatibel
#################################################################################################*)
(*################################### Baustein Beschreibung #######################################
Abhängigkeiten (von anderen Fuktionen und Quellen):
- keine
Inputs:
- I_BoolVal: Wert der in einen Real-Wert konvertiert werden soll
Outputs:
-
In-\Outputs:
-
Return-Value:
- in Real konvertierter Eingangswert
Funktionsbeschreibung:
Es wird das am Eingang I_BoolVal in einen Real-Wert gewandelt.
Konvertierungs-Regeln:
- true = 1.0
- false = 0.0
#################################################################################################*)
IF #I_BoolVal = true THEN
#BoolToReal := 1.0;
ELSE
#BoolToReal := 0.0;
END_IF;
END_FUNCTION

View File

@@ -1,15 +0,0 @@
TYPE "DatUztDtl.T_DatUztDtl"
VERSION : 0.1
STRUCT
Jr : Byte := 0; // Jahr
Mon : Byte := 0; // Monat
Tg : Byte := 0; // Tag
Std : Byte := 0; // Stunde
Min : Byte := 0; // Minute
Sek : Byte := 0; // Sekunde
Msek : Byte := 0; // Millisekunde
Tmp : Byte := 0; // Millisekunden und Wochentag (1-7, 1 = Sonntag)
END_STRUCT;
END_TYPE

View File

@@ -1,15 +0,0 @@
TYPE "DatUztDtl.T_DatUztMod"
VERSION : 0.1
STRUCT
Jr : Int := 0; // Jahr
Mon : Int := 0; // Monat
Tg : Int := 0; // Tag
Std : Int := 0; // Stunde
Min : Int := 0; // Minute
Sek : Int := 0; // Sekunde
Msek : Int := 0; // Millisekunde
WoTg : Int := 0; // Wochentag (1-7, 1 = Sonntag)
END_STRUCT;
END_TYPE

View File

@@ -1,64 +0,0 @@
FUNCTION "DatUztDtl" : Void
{ S7_Optimized_Access := 'FALSE' }
VERSION : 0.1
VAR_INPUT
I_DatUzt : Date_And_Time; // Datum und Uhrzeit
END_VAR
VAR_OUTPUT
O_DatUztMod : "DatUztDtl.T_DatUztMod"; // Datum und Uhrzeit modifiziert
END_VAR
VAR_TEMP
tempDatUzt : Date_And_Time; // Datum und Uhrzeit
tempDatUzDtl AT tempDatUzt : "DatUztDtl.T_DatUztDtl";
END_VAR
BEGIN
(*#################################################################################################
Copyright (c) Fondium Singen GmbH
### Änderungshistorie ###
Datum: Version: Bearbeiter: Beschreibung:
16.10.2019 0.0 St. Maier Neuerstellung
#################################################################################################*)
(*################################### Baustein Beschreibung #######################################
Abhängigkeiten (von anderen Fuktionen und Quellen):
-
Inputs:
-
Outputs:
- O_DatUzt: Uhrzeit und Datum der CPU
In-\Outputs:
-
Return-Value:
-
Funktionsbeschreibung:
Baustein konvertiert Datum und Uhrzeit und gibt dieses einzel aus.
#################################################################################################*)
#tempDatUzt := #I_DatUzt;
// Werte konvertieren
#O_DatUztMod.Jr := BCD16_TO_INT(#tempDatUzDtl.Jr) + 2000;
#O_DatUztMod.Mon := BCD16_TO_INT(#tempDatUzDtl.Mon);
#O_DatUztMod.Tg := BCD16_TO_INT(#tempDatUzDtl.Tg);
#O_DatUztMod.Std := BCD16_TO_INT(#tempDatUzDtl.Std);
#O_DatUztMod.Min := BCD16_TO_INT(#tempDatUzDtl.Min);
#O_DatUztMod.Sek := BCD16_TO_INT(#tempDatUzDtl.Sek);
#O_DatUztMod.Msek := (BCD16_TO_INT(#tempDatUzDtl.Msek) * 10) + WORD_TO_INT(#tempDatUzDtl.Tmp AND W#16#F0);
#O_DatUztMod.WoTg := WORD_TO_INT(#tempDatUzDtl.Tmp AND W#16#0F);
END_FUNCTION

View File

@@ -1,73 +0,0 @@
FUNCTION "HexToAscii" : Void
{ S7_Optimized_Access := 'FALSE' }
AUTHOR : FSI
VERSION : 0.1
VAR_INPUT
inputDWord : DWord;
END_VAR
VAR_OUTPUT
outputChar : Array[0..7] of Char;
END_VAR
VAR_TEMP
tmpBuffer : DWord;
tmpStoreAscii : Array[0..7] of Int;
tmpChkDWord : DWord;
tmpChkInt : Int;
i : Int;
END_VAR
BEGIN
(*############################################################################
### Änderungshistorie ###
Datum: Version: Bearbeiter: Beschreibung:
13.08.2019 0.0 343 Neuerstellung
11.10.2019 0.1 St. Maier Überarbeitung Kopf damit TIA kompatibel
############################################################################*)
#tmpBuffer := #inputDWord;
#i := 0;
REPEAT
// Übergabe und Umwandlung in CHAR für BYTE 0, wenn i=0
IF #i > 0 THEN // 1)
// Der Inhalt der Variablen "tmpbufffer" wird um 4 Bit nach rechts verschoben. ==> nächstes BYTE, wenn i>0.
#tmpBuffer := SHR(IN := #tmpBuffer, N := 4);
END_IF;
#tmpChkDWord := #tmpBuffer AND 16#0000000f;
#tmpChkInt := DWORD_TO_INT(#tmpChkDWord);
// Überprüfe, ob der konvertierte Wert größer ist als 9.
IF #tmpChkInt > 9 THEN
// Der konvertierte Wert ist > 9, somit liegt der Wert der Variablen vom Datentyp CHAR zwischen 'A' und 'F'. Addiere dazu den Offset "W#16#37".
#tmpChkInt := #tmpChkInt + 16#0037;
ELSE
// Der konvertierte Wert ist <) 9, somit liegt der Wert der Variablen vom Datentyp CHAR zwischen '1' und '9'. Addiere dazu den Offset "W#16#30".
#tmpChkInt := #tmpChkInt + 16#0030;
END_IF;
#tmpStoreAscii[#i] := #tmpChkInt;
#outputChar[#i] := INT_TO_CHAR(#tmpStoreAscii[#i]);
#i := #i + 1;
UNTIL #i = 8
END_REPEAT;
END_FUNCTION

View File

@@ -1,12 +0,0 @@
TYPE "TimeDtl"
VERSION : 0.1
STRUCT
Tg : DInt;
Std : DInt;
Min : DInt;
Sec : DInt;
Msec : DInt;
END_STRUCT;
END_TYPE

View File

@@ -1,69 +0,0 @@
FUNCTION "TimeToMinSecMses" : Void
{ S7_Optimized_Access := 'FALSE' }
VERSION : 0.1
VAR_INPUT
I_Zt : Time;
END_VAR
VAR_OUTPUT
O_ZtDtl : "TimeDtl";
END_VAR
VAR_TEMP
tmpZt : DInt;
END_VAR
VAR CONSTANT
MSEC_TO_MIN : DInt := 60000;
MSEC_TO_SEC : DInt := 1000;
END_VAR
BEGIN
(*#################################################################################################
Copyright (c) Fondium Singen GmbH
### Änderungshistorie ###
Datum: Version: Bearbeiter: Beschreibung:
15.10.2019 0.0 St. Maier Neuerstellung
#################################################################################################*)
(*################################### Baustein Beschreibung #######################################
Abhängigkeiten (von anderen Fuktionen und Quellen):
- keine
Inputs:
- I_Zt : Zeit die umgerechnet werden soll
Outputs:
- O_ZtDtl : Zeit aufgeschlüsselt
In-\Outputs:
-
Return-Value:
-
Funktionsbeschreibung:
Umrechnung der Eingangszeit in Minuten, Sekunden und Millisekunden.
#################################################################################################*)
// Zeit in dint konvertieren
#tmpZt := TIME_TO_DINT(#I_Zt);
// Umrechnung in Minuten
#O_ZtDtl.Min := #tmpZt / #MSEC_TO_MIN;
// Umrechnung in Sekunden
#O_ZtDtl.Sec := (#tmpZt MOD #MSEC_TO_MIN) / #MSEC_TO_SEC;
// Bestimmung der Millisekunden
#O_ZtDtl.Msec := (#tmpZt MOD #MSEC_TO_MIN) MOD #MSEC_TO_SEC;
END_FUNCTION

View File

@@ -1,73 +0,0 @@
FUNCTION "TimeToMinSecMsesDtl" : Void
{ S7_Optimized_Access := 'FALSE' }
VERSION : 0.1
VAR_INPUT
I_Zt : Time;
END_VAR
VAR_OUTPUT
O_Min : DInt;
O_Sec : DInt;
O_Msec : DInt;
END_VAR
VAR_TEMP
tmpZt : DInt;
END_VAR
VAR CONSTANT
MSEC_TO_MIN : DInt := 60000;
MSEC_TO_SEC : DInt := 1000;
END_VAR
BEGIN
(*#################################################################################################
Copyright (c) Fondium Singen GmbH
### Änderungshistorie ###
Datum: Version: Bearbeiter: Beschreibung:
15.10.2019 0.0 St. Maier Neuerstellung
#################################################################################################*)
(*################################### Baustein Beschreibung #######################################
Abhängigkeiten (von anderen Fuktionen und Quellen):
- keine
Inputs:
- I_Zt : Zeit die umgerechnet werden soll
Outputs:
- O_Min : Anteil der Minuten der Eingangszeit
- O_Sec : Anteil der Sekunden der Eingangszeit
- O_Msec : Anteil der Millisekunden der Eingangszeit
In-\Outputs:
-
Return-Value:
-
Funktionsbeschreibung:
Umrechnung der Eingangszeit in Minuten, Sekunden und Millisekunden.
#################################################################################################*)
// Zeit in dint konvertieren
#tmpZt := TIME_TO_DINT(#I_Zt);
// Umrechnung in Minuten
#O_Min := #tmpZt / #MSEC_TO_MIN;
// Umrechnung in Sekunden
#O_Sec := (#tmpZt MOD #MSEC_TO_MIN) / #MSEC_TO_SEC;
// Bestimmung der Millisekunden
#O_Msec := (#tmpZt MOD #MSEC_TO_MIN) MOD #MSEC_TO_SEC;
END_FUNCTION

View File

@@ -1,65 +0,0 @@
FUNCTION "TimeToSecMses" : Void
{ S7_Optimized_Access := 'FALSE' }
VERSION : 0.1
VAR_INPUT
I_Zt : Time;
END_VAR
VAR_OUTPUT
O_ZtDtl : "TimeDtl";
END_VAR
VAR_TEMP
tmpZt : DInt;
END_VAR
VAR CONSTANT
MSEC_TO_SEC : DInt := 1000;
END_VAR
BEGIN
(*#################################################################################################
Copyright (c) Fondium Singen GmbH
### Änderungshistorie ###
Datum: Version: Bearbeiter: Beschreibung:
15.10.2019 0.0 St. Maier Neuerstellung
#################################################################################################*)
(*################################### Baustein Beschreibung #######################################
Abhängigkeiten (von anderen Fuktionen und Quellen):
- keine
Inputs:
- I_Zt : Zeit die umgerechnet werden soll
Outputs:
- O_ZtDtl : Zeit aufgeschlüsselt
In-\Outputs:
-
Return-Value:
-
Funktionsbeschreibung:
Umrechnung der Eingangszeit in Sekunden und Millisekunden.
#################################################################################################*)
// Zeit in dint konvertieren
#tmpZt := TIME_TO_DINT(#I_Zt);
// Umrechnung in Sekunden
#O_ZtDtl.Sec := #tmpZt / #MSEC_TO_SEC;
// Bestimmung der Millisekunden
#O_ZtDtl.Msec := #tmpZt MOD #MSEC_TO_SEC;
END_FUNCTION

View File

@@ -1,67 +0,0 @@
FUNCTION "TimeToSecMsesDtl" : Void
{ S7_Optimized_Access := 'FALSE' }
VERSION : 0.1
VAR_INPUT
I_Zt : Time;
END_VAR
VAR_OUTPUT
O_Sec : DInt;
O_Msec : DInt;
END_VAR
VAR_TEMP
tmpZt : DInt;
END_VAR
VAR CONSTANT
MSEC_TO_SEC : DInt := 1000;
END_VAR
BEGIN
(*#################################################################################################
Copyright (c) Fondium Singen GmbH
### Änderungshistorie ###
Datum: Version: Bearbeiter: Beschreibung:
15.10.2019 0.0 St. Maier Neuerstellung
#################################################################################################*)
(*################################### Baustein Beschreibung #######################################
Abhängigkeiten (von anderen Fuktionen und Quellen):
- keine
Inputs:
- I_Zt : Zeit die umgerechnet werden soll
Outputs:
- O_Sec : Anteil der Sekunden der Eingangszeit
- O_Msec : Anteil der Millisekunden der Eingangszeit
In-\Outputs:
-
Return-Value:
-
Funktionsbeschreibung:
Umrechnung der Eingangszeit in Sekunden und Millisekunden.
#################################################################################################*)
// Zeit in dint konvertieren
#tmpZt := TIME_TO_DINT(#I_Zt);
// Umrechnung in Sekunden
#O_Sec := #tmpZt / #MSEC_TO_SEC;
// Bestimmung der Millisekunden
#O_Msec := #tmpZt MOD #MSEC_TO_SEC;
END_FUNCTION

View File

@@ -1,73 +0,0 @@
FUNCTION "TimeToStdMinSecMsec" : Void
{ S7_Optimized_Access := 'FALSE' }
VERSION : 0.1
VAR_INPUT
I_Zt : Time;
END_VAR
VAR_OUTPUT
O_ZtDtl : "TimeDtl";
END_VAR
VAR_TEMP
tmpZt : DInt;
END_VAR
VAR CONSTANT
MSEC_TO_STD : DInt := 3600000;
MSEC_TO_MIN : DInt := 60000;
MSEC_TO_SEC : DInt := 1000;
END_VAR
BEGIN
(*#################################################################################################
Copyright (c) Fondium Singen GmbH
### Änderungshistorie ###
Datum: Version: Bearbeiter: Beschreibung:
15.10.2019 0.0 St. Maier Neuerstellung
#################################################################################################*)
(*################################### Baustein Beschreibung #######################################
Abhängigkeiten (von anderen Fuktionen und Quellen):
- keine
Inputs:
- I_Zt : Zeit die umgerechnet werden soll
Outputs:
- O_ZtDtl : Zeit aufgeschlüsselt
In-\Outputs:
-
Return-Value:
-
Funktionsbeschreibung:
Umrechnung der Eingangszeit in Stunden, Minuten, Sekunden und Millisekunden.
#################################################################################################*)
// Zeit in dint konvertieren
#tmpZt := TIME_TO_DINT(#I_Zt);
// Umrechnung in Stunden
#O_ZtDtl.Std := #tmpZt / #MSEC_TO_STD;
// Umrechnung in Minuten
#O_ZtDtl.Min := (#tmpZt MOD #MSEC_TO_STD) / #MSEC_TO_MIN;
// Umrechnung in Sekunden
#O_ZtDtl.Sec := ((#tmpZt MOD #MSEC_TO_STD) MOD #MSEC_TO_MIN) / #MSEC_TO_SEC;
// Bestimmung der Millisekunden
#O_ZtDtl.Msec := ((#tmpZt MOD #MSEC_TO_STD) MOD #MSEC_TO_MIN) MOD #MSEC_TO_SEC;
END_FUNCTION

View File

@@ -1,79 +0,0 @@
FUNCTION "TimeToStdMinSecMsecDtl" : Void
{ S7_Optimized_Access := 'FALSE' }
VERSION : 0.1
VAR_INPUT
I_Zt : Time;
END_VAR
VAR_OUTPUT
O_Std : DInt;
O_Min : DInt;
O_Sec : DInt;
O_Msec : DInt;
END_VAR
VAR_TEMP
tmpZt : DInt;
END_VAR
VAR CONSTANT
MSEC_TO_STD : DInt := 3600000;
MSEC_TO_MIN : DInt := 60000;
MSEC_TO_SEC : DInt := 1000;
END_VAR
BEGIN
(*#################################################################################################
Copyright (c) Fondium Singen GmbH
### Änderungshistorie ###
Datum: Version: Bearbeiter: Beschreibung:
15.10.2019 0.0 St. Maier Neuerstellung
#################################################################################################*)
(*################################### Baustein Beschreibung #######################################
Abhängigkeiten (von anderen Fuktionen und Quellen):
- keine
Inputs:
- I_Zt : Zeit die umgerechnet werden soll
Outputs:
- O_Std : Anteil der Stunden der Eingangszeit
- O_Min : Anteil der Minuten der Eingangszeit
- O_Sec : Anteil der Sekunden der Eingangszeit
- O_Msec : Anteil der Millisekunden der Eingangszeit
In-\Outputs:
-
Return-Value:
-
Funktionsbeschreibung:
Umrechnung der Eingangszeit in Stunden, Minuten, Sekunden und Millisekunden.
#################################################################################################*)
// Zeit in dint konvertieren
#tmpZt := TIME_TO_DINT(#I_Zt);
// Umrechnung in Stunden
#O_Std := #tmpZt / #MSEC_TO_STD;
// Umrechnung in Minuten
#O_Min := (#tmpZt MOD #MSEC_TO_STD) / #MSEC_TO_MIN;
// Umrechnung in Sekunden
#O_Sec := ((#tmpZt MOD #MSEC_TO_STD) MOD #MSEC_TO_MIN) / #MSEC_TO_SEC;
// Bestimmung der Millisekunden
#O_Msec := ((#tmpZt MOD #MSEC_TO_STD) MOD #MSEC_TO_MIN) MOD #MSEC_TO_SEC;
END_FUNCTION

View File

@@ -1,77 +0,0 @@
FUNCTION "TimeToTgStdMinSecMsec" : Void
{ S7_Optimized_Access := 'FALSE' }
VERSION : 0.1
VAR_INPUT
I_Zt : Time;
END_VAR
VAR_OUTPUT
O_ZtDtl : "TimeDtl";
END_VAR
VAR_TEMP
tmpZt : DInt;
END_VAR
VAR CONSTANT
MSEC_TO_TG : DInt := 86400000;
MSEC_TO_STD : DInt := 3600000;
MSEC_TO_MIN : DInt := 60000;
MSEC_TO_SEC : DInt := 1000;
END_VAR
BEGIN
(*#################################################################################################
Copyright (c) Fondium Singen GmbH
### Änderungshistorie ###
Datum: Version: Bearbeiter: Beschreibung:
15.10.2019 0.0 St. Maier Neuerstellung
#################################################################################################*)
(*################################### Baustein Beschreibung #######################################
Abhängigkeiten (von anderen Fuktionen und Quellen):
- keine
Inputs:
- I_Zt : Zeit die umgerechnet werden soll
Outputs:
- O_ZtDtl : Zeit aufgeschlüsselt
In-\Outputs:
-
Return-Value:
-
Funktionsbeschreibung:
Umrechnung der Eingangszeit in Tage, Stunden, Minuten, Sekunden und Millisekunden.
#################################################################################################*)
// Zeit in dint konvertieren
#tmpZt := TIME_TO_DINT(#I_Zt);
// Umrechung in Tage
#O_ZtDtl.Std := #tmpZt / #MSEC_TO_TG;
// Umrechnung in Stunden
#O_ZtDtl.Std := (#tmpZt MOD #MSEC_TO_TG) / #MSEC_TO_STD;
// Umrechnung in Minuten
#O_ZtDtl.Min := ((#tmpZt MOD #MSEC_TO_TG) MOD #MSEC_TO_STD) / #MSEC_TO_MIN;
// Umrechnung in Sekunden
#O_ZtDtl.Sec := (((#tmpZt MOD #MSEC_TO_TG) MOD #MSEC_TO_STD) MOD #MSEC_TO_MIN) / #MSEC_TO_SEC;
// Bestimmung der Millisekunden
#O_ZtDtl.Msec := (((#tmpZt MOD #MSEC_TO_TG) MOD #MSEC_TO_STD) MOD #MSEC_TO_MIN) MOD #MSEC_TO_SEC;
END_FUNCTION

View File

@@ -1,84 +0,0 @@
FUNCTION "TimeToTgStdMinSecMsecDtl" : Void
{ S7_Optimized_Access := 'FALSE' }
VERSION : 0.1
VAR_INPUT
I_Zt : Time;
END_VAR
VAR_OUTPUT
O_Tg : DInt;
O_Std : DInt;
O_Min : DInt;
O_Sec : DInt;
O_Msec : DInt;
END_VAR
VAR_TEMP
tmpZt : DInt;
END_VAR
VAR CONSTANT
MSEC_TO_TG : DInt := 86400000;
MSEC_TO_STD : DInt := 3600000;
MSEC_TO_MIN : DInt := 60000;
MSEC_TO_SEC : DInt := 1000;
END_VAR
BEGIN
(*#################################################################################################
Copyright (c) Fondium Singen GmbH
### Änderungshistorie ###
Datum: Version: Bearbeiter: Beschreibung:
15.10.2019 0.0 St. Maier Neuerstellung
#################################################################################################*)
(*################################### Baustein Beschreibung #######################################
Abhängigkeiten (von anderen Fuktionen und Quellen):
- keine
Inputs:
- I_Zt : Zeit die umgerechnet werden soll
Outputs:
- O_Tg : Anteil der Tage der Eingangszeit
- O_Std : Anteil der Stunden der Eingangszeit
- O_Min : Anteil der Minuten der Eingangszeit
- O_Sec : Anteil der Sekunden der Eingangszeit
- O_Msec : Anteil der Millisekunden der Eingangszeit
In-\Outputs:
-
Return-Value:
-
Funktionsbeschreibung:
Umrechnung der Eingangszeit in Tage, Stunden, Minuten, Sekunden und Millisekunden.
#################################################################################################*)
// Zeit in dint konvertieren
#tmpZt := TIME_TO_DINT(#I_Zt);
// Umrechung in Tage
#O_Tg := #tmpZt / #MSEC_TO_TG;
// Umrechnung in Stunden
#O_Std := (#tmpZt MOD #MSEC_TO_TG) / #MSEC_TO_STD;
// Umrechnung in Minuten
#O_Min := ((#tmpZt MOD #MSEC_TO_TG) MOD #MSEC_TO_STD) / #MSEC_TO_MIN;
// Umrechnung in Sekunden
#O_Sec := (((#tmpZt MOD #MSEC_TO_TG) MOD #MSEC_TO_STD) MOD #MSEC_TO_MIN) / #MSEC_TO_SEC;
// Bestimmung der Millisekunden
#O_Msec := (((#tmpZt MOD #MSEC_TO_TG) MOD #MSEC_TO_STD) MOD #MSEC_TO_MIN) MOD #MSEC_TO_SEC;
END_FUNCTION

View File

@@ -1,32 +0,0 @@
FUNCTION "ByteOfDWord" : Byte
{ S7_Optimized_Access := 'FALSE' }
VERSION : 0.1
VAR_INPUT
I_In : DWord; // Eingangs-DWORD
I_N : Int; // Byte-Nr
END_VAR
BEGIN
(*#################################################################################################
Copyright (c) Fondium Singen GmbH
### Änderungshistorie ###
Datum: Version: Bearbeiter: Beschreibung:
04.03.2021 0.0 St. Maier Neuerstellung
#################################################################################################*)
(*#################################################################################################
Beschreibung:
Der Funktion zerlegt ein Byte(I_In) in seine einzelnen Bits (O_B0 .. O_B7)
#################################################################################################*)
#ByteOfDWord := DWORD_TO_BYTE(SHR(IN := #I_In, N := WORD_TO_INT(SHL(IN := INT_TO_WORD(#I_N), N := 3))));
END_FUNCTION

View File

@@ -1,56 +0,0 @@
FUNCTION "ByteToBits" : Void
{ S7_Optimized_Access := 'FALSE' }
VERSION : 0.1
VAR_INPUT
I_In : Byte; // Eingangsbyte
END_VAR
VAR_OUTPUT
O_B0 : Bool; // Bit 0
O_B1 : Bool; // Bit 1
O_B2 : Bool; // Bit 2
O_B3 : Bool; // Bit 3
O_B4 : Bool; // Bit 4
O_B5 : Bool; // Bit 5
O_B6 : Bool; // Bit 6
O_B7 : Bool; // Bit 7
END_VAR
VAR_TEMP
x : Byte;
tx AT x : Array[0..7] of Bool;
END_VAR
BEGIN
(*#################################################################################################
Copyright (c) Fondium Singen GmbH
### Änderungshistorie ###
Datum: Version: Bearbeiter: Beschreibung:
04.03.2021 0.0 St. Maier Neuerstellung
#################################################################################################*)
(*#################################################################################################
Beschreibung:
Der Funktion zerlegt ein Byte(I_In) in seine einzelnen Bits (O_B0 .. O_B7)
#################################################################################################*)
#x := #I_In;
#O_B0 := #tx[0];
#O_B1 := #tx[1];
#O_B2 := #tx[2];
#O_B3 := #tx[3];
#O_B4 := #tx[4];
#O_B5 := #tx[5];
#O_B6 := #tx[6];
#O_B7 := #tx[7];
END_FUNCTION

View File

@@ -1,200 +0,0 @@
FUNCTION_BLOCK "CrcGen"
TITLE = 'CRC_GEN'
{ S7_Optimized_Access := 'FALSE' }
AUTHOR : hugo
FAMILY : LOGIC
NAME : CRCGEN
VERSION : 2.0
//
//CRC_GEN generates a CRC checksum from a block of data and returns the checksum in a DWORD to be connected to the data for transmission.
//the CRC Polynom is specified with the config variable PN and the length of the Polynom is specified by PL
//A Polynom x4 + X + 1 is represented by 0011 with length 4, the highest order bit is not specified at all..
//The input data is an array of byte of any size, the function is called by CRC_GEN(ADR(array),SIZEOF(array), ....).
//
//uses: REVERSE (FC310)
// REFLECT (FC426)
VAR_INPUT
PT : Pointer;
_PT { S7_HMI_Accessible := 'False'; S7_HMI_Visible := 'False'} AT PT : Struct
DBNr { S7_HMI_Accessible := 'False'; S7_HMI_Visible := 'False'} : Word;
Adr { S7_HMI_Accessible := 'False'; S7_HMI_Visible := 'False'} : DWord;
END_STRUCT;
SIZE : Int;
PL : Int;
PN : DWord;
INIT : DWord;
REV_IN : Bool;
REV_OUT : Bool;
XOR_OUT : DWord;
END_VAR
VAR_OUTPUT
CRC_GEN : DWord;
_CRC_GEN { S7_HMI_Accessible := 'False'; S7_HMI_Visible := 'False'} AT CRC_GEN : Array[0..31] of Bool;
END_VAR
VAR_TEMP
pos : Int;
shift : Int;
dx : Byte;
_dx AT dx : Array[0..7] of Bool;
bits : Int;
rTEST_DB : Int;
Adr : Int;
DB_LENGTH : Word;
WRITE_PROT : Bool;
END_VAR
BEGIN
(*#################################################################################################
Copyright (c) Fondium Singen GmbH
### Änderungshistorie ###
Datum: Version: Bearbeiter: Beschreibung:
04.03.2021 0.0 St. Maier Neuerstellung
#################################################################################################*)
(*#################################################################################################
Beschreibung:
Die Funktion generiert eine CRC-Checksumme aus einen beliebig großen Array of Byte. Beim Aufruf
wird der Funktion ein Pointer auf das zu bearbeitende Array und dessen Größe in Bytes übergeben.
Das Polynom kann ein beliebiges POLYNOM bis maximal 32 Bit Länge sein. Ein Polynom X³ + X² + 1
wird mit 101 dargestellt (1*X³ + 1*X² + 0*X¹ + 1* X⁰). Das höchstwertige Bit, in diesem Fall
1*X³ wird dabei im Polynom nicht angegeben den es ist immer eins. Es können Polynome bis X³²
(CRC 32) verarbeitet werden. Durch den Wert INIT kann dem CR eine Startwert übergeben werden,
üblich sind hier 0000 und FFFF. Der zu verwendende Startwert ist der in der Literatur übliche
„Direct Initial Value“. Der Eingan XOR_OUT legt fest mit welcher Bitfolge die Checksumme am Ende
mit XOR verknüpft wird. Die Eingänge REV_IN und REV_OUT legen die Bitfolge der Daten Fest.
Wenn REV_IN = TRUE wird jedes Byte mit LSB beginnend verarbeitet, REV_IN = FALSE wird jeweils
mit MSB begonnen. REV_OUT=TRUE dreht entsprechend die Bitfolge der Checksumme um. Der Bautein
benötigt eine Mindestlänge der zu verarbeitenden Daten von 4 Bytes, und ist nach oben nur durch
die maximale Array Größe begrenzt.
Die weiter unten folgende CRC Tabelle gibt nähere Auskunft über gebräuchliche CRC's und deren
Setup Daten für CrcGen. Aufgrund der Vielzahl von möglichen und auch gebräuchlichen CRC's ist
es uns nicht möglich eine vollständige Liste aufzuführen. Für weitergehende Recherchen ist die
Webseite http://regregex.bbcmicro.net/crc-catalogue.htm zu empfehlen.
Online Berechnungen zum testen sind mit folgendem Java Tool möglich:
http://zorc.breitbandkatze.de/crc.html
#################################################################################################*)
(* Datenbaustein Testen *)
#rTEST_DB := TEST_DB(DB_NUMBER := #_PT.DBNr
, DB_LENGTH => #DB_LENGTH
, WRITE_PROT => #WRITE_PROT
);
// Ende wenn Test-DB <> 0 = Fehler
IF #rTEST_DB <> 0 THEN
RETURN;
END_IF;
// Ende wenn DB zu klein
IF WORD_TO_INT(#DB_LENGTH) / 1 < #SIZE THEN
RETURN;
END_IF;
#Adr := DWORD_TO_INT(SHR(IN := SHL(IN := #_PT.Adr, N := 8), N := 11));
// align polygon
#shift := 32 - #PL;
#PN := SHL(IN := #PN, N := #shift);
(* load first 4 bytes into register minimum message size is 4 bytes
for smaller messages fill with 0#s at the beginning*)
FOR #pos := 0 TO 3 DO
IF #REV_IN THEN
#CRC_GEN := SHL(IN := #CRC_GEN, N := 8) OR "Reverse"(WORD_TO_BLOCK_DB(#_PT.DBNr).DB(#Adr + #pos));
ELSE
#CRC_GEN := SHL(IN := #CRC_GEN, N := 8) OR WORD_TO_BLOCK_DB(#_PT.DBNr).DB(#Adr + #pos);
END_IF;
END_FOR;
#pos := 4;
// XOR with #INIT value
#CRC_GEN := #CRC_GEN XOR SHL(IN := #INIT, N := #shift);
// calculate CRC FOR each byte
WHILE #pos < #SIZE DO
IF #REV_IN THEN
#dx := "Reverse"(WORD_TO_BLOCK_DB(#_PT.DBNr).DB(#Adr + #pos));
ELSE
#dx := WORD_TO_BLOCK_DB(#_PT.DBNr).DB(#Adr + #pos);
END_IF;
#pos := #pos + 1;
// crc calculation FOR one byte
FOR #bits := 0 TO 7 DO
IF #_CRC_GEN[7] THEN
#CRC_GEN := (SHL(IN := #CRC_GEN, N := 1) OR BOOL_TO_DWORD(#_dx[7])) XOR #PN;
ELSE
#CRC_GEN := SHL(IN := #CRC_GEN, N := 1) OR BOOL_TO_DWORD(#_dx[7]);
END_IF;
#dx := SHL(IN := #dx, N := 1);
END_FOR;
END_WHILE;
// all bytes are processed, need TO finish the registers 32 bits
FOR #bits := 0 TO 31 DO
IF #_CRC_GEN[7] THEN
#CRC_GEN := (SHL(IN := #CRC_GEN, N := 1) OR BOOL_TO_DWORD(#_dx[7])) XOR #PN;
ELSE
#CRC_GEN := SHL(IN := #CRC_GEN, N := 1) OR BOOL_TO_DWORD(#_dx[7]);
END_IF;
END_FOR;
// final XOR
#CRC_GEN := SHR(IN := #CRC_GEN, N := #shift) XOR #XOR_OUT;
// "Reverse" the crc_out put IF necessary
IF #REV_OUT THEN
#CRC_GEN := "Reflect"(I_D := #CRC_GEN,
I_L := #PL);
END_IF;
(* typical crc polynoms
CRC-4-ITU x4 + x + 1 (ITU G.704, p. 12) 0x3 or 0xC (0x9)
CRC-5-ITU x5 + x4 + x2 + 1 (ITU G.704, p. 9) 0x15 or 0x15 (0x0B) Bluetooth
CRC-5-USB x5 + x2 + 1 (use: USB token packets) 0x05 or 0x14 (0x9)
CRC-6-ITU x6 + x + 1 (ITU G.704, p. 3) 0x03 or 0x30 (0x21)
CRC-7 x7 + x3 + 1 (use: telecom systems, MMC) 0x09 or 0x48 (0x11)
CRC-8-ATM x8 + x2 + x + 1 (use: ATM HEC) 0x07 or 0xE0 (0xC1)
CRC-8-CCITT x8 + x7 + x3 + x2 + 1 (use: 1-Wire bus) 0x8D or 0xB1 (0x63)
CRC-8-Dallas/Maxim x8 + x5 + x4 + 1 (use: 1-Wire bus) 0x31 or 0x8C (0x19)
CRC-8 x8 + x7 + x6 + x4 + x2 + 1 0xD5 or 0xAB (0x57)
CRC-8-SAE J1850 x8 + x4 + x3 + x2 + 1 0x1D or 0xB8
CRC-10 x10 + x9 + x5 + x4 + x + 1 0x233 or 0x331 (0x263)
CRC-12 x12 + x11 + x3 + x2 + x + 1 (use: telecom systems) 0x80F or 0xF01 (0xE03)
CRC-15-CAN x15 + x14 + x10 + x8 + x7 + x4 + x3 + 1 0x4599 or 0x4CD1 (0x19A3)
CRC-16-Fletcher Not a CRC; see Fletcher's checksum Used in Adler-32 A & B CRCs
CRC-16-CCITT x16 + x12 + x5 + 1 (XMODEM,X.25, V.41, Bluetooth, PPP, IrDA; known as "CRC-CCITT") 0x1021 or 0x8408 (0x0811)
CRC-16-IBM x16 + x15 + x2 + 1 (USB, many others; also known as "CRC-16") 0x8005 or 0xA001 (0x4003)
CRC-24-Radix-64 x24 + x23 + x18 + x17 + x14 + x11 + x10 + x7 + x6 + x5 + x4 + x3 + x + 1 0x864CFB or 0xDF3261 (0xBE64C3)
CRC-32-Adler Not a CRC; see Adler-32 See Adler-32
CRC-32-MPEG2 x32 + x26 + x23 + x22 + x16 + x12 + x11 + x10 + x8 + x7 + x5 + x4 + x2 + x + 1 0x04C11DB7 or 0xEDB88320 (0xDB710641) Also used in IEEE 802.3
CRC-32-IEEE 802.3 x32 + x26 + x23 + x22 + x16 + x12 + x11 + x10 + x8 + x7 + x5 + x4 + x2 + x + 1 (V.42) 0x04C11DB7 or 0xEDB88320 (0xDB710641)
CRC-32C (Castagnoli) x32 + x28 + x27 + x26 + x25 + x23 + x22 + x20 + x19 + x18 + x14 + x13 + x11 + x10 + x9 + x8 + x6 + 1 0x1EDC6F41 or 0x82F63B78 (0x05EC76F1)
CRC-64-ISO x64 + x4 + x3 + x + 1 (use: ISO 3309) 0x000000000000001B or 0xD800000000000000 (0xB000000000000001)
CRC-64-ECMA-182 x64 + x62 + x57 + x55 + x54 + x53 + x52 + x47 + x46 + x45 + x40 + x39 + x38 + x37 + x35 + x33 + x32 + x31 + x29 + x27 + x24 + x23 + x22 + x21 + x19 + x17 + x13 + x12 + x10 + x9 + x7 + x4 + x + 1
(as described in ECMA-182 p.63) 0x42F0E1EBA9EA3693 or 0xC96C5795D7870F42 (0x92D8AF2BAF0E1E85)
*)
END_FUNCTION_BLOCK

View File

@@ -1,57 +0,0 @@
FUNCTION "Reflect" : DWord
{ S7_Optimized_Access := 'FALSE' }
VERSION : 0.1
VAR_INPUT
I_D : DWord; // Eingangswert
I_L : Int; // Anzahl der zu drehenden Bits
END_VAR
VAR_TEMP
tD : DWord;
i : Int;
END_VAR
BEGIN
(*#################################################################################################
Copyright (c) Fondium Singen GmbH
### Änderungshistorie ###
Datum: Version: Bearbeiter: Beschreibung:
04.03.2021 0.0 St. Maier Neuerstellung
#################################################################################################*)
(*#################################################################################################
Beschreibung:
Die Funktion dreht die Reihenfolge der durch die Anzahl I_L spezifzierten Bits-
Bits in einem DWORD um. Die höherwertigen Bits als die durch die Länge
I_L spezifzierten bleiben unverändert.
Beispiel:
REVERSE(10101010 00000000 11111111 10011110, 8)
ergibt 10101010 00000000 11111111 01111001
Beispiel:
REVERSE(10101010 00000000 11111111 10011110, 32)
ergibt 01111001 11111111 00000000 01010101
#################################################################################################*)
#tD := #I_D;
#Reflect := 0;
FOR #i := 1 TO #I_L DO
#Reflect := SHL(IN := #Reflect, N := 1) OR (#tD AND DW#16#0000_0001); //BOOL_TO_DWORD(D.0);
#tD := SHR(IN := #tD, N := 1);
END_FOR;
#Reflect := #Reflect OR SHL(IN := #tD, N := #I_L);
END_FUNCTION

View File

@@ -1,31 +0,0 @@
FUNCTION "Reverse" : Byte
{ S7_Optimized_Access := 'FALSE' }
VERSION : 0.1
VAR_INPUT
I_In : Byte; // Eingangswert
END_VAR
BEGIN
(*#################################################################################################
Copyright (c) Fondium Singen GmbH
### Änderungshistorie ###
Datum: Version: Bearbeiter: Beschreibung:
04.03.2021 0.0 St. Maier Neuerstellung
#################################################################################################*)
(*#################################################################################################
Beschreibung:
Die Funktion dreht die Reihenfolge in einem Byte um. Bit 7 von I_In wir zu Bit 0, Bit 6 wird
zu Bit 1 usw.
#################################################################################################*)
#Reverse := SHL(IN := #I_In, N := 7) OR SHR(IN := #I_In, N := 7) OR (ROR(IN := #I_In, N := 3) AND 2#01000100) OR (ROL(IN := #I_In, N := 3) AND 2#00100010)OR (SHL(IN := #I_In, N := 1) AND 2#00010000) OR (SHR(IN := #I_In, N := 1) AND 2#00001000);
END_FUNCTION

View File

@@ -1,117 +0,0 @@
FUNCTION_BLOCK "Schichtpl.Mgt"
{ S7_Optimized_Access := 'FALSE' }
VERSION : 0.1
VAR_INPUT
I_GplSchichten : Any; // geplante Schichten
END_VAR
VAR_OUTPUT
O_SchichtStrt : Time; // Produktion startet in x
O_SchichtEnd : Time; // Produktion Ende seit x
O_Prdkt : Bool; // Produktion
END_VAR
VAR
tmpPrdktEnd { S7_HMI_Visible := 'False'} : Date_And_Time;
flnkPrdktEnd { S7_HMI_Visible := 'False'} : "Flnk";
END_VAR
VAR_TEMP
actSysZt : Date_And_Time; // aktuelle Systemzeit
err : Int; // Fehler von Systemzeit auslesen
adrOffset : Int; // Adress-Offset
adrLng : Int; // Adress-Länge
noElements : Int; // Anzahl der Elemente
i : Int; // Schleifenzähler
pTmpData : Any; // Pointer Tmp-Daten
pTmpDataAny AT pTmpData : "Any.T_AnyPoint"; // Pointer Tmp-Daten Detail
tmpSchicht : Array[0..1] of "Schichtpl.T_Schicht"; // Tmp Schichten
strtGef : Bool; // Start gefunden
endGef : Bool; // Ende gefunden
END_VAR
BEGIN
(*#################################################################################################
Copyright (c) Fondium Singen GmbH
### Änderungshistorie ###
Datum: Version: Bearbeiter: Beschreibung:
07.03.2021 0.0 St. Maier Neuerstellung
#################################################################################################*)
(*#################################################################################################
Beschreibung:
???
#################################################################################################*)
// aktuelle Systemzeit auslesen
#err := RD_SYS_T(#actSysZt);
// Produktionsende
#flnkPrdktEnd(I_Val := #O_Prdkt); // Flankenauswertung
IF #flnkPrdktEnd.O_FlnkNeg THEN
#tmpPrdktEnd := #actSysZt; // Zeitstempel Produktionsende speichern
END_IF;
// Any-Pointer initialisieren
#pTmpData := #I_GplSchichten;
// Offseet bestimmen
#adrOffset := "Any.GetOffset"(#I_GplSchichten);
// Länge berechnen des gesamten Datenbereichs
#adrLng := "Any.NoOfBytes"(#I_GplSchichten);
// Anzahl der Einzelelemente/Typen bestimmen
#noElements := "Any.NoOfBytes"(#I_GplSchichten) / "Any.NoOfBytes"(#tmpSchicht);
// Länge des Typs eintragen
#pTmpDataAny.DataCount := #adrLng / #noElements * 2;
#strtGef := false;
#endGef := false;
FOR #i := 0 TO #noElements - 2 DO
// Daten zum Kopieren zusammenstellen
#pTmpDataAny.BytePointer := dw#16#84000000 OR SHL(IN := WORD_TO_DWORD(INT_TO_WORD(#adrOffset + #adrLng / #noElements * #i)), N := 3); // Byte-Adresse in Pointer laden
#err := BLKMOV(SRCBLK := #pTmpData, DSTBLK => #tmpSchicht);
IF #tmpSchicht[0].Strt > DT#1990-1-1-00:00:00 AND #tmpSchicht[0].End > DT#1990-1-1-00:00:00 THEN
// Schicht Start finden
IF (#tmpSchicht[0].Strt > #actSysZt OR (#tmpSchicht[1].Strt > #actSysZt AND #tmpSchicht[0].Strt < #actSysZt)) AND NOT #strtGef THEN
#O_SchichtStrt := #tmpSchicht[0].Strt - #actSysZt; // Zeit bis Schichtstart
#strtGef := true;
END_IF;
// Schicht Ende finden
IF #tmpSchicht[0].End <> #tmpSchicht[1].Strt AND #strtGef AND NOT #endGef AND #O_Prdkt THEN
#O_SchichtEnd := #tmpSchicht[0].End - #actSysZt;
#endGef := true;
ELSIF NOT #O_Prdkt THEN
#O_SchichtEnd := #tmpPrdktEnd - #actSysZt;
END_IF;
END_IF;
END_FOR;
#O_Prdkt := #O_SchichtStrt < t#0ms;
END_FUNCTION_BLOCK

View File

@@ -1,10 +0,0 @@
TYPE "Schichtpl.T_Schicht"
VERSION : 0.1
STRUCT
Schicht : Char; // Schicht F = Frühschicht, S= Spätschicht, N = Nachtschicht
Strt : Date_And_Time; // Schichtbeginn
End : Date_And_Time; // Schichtende
END_STRUCT;
END_TYPE

View File

@@ -1,8 +0,0 @@
TYPE "Schichtpl.T_Schichten"
VERSION : 0.1
STRUCT
Schichten : Array[0..9] of "Schichtpl.T_Schicht"; // geplante Schichten
END_STRUCT;
END_TYPE

View File

@@ -1,114 +0,0 @@
FUNCTION_BLOCK "SigGen"
{ S7_Optimized_Access := 'FALSE' }
VERSION : 0.1
VAR_INPUT
I_Rst : Bool; // Reset der Ausgangssignale
I_Amp : Real; // Amplitude des Signals
I_Offs : Real; // Signal Offset
I_ZylZtSig : DInt; // Periode des Signals in ms
I_ZylZtOb : Int; // Zykluszeit des OBs in ms
END_VAR
VAR_OUTPUT
O_Rec : Real; // Rechteck-Signal
O_Sz : Real; // Sägezahn-Signal
O_Dr : Real; // Dreieck-Signal
O_Sin : Real; // Sinus-Signal
O_Cnt : DInt; // Zähler-Signal
END_VAR
VAR
nloop : DInt; // Schleifenzähler
loop_max : DInt; // Anzahl der Schritte in einem Durchlauf -> Sinus
loop_half : DInt; // hal of the number for the signal in one piriod -> Rectangle, Sawtooth
nsaw : DInt; // Schrittzähler für Sägezahn-Signal
ntri : DInt; // Schrittzähler für Dreieck-Signal
ntri_max : DInt; // max. Schritte für Dreieck-Signal
tri_dir : Bool; // toggel bit für positives/negatives Zählen Dreieck-Signal
nsin : DInt; // Schrittzähler für Sinus-Signal
END_VAR
BEGIN
(*#################################################################################################
Copyright (c) Fondium Singen GmbH
### Änderungshistorie ###
Datum: Version: Bearbeiter: Beschreibung:
24.02.2021 0.0 St. Maier Neuerstellung
#################################################################################################*)
// Program
#loop_max := ROUND(DINT_TO_REAL(#I_ZylZtSig) / INT_TO_REAL(#I_ZylZtOb)); //number of steps needed for the complete periodic time -> Sinus
#loop_half := ROUND(DINT_TO_REAL(#I_ZylZtSig) / (real#2.0 * INT_TO_REAL(#I_ZylZtOb))); // number of steps needed for the half periodic time -> Rectangle, Sawtooth
#ntri_max := ROUND(DINT_TO_REAL(#loop_half) / real#2.0); // setting maximum for the Triangle signal to the half, counter is going to the negativ maximum as well
// Reset of all output values if RESET is TRUE
IF #I_Rst = TRUE THEN
#O_Rec := 0.0;
#O_Dr := 0.0;
#O_Sz := 0.0;
#O_Sin := 0.0;
#O_Cnt := 0;
#nloop := 0;
#nsaw := 0;
#ntri := 0;
#tri_dir := FALSE;
#nsin := 0;
ELSE
//
// Building the output values
//
#O_Cnt := #nloop; // set output to the actual number of the loop counter
// Loop counter to build the positive and negative oscilation
IF #nloop < #loop_half THEN
#O_Rec := #I_Offs + #I_Amp; // Rectangle-Signal is set to high
ELSE
#O_Rec := #I_Offs - #I_Amp; // Rectangle-Signal is set to low
END_IF;
#nloop := #nloop + 1; // increment each time if the FB is startet
IF #nloop = #loop_max THEN // set loop counter to zero at the end of the piriod
#nloop := 0;
END_IF;
// Building the Sawtooth Signal
#O_Sz := #I_Offs + #I_Amp * DINT_TO_REAL(#nsaw) / DINT_TO_REAL(#loop_half);
#nsaw := #nsaw + 1; // increment counter used for the Sawtooth signal
IF #nsaw = #loop_half THEN
#nsaw := 0;
END_IF;
// Building the Triangle Signal
#O_Dr := #I_Amp * DINT_TO_REAL(#ntri) / DINT_TO_REAL(#ntri_max);
IF #tri_dir = FALSE THEN // check dircetion for the counter
#ntri := #ntri + 1; // build poistive ramp
ELSE
#ntri := #ntri - 1; // build negative ramp
END_IF;
IF #ntri >= #ntri_max THEN // toggle the direction to build the triangle signal to negativ ramp
#tri_dir := TRUE;
END_IF;
IF #ntri <= (-1 * #ntri_max) THEN // toggle the direction to build the triangle signal to positive ramp
#tri_dir := FALSE;
END_IF;
// Building the Sinus Signal (counting up until 2*PI)
#O_Sin := #I_Offs + #I_Amp * SIN(real#6.283185 * DINT_TO_REAL(#nsin) / DINT_TO_REAL(#loop_max));
#nsin := #nsin + 1; // increment counter for the
IF #nsin = #loop_max THEN // set counter to 0 if full periodic is reached
#nsin := 0;
END_IF;
END_IF;
END_FUNCTION_BLOCK

View File

@@ -1,11 +0,0 @@
TYPE "Trend.T_Trend"
VERSION : 0.1
STRUCT
Q : Bool; // I_X steigend = TRUE
TU : Bool; // TRUE wenn sich Eingang I_X erhöht
TD : Bool; // TRUE wenn sich Eingang I_X reduziert
D : Real; // Deltas der Eingangsänderung
END_STRUCT;
END_TYPE

View File

@@ -1,11 +0,0 @@
TYPE "Trend.T_Trend_DINT"
VERSION : 0.1
STRUCT
Q : Bool; // I_X steigend = TRUE
TU : Bool; // TRUE wenn sich Eingang I_X erhöht
TD : Bool; // TRUE wenn sich Eingang I_X reduziert
D : DInt; // Deltas der Eingangsänderung
END_STRUCT;
END_TYPE

View File

@@ -1,50 +0,0 @@
FUNCTION_BLOCK "Trend"
{ S7_Optimized_Access := 'FALSE' }
VERSION : 0.1
VAR_INPUT
I_X : Real; // Eingangssignal
END_VAR
VAR_OUTPUT
O_Data : "Trend.T_Trend";
END_VAR
VAR
lastX : Real;
END_VAR
BEGIN
(*#################################################################################################
Copyright (c) Fondium Singen GmbH
### Änderungshistorie ###
Datum: Version: Bearbeiter: Beschreibung:
16.02.2021 0.0 St. Maier Neuerstellung
#################################################################################################*)
(*#################################################################################################
Beschreibung:
Die Funktion überwacht den Eingang I_X und zeigt am Ausgang O_Data.Q an ob I_X steigt (O_Data.Q
= TRUE) oder I_X fällt (O_Data.Q = FALSE). wenn sich I_X nicht verändert bleibt O_Data.Q auf
seinen letzten Wert stehen. Erhöht sich I_X so wird der Ausgang O_Data.TU für
einen Zyklus TRUE und am Ausgang D wird I_X lastX angezeigt. Ist I_X
niedriger als lastX so wird O_Data.TD für einen Zyklus TRUE und am Ausgang O_Data.D
wird lastX I_X ausgegeben. lastX ist ein interner Wert des Bausteins
und ist der Wert von I_X im letzten Zyklus.
#################################################################################################*)
#O_Data.TU := #I_X > #lastX;
#O_Data.TD := #I_X < #lastX;
#O_Data.Q := #O_Data.TU OR #O_Data.TD;
#O_Data.D := #I_X - #lastX;
#lastX := #I_X;
END_FUNCTION_BLOCK

View File

@@ -1,62 +0,0 @@
FUNCTION_BLOCK "TrendEx"
{ S7_Optimized_Access := 'FALSE' }
VERSION : 0.1
VAR_INPUT
I_X : Real; // Eingangssignal
I_N : Int; // Anzahl der Mittelwerte
END_VAR
VAR_OUTPUT
O_Q : "Trend.T_Trend"; // I_X steigend = TRUE
END_VAR
VAR
fltMav : "FltMav_Real"; // Moving Average Filter
tmpX : Real;
lastX : Real;
END_VAR
BEGIN
(*#################################################################################################
Copyright (c) Fondium Singen GmbH
### Änderungshistorie ###
Datum: Version: Bearbeiter: Beschreibung:
16.02.2021 0.0 St. Maier Neuerstellung
#################################################################################################*)
(*#################################################################################################
Beschreibung:
Die Funktion überwacht den Eingang I_X und zeigt am Ausgang O_Data.Q an ob I_X steigt (O_Data.Q
= TRUE) oder I_X fällt (O_Data.Q = FALSE). wenn sich I_X nicht verändert bleibt O_Data.Q auf
seinen letzten Wert stehen. Erhöht sich I_X so wird der Ausgang O_Data.TU für
einen Zyklus TRUE und am Ausgang D wird I_X lastX angezeigt. Ist I_X
niedriger als lastX so wird O_Data.TD für einen Zyklus TRUE und am Ausgang O_Data.D
wird lastX I_X ausgegeben. lastX ist ein interner Wert des Bausteins
und ist der Wert von I_X im letzten Zyklus.
#################################################################################################*)
// Mittelwertbildung
#fltMav(I_X:=#I_X,
I_N:=#I_N,
O_Y=>#tmpX);
// Auswertung
#O_Q.TU := #tmpX > #lastX;
#O_Q.TD := #tmpX < #lastX;
#O_Q.Q := #O_Q.TU OR #O_Q.TD;
#O_Q.D := #tmpX - #lastX;
#lastX := #tmpX;
END_FUNCTION_BLOCK

View File

@@ -1,62 +0,0 @@
FUNCTION_BLOCK "TrendEx_DINT"
{ S7_Optimized_Access := 'FALSE' }
VERSION : 0.1
VAR_INPUT
I_X : DInt; // Eingangssignal
I_N : Int; // Anzahl der Mittelwerte
END_VAR
VAR_OUTPUT
O_Q : "Trend.T_Trend_DINT"; // I_X steigend = TRUE
END_VAR
VAR
fltMav : "FltMav"; // Moving Average Filter
tmpX : DInt;
lastX : DInt;
END_VAR
BEGIN
(*#################################################################################################
Copyright (c) Fondium Singen GmbH
### Änderungshistorie ###
Datum: Version: Bearbeiter: Beschreibung:
16.02.2021 0.0 St. Maier Neuerstellung
#################################################################################################*)
(*#################################################################################################
Beschreibung:
Die Funktion überwacht den Eingang I_X und zeigt am Ausgang O_Data.Q an ob I_X steigt (O_Data.Q
= TRUE) oder I_X fällt (O_Data.Q = FALSE). wenn sich I_X nicht verändert bleibt O_Data.Q auf
seinen letzten Wert stehen. Erhöht sich I_X so wird der Ausgang O_Data.TU für
einen Zyklus TRUE und am Ausgang D wird I_X lastX angezeigt. Ist I_X
niedriger als lastX so wird O_Data.TD für einen Zyklus TRUE und am Ausgang O_Data.D
wird lastX I_X ausgegeben. lastX ist ein interner Wert des Bausteins
und ist der Wert von I_X im letzten Zyklus.
#################################################################################################*)
// Mittelwertbildung
#fltMav(I_X:=#I_X,
I_N:=#I_N,
O_Y=>#tmpX);
// Auswertung
#O_Q.TU := #tmpX > #lastX;
#O_Q.TD := #tmpX < #lastX;
#O_Q.Q := #O_Q.TU OR #O_Q.TD;
#O_Q.D := #tmpX - #lastX;
#lastX := #tmpX;
END_FUNCTION_BLOCK

View File

@@ -1,50 +0,0 @@
FUNCTION_BLOCK "Trend_DINT"
{ S7_Optimized_Access := 'FALSE' }
VERSION : 0.1
VAR_INPUT
I_X : DInt; // Eingangssignal
END_VAR
VAR_OUTPUT
O_Data : "Trend.T_Trend_DINT";
END_VAR
VAR
lastX : DInt;
END_VAR
BEGIN
(*#################################################################################################
Copyright (c) Fondium Singen GmbH
### Änderungshistorie ###
Datum: Version: Bearbeiter: Beschreibung:
16.02.2021 0.0 St. Maier Neuerstellung
#################################################################################################*)
(*#################################################################################################
Beschreibung:
Die Funktion überwacht den Eingang I_X und zeigt am Ausgang O_Data.Q an ob I_X steigt (O_Data.Q
= TRUE) oder I_X fällt (O_Data.Q = FALSE). wenn sich I_X nicht verändert bleibt O_Data.Q auf
seinen letzten Wert stehen. Erhöht sich I_X so wird der Ausgang O_Data.TU für
einen Zyklus TRUE und am Ausgang D wird I_X lastX angezeigt. Ist I_X
niedriger als lastX so wird O_Data.TD für einen Zyklus TRUE und am Ausgang O_Data.D
wird lastX I_X ausgegeben. lastX ist ein interner Wert des Bausteins
und ist der Wert von I_X im letzten Zyklus.
#################################################################################################*)
#O_Data.TU := #I_X > #lastX;
#O_Data.TD := #I_X < #lastX;
#O_Data.Q := #O_Data.TU OR #O_Data.TD;
#O_Data.D := #I_X - #lastX;
#lastX := #I_X;
END_FUNCTION_BLOCK

View File

@@ -1,56 +0,0 @@
FUNCTION "BlkMovExt" : Int
TITLE = 'Memory Compare'
{ S7_Optimized_Access := 'FALSE' }
AUTHOR : Smiffy
VERSION : 0.1
VAR_INPUT
I_DbName : Any;
I_DbNo : Int;
END_VAR
VAR_TEMP
pIN1 : Any; // DB address ANY pointer - used for accessing DB data
pAnyIN1 AT pIN1 : Struct // Diassembled ANY pointer structure
S7Code : Byte; // Code for S7 (fixed at 16#10)
DataType : Byte; // Code for data type
Length : Int; // Repetition factor = Send/receive length
DBNumber : Int; // Data block Number
MemoryArea : Byte; // Specified memory area = 0x84 = data block
ByteAddressMSB : Byte; // Byte address most significant bits
ByteAddressLSB : Word; // Byte address least significant bits
END_STRUCT;
pIN2 : Any; // DB address ANY pointer - used for accessing DB data
pAnyIN2 AT pIN2 : Struct // Diassembled ANY pointer structure
S7Code : Byte; // Code for S7 (fixed at 16#10)
DataType : Byte; // Code for data type
Length : Int; // Repetition factor = Send/receive length
DBNumber : Int; // Data block Number
MemoryArea : Byte; // Specified memory area = 0x84 = data block
ByteAddressMSB : Byte; // Byte address most significant bits
ByteAddressLSB : Word; // Byte address least significant bits
END_STRUCT;
END_VAR
BEGIN
(*#################################################################################################
Copyright (c) Fondium Singen GmbH
### Änderungshistorie ###
Datum: Version: Bearbeiter: Beschreibung:
08.12.2020 0.0 St. Maier Neuerstellung
#################################################################################################*)
#pIN1 := #I_DbName;
#pIN2 := #pIN1;
#pAnyIN2.DBNumber := #I_DbNo;
#BlkMovExt := BLKMOV(SRCBLK:=#pIN1, DSTBLK=>#pIN2);
END_FUNCTION

View File

@@ -1,118 +0,0 @@
FUNCTION "MemCmp" : Bool
TITLE = 'Memory Compare'
{ S7_Optimized_Access := 'FALSE' }
AUTHOR : Smiffy
VERSION : 0.1
VAR_INPUT
I_In1 : Any; // Quelle 1
I_In2 : Any; // Quelle 2
END_VAR
VAR_TEMP
retVal : Int;
in1End : DInt; // End addresses for memory areas
in2End : DInt; // End addresses for memory areas
tst1 : Byte;
tst2 : Byte;
memPtr : DInt; // Current memory pointer
pIN1 : Any; // DB address ANY pointer - used for accessing DB data
pAnyIN1 AT pIN1 : Struct // Diassembled ANY pointer structure
S7Code : Byte; // Code for S7 (fixed at 16#10)
DataType : Byte; // Code for data type
Length : Int; // Repetition factor = Send/receive length
DBNumber : Int; // Data block Number
MemoryArea : Byte; // Specified memory area = 0x84 = data block
ByteAddressMSB : Byte; // Byte address most significant bits
ByteAddressLSB : Word; // Byte address least significant bits
END_STRUCT;
u1Addr : DInt; // Union pointer for calculation of byte offset address
u1 AT u1Addr : Struct // This is equivalent to a union in 'c' dword goes in and word / byte LSB / byte MSB come out
ByteAddrLSBPad : Byte; // Not Used
ByteAddrMSB : Byte; // Byte address most significant bits
WordAddr : Word; // Byte address least significant bits
END_STRUCT;
pIN2 : Any; // DB address ANY pointer - used for accessing DB data
pAnyIN2 AT pIN2 : Struct // Diassembled ANY pointer structure
S7Code : Byte; // Code for S7 (fixed at 16#10)
DataType : Byte; // Code for data type
Length : Int; // Repetition factor = Send/receive length
DBNumber : Int; // Data block Number
MemoryArea : Byte; // Specified memory area = 0x84 = data block
ByteAddressMSB : Byte; // Byte address most significant bits
ByteAddressLSB : Word; // Byte address least significant bits
END_STRUCT;
u2Addr : DInt; // Union pointer for calculation of byte offset address
u2 AT u2Addr : Struct // This is equivalent to a union in 'c' dword goes in and word / byte LSB / byte MSB come out
ByteAddrLSBPad : Byte; // Not Used
ByteAddrMSB : Byte; // Byte address most significant bits
WordAddr : Word; // Byte address least significant bits
END_STRUCT;
END_VAR
BEGIN
(*#################################################################################################
Copyright (c) Fondium Singen GmbH
### Änderungshistorie ###
Datum: Version: Bearbeiter: Beschreibung:
24.11.2020 0.0 St. Maier Neuerstellung
#################################################################################################*)
(*#################################################################################################
Beschreibung:
Die Funktion vergleicht zwei Speicherbereiche (IN1, IN2). Sind die Bereiche gleich, liefert
die Funktion eine "true" ansonsten ein "false".
#################################################################################################*)
#pIN1 := #I_In1;
#pAnyIN1.DataType := 16#02;
#u1.ByteAddrMSB := #pAnyIN1.ByteAddressMSB;
#u1.WordAddr := #pAnyIN1.ByteAddressLSB;
#in1End := #u1Addr + (#pAnyIN1.Length * 8);
#pAnyIN1.Length := 1;
#pIN2 := #I_In2;
#pAnyIN2.DataType := 16#02;
#u2.ByteAddrMSB := #pAnyIN2.ByteAddressMSB;
#u2.WordAddr := #pAnyIN2.ByteAddressLSB;
#in2End := #u2Addr + (#pAnyIN2.Length * 8);
#pAnyIN2.Length := 1;
WHILE (#u1Addr < #in1End) AND (#u2Addr < #in2End) DO
#retVal := BLKMOV(SRCBLK := #pIN1, DSTBLK => #tst1);
IF #retVal <> 0 THEN
#MemCmp := FALSE;
RETURN;
END_IF;
#retVal := BLKMOV(SRCBLK := #pIN2, DSTBLK => #tst2);
IF #retVal <> 0 THEN
#MemCmp := FALSE;
RETURN;
END_IF;
IF #tst1 <> #tst2 THEN
#MemCmp := FALSE;
RETURN;
END_IF;
#u1Addr := #u1Addr + 8;
#pAnyIN1.ByteAddressMSB := #u1.ByteAddrMSB;
#pAnyIN1.ByteAddressLSB := #u1.WordAddr;
#u2Addr := #u2Addr + 8;
#pAnyIN2.ByteAddressMSB := #u2.ByteAddrMSB;
#pAnyIN2.ByteAddressLSB := #u2.WordAddr;
END_WHILE;
#MemCmp := TRUE;
END_FUNCTION

View File

@@ -1,62 +0,0 @@
FUNCTION "MemCmpExt" : Bool
TITLE = 'Memory Compare'
{ S7_Optimized_Access := 'FALSE' }
AUTHOR : Smiffy
VERSION : 0.1
VAR_INPUT
I_DbName : Any;
I_DbNo : Int;
END_VAR
VAR_OUTPUT
O_Len : Word;
END_VAR
VAR_TEMP
pIN1 : Any; // DB address ANY pointer - used for accessing DB data
pAnyIN1 AT pIN1 : Struct // Diassembled ANY pointer structure
S7Code : Byte; // Code for S7 (fixed at 16#10)
DataType : Byte; // Code for data type
Length : Int; // Repetition factor = Send/receive length
DBNumber : Int; // Data block Number
MemoryArea : Byte; // Specified memory area = 0x84 = data block
ByteAddressMSB : Byte; // Byte address most significant bits
ByteAddressLSB : Word; // Byte address least significant bits
END_STRUCT;
pIN2 : Any; // DB address ANY pointer - used for accessing DB data
pAnyIN2 AT pIN2 : Struct // Diassembled ANY pointer structure
S7Code : Byte; // Code for S7 (fixed at 16#10)
DataType : Byte; // Code for data type
Length : Int; // Repetition factor = Send/receive length
DBNumber : Int; // Data block Number
MemoryArea : Byte; // Specified memory area = 0x84 = data block
ByteAddressMSB : Byte; // Byte address most significant bits
ByteAddressLSB : Word; // Byte address least significant bits
END_STRUCT;
END_VAR
BEGIN
(*#################################################################################################
Copyright (c) Fondium Singen GmbH
### Änderungshistorie ###
Datum: Version: Bearbeiter: Beschreibung:
03.12.2020 0.0 St. Maier Neuerstellung
#################################################################################################*)
#pIN1 := #I_DbName;
#pIN2 := #pIN1;
#pAnyIN2.DBNumber := #I_DbNo;
#MemCmpExt := "MemCmp"(I_In1:=#pIN1,
I_In2:=#pIN2
);
#O_Len := INT_TO_WORD(#pAnyIN1.Length);
END_FUNCTION

View File

@@ -1,176 +0,0 @@
FUNCTION "MemCmpOpt" : Bool
{ S7_Optimized_Access := 'FALSE' }
VERSION : 0.1
VAR_INPUT
I_In1 : Any; // Quelle 1
I_In2 : Any; // Quelle 2
END_VAR
VAR_TEMP
in1End : DInt; // End addresses for memory areas
in2End : DInt; // End addresses for memory areas
pIN1 : Any; // DB address ANY pointer - used for accessing DB data
pAnyIN1 AT pIN1 : Struct // Diassembled ANY pointer structure
S7Code : Byte; // Code for S7 (fixed at 16#10)
DataType : Byte; // Code for data type
Length : Int; // Repetition factor = Send/receive length
DBNumber : Int; // Data block Number
MemoryArea : Byte; // Specified memory area = 0x84 = data block
ByteAddressMSB : Byte; // Byte address most significant bits
ByteAddressLSB : Word; // Byte address least significant bits
END_STRUCT;
u1Addr : DInt; // Union pointer for calculation of byte offset address
u1 AT u1Addr : Struct // This is equivalent to a union in 'c' dword goes in and word / byte LSB / byte MSB come out
ByteAddrLSBPad : Byte; // Not Used
ByteAddrMSB : Byte; // Byte address most significant bits
WordAddr : Word; // Byte address least significant bits
END_STRUCT;
pIN2 : Any; // DB address ANY pointer - used for accessing DB data
pAnyIN2 AT pIN2 : Struct // Diassembled ANY pointer structure
S7Code : Byte; // Code for S7 (fixed at 16#10)
DataType : Byte; // Code for data type
Length : Int; // Repetition factor = Send/receive length
DBNumber : Int; // Data block Number
MemoryArea : Byte; // Specified memory area = 0x84 = data block
ByteAddressMSB : Byte; // Byte address most significant bits
ByteAddressLSB : Word; // Byte address least significant bits
END_STRUCT;
u2Addr : DInt; // Union pointer for calculation of byte offset address
u2 AT u2Addr : Struct // This is equivalent to a union in 'c' dword goes in and word / byte LSB / byte MSB come out
ByteAddrLSBPad : Byte; // Not Used
ByteAddrMSB : Byte; // Byte address most significant bits
WordAddr : Word; // Byte address least significant bits
END_STRUCT;
step : Int; // Schrittweite für die Adressen
tmpDWord : Array[0..1] of DWord; // temporäres Doppelwort zum Zwischenspeichern
tmpData : Struct // temporäre Daten
data : DInt; // Adresse
dbNo : Word; // Datenbaustein Nummer
memArea : Int; // Speicherbereich
END_STRUCT;
i : Int; // Zählervariable
END_VAR
VAR CONSTANT
LEN_DW : Int := 4; // Doppelwort
LEN_W : Int := 2; // Wort
END_VAR
BEGIN
(*#################################################################################################
Copyright (c) Fondium Singen GmbH
### Änderungshistorie ###
Datum: Version: Bearbeiter: Beschreibung:
11.01.2020 0.0 St. Maier Neuerstellung
06.03.2021 1.0 St. Maier Schrittweitenberechnung angepasst
#################################################################################################*)
(*#################################################################################################
Beschreibung:
Die Funktion vergleicht den Inhalte zweier Datenbereiche (IN1, IN2). Sind die Datenbausteinge
gleich, liefert die Funktion eine "true" ansonsten ein "false".
#################################################################################################*)
#pIN1 := #I_In1;
#u1.ByteAddrMSB := #pAnyIN1.ByteAddressMSB;
#u1.WordAddr := #pAnyIN1.ByteAddressLSB;
#in1End := WORD_TO_INT(#u1.WordAddr) / 8 + #pAnyIN1.Length;
#u1Addr := #u1Addr / 8;
#pIN2 := #I_In2;
#u2.ByteAddrMSB := #pAnyIN2.ByteAddressMSB;
#u2.WordAddr := #pAnyIN2.ByteAddressLSB;
#in2End := WORD_TO_INT(#u2.WordAddr) / 8 + #pAnyIN2.Length;
#u2Addr := #u2Addr / 8;
// Schrittweiten berechnen
IF #pAnyIN1.Length / #LEN_DW >= 1 AND #pAnyIN2.Length / #LEN_DW >= 1 THEN
#step := #LEN_DW;
ELSE
#step := #LEN_W;
END_IF;
WHILE (#u1Addr < #in1End) AND (#u2Addr < #in2End) DO
FOR #i := 0 TO 1 DO
CASE #i OF
0: // Parameter Eingangspointer 1
#tmpData.data := #u1Addr; // Adresse zwischenspeichern
#tmpData.dbNo := INT_TO_WORD(#pAnyIN1.DBNumber); // Datenbaustein-Nr. zwischenspeichern
#tmpData.memArea := WORD_TO_INT(#pAnyIN1.MemoryArea); // Speicherbereich
1: // Parameter Eingangspointer 2
#tmpData.data := #u2Addr; // Adresse zwischenspeichern
#tmpData.dbNo := INT_TO_WORD(#pAnyIN2.DBNumber); // Datenbaustein-Nr. zwischenspeichern
#tmpData.memArea := WORD_TO_INT(#pAnyIN2.MemoryArea); // Speicherbereich
END_CASE;
CASE #tmpData.memArea OF
129: // Eingänge (0x81)
IF #step = #LEN_DW THEN // Doppelwort
#tmpDWord[#i] := %ED(#tmpData.data);
ELSE
#tmpDWord[#i] := %EW(#tmpData.data);
END_IF;
130: // Ausgänge (0x82)
IF #step = #LEN_DW THEN // Doppelwort
#tmpDWord[#i] := %AD(#tmpData.data);
ELSE
#tmpDWord[#i] := %AW(#tmpData.data);
END_IF;
131: // Merkerbereich (0x83)
IF #step = #LEN_DW THEN // Doppelwort
#tmpDWord[#i] := %MD(#tmpData.data);
ELSE
#tmpDWord[#i] := %MW(#tmpData.data);
END_IF;
132,132: // Datenbaustein (0x84)
IF #step = #LEN_DW THEN // Doppelwort
#tmpDWord[#i] := WORD_TO_BLOCK_DB(#tmpData.dbNo).DD(#tmpData.data);
ELSE
#tmpDWord[#i] := WORD_TO_BLOCK_DB(#tmpData.dbNo).DW(#tmpData.data);
END_IF;
ELSE // Statement section ELSE
#MemCmpOpt := FALSE;
RETURN;
END_CASE;
END_FOR;
// Daten vergleichen
IF #tmpDWord[0] <> #tmpDWord[1] THEN
#MemCmpOpt := FALSE;
RETURN;
END_IF;
// Schrittweite am Ende des Datenbereichs bestimmen
IF #in1End - #u1Addr < #LEN_DW OR #in2End - #u2Addr < #LEN_DW THEN
#step := #LEN_W;
END_IF;
// Adressen inkrementieren
#u1Addr := #u1Addr + #step;
#u2Addr := #u2Addr + #step;
END_WHILE;
#MemCmpOpt := TRUE;
END_FUNCTION

View File

@@ -1,62 +0,0 @@
FUNCTION "MemCmpOptExt" : Bool
TITLE = 'Memory Compare'
{ S7_Optimized_Access := 'FALSE' }
AUTHOR : Smiffy
VERSION : 0.1
VAR_INPUT
I_DbName : Any;
I_DbNo : Int;
END_VAR
VAR_OUTPUT
O_Len : Word;
END_VAR
VAR_TEMP
pIN1 : Any; // DB address ANY pointer - used for accessing DB data
pAnyIN1 AT pIN1 : Struct // Diassembled ANY pointer structure
S7Code : Byte; // Code for S7 (fixed at 16#10)
DataType : Byte; // Code for data type
Length : Int; // Repetition factor = Send/receive length
DBNumber : Int; // Data block Number
MemoryArea : Byte; // Specified memory area = 0x84 = data block
ByteAddressMSB : Byte; // Byte address most significant bits
ByteAddressLSB : Word; // Byte address least significant bits
END_STRUCT;
pIN2 : Any; // DB address ANY pointer - used for accessing DB data
pAnyIN2 AT pIN2 : Struct // Diassembled ANY pointer structure
S7Code : Byte; // Code for S7 (fixed at 16#10)
DataType : Byte; // Code for data type
Length : Int; // Repetition factor = Send/receive length
DBNumber : Int; // Data block Number
MemoryArea : Byte; // Specified memory area = 0x84 = data block
ByteAddressMSB : Byte; // Byte address most significant bits
ByteAddressLSB : Word; // Byte address least significant bits
END_STRUCT;
END_VAR
BEGIN
(*#################################################################################################
Copyright (c) Fondium Singen GmbH
### Änderungshistorie ###
Datum: Version: Bearbeiter: Beschreibung:
19.01.2021 0.0 St. Maier Neuerstellung
#################################################################################################*)
#pIN1 := #I_DbName;
#pIN2 := #pIN1;
#pAnyIN2.DBNumber := #I_DbNo;
#MemCmpOptExt := "MemCmpOpt"(I_In1 := #pIN1,
I_In2 := #pIN2
);
#O_Len := INT_TO_WORD(#pAnyIN1.Length);
END_FUNCTION

View File

@@ -1,228 +0,0 @@
FUNCTION_BLOCK "Chronometer"
{ S7_Optimized_Access := 'FALSE' }
AUTHOR : FSI
VERSION : 0.1
VAR_INPUT
I_Enable : Bool;
I_Reset : Bool;
END_VAR
VAR_OUTPUT
O_Days : DInt;
O_Out : Time;
O_Reset : Bool;
O_Overflow : Bool;
O_DataInconsistence : Bool;
END_VAR
VAR
lastDateAndTime : Date_And_Time;
t_0 { S7_HMI_Accessible := 'False'; S7_HMI_Visible := 'False'} AT lastDateAndTime : Struct
Y { S7_HMI_Accessible := 'False'; S7_HMI_Visible := 'False'} : Byte;
M { S7_HMI_Accessible := 'False'; S7_HMI_Visible := 'False'} : Byte;
D { S7_HMI_Accessible := 'False'; S7_HMI_Visible := 'False'} : Byte;
H { S7_HMI_Accessible := 'False'; S7_HMI_Visible := 'False'} : Byte;
MI { S7_HMI_Accessible := 'False'; S7_HMI_Visible := 'False'} : Byte;
S { S7_HMI_Accessible := 'False'; S7_HMI_Visible := 'False'} : Byte;
CS { S7_HMI_Accessible := 'False'; S7_HMI_Visible := 'False'} : Byte;
MS { S7_HMI_Accessible := 'False'; S7_HMI_Visible := 'False'} : Byte;
END_STRUCT;
actualDateAndTime : Date_And_Time;
t_1 { S7_HMI_Accessible := 'False'; S7_HMI_Visible := 'False'} AT actualDateAndTime : Struct
Y { S7_HMI_Accessible := 'False'; S7_HMI_Visible := 'False'} : Byte;
M { S7_HMI_Accessible := 'False'; S7_HMI_Visible := 'False'} : Byte;
D { S7_HMI_Accessible := 'False'; S7_HMI_Visible := 'False'} : Byte;
H { S7_HMI_Accessible := 'False'; S7_HMI_Visible := 'False'} : Byte;
MI { S7_HMI_Accessible := 'False'; S7_HMI_Visible := 'False'} : Byte;
S { S7_HMI_Accessible := 'False'; S7_HMI_Visible := 'False'} : Byte;
CS { S7_HMI_Accessible := 'False'; S7_HMI_Visible := 'False'} : Byte;
MS { S7_HMI_Accessible := 'False'; S7_HMI_Visible := 'False'} : Byte;
END_STRUCT;
firstScan : Bool;
day0 : DInt;
day1 : DInt;
deltaDay : DInt;
time0 : DInt;
time1 : DInt;
deltaTime : DInt;
END_VAR
VAR_TEMP
rv : Int;
END_VAR
BEGIN
(*############################################################################
### Änderungshistorie ###
Datum: Version: Bearbeiter: Beschreibung:
21.03.2019 0.0 St. Maier Neuerstellung
11.10.2019 0.1 St. Maier Überarbeitung Kopf damit TIA kompatibel
############################################################################*)
ENO := true;
// Reset
#O_Reset := #I_Reset;
IF #I_Reset = true THEN
#O_Days := 0;
#O_Out := DINT_TO_TIME(0);
#O_Overflow := 0;
#O_DataInconsistence := false;
#firstScan := true;
#day0 := 0;
#day1 := 0;
#deltaDay := 0;
#time0 := 0;
#time1 := 0;
#deltaTime := 0;
ELSIF #I_Enable = true THEN
IF #firstScan= true THEN
#rv := RD_SYS_T(OUT => #lastDateAndTime);
#time0 := INT_TO_DINT(WORD_TO_INT(BYTE_TO_WORD(#t_0.MS))/16*10 + WORD_TO_INT(BYTE_TO_WORD(#t_0.MS))MOD 16)/10;
#time0 := #time0 + INT_TO_DINT(WORD_TO_INT(BYTE_TO_WORD(#t_0.CS))/16*10 + WORD_TO_INT(BYTE_TO_WORD(#t_0.CS))MOD 16)*10;
#time0 := #time0 + INT_TO_DINT(WORD_TO_INT(BYTE_TO_WORD(#t_0.S ))/16*10 + WORD_TO_INT(BYTE_TO_WORD(#t_0.S ))MOD 16)*1000;
#time0 := #time0 + INT_TO_DINT(WORD_TO_INT(BYTE_TO_WORD(#t_0.MI))/16*10 + WORD_TO_INT(BYTE_TO_WORD(#t_0.MI))MOD 16)*60000;
#time0 := #time0 + INT_TO_DINT(WORD_TO_INT(BYTE_TO_WORD(#t_0.H ))/16*10 + WORD_TO_INT(BYTE_TO_WORD(#t_0.H ))MOD 16)*3600000;
// Tage lesen
#day0 := INT_TO_DINT(WORD_TO_INT(BYTE_TO_WORD(#t_0.D ))/16*10 + WORD_TO_INT(BYTE_TO_WORD(#t_0.D ))MOD 16);
#day0 := #day0 + INT_TO_DINT(WORD_TO_INT(BYTE_TO_WORD(#t_0.Y ))/16*10 + WORD_TO_INT(BYTE_TO_WORD(#t_0.Y ))MOD 16)*365;
#day0 := #day0 + INT_TO_DINT(WORD_TO_INT(BYTE_TO_WORD(#t_0.Y ))/16*10 + WORD_TO_INT(BYTE_TO_WORD(#t_0.Y ))MOD 16)/4;
IF (WORD_TO_INT(BYTE_TO_WORD(#t_0.Y ))/16*10 + WORD_TO_INT(BYTE_TO_WORD(#t_0.Y ))MOD 16)MOD 4=0 THEN
CASE WORD_TO_INT(BYTE_TO_WORD(#t_0.M)) OF
1: #day0 := #day0 + 0;
2: #day0 := #day0 + 31;
3: #day0 := #day0 + 60;
4: #day0 := #day0 + 91;
5: #day0 := #day0 + 121;
6: #day0 := #day0 + 152;
7: #day0 := #day0 + 182;
8: #day0 := #day0 + 213;
9: #day0 := #day0 + 244;
16: #day0 := #day0 + 274;
17: #day0 := #day0 + 305;
18: #day0 := #day0 + 335;
ELSE:
#O_DataInconsistence := TRUE;
END_CASE;
ELSE
CASE WORD_TO_INT(BYTE_TO_WORD(#t_0.M)) OF
1: #day0 := #day0 + 0;
2: #day0 := #day0 + 31;
3: #day0 := #day0 + 59;
4: #day0 := #day0 + 90;
5: #day0 := #day0 + 120;
6: #day0 := #day0 + 151;
7: #day0 := #day0 + 181;
8: #day0 := #day0 + 212;
9: #day0 := #day0 + 243;
16: #day0 := #day0 + 273;
17: #day0 := #day0 + 304;
18: #day0 := #day0 + 334;
ELSE:
#O_DataInconsistence := TRUE;
END_CASE;
END_IF;
#firstScan := FALSE;
END_IF;
#rv := RD_SYS_T(OUT => #actualDateAndTime);
// Read time / Zeit lesen
#time1 := INT_TO_DINT(WORD_TO_INT(BYTE_TO_WORD(#t_1.MS))/ 16 * 10 + WORD_TO_INT(BYTE_TO_WORD(#t_1.MS))MOD 16) / 10;
#time1 := #time1 + INT_TO_DINT(WORD_TO_INT(BYTE_TO_WORD(#t_1.CS))/ 16 * 10 + WORD_TO_INT(BYTE_TO_WORD(#t_1.CS))MOD 16) * 10;
#time1 := #time1 + INT_TO_DINT(WORD_TO_INT(BYTE_TO_WORD(#t_1.S ))/ 16 * 10 + WORD_TO_INT(BYTE_TO_WORD(#t_1.S ))MOD 16) * 1000;
#time1 := #time1 + INT_TO_DINT(WORD_TO_INT(BYTE_TO_WORD(#t_1.MI))/ 16 * 10 + WORD_TO_INT(BYTE_TO_WORD(#t_1.MI))MOD 16) * 60000;
#time1 := #time1 + INT_TO_DINT(WORD_TO_INT(BYTE_TO_WORD(#t_1.H ))/ 16 * 10 + WORD_TO_INT(BYTE_TO_WORD(#t_1.H ))MOD 16) * 3600000;
// Read days / Tage lesen
#day1 := INT_TO_DINT(WORD_TO_INT(BYTE_TO_WORD(#t_1.D ))/ 16 * 10 + WORD_TO_INT(BYTE_TO_WORD(#t_1.D ))MOD 16);
#day1 := #day1 + INT_TO_DINT(WORD_TO_INT(BYTE_TO_WORD(#t_1.Y ))/ 16 * 10 + WORD_TO_INT(BYTE_TO_WORD(#t_1.Y ))MOD 16) * 365;
#day1 := #day1 + INT_TO_DINT(WORD_TO_INT(BYTE_TO_WORD(#t_1.Y ))/ 16 * 10 + WORD_TO_INT(BYTE_TO_WORD(#t_1.Y ))MOD 16) / 4;
IF (WORD_TO_INT(BYTE_TO_WORD(#t_1.Y ))/ 16 * 10 + WORD_TO_INT(BYTE_TO_WORD(#t_1.Y ))MOD 16)MOD 4 = 0 THEN
CASE WORD_TO_INT(BYTE_TO_WORD(#t_1.M)) OF
1: #day1 := #day1 + 0;
2: #day1 := #day1 + 31;
3: #day1 := #day1 + 60;
4: #day1 := #day1 + 91;
5: #day1 := #day1 + 121;
6: #day1 := #day1 + 152;
7: #day1 := #day1 + 182;
8: #day1 := #day1 + 213;
9: #day1 := #day1 + 244;
16: #day1 := #day1 + 274;
17: #day1 := #day1 + 305;
18: #day1 := #day1 + 335;
ELSE:
#O_DataInconsistence := TRUE;
END_CASE;
ELSE
CASE WORD_TO_INT(BYTE_TO_WORD(#t_1.M)) OF
1: #day1 := #day1 + 0;
2: #day1 := #day1 + 31;
3: #day1 := #day1 + 59;
4: #day1 := #day1 + 90;
5: #day1 := #day1 + 120;
6: #day1 := #day1 + 151;
7: #day1 := #day1 + 181;
8: #day1 := #day1 + 212;
9: #day1 := #day1 + 243;
16: #day1 := #day1 + 273;
17: #day1 := #day1 + 304;
18: #day1 := #day1 + 334;
ELSE:
#O_DataInconsistence := TRUE;
END_CASE;
END_IF;
// Berechne die abgelaufene Zeit und die Tage
#deltaTime := #time1 - #time0;
#deltaDay := 0;
WHILE #deltaTime > 86400000 DO
#deltaTime := #deltaTime - 86400000;
#deltaDay := #deltaDay + 1;
END_WHILE;
WHILE #deltaTime < 0 DO
#deltaTime := #deltaTime + 86400000;
#deltaDay := #deltaDay - 1;
END_WHILE;
#deltaDay := #deltaDay + #day1 - #day0;
IF #deltaDay < 0 THEN
#O_DataInconsistence := TRUE;
END_IF;
#O_Out := DINT_TO_TIME(#deltaTime);
#O_Days := #deltaDay;
ELSE
#firstScan := TRUE;
END_IF;
END_FUNCTION_BLOCK

View File

@@ -1,168 +0,0 @@
FUNCTION_BLOCK "SkLfztUebw.Main"
{ S7_Optimized_Access := 'FALSE' }
VERSION : 0.1
VAR_INPUT
I_StepNr : Int; // aktuelle Schrittnummer
"I_STIME.tx" : DWord; // Zeit
I_LfztUebw : Any; // Register Schrittzeiten
END_VAR
VAR
zylZt : Time; // zuletzt gemessene Zykluszeit
tx : Time; // aktuelle Systemzeit
anyFlt : Word; // Fehler beim Bestimmen der Länge
stepNrs : DInt; // Anzahl der Schritte
zylZtSum : DInt; // Summe der Zykluszeiten
tempStepZt : "SkLfztUebw.T_Lfzt"; // Temp Variable zur Bestimmung der Anzahl Schritte
tempGesStepZt : "SkLfztUebw.T_Lfzt";
flkStep : "Flnk.NrVal"; // Flankenauswertung bei Schritt-Nr. Änderung
END_VAR
VAR_TEMP
TOP_SI : Struct
EV_CLASS : Byte;
EV_NUM : Byte;
PRIORITY : Byte;
NUM : Byte;
TYP2_3 : Byte;
TYP1 : Byte;
ZI1 : Word;
ZI2_3 : DWord;
END_STRUCT;
START_UP_SI : Struct
EV_CLASS : Byte;
EV_NUM : Byte;
PRIORITY : Byte;
NUM : Byte;
TYP2_3 : Byte;
TYP1 : Byte;
ZI1 : Word;
ZI2_3 : DWord;
END_STRUCT;
err : Int;
END_VAR
VAR CONSTANT
GES_ZT : Int := 0;
STEP01 : Int := 1;
END_VAR
BEGIN
(*#################################################################################################
Copyright (c) Fondium Singen GmbH
### Änderungshistorie ###
Datum: Version: Bearbeiter: Beschreibung:
23.09.2019 0.0 St. Maier Neuerstellung
11.10.2019 0.1 St. Maier Überarbeitung Kopf damit TIA kompatibel
#################################################################################################*)
(*################################### Baustein Beschreibung #######################################
Abhängigkeiten (von anderen Fuktionen und Quellen):
- RD_SINFO
- CpuZeit
Inputs:
-
Outputs:
-
In-\Outputs:
- IO_ZylZtShiftReg: Schieberegister für Zykluszeiten
Return-Value:
-
Funktionsbeschreibung:
#################################################################################################*)
(* aktuelle Startinformationen auslesen *)
(* OB1_SCAN_1 BYTE - B#16#01: Abschluss des Neustarts (Warmstarts)
- B#16#02: Abschluss des Wiederanlaufs
- B#16#03: Abschluss des freien Zyklus
- B#16#04: Abschluss des Kaltstarts
- B#16#05: Erster OB 1-Zyklus der neuen Master-CPU nach
Master-Reserve-Umschaltung und STOP des
bisherigen Masters *)
#err := RD_SINFO(TOP_SI => #TOP_SI
, START_UP_SI => #START_UP_SI
);
// Zurücksetzen der letzten Zykluszeit bei System start
IF #TOP_SI.EV_NUM <> 3 THEN
#zylZt := t#0ms;
END_IF;
// Infos wie Array-Länge von Schieberegister bestimmen
#anyFlt := "Any.Struct"(I_UDT := #tempStepZt
, I_StartBitAndRange := #I_LfztUebw
, O_DataCount => #stepNrs
);
// Funktion beenden, wenn Schritt 0 oder Schritt-Nr. größer als max. Schrittanzahl am Eingang ansteht
IF #I_StepNr = #GES_ZT OR #I_StepNr >= (#stepNrs) THEN
#zylZt := t#0ms;
RETURN;
END_IF;
// Flankenauswertung bei Schritt-Nr. Änderungen
#flkStep(I_Val := #I_StepNr// IN: DINT
);
// Flanke bei Schrittwechsel
IF #flkStep.O_Flnk THEN
// Schrittzeit zurücksetzen
//IO_LfztUebw.Data[#I_StepNr].lfztAkt := t#0ms;
#tempStepZt.lfztAkt := t#0ms;
// Gesamt-Zeit der Schrittkette bei Schritt 1 zurücksetzen
IF #I_StepNr = #STEP01 THEN
//IO_LfztUebw.Data[I_CONST_STEPS.GES_ZT].lfztAkt := t#0ms;
#tempGesStepZt.lfztAkt := t#0ms;
END_IF;
END_IF;
#tx := DINT_TO_TIME(DWORD_TO_DINT(#"I_STIME.tx")) - #zylZt;
// Gesamt- und Schrittzeitbestimmung
IF #zylZt > t#0ms THEN
// Gesamt-Zeit Bestimmung
//IO_LfztUebw.Data[I_CONST_STEPS.GES_ZT].lfztAkt := IO_LfztUebw.Data[I_CONST_STEPS.GES_ZT].lfztAkt + #tx;
#tempGesStepZt.lfztAkt := #tempGesStepZt.lfztAkt + #tx;
"UdtInAnyKop"(I_SrcUdtAry:= #tempGesStepZt,
I_DestUdtAry:=#I_LfztUebw ,
I_DestIndex:=0,
O_Ret=> #err);
// Schrittzeit Bestimmung
//IO_LfztUebw.Data[#I_StepNr].lfztAkt := IO_LfztUebw.Data[#I_StepNr].lfztAkt + #tx;
#tempStepZt.lfztAkt := #tempStepZt.lfztAkt + #tx;
"UdtInAnyKop"(I_SrcUdtAry:= #tempStepZt,
I_DestUdtAry:=#I_LfztUebw ,
I_DestIndex:=#I_StepNr,
O_Ret=> #err);
END_IF;
#zylZt := #zylZt + #tx;
END_FUNCTION_BLOCK

View File

@@ -1,168 +0,0 @@
FUNCTION_BLOCK "SkLfztUebw.Main_1"
{ S7_Optimized_Access := 'FALSE' }
VERSION : 0.1
VAR_INPUT
I_StepNr : Int; // aktuelle Schrittnummer
"I_STIME.tx" : DWord; // Zeit
I_LfztUebw : Any; // Register Schrittzeiten
END_VAR
VAR
zylZt : Time; // zuletzt gemessene Zykluszeit
tx : Time; // aktuelle Systemzeit
anyFlt : Word; // Fehler beim Bestimmen der Länge
stepNrs : DInt; // Anzahl der Schritte
zylZtSum : DInt; // Summe der Zykluszeiten
tempStepZt : "SkLfztUebw.T_Lfzt"; // Temp Variable zur Bestimmung der Anzahl Schritte
tempGesStepZt : "SkLfztUebw.T_Lfzt";
flkStep : "Flnk.NrVal"; // Flankenauswertung bei Schritt-Nr. Änderung
END_VAR
VAR_TEMP
TOP_SI : Struct
EV_CLASS : Byte;
EV_NUM : Byte;
PRIORITY : Byte;
NUM : Byte;
TYP2_3 : Byte;
TYP1 : Byte;
ZI1 : Word;
ZI2_3 : DWord;
END_STRUCT;
START_UP_SI : Struct
EV_CLASS : Byte;
EV_NUM : Byte;
PRIORITY : Byte;
NUM : Byte;
TYP2_3 : Byte;
TYP1 : Byte;
ZI1 : Word;
ZI2_3 : DWord;
END_STRUCT;
err : Int;
END_VAR
VAR CONSTANT
GES_ZT : Int := 0;
STEP01 : Int := 1;
END_VAR
BEGIN
(*#################################################################################################
Copyright (c) Fondium Singen GmbH
### Änderungshistorie ###
Datum: Version: Bearbeiter: Beschreibung:
23.09.2019 0.0 St. Maier Neuerstellung
11.10.2019 0.1 St. Maier Überarbeitung Kopf damit TIA kompatibel
#################################################################################################*)
(*################################### Baustein Beschreibung #######################################
Abhängigkeiten (von anderen Fuktionen und Quellen):
- RD_SINFO
- CpuZeit
Inputs:
-
Outputs:
-
In-\Outputs:
- IO_ZylZtShiftReg: Schieberegister für Zykluszeiten
Return-Value:
-
Funktionsbeschreibung:
#################################################################################################*)
(* aktuelle Startinformationen auslesen *)
(* OB1_SCAN_1 BYTE - B#16#01: Abschluss des Neustarts (Warmstarts)
- B#16#02: Abschluss des Wiederanlaufs
- B#16#03: Abschluss des freien Zyklus
- B#16#04: Abschluss des Kaltstarts
- B#16#05: Erster OB 1-Zyklus der neuen Master-CPU nach
Master-Reserve-Umschaltung und STOP des
bisherigen Masters *)
#err := RD_SINFO(TOP_SI => #TOP_SI
, START_UP_SI => #START_UP_SI
);
// Zurücksetzen der letzten Zykluszeit bei System start
IF #TOP_SI.EV_NUM <> 3 THEN
#zylZt := t#0ms;
END_IF;
// Infos wie Array-Länge von Schieberegister bestimmen
#anyFlt := "Any.Struct"(I_UDT := #tempStepZt
, I_StartBitAndRange := #I_LfztUebw
, O_DataCount => #stepNrs
);
// Funktion beenden, wenn Schritt 0 oder Schritt-Nr. größer als max. Schrittanzahl am Eingang ansteht
IF #I_StepNr = #GES_ZT OR #I_StepNr >= (#stepNrs) THEN
#zylZt := t#0ms;
RETURN;
END_IF;
// Flankenauswertung bei Schritt-Nr. Änderungen
#flkStep(I_Val := #I_StepNr// IN: DINT
);
// Flanke bei Schrittwechsel
IF #flkStep.O_Flnk THEN
// Schrittzeit zurücksetzen
//IO_LfztUebw.Data[#I_StepNr].lfztAkt := t#0ms;
#tempStepZt.lfztAkt := t#0ms;
// Gesamt-Zeit der Schrittkette bei Schritt 1 zurücksetzen
IF #I_StepNr = #STEP01 THEN
//IO_LfztUebw.Data[I_CONST_STEPS.GES_ZT].lfztAkt := t#0ms;
#tempGesStepZt.lfztAkt := t#0ms;
END_IF;
END_IF;
#tx := DINT_TO_TIME(DWORD_TO_DINT(#"I_STIME.tx")) - #zylZt;
// Gesamt- und Schrittzeitbestimmung
IF #zylZt > t#0ms THEN
// Gesamt-Zeit Bestimmung
//IO_LfztUebw.Data[I_CONST_STEPS.GES_ZT].lfztAkt := IO_LfztUebw.Data[I_CONST_STEPS.GES_ZT].lfztAkt + #tx;
#tempGesStepZt.lfztAkt := #tempGesStepZt.lfztAkt + #tx;
"UdtInAnyKop"(I_SrcUdtAry:= #tempGesStepZt,
I_DestUdtAry:=#I_LfztUebw ,
I_DestIndex:=0,
O_Ret=> #err);
// Schrittzeit Bestimmung
//IO_LfztUebw.Data[#I_StepNr].lfztAkt := IO_LfztUebw.Data[#I_StepNr].lfztAkt + #tx;
#tempStepZt.lfztAkt := #tempStepZt.lfztAkt + #tx;
"UdtInAnyKop"(I_SrcUdtAry:= #tempStepZt,
I_DestUdtAry:=#I_LfztUebw ,
I_DestIndex:=#I_StepNr,
O_Ret=> #err);
END_IF;
#zylZt := #zylZt + #tx;
END_FUNCTION_BLOCK

View File

@@ -1,10 +0,0 @@
TYPE "SkLfztUebw.T_Lfzt"
VERSION : 0.1
STRUCT
lfztMin : Time; // minimale zulässige Laufzeit
lfztMax : Time; // maximale zulässige Laufzeit
lfztAkt : Time; // aktelle Laufzeit
END_STRUCT;
END_TYPE

Some files were not shown because too many files have changed in this diff Show More