Step 7 Maximalwert eines Analogwertes ermitteln und mitloggen

Hmm, soviele Baustellen in Deinen verschiedenen Programmversionen...
Hier mal ein Beispielcode für 100 Messreihen.

Der Log-DB:
Code:
   0.0  STRUCT
  +0.0   Tab_Len : INT  := 100;            //Anzahl Werte in Tabelle = Anzahl Messreihen
  +2.0   Tab_Idx : INT  := 99;             //Index Tabellenplatz aktuelle Messreihe (0..99)
  +4.0   MaxWert : ARRAY [0 .. 99] OF      //Tabelle Maxwerte je Messreihe
  *4.0             REAL := 0.000000e+000;
=404.0  END_STRUCT ;

Der Log-FC Deklarationen:
Code:
VAR_INPUT
  IN_Messreihe_Aktiv : BOOL ;
  IN_Messwert : REAL ;
  IN_LogDBNr : INT ;
END_VAR
VAR_IN_OUT
  IO_FHM : BOOL ;	//Flankenhilfsmerker
END_VAR
VAR_TEMP
  tmp_DBNr : INT ;
  tmp_Tab_Ptr : DWORD ;
END_VAR
Der Log-FC Code:
Code:
      U     #IN_Messreihe_Aktiv
      FP    #IO_FHM                     //IN_OUT: Flankenhilfsmerker
      SPBN  Mlog

//Messreihe gerade gestartet
//Index auf nächsten Tabellenplatz in LogDB weiterstellen (Ringpuffer) ...
      L     #IN_LogDBNr
      T     #tmp_DBNr
      AUF   DB [#tmp_DBNr]
      L     DBW    2                    //[IN_LogDBNr].Tab_Idx: aktueller Platz (0..99)
      +     1                           //auf nächsten Platz weiterstellen
      L     DBW    0                    //[IN_LogDBNr].Tab_Len: Anzahl Tabellenplätze (100)
      MOD                               //auf 0..99 begrenzen
      T     DBW    2                    //[IN_LogDBNr].Tab_Idx: aktueller Platz (0..99) merken

      SLD   5                           //Index --> P#<Index * 4 Byte>.0  (für REAL-Tabelle)
      L     P#4.0                       //Offset Tabelle "MaxWert" im DB: +4.0
      +D                                //dazurechnen
      T     #tmp_Tab_Ptr                //Pointer in REAL-Tabelle

//... und geloggten Maxwert initialisieren
//      L     -3.402823e+038              //minimal möglicher REAL-Wert
      L     #IN_Messwert                //erster Messwert
      T     DBD [#tmp_Tab_Ptr]          //als MaxWert Anfangswert
      SPA   Mend


Mlog: U     #IN_Messreihe_Aktiv
      SPBN  Mend

//Adresse aktueller MaxWert[Index] ermitteln
      L     #IN_LogDBNr
      T     #tmp_DBNr
      AUF   DB [#tmp_DBNr]
      L     DBW    2                    //[IN_LogDBNr].Tab_Idx: aktueller Platz (0..99)
      SLD   5                           //Index --> P#<Index * 4 Byte>.0  (für REAL-Tabelle)
      L     P#4.0                       //Offset Tabelle "MaxWert" im DB: +4.0
      +D                                //dazurechnen
      T     #tmp_Tab_Ptr                //Pointer in REAL-Tabelle

//Messwert > bisheriger Maxwert?
      L     DBD [#tmp_Tab_Ptr]          //bisheriger MaxWert [IN_LogDBNr].MaxWert[Tab_Idx]
      L     #IN_Messwert
      <R                                //Messwert > bisheriger Maxwert?
      SPBN  Mend                        //nein --> nichts tun
      T     DBD [#tmp_Tab_Ptr]          //ja   --> als neuen Maxwert speichern

Mend: SET

Warum gibst Du eigentlich die DB-Nr variabel vor? Dadurch geht das ganze leider nicht mehr schön symbolisch.
Für die Referenzdaten ist es übrigens besser, wenn Du den DB als BLOCK_DB übergibst statt die DB-Nummer als INT.

Harald
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo PN/DP,
1000 Dank für deinen Programmcode!!!
Ich werde es sofot ausprobieren.. bin schon sehr gespannt.
Und ja, es war vielleicht eine nicht so gute Idee die DBNr. varaiabel vorzugeben.

DANKE!!!!
 
Hallo PN/DP,
ich habe soweit alles eingerichtet... den DB, FC und alle Deklarationen.
Zwei Fragen hätte ich da noch :
In der DB- Tabelle... sind die beiden Variablen Tab_Len und Tab_Idx mit dem Anfangswert vorbelegt ... quasi die 100 und die 99 in die Tabelle als Anfangswert eintragen, oder??
Worauf ich mir auch noch nicht 100 Prozentig einen Reihm bilden kann ist der erste Abschnitt des Programms:

AUF DB [#tmp_DBNr]
L DBW 2 //[IN_LogDBNr].Tab_Idx: aktueller Platz (0..99)
+ 1 //auf nächsten Platz weiterstellen
L DBW 0 //[IN_LogDBNr].Tab_Len: Anzahl Tabellenplätze (100)
MOD //auf 0..99 begrenzen
T DBW 2 //[IN_LogDBNr].Tab_Idx: aktueller Platz (0..99) merken

SLD 5 //Index --> P#<Index * 4 Byte>.0 (für REAL-Tabelle)
L P#4.0 //Offset Tabelle "MaxWert" im DB: +4.0
+D //dazurechnen
T #tmp_Tab_Ptr

Hier wird der DB geöffnet und dann werden aus dem DB die beiden Wörter Adresse 0.0 und 2.0 bzw die Intvariablen geladen....
Dann werden sie durch sich dividiert und der Rest wieder in 2.0 geladen....
Wenn ich das ganze Starte über "U #IN_Messreihe_Aktiv" wird der Maxwert in die erste Adresse eingetragen ... sonst passiert nichts. Auch wird nichts in Adresse 0.0 und 2.0 eingetragen.


Sorry, dass ich da noch nicht so fit bin und so viele Fragen stelle ... ich bin noch ziemlich am Anfang und das ist mein erstes Projekt in der Größenordnung.

Gruß
Rafael
 
Zuletzt bearbeitet:
In der DB- Tabelle... sind die beiden Variablen Tab_Len und Tab_Idx mit dem Anfangswert vorbelegt ... quasi die 100 und die 99 in die Tabelle als Anfangswert eintragen, oder??
Ja richtig. Die 100 und die 99 sind die Anfangswerte, mit denen auch der Aktualwert initialisiert sein muß. (DB Ansicht > Datensicht + Bearbeiten > Datenbaustein initialisieren)
Die Vorbelegung von Tab_Len ist wichtig und darf nicht größer als die tatsächliche Arraygröße sein. Du könntest auch statt der Variable im Programm eine konstante feste Größe eintragen. Die Verwendung der Variable macht das ganze aber universeller und leichter für andere Arraygrößen änderbar.
Die Vorbelegung von Tab_Idx ist optional, beim Start des Loggings wird geprüft, ob der Wert innerhalb des Arrays liegt (ob er 0 .. Tab_Len - 1 ist). Bei Vorbelegung mit 99 (Tab_Len - 1) beginnt das erste Logging freundlicherweise im ersten Array-Element.


Worauf ich mir auch noch nicht 100 Prozentig einen Reihm bilden kann ist der erste Abschnitt des Programms
Bei der steigenden Flanke von #IN_Messreihe_Aktiv (Start der Messreihe) wird gelesen, welcher Wert im Schreibindex Tab_Idx (DBW2) steht (von der Messreihe vorher), der Wert wird um 1 erhöht (auf das nächste Array-Element weitergestellt), und dann mittels MOD mit Tab_Len (DBW0) dafür gesorgt, daß der Index nur Werte von 0..99 (Tab_Len - 1) hat und in wieder Tab_Idx (DBW2) gespeichert (gemerkt für die Verwendung in dieser Messreihe).
Wenn bei dem Erhöhen ein Ergebnis größer Arraygröße rauskommt (>= Tab_Len), dann wird durch das MOD der Wert auf 0..99 "gemappt" und das Array wieder von unten her neu überschieben (Ringpuffer).

"SLD 5": zusammengefasst Multiplikation * 8 (um aus dem Index eine Byteadresse P#<Index>.0 zu machen) und weitere * 4 (weil es ein REAL-Array ist und ein REAL-Wert 4 Byte belegt)
Danach wird noch die Anfangsadresse des Arrays im DB dazuaddiert (+ P#4.0) --> ergibt die Adresse von [IN_LogDBNr].MaxWert[Tab_Idx]


Wenn ich das ganze Starte über "U #IN_Messreihe_Aktiv" wird der Maxwert in die erste Adresse eingetragen ... sonst passiert nichts. Auch wird nichts in Adresse 0.0 und 2.0 eingetragen.
Das DBW2 muß beim ersten Durchlauf mit #IN_Messreihe_Aktiv = TRUE verändert worden sein: das gerade oben beschriebene Weiterstellen um 1 auf das nächste Array-Element.

Solange #IN_Messreihe_Aktiv = TRUE ist wird bei jedem Durchlauf geprüft, ob der #IN_Messwert größer als der bisher in [IN_LogDBNr].MaxWert[Tab_Idx] gespeicherte Wert ist und ggf. in [IN_LogDBNr].MaxWert[Tab_Idx] geschrieben.

Du mußt nun von außen dafür sorgen, daß #IN_Messreihe_Aktiv genau so lange TRUE ist wie Deine Messreihe andauert. Danach muß #IN_Messreihe_Aktiv FALSE werden und bei der nächsten Messreihe wieder TRUE --> dadurch wird wie beschrieben Tab_Idx auf das nächste Array-Element weitergestellt und der MaxWert der nächsten Messreihe mitgeloggt.

Spiele mal mit Deiner Variable, welche Du an #IN_Messreihe_Aktiv angegeben hast (0, 1, 0, 1 ...) und beobachte Tab_Idx. Dann spiele mit dem Messwert bei aktivem #IN_Messreihe_Aktiv und beobachte [IN_LogDBNr].MaxWert[Tab_Idx].

Harald
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo Harald, :D
wow!! 1000 Dank für die schnelle und vor allem ausführliche Erläuterung. Ich habe alles verstanden und richtig was dazu gelernt!!! DANKE !!.... UND diese Lösung ist wirklich klasse!!!!!:D
Der Fehler, den ich natürlich gemacht habe, waren die Anfangswerte von Tab_Len und Tab_Idx in dem DB. Die standen natürlich noch auf "0". Ich hatte den Datenbaustein auch noch nicht initialisiert.
Was ich auch noch anpassen musste war der Array- Wert. Diesen habe ich auf ARRAY [0..100] gesetzt... mit ARRAY [0..99] stieg die SPS immer mit dem Eintrag des 99ten Wertes aus da der Tab_Len Wert größer war und das Programm wahrscheinlich einen Messwert in die Zeile 100 in der Tabelle schreiben wollte, die nicht da war... denke ich.
Nun läuft es!

Gruß
Rafael
 
Zurück
Oben