Applikationsobjekte definieren und konfigurieren
Applikationsobjekte = Single Points, Double Points, Measured Values, Short Floating Point Values usw.
In diesem Beispiel wurden die Befehle so konfiguriert, dass die Prozessdaten der Befehle im gleichen Speicherbereich aber auf einem anderen Byte-/Bit-Offset wie die Daten der Information in Überwachungsrichtung liegen. Sie können aber auch die Befehle auf den gleichen Byte- Bit-Offset wie die Information in Überwachungsrichtung legen.
Beispiel:
C_SC_NA_1 mit IOA = 10 auf den gleichen Byte- und Bit-Offset wie M_SP_NA_1 mit IOA = 100 (beide Byte-Offset = 100 und Bit-Offset = 0). In diesem Fall wird eine Wertänderung durch ein Kommando von der Leitstation eine Übertragung des M_SP_NA_1 mit der Objektadresse 100 und Übertragungsursache <11> (returned by remote command) zur Folge haben.
Als Beispiel für das Tutorial werden folgende Applikationsobjekte:
Arrayelement | ASDU identifier | Objektadresse | Group-Konfigurationsparameter | Basiszeitmultiplikator | SPS-Prozessdatenbereich | Offset | Offset | Prozessdatenbreite in der TwinCAT SPS |
0 | M_SP_NA_1 | 100 | Generalabfrage | 0 | Merker | 100 | 0 | 1 Bit |
1 | M_SP_NA_1 | 101 | Generalabfrage | 0 | Merker | 100 | 1 | 1 Bit |
2 | M_SP_TB_1 | 102 | Generalabfrage | 0 | Merker | 100 | 2 | 1 Bit |
3 | M_DP_NA_1 | 200 | Generalabfrage | 0 | Merker | 200 | 0 | 2 Bits |
4 | M_DP_NA_1 | 201 | Generalabfrage | 0 | Merker | 200 | 2 | 2 Bits |
5 | M_DP_TB_1 | 202 | Generalabfrage | 0 | Merker | 200 | 4 | 2 Bits |
6 | M_ST_NA_1 | 300 | Generalabfrage | 0 | Merker | 300 | 0 | 1 Byte |
7 | M_ST_NA_1 | 301 | Generalabfrage | 0 | Merker | 301 | 0 | 1 Byte |
8 | M_ST_TB_1 | 302 | Generalabfrage | 0 | Merker | 302 | 0 | 1 Byte |
9 | M_BO_NA_1 | 400 | Generalabfrage | 0 | Merker | 400 | 0 | 4 Byte |
10 | M_BO_NA_1 | 401 | Generalabfrage | 0 | Merker | 404 | 0 | 4 Byte |
11 | M_BO_TB_1 | 402 | Generalabfrage | 0 | Merker | 408 | 0 | 4 Byte |
12 | M_ME_NA_1 | 500 | Generalabfrage | 0 | Merker | 500 | 0 | 2 Byte |
13 | M_ME_NA_1 | 501 | Generalabfrage | 0 | Merker | 502 | 0 | 2 Byte |
14 | M_ME_TD_1 | 502 | Generalabfrage | 0 | Merker | 504 | 0 | 2 Byte |
15 | M_ME_NB_1 | 600 | Generalabfrage | 0 | Merker | 600 | 0 | 2 Byte |
16 | M_ME_NB_1 | 601 | Generalabfrage | 0 | Merker | 602 | 0 | 2 Byte |
17 | M_ME_TE_1 | 602 | Generalabfrage | 0 | Merker | 604 | 0 | 2 Byte |
18 | M_ME_NC_1 | 700 | Generalabfrage | 0 | Merker | 700 | 0 | 4 Byte |
19 | M_ME_NC_1 | 701 | Generalabfrage | 0 | Merker | 704 | 0 | 4 Byte |
20 | M_ME_TF_1 | 702 | Generalabfrage | 0 | Merker | 708 | 0 | 4 Byte |
21 | M_IT_NA_1 | 800 | Generalzählerabfrage und Mode A (lokal Umspeichern mit Spontanübertragung alle 15s) | 0 | Merker | 800 | 0 | 4 Byte |
22 | M_IT_NA_1 | 801 | Generalzählerabfrage und Mode A (lokal Umspeichern mit Spontanübertragung alle 15s) | 0 | Merker | 804 | 0 | 4 Byte |
23 | M_IT_TB_1 | 802 | Generalzählerabfrage und Mode A (lokal Umspeichern mit Spontanübertragung alle 15s) | 0 | Merker | 808 | 0 | 4 Byte |
Commands |
|
|
|
|
|
|
|
|
24 | C_SC_NA_1 | 10 | - | 0 | Merker | 2100 | 0 | 1 Bit |
25 | C_SC_NA_1 | 11 | - | 0 | Merker | 2100 | 1 | 1 Bit |
26 | C_SC_TA_1 | 12 | - | 0 | Merker | 2100 | 2 | 1 Bit |
27 | C_DC_NA_1 | 20 | - | 0 | Merker | 2200 | 0 | 2 Bit |
28 | C_DC_NA_1 | 21 | - | 0 | Merker | 2200 | 2 | 2 Bit |
29 | C_DC_TA_1 | 22 | - | 0 | Merker | 2200 | 4 | 2 Bit |
30 | C_RC_NA_1 | 30 | - | 0 | Merker | 2300 | 0 | 1 Byte |
31 | C_RC_NA_1 | 31 | - | 0 | Merker | 2301 | 0 | 1 Byte |
32 | C_RC_TA_1 | 32 | - | 0 | Merker | 2302 | 0 | 1 Byte |
33 | C_BO_NA_1 | 40 | - | 0 | Merker | 2400 | 0 | 4 Byte |
34 | C_BO_NA_1 | 41 | - | 0 | Merker | 2404 | 0 | 4 Byte |
35 | C_BO_TA_1 | 42 | - | 0 | Merker | 2408 | 0 | 4 Byte |
36 | C_SE_NA_1 | 50 | - | 0 | Merker | 2500 | 0 | 2 Byte |
37 | C_SE_NA_1 | 51 | - | 0 | Merker | 2502 | 0 | 2 Byte |
38 | C_SE_TA_1 | 52 | - | 0 | Merker | 2504 | 0 | 2 Byte |
39 | C_SE_NB_1 | 60 | - | 0 | Merker | 2600 | 0 | 2 Byte |
40 | C_SE_NB_1 | 61 | - | 0 | Merker | 2602 | 0 | 2 Byte |
41 | C_SE_TB_1 | 62 | - | 0 | Merker | 2604 | 0 | 2 Byte |
42 | C_SE_NC_1 | 70 | - | 0 | Merker | 2700 | 0 | 4 Byte |
43 | C_SE_NC_1 | 71 | - | 0 | Merker | 2704 | 0 | 4 Byte |
44 | C_SE_TC_1 | 72 | - | 0 | Merker | 2708 | 0 | 4 Byte |
Datenbankvariable deklarieren
Die Applikationsobjekt-Datenbank ist eine Array-Variable vom Typ ST_IEC870_5_101AODBEntry. Jedes Array-Element entspricht einem Applikationsobjekt. Die maximale Anzahl der Applikationsobjekte ist frei wählbar und nur durch den verfügbaren Speicher begrenzt. Sie müssen sich auf eine konstante maximale Anzahl während der SPS-Programmierung festlegen. Zur Laufzeit kann die maximale Anzahl der Applikationsobjekte nicht mehr verändert werden.
In unserem Beispiel werden 50 Applikationsobjekte deklariert. Diese Anzahl reicht für die meisten Anwendungen aus. Beachten Sie, dass sehr viele Applikationsobjekte auch entsprechend viel Speicher und Laufzeit benötigen.
Definieren Sie folgende Variable in MAIN:
PROGRAM MAIN
VAR
AODB : ARRAY[0..49] OF ST_IEC870_5_101AODBEntry;
END_VAR
Applikationsobjekte konfigurieren
Während der Konfiguration der einzelnen Applikationsobjekte werden unter anderem der Objekt-Typ ( M_SP_NA_1, M_DP_NA_1, M_ST_NA_1 usw.), die Objekt-Adresse und weitere Objekt-Parameter festgelegt.
Die Konfiguration der gewünschten Applikationsobjekte wird zur Programmlaufzeit durchgeführt. Jedes Applikationsobjekt (Datenbank-Array-Element) wird durch einen einmaligen Aufruf der F_iecInitAOEntry-Funktion konfiguriert. Das zu konfigurierende Array-Element wird an die Funktion per VAR_IN_OUT übergeben. Im Regelfall wird die Konfiguration beim SPS-Programmstart einmalig in einer Init-Routine durchgeführt. Die Funktion F_iecInitAOEntry erwartet folgende Funktionsparameter (von links nach rechts):
FUNCTION F_iecInitAOEntry : UDINT
VAR_INPUT
eType : E_IEC870_5_101TcTypeID;
objAddr : DWORD := 0;
group : DWORD := 0;
multiplier : BYTE := 0;
ioMapType : E_IEC870_5_101IOMappingType;
byteOffs : UDINT := 0;
bitOffs : UDINT := 0;
END_VAR
VAR_IN_OUT
dbEntry : ST_IEC870_5_101AODBEntry;
END_VAR
eType: Applikationsobjekt-Typ (ASDU identifier, z.B.: M_SP_NA_1 für Single Point oder M_DP_NA_1 für Double Point ). Beachten Sie, dass nur die in der Kompatibilitätsliste aufgeführten ASDU-Typen verwendet werden können. Unzulässige Typen werden ignoriert.
objAddr : Objektadresse, z.B. 100. Jedes Applikationsobjekt sollte mit einer eindeutigen Adresse konfiguriert werden.
group: Group-Konfigurationsparameter. Die verfügbaren Group-Parameter sind als Konstanten definiert und können mit ODER-Operator kombiniert werden. Z.B.: IEC870_GRP_INROGEN OR IEC870_GRP_PERCYC.
Hier finden Sie die Beschreibung aller Group-Konfigurationsparameter.
mutiplier: Basiszeitmultiplikator für die zyklische/periodische Datenübertragung ( 0=Deaktiviert). Die Basiszeit wird über die Systemparameter konfiguriert. Wurde die Basiszeit z.B. auf T#10s gesetzt und der Multiplikator auf den Wert 2, dann werden die periodischen/zyklischen Daten des Applikationsobjekts alle 20 Sekunden gesendet.
ioMapType: Dieser Parameter legt fest, aus oder in welchen Prozessdatenbereich der TwinCAT SPS die IEC-Prozessdaten zur Laufzeit gemappt werden sollen (inputs, outputs, memory, data).
byteOffs: Prozessdatenbereich Byteoffset;
bitOffs: Prozessdatenbereich Bitoffset;
dbEntry: Applikationsobjekt das konfiguriert werden soll (ein Datenbankvariable-Arrayelement, das an die Funktion per VAR_IN_OUT übergeben wird).
Um die Applikationsobjekte beim Programmstart zu konfigurieren wird in MAIN folgender SPS-Code hinzugefügt:
PROGRAM MAIN
VAR
AODB : ARRAY[0..49] OF ST_IEC870_5_101AODBEntry;
init : BOOL := TRUE;
initError : UDINT;
END_VAR
IF init THEN
init := FALSE;
(* Monitored Single Points *)
initError := F_iecInitAOEntry( M_SP_NA_1, 100, IEC870_GRP_INROGEN, 0, MAP_AREA_MEMORY, 100, 0, AODB[0] );
initError := F_iecInitAOEntry( M_SP_NA_1, 101, IEC870_GRP_INROGEN, 0, MAP_AREA_MEMORY, 100, 1, AODB[1] );
initError := F_iecInitAOEntry( M_SP_TB_1, 102, IEC870_GRP_INROGEN, 0, MAP_AREA_MEMORY, 100, 2, AODB[2]);
(* Double Points*)
initError := F_iecInitAOEntry( M_DP_NA_1, 200, IEC870_GRP_INROGEN, 0, MAP_AREA_MEMORY, 200, 0, AODB[3] );
initError := F_iecInitAOEntry( M_DP_NA_1, 201, IEC870_GRP_INROGEN, 0, MAP_AREA_MEMORY, 200, 2, AODB[4] );
initError := F_iecInitAOEntry( M_DP_TB_1, 202, IEC870_GRP_INROGEN, 0, MAP_AREA_MEMORY, 200, 4, AODB[5] );
(* Regulating step value *)
initError := F_iecInitAOEntry( M_ST_NA_1, 300, IEC870_GRP_INROGEN, 0, MAP_AREA_MEMORY, 300, 0, AODB[6] );
initError := F_iecInitAOEntry( M_ST_NA_1, 301, IEC870_GRP_INROGEN, 0, MAP_AREA_MEMORY, 301, 0, AODB[7] );
initError := F_iecInitAOEntry( M_ST_TB_1, 302, IEC870_GRP_INROGEN, 0, MAP_AREA_MEMORY, 302, 0, AODB[8] );
(* 32 bit string*)
initError := F_iecInitAOEntry( M_BO_NA_1, 400, IEC870_GRP_INROGEN, 0, MAP_AREA_MEMORY, 400, 0, AODB[9] );
initError := F_iecInitAOEntry( M_BO_NA_1, 401, IEC870_GRP_INROGEN, 0, MAP_AREA_MEMORY, 404, 0, AODB[10] );
initError := F_iecInitAOEntry( M_BO_TB_1, 402, IEC870_GRP_INROGEN, 0, MAP_AREA_MEMORY, 408, 0, AODB[11] );
(* Measured value, normalized value *)
initError := F_iecInitAOEntry( M_ME_NA_1, 500, IEC870_GRP_INROGEN, 0, MAP_AREA_MEMORY, 500, 0, AODB[12] );
initError := F_iecInitAOEntry( M_ME_NA_1, 501, IEC870_GRP_INROGEN, 0, MAP_AREA_MEMORY, 502, 0, AODB[13] );
initError := F_iecInitAOEntry( M_ME_TD_1, 502, IEC870_GRP_INROGEN, 0, MAP_AREA_MEMORY, 504, 0, AODB[14] );
(* Mesured value, scaled value *)
initError := F_iecInitAOEntry( M_ME_NB_1, 600, IEC870_GRP_INROGEN, 0, MAP_AREA_MEMORY, 600, 0, AODB[15] );
initError := F_iecInitAOEntry( M_ME_NB_1, 601, IEC870_GRP_INROGEN, 0, MAP_AREA_MEMORY, 602, 0, AODB[16] );
initError := F_iecInitAOEntry( M_ME_TE_1, 602, IEC870_GRP_INROGEN, 0, MAP_AREA_MEMORY, 604, 0, AODB[17] );
(* Measured value , short floating point value *)
initError := F_iecInitAOEntry( M_ME_NC_1, 700, IEC870_GRP_INROGEN, 0, MAP_AREA_MEMORY, 700, 0, AODB[18] );
initError := F_iecInitAOEntry( M_ME_NC_1, 701, IEC870_GRP_INROGEN, 0, MAP_AREA_MEMORY, 704, 0, AODB[19] );
initError := F_iecInitAOEntry( M_ME_TF_1, 702, IEC870_GRP_INROGEN, 0, MAP_AREA_MEMORY, 708, 0, AODB[20] );
(* Integrated totals *)
initError := F_iecInitAOEntry( M_IT_NA_1, 800, IEC870_GRP_REQCOGEN OR IEC870_GRP_LOCFREEZE, 0, MAP_AREA_MEMORY, 800, 0, AODB[21] );
initError := F_iecInitAOEntry( M_IT_NA_1, 801, IEC870_GRP_REQCOGEN OR IEC870_GRP_LOCFREEZE, 0, MAP_AREA_MEMORY, 804, 0, AODB[22] );
initError := F_iecInitAOEntry( M_IT_TB_1, 802, IEC870_GRP_REQCOGEN OR IEC870_GRP_LOCFREEZE, 0, MAP_AREA_MEMORY, 808, 0, AODB[23] );
(* Single commands *)
initError := F_iecInitAOEntry( C_SC_NA_1, 10, 0, 0, MAP_AREA_MEMORY, 2100, 0, AODB[24] );
initError := F_iecInitAOEntry( C_SC_NA_1, 11, 0, 0, MAP_AREA_MEMORY, 2100, 1, AODB[25] );
initError := F_iecInitAOEntry( C_SC_TA_1, 12, 0, 0, MAP_AREA_MEMORY, 2100, 2, AODB[26] );
(* Double commands *)
initError := F_iecInitAOEntry( C_DC_NA_1, 20, 0, 0, MAP_AREA_MEMORY, 2200, 0, AODB[27] );
initError := F_iecInitAOEntry( C_DC_NA_1, 21, 0, 0, MAP_AREA_MEMORY, 2200, 2, AODB[28] );
initError := F_iecInitAOEntry( C_DC_TA_1, 22, 0, 0, MAP_AREA_MEMORY, 2200, 4, AODB[29] );
(* Regulating step commands *)
initError := F_iecInitAOEntry( C_RC_NA_1, 30, 0, 0, MAP_AREA_MEMORY, 2300, 0, AODB[30] );
initError := F_iecInitAOEntry( C_RC_NA_1, 31, 0, 0, MAP_AREA_MEMORY, 2301, 0, AODB[31] );
initError := F_iecInitAOEntry( C_RC_TA_1, 32, 0, 0, MAP_AREA_MEMORY, 2302, 0, AODB[32] );
(* 32 bit string commands *)
initError := F_iecInitAOEntry( C_BO_NA_1, 40, 0, 0, MAP_AREA_MEMORY, 2400, 0, AODB[33] );
initError := F_iecInitAOEntry( C_BO_NA_1, 41, 0, 0, MAP_AREA_MEMORY, 2404, 0, AODB[34] );
initError := F_iecInitAOEntry( C_BO_TA_1, 42, 0, 0, MAP_AREA_MEMORY, 2408, 0, AODB[35] );
(* Set point, normalized values*)
initError := F_iecInitAOEntry( C_SE_NA_1, 50, 0, 0, MAP_AREA_MEMORY, 2500, 0, AODB[36] );
initError := F_iecInitAOEntry( C_SE_NA_1, 51, 0, 0, MAP_AREA_MEMORY, 2502, 0, AODB[37] );
initError := F_iecInitAOEntry( C_SE_TA_1, 52, 0, 0, MAP_AREA_MEMORY, 2504, 0, AODB[38] );
(* Set point, scaled valuess *)
initError := F_iecInitAOEntry( C_SE_NB_1, 60, 0, 0, MAP_AREA_MEMORY, 2600, 0, AODB[39] );
initError := F_iecInitAOEntry( C_SE_NB_1, 61, 0, 0, MAP_AREA_MEMORY, 2602, 0, AODB[40] );
initError := F_iecInitAOEntry( C_SE_TB_1, 62, 0, 0, MAP_AREA_MEMORY, 2604, 0, AODB[41] );
(* Set point, short floating point values *)
initError := F_iecInitAOEntry( C_SE_NC_1, 70, 0, 0, MAP_AREA_MEMORY, 2700, 0, AODB[42] );
initError := F_iecInitAOEntry( C_SE_NC_1, 71, 0, 0, MAP_AREA_MEMORY, 2704, 0, AODB[43] );
initError := F_iecInitAOEntry( C_SE_TC_1, 72, 0, 0, MAP_AREA_MEMORY, 2708, 0, AODB[44] );
END_IF
Das zugehörige Tutorial SPS-Beispiel kann hier heruntergeladen werden.