TIA AWL 300 ändern auf 1500

motormann

Level-1
Beiträge
3
Reaktionspunkte
0
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo zusammen,
ich möchte ein altes Projekt aus einer 300´ter in einer 1500 ändern. Da ja in der 1500'ter AWL nicht mehr wirklich zeitgemäß ist, soll es angepasst werden. Leider kenne ich mich mit AWL nicht so recht aus und komme hier an meine grenzen. Mein erster Gedanke ist es in SCL und einer Mischung mit FUP zu realisieren. Die Daten in den DB mit einer FOR schleife bei jedem Takt zuschreiben ist einfach. In dem Schieberegister sind die Werte /Tag (1440 min =24 Stunden) vorhanden. Jetzt fehlt mir nur der faden um die Daten wieder passend aus der schleife zu lesen. Die schleife hatte ich mir gedacht, damit die ersten Werte im DB ja auch die letzten sind die eingeschrieben werden, und somit das auslesen für den Kurzzeitwert einfacher ist. Mir gelingt aber das auslesen nicht wirklich... im Anhang mal das Original


FUNCTION_BLOCK "DAY"
TITLE = Bearbeitung des Tagesspeichers mit 1440 Werten
{ S7_Optimized_Access := 'FALSE' }
AUTHOR : Wandt
FAMILY : Anwender
NAME : DAY_MEM
VERSION : 1.0
VAR_INPUT
MENGE : Real; // Mengenwert pro Minute
TAKT : Bool; // Minutentakt
RESET : Bool; // KZW zurücksetzen
ZEIT : Int; // Zeitvorgabe KZW
END_VAR

VAR_OUTPUT
ZEIGER : Int; // interner Speicher-Pointer Umlaufspeicher
ANZ_KZW : Int; // Anzahl Werte für KZW
ANZ_GES : Int; // Anzahl Werte für Tagesspeicher
KZW : Real; // Kurzzeitwert (Menge)
h24 : Real; // 24h-Wert (Menge)
KZW_VOLL : Bool; // Anzahl KZW = SOLL
h24_VOLL : Bool; // Anzahl 24h = 1440
END_VAR

VAR
MEMORY { S7_SetPoint := 'False'} : "Tagespeicher"; // Bereich des Umlaufspeichers
END_VAR

VAR_TEMP
AR1_ALT : DWord; // Hilfsregister AR1
AR2_ALT : DWord; // Hilfsregister AR2
ZAEHLER : Int; // Hilfszähler für Schleifenbearbeitung
H_ZEIGER : Int; // Hilfszeiger für Schleifenbearbeitung
END_VAR


BEGIN
NETWORK
TITLE = Allgemein
U #RESET ;// Reset ?
SPB RESE;
UN #TAKT ;// keine Takt-Signal ?
BEB;
STRT: TAR1 #AR1_ALT ;// AR1 retten
TAR2 #AR2_ALT ;// AR2 retten

NETWORK
TITLE = Pointer berechnen
L 1440;
L #ZEIGER ;// Pointer auf Speicherzelle
>I ;// Letzte Zelle noch nicht beschrieben ?
SPB goon;
L 0 ;// Pointer löschen
goon: + 1 ;// Pointerwert + 1
T #ZEIGER ;// -> Pointer
L 4;
*I ;// Pointer * 4
+ 20 ;// + Offset Speicherbeginn
SLW 3 ;// -> Pointerformat
TAR2 ;// AR2 -> Akku 1
+D ;// AR2 + Pointer
LAR1 ;// -> AR1
L #ANZ_GES;
+ 1 ;// Anzahl gesamt + 1
T #ANZ_GES;
L 1440 ;// Soll = 1440
<I ;// 1440 Werte erreicht ?
SPB AnzK;
S #h24_VOLL ;// -> Meldung 1440 Werte erreicht
T #ANZ_GES ;// Anzahl gesamt auf 1440 begrenzen
AnzK: L #ANZ_KZW;
+ 1 ;// Anzahl KZW + 1
T #ANZ_KZW;
L #ZEIT ;// Vorgabezeit
<I ;// vorgegebene Anzahl erreicht ?
SPB nw3;
S #KZW_VOLL ;// -> Meldung Anzahl Kurzzeitwerte erreicht
L 1;
<I;
SPB Eint;
TAK;
Eint: T #ANZ_KZW ;// Anzahl KZW auf Vorgabe begrenzen

NETWORK
TITLE = Wert eintragen
nw3: L #MENGE ;// aktueller Mengenwert
T DID[ AR1, P#0.0] ;// -> Ringspeicher eintragen

NETWORK
TITLE = KZW aus der Summe der letzten n Werte berechnen (ANZ_KZW)
L 0.0;
T #KZW ;// KZW löschen
L #ZEIGER;
T #H_ZEIGER ;// Zeiger -> Hilfszeiger
L #ANZ_KZW ;// Vorbelegung Anzahl Durchläufe
SCHL1: T #ZAEHLER ;// Zähler aktualisieren
L DID[ AR1, P#0.0] ;// Wert aus Ringspeicher laden
L #KZW;
+R ;// zu KZW addieren
T #KZW ;// Summe in KZW ablegen
L #H_ZEIGER;
+ -1 ;// Hilfszeiger - 1
T #H_ZEIGER;
L 0;
>I ;// Hilfszeiger = 0 ?
SPB PNTR1;
L 1440;
T #H_ZEIGER ;// Hilfszeiger -> Speicherende
PNTR1: L #H_ZEIGER;
L 4;
*I ;// Hilfszeiger * 4
+ 20 ;// + Offset Speicherbeginn
SLW 3 ;// -> Pointerformat
TAR2 ;// AR2 -> Akku 1
+D ;// AR2 + Pointer
LAR1 ;// -> AR1
L #ZAEHLER ;// Zaehler -> Akku 1
LOOP SCHL1 ;// Akku 1 dekrementieren und Sprung

NETWORK
TITLE =
L #ZEIGER ;// Pointer laden
L 4;
*I ;// Pointer * 4
+ 20 ;// + Offset Speicherbeginn
SLW 3 ;// -> Pointerformat
TAR2 ;// AR2 -> Akku 1
+D ;// AR2 + Pointer
LAR1 ;// -> AR1
L 0.0;
T #h24 ;// 24h-Wert löschen
L #ZEIGER;
T #H_ZEIGER ;// Zeiger -> Hilfszeiger
L #ANZ_GES ;// Vorbelegung Anzahl Durchläufe
SCHL: T #ZAEHLER ;// Zähler aktualisieren
L DID[ AR1, P#0.0] ;// Wert aus Ringspeicher laden
L #h24;
+R ;// zu 24h-Wert addieren
T #h24 ;// Summe in 24h-Wert ablegen
L #H_ZEIGER;
+ -1 ;// Hilfszeiger - 1
T #H_ZEIGER;
L 0;
>I ;// Hilfszeiger = 0 ?
SPB PNTR2;
L 1440;
T #H_ZEIGER ;// Hilfszeiger -> Speicherende
PNTR2: L #H_ZEIGER;
L 4;
*I ;// Hilfszeiger * 4
+ 20 ;// + Offset Speicherbeginn
SLW 3 ;// -> Pointerformat
TAR2 ;// AR2 -> Akku 1
+D ;// AR2 + Pointer
LAR1 ;// -> AR1
L #ZAEHLER ;// Zaehler -> Akku 1
LOOP SCHL ;// Akku 1 dekrementieren und Sprung
LAR1 #AR1_ALT ;// AR1 zurückschreiben
LAR2 #AR2_ALT ;// AR2 zurückschreiben
BE ;// ENDE

NETWORK
TITLE = Anzahl KZW = SOLL
RESE: R #KZW_VOLL ;// Meldung "KZW voll" löschen
R #h24_VOLL ;// Meldung "h24 voll" löschen
L 0;
T #ANZ_KZW ;// Anzahl KZW löschen
T #ANZ_GES ;// Anzahl gesamt löschen
SPA STRT ;// -> Baustein bearbeiten

END_FUNCTION_BLOCK
 
ist doch bei ner Migration immer das selbe.

Entweder die Anlage/Maschine verstehen und komplett neu programmieren, oder den Originalcode identisch "nachprogrammieren", oder ne Mischung aus beidem ;)

Würde aber das AWL gern verstehen wollen was da läuft...

naja, da musst mal tiefer in die AWL-Pointerei einsteigen ;)

Oft muss man in 300er-AWL "pointern", da es keine andere Möglichkeit gibt, variabel auf Array-Elemente zuzugreifen. Bei 1500er-AWL geht das einfacher.
 
Zuletzt bearbeitet:
Programmiere das blos nicht 1:1 nach, vermutlich haut dir der TIA-AWL-Compiler den Code eh' um die Ohren. Z.B. einen Output rücklesen, ohne vorher was hineinzuschreiben (#ZEIGER) ...
FUNCTION_BLOCK "DAY"
(...)
VAR_OUTPUT
ZEIGER : Int; // interner Speicher-Pointer Umlaufspeicher
(...)
NETWORK
TITLE = Pointer berechnen
L 1440;
L #ZEIGER ;// Pointer auf Speicherzelle
>I ;// Letzte Zelle noch nicht beschrieben ?
Was da im Kommentar als "Pointer" bezeichnet ist, ist auch eigentlich kein Speicher-Pointer, sondern ein Index in ein Array (auch wenn der im Endeffekt auf was zeigt).

Durchdenke was der Code machen soll und programmiere das in SCL neu.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Ja das wäre das beste! Würde aber das AWL gern verstehen wollen was da läuft...
Dazu du wirst dich ein wenig reinknien müssen. Ich glaube kaum, dass dieses Thema exclusiv für dich noch einmal komplett aufbereitet wird. Zudem gibt es dazu massenhaft Literatur und Onlinehilfe. Du kannst natürlich konkrete Fragen stellen.
 
Hallo zusammen, hier habe ich das mal versucht es zu schreiben. Scheinbar läuft auch der Baustein. Würdet Ihr hier etwas anders bauen??

FUNCTION_BLOCK "Tag_Menge"
{ S7_Optimized_Access := 'TRUE' }
AUTHOR :
VERSION : 0.1
VAR_INPUT DB_SPECIFIC
Menge : Real;
END_VAR
VAR_INPUT
Takt : Bool;
Reset : Bool;
END_VAR
VAR_INPUT DB_SPECIFIC
Zeit : Int;
END_VAR

VAR_OUTPUT
Anz_KZW : Int;
KZW_voll : Bool;
Anz_h24 : Int;
h24_voll : Bool;
END_VAR
VAR_OUTPUT DB_SPECIFIC
KZW : Real;
h24 : Real;
END_VAR

VAR DB_SPECIFIC
KZW_Zähler : Int;
h24_Zähler : Int;
Messwert : Array[1..1440] of Real;
END_VAR
VAR
P_Trigger {InstructionName := 'R_TRIG'; LibVersion := '1.0'} : R_TRIG;
Datenbearbeitung { S7_SetPoint := 'True'} : Bool;
END_VAR

VAR_TEMP
Laufvariable_Speicher : Int;
Laufvariable_KZW : Int;
Laufvariable_24h : Int;
END_VAR


BEGIN
REGION Eingänge Einlesen
// Takt Einlesen und als Flanke Merken

#P_Trigger.CLK := #Takt;
#P_Trigger(CLK := #Takt,
Q => #Datenbearbeitung);


IF #Reset THEN
// Messwerte (KZW und 24h-Wert) zurücksetzen
#KZW_Zähler := 0;
#h24_Zähler := 0;
;
END_IF;


END_REGION

REGION Hauptschleife bei Flanke Positiv

// wenn positive Flanke "Daten schieben"...
IF #Datenbearbeitung THEN


REGION #KZW Zählen und auf Zeitwert begrenzen

// KZW Zähler zählen, berechnen und auf Zeit begrenzen
IF #KZW_Zähler < #Zeit THEN

// KZW_Zähler um einen Wert weiter Zählen
#KZW_Zähler := #KZW_Zähler + 1;
#KZW_voll := FALSE;
ELSE
// KZW Zähler ist voll
#KZW_voll := TRUE;
END_IF;

// KZW Zähler für den Ausgang
#Anz_KZW := #KZW_Zähler;

END_REGION

REGION #h24 zählen und auf Tageswert (1440) begrenzen

// 24h Zähler zählen, berechnen und auf Zeit begrenzen
IF #h24_Zähler < 1440 THEN

// KZW_Zähler um einen Wert weiter Zählen
#h24_Zähler := #h24_Zähler + 1;
#h24_voll := FALSE;
ELSE
// h24 Zähler ist voll
#h24_voll := TRUE;
END_IF;

// h24 Zähler für den Ausgang
#Anz_h24 := #h24_Zähler;

END_REGION


REGION Daten in DB Einlesen

// dann FOR-Schleife ausführen.
FOR #Laufvariable_Speicher := 1440 TO 2 BY -1 DO

// Registerplatz 1440 bis 2 mit Daten des vorherigen Platzes beschreiben
#Messwert[#Laufvariable_Speicher] := #Messwert[#Laufvariable_Speicher - 1];

END_FOR;

// nach Ablauf der FOR-Schleife -> Registerplatz 1 mit Quelldaten beschreiben
#Messwert[1] := #Menge;

END_REGION

REGION KZW aus Speicher lesen und berechnen

// KZW auf Null setzen
#KZW := 0.0;

// dann FOR-Schleife ausführen.
FOR #Laufvariable_KZW := 1 TO #"KZW_Zähler" BY +1 DO

// Registerplatz von Messwert 1 bis Zeit Ende auslesen und berechnen
#KZW := #KZW + #Messwert[#Laufvariable_KZW];

END_FOR;

END_REGION

REGION 24h Wert aus Speicher lesen und berechnen

// 24h auf Null setzen
#h24 := 0.0;

// dann FOR-Schleife ausführen.
FOR #Laufvariable_24h := 1 TO #h24_Zähler BY +1 DO

// Registerplatz von Messwert 1 bis Zeit Ende auslesen und berechnen
#h24 := #h24 + #Messwert[#Laufvariable_24h];

END_FOR;

END_REGION

;
END_IF;
END_REGION

END_FUNCTION_BLOCK
 
Benutz die Code Klammern im Symbolleiste bei weitere Optionen.
Dan ist es besser lesbar

Code:
FUNCTION_BLOCK "Tag_Menge"
{ S7_Optimized_Access := 'TRUE' }
AUTHOR :
VERSION : 0.1
VAR_INPUT DB_SPECIFIC
Menge : Real;
END_VAR
VAR_INPUT
Takt : Bool;
Reset : Bool;
END_VAR
VAR_INPUT DB_SPECIFIC
Zeit : Int;
END_VAR

VAR_OUTPUT
Anz_KZW : Int;
KZW_voll : Bool;
Anz_h24 : Int;
h24_voll : Bool;
END_VAR
VAR_OUTPUT DB_SPECIFIC
KZW : Real;
h24 : Real;
END_VAR

VAR DB_SPECIFIC
KZW_Zähler : Int;
h24_Zähler : Int;
Messwert : Array[1..1440] of Real;
END_VAR
VAR
P_Trigger {InstructionName := 'R_TRIG'; LibVersion := '1.0'} : R_TRIG;
Datenbearbeitung { S7_SetPoint := 'True'} : Bool;
END_VAR

VAR_TEMP
Laufvariable_Speicher : Int;
Laufvariable_KZW : Int;
Laufvariable_24h : Int;
END_VAR


BEGIN
REGION Eingänge Einlesen
// Takt Einlesen und als Flanke Merken

#P_Trigger.CLK := #Takt;
#P_Trigger(CLK := #Takt,
Q => #Datenbearbeitung);


IF #Reset THEN
// Messwerte (KZW und 24h-Wert) zurücksetzen
#KZW_Zähler := 0;
#h24_Zähler := 0;
;
END_IF;


END_REGION

REGION Hauptschleife bei Flanke Positiv

// wenn positive Flanke "Daten schieben"...
IF #Datenbearbeitung THEN


REGION #KZW Zählen und auf Zeitwert begrenzen

// KZW Zähler zählen, berechnen und auf Zeit begrenzen
IF #KZW_Zähler < #Zeit THEN

// KZW_Zähler um einen Wert weiter Zählen
#KZW_Zähler := #KZW_Zähler + 1;
#KZW_voll := FALSE;
ELSE
// KZW Zähler ist voll
#KZW_voll := TRUE;
END_IF;

// KZW Zähler für den Ausgang
#Anz_KZW := #KZW_Zähler;

END_REGION

REGION #h24 zählen und auf Tageswert (1440) begrenzen

// 24h Zähler zählen, berechnen und auf Zeit begrenzen
IF #h24_Zähler < 1440 THEN

// KZW_Zähler um einen Wert weiter Zählen
#h24_Zähler := #h24_Zähler + 1;
#h24_voll := FALSE;
ELSE
// h24 Zähler ist voll
#h24_voll := TRUE;
END_IF;

// h24 Zähler für den Ausgang
#Anz_h24 := #h24_Zähler;

END_REGION


REGION Daten in DB Einlesen

// dann FOR-Schleife ausführen.
FOR #Laufvariable_Speicher := 1440 TO 2 BY -1 DO

// Registerplatz 1440 bis 2 mit Daten des vorherigen Platzes beschreiben
#Messwert[#Laufvariable_Speicher] := #Messwert[#Laufvariable_Speicher - 1];

END_FOR;

// nach Ablauf der FOR-Schleife -> Registerplatz 1 mit Quelldaten beschreiben
#Messwert[1] := #Menge;

END_REGION

REGION KZW aus Speicher lesen und berechnen

// KZW auf Null setzen
#KZW := 0.0;

// dann FOR-Schleife ausführen.
FOR #Laufvariable_KZW := 1 TO #"KZW_Zähler" BY +1 DO

// Registerplatz von Messwert 1 bis Zeit Ende auslesen und berechnen
#KZW := #KZW + #Messwert[#Laufvariable_KZW];

END_FOR;

END_REGION

REGION 24h Wert aus Speicher lesen und berechnen

// 24h auf Null setzen
#h24 := 0.0;

// dann FOR-Schleife ausführen.
FOR #Laufvariable_24h := 1 TO #h24_Zähler BY +1 DO

// Registerplatz von Messwert 1 bis Zeit Ende auslesen und berechnen
#h24 := #h24 + #Messwert[#Laufvariable_24h];

END_FOR;

END_REGION

;
END_IF;
END_REGION

END_FUNCTION_BLOCK
 
Zurück
Oben