Step 7 Problem REAL-Werte kontinuierlich in ARRAY speichern

DocSnyda

New member
Beiträge
3
Punkte Reaktionen
0
Zuviel Werbung?
->Hier kostenlos registrieren
Hallo zusammen,

Ich programmiere gerade eine alte 315-2-DP mit TIA-Portal v.11 (STEP 7 Prof.) in AWL und kommen an einem Problem nicht weiter. Ich bin neu in der Simatic Welt und habe schon vieles hier gelesen und versucht das Problem zu lösen. Leider komme ich an dieser Stelle seit Tagen nicht weiter.

Ich möchte Analogwerte einer Spannungsmessung im 1s Takt fortlaufend in einem Array speichern und zu einem bestimmten Zeitpunkt (ausgelöst durch einen Näherungssensor), den Mittelwert dieses Arrays auswerten.

Ich bin schon in der lage im 1s Takt die Werte aus dem Analogeingang als WORD, durch Auswertung einer pos. Flanke, fortlaufend im Array zu speichern, ohne eine Fehlermeldung o.ä. zu bekommen.

Desweiteren funktioniert auch die Analogwert-Skalierung mit der Funktion "SCALE".

Leider bekomme ich es nicht hin, dass mir der Analogwert zuerst in einen REAL-Wert zwischengespeichert und anschließend fortlaufend ins Array geschrieben wird.

Es scheint als würde die CPU nach dem ersten SCALE nicht mehr weiter arbeiten, da mir der erste Wert ins Array geschrieben wird und der Index noch inkrementiert wird, dann aber nichts weiter passiert.

Ich hab nun versucht zuerst das WORD aus dem Analogeingang in eine DB zu schreiben, um dann anschließend diese Werte zu skalieren und in eine weitere DB zu schreiben. Dabei tritt leider das selbe Problem auf, es wird der erste Werte in die DB geschrieben und dann passiert nichts mehr, obwohl ich sehen kann, dass der Taktgeber noch weiter arbeitet.

Wenn ich nun den unteren Teil mit der Skalierung heraus nehme, funktioniert alles einwandfrei.

// Auswertung pos. Flanke

U "Taktzyklus"
FP "Merker_Flanke"
= "Trigger"

// WORD fortlaufend in Array speichern bis Array voll

L "Index"
L 500
>I
= "Merker_Vergleich"
U "Merker_Vergleich"
SPB ENDE

UN "Trigger"
SPB ENDE

L "Index" //Index der Sprungadresse
SLD 3
LAR1
L "Messwert":p
AUF "Datenbaustein_1"
T DBW [ AR1 , P#0.0 ]

L "Index"
L 2
+I
T "Index"
ENDE: R "Trigger"

// MB2 mit der Zahl 0 füllen

U "Sensor_1"
SPBNB Label_0
L 0
T "DUMMY"
CALL FILL
BVAL :=P#M2.0 BYTE 1
RET_VAL :="RET_VAL_FILL"
BLK :="Index"
Label_0 : NOP 0

// Werte aus dem WORD Array in REAL skalieren und in einer anderen DB speichern

L 1
T "Unsigned_Byte"

L "Datenbaustein_1".Transmission[0]
T "Word_to_INT"

U "Unsigned_Bit"
= %L20.0
BLD 103
CALL SCALE
IN :="Word_to_INT"
HI_LIM :=0.08
LO_LIM :=0.0
BIPOLAR :=%L20.0
RET_VAL :="RET_VAL_SCALE"
OUT :="Datenbaustein_2".Ergebnis[0]

Habt ihr eine Idee wie ich dieses Problem lösen könnte ?

Danke schonmal.

Viele Grüße,
Doc
 
Zuletzt bearbeitet:

PN/DP

User des Jahres 2011-2013; 2015-2017; 2020-2021
Beiträge
17.562
Punkte Reaktionen
5.166
Kann es sein, daß Dein Signal vom "Sensor_1" gleich wieder 0 wird und Dein Programm deshalb "Index" immer wieder löscht? Verwende ggf. einen zusätzlichen "Freigabe_Speichern" Merker.
Das Setzen des Index auf 0 muß man nicht so umständlich mit FILL machen, man kann einfach eine 0 in die Variable schreiben.
Ich würde nicht den "Index" Adress-weise inkrementieren (+2 Byte), sondern unabhängig vom Array-Datentyp immer nur Element-weise +1
Daß der Index in ein WORD- oder DWORD- oder REAL-Array zeigt, erst bei der Adressberechnung berücksichtigen.
Code:
U "Sensor_1" //oder "Freigabe_Speichern"
FP "FPM_Start_speichern" //Flankenmerker
SPBNB Label_0
L 0
T "Index"
Label_0 : NOP 0

U "Taktzyklus" //1s Takt
FP "Merker_Flanke"
U "Freigabe_Speichern"
= "Trigger" //1 Zyklus langer Impuls

U(
L "Index"
L 250 //Anzahl Einträge im Array, z.B. ARRAY[0..249] OF WORD (oder REAL)
<I
)
U "Trigger"
SPBN ENDE

//Wert in nächstes Array-Element (Array-Platz) speichern
L "Index" //0..249
+ 1
T "Index"
+ -1
SLD 3 //Index --> P#<Index>.0
SLD 1 //*2 bei WORD / SLD 2 = *4 bei REAL oder DWORD
L P#0.0 //Anfangsadresse des Arrays im Array-DB
+D //dazu rechnen
LAR1
L "Messwert":P  //WORD
AUF "Datenbaustein_1" //Array-DB
T DBW [ AR1 , P#0.0 ] //oder "DBD" bei REAL/DWORD

ENDE: CLR  //(CLR ist besser als "NOP 0")

// Werte aus dem Array in einen anderen DB speichern
...

Deine Kommentare sind oft nichtssagend und falsch und irreführend. (PS: OK, hast Du jetzt teilweise korrigiert)
Der Wert aus dem Analogeingang ist kein DWORD (32 Bit) sondern ein WORD (16 Bit)
Dein Array ist kein DWORD-Array sondern ein WORD-Array
"MB2 mit der Zahl 0 füllen" - das muß man nicht mit diesen Worten "kommentieren"

Weil es anscheinend nur 250 Werte sind, würde ich zuerst den Analogwert skalieren und die skalierten REAL-Werte im Array speichern. Das läßt sich besser beobachten und einfacher weiterverarbeiten.

Harald
 
OP
D

DocSnyda

New member
Beiträge
3
Punkte Reaktionen
0
Zuviel Werbung?
->Hier kostenlos registrieren
Vielen Dank Harald für deine Mühe, die wertvollen Tipps und deinen Code.

Der Code funktioniert soweit gut, so wie du ihn geschrieben hast. Allerdings habe ich hier genau dasselbe Problem, sobald ich den SCALE Baustein einfüge und direkt REAL Werte einspeichern möchte. Der Index bleibt dann nämlioch 0 und es wird nur der erste REAL-Wert in die DB eingespeichert. Ich kann auch beobachten, wie sich die Variable Skal_Messwert geringfügig ändert (durch vorhandene Spannungsschwankungen), aber der Index dauerhaft bei 0 bleibt.

Ich vermute das ich irgendwas mit dem SCALE-Baustein falsch gemacht habe.


Code:
U "Sensor_1" //oder "Freigabe_Speichern"
FP "FPM_Start_speichern" //Flankenmerker
SPBNB Label_0
L 0
T "Index"
Label_0 : NOP 0

U "Taktzyklus" //1s Takt
FP "Merker_Flanke"
U "Freigabe_Speichern"
= "Trigger" //1 Zyklus langer Impuls

U(
L "Index"
L 250 //Anzahl Einträge im Array, z.B. ARRAY[0..249] OF WORD (oder REAL)
<I
)
U "Trigger"
SPBN ENDE

//Wert in nächstes Array-Element (Array-Platz) speichern
L "Index" //0..249
+ 1
T "Index"
+ -1
SLD 3 //Index --> P#<Index>.0
SLD 1 //*2 bei WORD / SLD 2 = *4 bei REAL oder DWORD
L P#0.0 //Anfangsadresse des Arrays im Array-DB
+D //dazu rechnen
LAR1

[COLOR=#ff0000]      L     1
      T     "Unsigned_Byte"
      U     "Unsigned_Bit"
      =     %L20.0
      BLD   103
      CALL  SCALE
         IN      :="Messwert":P
         HI_LIM  :=0.08
         LO_LIM  :=0.0
         BIPOLAR :=%L20.0
         RET_VAL :="RET_VAL_SCALE"
         OUT     :="Skal_Messwert"[/COLOR]

L [COLOR=#ff0000]"Skal_Messwert"[/COLOR]  //WORD
AUF [COLOR=#ff0000]"Datenbaustein_2"[/COLOR] //Array-DB (REAL DB)
T DB[COLOR=#ff0000]D[/COLOR] [ AR1 , P#0.0 ] //oder "DBD" bei REAL/DWORD

ENDE: CLR  //(CLR ist besser als "NOP 0")

// Werte aus dem Array in einen anderen DB speichern
...

Danke schonmal.

Viele Grüße,
Doc
 

PN/DP

User des Jahres 2011-2013; 2015-2017; 2020-2021
Beiträge
17.562
Punkte Reaktionen
5.166
Hast Du vielleicht Adress-Überschneidungen von "Index" mit Deinen Variablen "Unsigned_Byte", "Unsigned_Bit", "RET_VAL_SCALE" oder "Skal_Messwert"?
Lege mal die nur temporär benötigten Variablen in TEMP:
* RET_VAL_SCALE : WORD
* Skal_Messwert : REAL

Code:
...
U(
L "Index"
L 250 //Anzahl Einträge im Array, z.B. ARRAY[0..249] OF [COLOR="#0000FF"]REAL[/COLOR]
<I
)
U "Trigger"
SPBN ENDE

//Wert holen und in REAL wandeln
CALL  SCALE
 IN      :="Messwert":P
 HI_LIM  :=0.08
 LO_LIM  :=0.0
 BIPOLAR :=[COLOR="#0000FF"]true[/COLOR]
 RET_VAL :=[COLOR="#0000FF"]#RET_VAL_SCALE[/COLOR]
 OUT     :=[COLOR="#0000FF"]#Skal_Messwert[/COLOR]

//Wert in nächstes Array-Element (Array-Platz) speichern
L "Index" //0..249
+ 1
T "Index"
+ -1
SLD 3 //Index --> P#<Index>.0
SLD [COLOR="#0000FF"]2[/COLOR] //*2 bei WORD / SLD 2 = *4 bei REAL oder DWORD
L P#0.0 //Anfangsadresse des Arrays im Array-DB
+D //dazu rechnen
LAR1

L [COLOR="#0000FF"]#Skal_Messwert[/COLOR]  //[COLOR="#0000FF"]REAL[/COLOR]
AUF "Datenbaustein_2" //Array-DB (REAL DB)
T [COLOR="#0000FF"]DBD[/COLOR] [ AR1 , P#0.0 ]

ENDE: CLR  //(CLR ist besser als "NOP 0")

// Werte aus dem Array in einen anderen DB speichern
...

Harald
 
OP
D

DocSnyda

New member
Beiträge
3
Punkte Reaktionen
0
Hast Du vielleicht Adress-Überschneidungen von "Index" mit Deinen Variablen "Unsigned_Byte", "Unsigned_Bit", "RET_VAL_SCALE" oder "Skal_Messwert"?

Es hat funktioniert. Ich weiß zwar nicht wie ich die Variablen temporär anlege, weil er mit beim einsetzen von #RET_VAL_SCALE eine Fehlermeldung rausgegeben hat. Ich glaube aber es lag an einer Adress-Überschneidung, weil der Index im MW101 und Return-Wert der SCALE Funktion in MW 102 gespeichert wurde. Wenn ich es richtig verstanden habe, dann ist das Index "WORD" in MW101 genau 2 Byte lang und überschneidet sich mit dem MW102 ? Jedenfalls funktioniert es korrekt, nachdem ich die Variable RET_VAL_SCALE in MW103 geändert habe.

Vielen Dank für die Hilfe und noch einen schönen Tag.

VG,
Doc
 

PN/DP

User des Jahres 2011-2013; 2015-2017; 2020-2021
Beiträge
17.562
Punkte Reaktionen
5.166
Ich weiß zwar nicht wie ich die Variablen temporär anlege, weil er mit beim einsetzen von #RET_VAL_SCALE eine Fehlermeldung rausgegeben hat.
Laß bei der Deklaration im Bausteinkopf (im Temp-Bereich) das # vor dem Variablen-Name weg, so wie ich in #4 geschrieben hatte (also nur: RET_VAL_SCALE : Word)
Bei der Verwendung der lokalen/TEMP-Variablen wird dann automatisch das # vor den Variablenname gesetzt als Hinweis, daß es eine lokale Variable des Bausteins ist und nicht eine globale PLC-Variable.

Wenn ich es richtig verstanden habe, dann ist das Index "WORD" in MW101 genau 2 Byte lang und überschneidet sich mit dem MW102 ?
Ja, genauso ist das. Deshalb die Regel: WORDs und DWORDs und REALs auf geraden, durch 2 bzw. 4 teilbaren Adressen anzulegen (so wie auch der DB-Editor die Adressen vergibt):
- MW100
- MW102
- MD104
- MD108
- MW112
- MW114
...

Harald
 
Oben