Step 7 Probleme mit Loop und globalen DBs

Noebsi

Level-2
Beiträge
25
Reaktionspunkte
1
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo!

Ich bin neu auf dem Forum hier und generell auch in der SPS Programmierung.
Da ich mit KOP, FUP und SCL einigermaßen klar komme, wollte ich mich hier einmal an AWL versuchen.

Das ganze läuft in der Simulierung auf einer 300er CPU und ich programmiere im Simatic Manager.
Das Programm habe ich zuvor in gleicher Weiße in SCL funktionierend geschrieben.
Jedoch stoppt mir dieses Programm die CPU nach ein par Sekunden.
Wenn ich nun wie unten angegeben diese 3 Zeilen aus kommentiere, läuft das Programm zumindest durchgehend ohne Abbruch.

Außerdem bekomme ich seltsame Werte in meine REAL Arrays in den Datenbausteinen, wenn ich verkürzt versuche diese zu schreiben.

Das Programm soll mir Werte von IN auf meinen globalen DB1 ins Array[0..10] schreiben und das jede Sekunde einmal mithilfe des Eingang M0.5=TAKT machen.
Außerdem sollen im Anschluss jede Sekunde die Werte von DB1 genommen und in meinen globalen DB2 ins Array[0..10] umgedreht (unten nach oben) geschrieben werden.
--> In DB2 alle auf einmal, deswegen LOOP.
--> DB1 Soll jedoch nur jeden Durchlauf einmal Daten schreiben

Im Internet und in der HilfeDoku finde ich nicht heraus warum mein Programm fehlerhaft ist und auf Papier Zeile nach Zeile durchgegangen klingt es auch korrekt.

Könnte mir hier bitte jemand mit etwas mehr Erfahrung in der AWL Programmierung helfen?

Bg
Noebsi

Code:
      U     #TAKT
      UN    #sFlankenMerker
      =     #sPosFlanke                 //Taktprüfer
      U     #sPosFlanke
      SPB   THEN                        //Bei positiver Flanke wird gearbeitet
      SPA   ELSE                        //Sonst übergeht SPB Befehl undspringt hier absolut zu ELSE
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
THEN: AUF   "DB_DATA"                   //Arbeite in DB1
      L     #tZaehler
      SLD   3
      LAR1                              //Schiebe AKKU1(Zähler) ins Adressregister
      L     #IN
      T     DBB [AR1,P#0.0]             //Schreibe AKKU1(IN) auf Byte AR1(Zähler) der offenen Datenbank(DB1)
      L     40                          //Lade den Wert 40 in AKKU1 (Weil 0-10 ArrayMember mit je 4 Byte)
//DBZw:
      T     #tDB2Counter                //Schreibe den Wert von AKKU1 auf den DB2Counter (Quasi DB2Counter := 40 TO 0 BY -4)
      L     #tDB2Counter
      L     3                           //Lade 3 in AKKU1 --> alter AKKU1 wird zu AKKU2 --> AK1=3, AK2=DB2Counter
      ==D                               //TRUE wenn AKKU1 und AKKU2 gleich sind
      SPB   LETZ
      SPA   NORM                        //Wenn SPB nicht TRUE war dann springe absolut auf NORM
LETZ: L     #tDB2Counter
      +     -3
      T     #tDB2Counter                //Da letzter Durchlauf, subtrahiere 3 von DB2Counter damit DB2Counter = 0 wird
NORM: AUF   "DB_DATA"                   //Öffne sicherheitshalber nochmals DB1
      L     #tForZaehler
      SLD   3
      LAR1                              //Schiebe AKKU1(Schleifenzähler) ins Adressregister
      L     DBB [AR1,P#0.0]             //Lade den Wert von Byte AR1(Schleifenzähler) der offenen Datenbank (DB1) auf AKKU1
      T     #tSave                      //Schreibe den Wert von AKKU1(DB1.DATA[Schleifenzähler]) auf einen Zwischenspeicher
      AUF   "DB_DATA_REVERSE"           //Arbeite in DB2
      L     #tDB2Counter
      SLD   3
      LAR1                              //Schiebe AKKU1(DB2Counter) ins Adressregister
      L     #tSave
      T     DBB [AR1,P#0.0]             //Schreibe von AKKU1(Zwischenspeicher) auf Byte AR1(DB2Counter) der offenen Datenbank(DB2)
      L     #tForZaehler
      +     4                           //Addiere zu AKKU1(Schleifenzähler) 4 dazu --> Schleifenzähler += 4 (4 Byte Sprünge im Array, da REAL Werte)
      T     #tForZaehler
      L     #tDB2Counter
      L     4
      <=D
      SPB   LAST                        //Vergleiche ob DB2Counter<=4 ist, da dann letzter Durchlauf ist/folgt
      L     #tDB2Counter
      +     -3
      T     #tDB2Counter                //Schreibe den Wert von AKKU1 in den DB2Counter (=DB2Counter-3, nur-3 da LOOP automatisch-1 von AKKU1 abzieht)
LAST: L     #tDB2Counter
      L     0
      ==D                               //Wenn Letzter Durchlauf Sprung, prüfe ob bereits gewesen(=0) oder noch kommt(=4)
      SPB   EINS
      SPA   NULL
EINS: L     1                           //Schreibe 1 in DB2Counter wenn DB2Counter = 0, damit Loop nicht 0-1 rechnet
      T     #tDB2Counter
NULL: L     #tDB2Counter
//      LOOP  DBZw                        //Ziehe 1 von AKKU1 ab und springe zu DBZw wenn AKKU1 <> 0
      L     0
      T     #tForZaehler                //Setze Schleifenzähler nach Schleife zurück
      L     #tZaehler
      +     4
      T     #tZaehler                   //Zähle einen Durchlauf auf
      L     44                          //Lade 44 in AKKU1 --> alter AKKU1 wird zu AKKU2 --> AK1=44, AK2=Zähler
//      ==D                               //TRUE wenn AKKU1 und AKKU2 gleich sind --> Datenbaustein voll
      SPB   FULL
      SPA   ELSE                        //Wenn DB1 nicht voll dann gehe normal weiter
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
FULL: L     0
      T     #tZaehler                   //Setze Zähler zurück, wenn Datenbaustein voll
ELSE: U     #TAKT
      SPB   EIN
      R     #sFlankenMerker             //Resete den Flankenmerker
      SPA   ENDE                        //Wenn TAKT FALSE wird SPB übergangen und absolut auf AUS gesprungen
EIN:  S     #sFlankenMerker             //Setze den Flankenmerker
      SPA   ENDE
ENDE: L     0
 
Zuletzt bearbeitet von einem Moderator:
Hallo
dein Löschen deiner Frage ist sehr schlechtes Benehmen. Jetzt habe ich so viel Zeit geopfert, um dir eine Antwort zu schreiben, jetzt poste ich die auch...

Deine Aufgabenbeschreibung klingt ziemlich verworren und schwer verstehbar, eventuell sieht dein Code im Detail auch deshalb so verworren aus?

Warum geht die CPU in STOP? Zykluszeit-Überschreitung, Zugriffsfehler bei Lesen oder Schreiben, ...?
Warum kopierst du umständlich byteweise, sind in den Array nicht REALs drin? REAL kann man viel einfacher als Doppelwort auf einmal anfassen/kopieren.
Ist dein Programmcode in einem FC oder einem FB?
Liegt tZaehler in TEMP? TEMP-Speicher kann sich nichts bis zum nächsten Programmdurchlauf merken.
Beachte: der CPU-Taktmerker M0.5 ändert sich azyklisch zum OB1, der darf nur einmal im Zyklus abgefagt werden. Beim zweiten Lesen kann ein anderer Wert drin sein als beim ersten Lesen.
Bits/BOOLs kopiert man mit U Bit / = Kopie, und nicht so verschwurbelt mit IF Bit THEN S Kopie ELSE R Kopie
DB heißt nicht "Datenbank" sondern "Datenbaustein"
...

Ich versuche mal zusammenzufassen, was du vermutlich gemeint haben könntest:
Du hast zwei Arrays
• DB1 "DB_DATA" mit einem Array_1 [0..10] OF REAL //11 REAL Werte
• DB2 "DB_DATA_REVERSE" mit einem Array_2 [0..10] OF REAL //11 REAL Werte

Das Array_1 ist ein Ringpuffer? Neue Werte werden immer ans aktuelle Ende geschrieben? Oder soll der aktuelle Inhalt um eine Stelle nach vorn (zu Index 0) verschoben werden und der neue Wert immer bei Index 10 geschrieben werden?

Du willst jede Sekunde einen neuen Wert in das Array_1 schreiben, und danach das Array_1 in umgekehrter Reihenfolge in Array_2 kopieren?
 
Zurück
Oben