Ringpuffer mit Mittelwert

taucherd

Level-2
Beiträge
61
Reaktionspunkte
4
Zuviel Werbung?
-> Hier kostenlos registrieren
Habe diverse Programmteile vom Forum zu einem Ringpuffer zusammengefügt. Soweit funktioniert es ja aber es gibt ein Problem.
den Datenanfang beim Abspeichern: dieser wird im NW4 erst aktualisiert wenn das Datenende erreicht wurde.
Habe es schon mit einer Schleife versucht, aber irgendwie .....

Es gibt sicher eine Lösung dafür, aber leider gelingt es mir nicht.
habe das Programm hinzugefügt, danke.

Schön langsam wird es mit den Pointern :-D
 
Zuletzt bearbeitet:
Habe kurz mal dein Programm überflogen...
Warum Bildest du dir immer einen Pointer mit SLD 3 und dann Speicherst das ab damit du Speicherindirekt adressieren kannst?

zb:
Code:
      T     #Index               
      SLD   3                       
      T     #Ind_pointer                // Pointer-Adresse
      L     #Real_IN
      T     DBD [#Ind_pointer]         //Das ist eine speicherindirekte adressierung! Du greifst auf das Byte zu das in deiner Variable Ind_pointer steht!

das sollte so sein:

Code:
      T     #Index               
      SLD   3 
      LAR 1               
      L     #Real_IN
      T     DBD [AR1,P#0.0] //Das ist eine Adressregister indirekte adressierung! Du greifst auf die Adresse zu die im AR 1 steht mit dem Offset 0.0!
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Habe kurz mal dein Programm überflogen...
Warum Bildest du dir immer einen Pointer mit SLD 3 und dann Speicherst das ab damit du Speicherindirekt adressieren kannst?

zb:
Code:
      T     #Index               
      SLD   3                       
      T     #Ind_pointer                // Pointer-Adresse
      L     #Real_IN
      T     DBD [#Ind_pointer]         //Das ist eine speicherindirekte adressierung! Du greifst auf das Byte zu das in deiner Variable Ind_pointer steht!

das sollte so sein:

Code:
      T     #Index               
      SLD   3 
      LAR 1               
      L     #Real_IN
      T     DBD [AR1,P#0.0] //Das ist eine Adressregister indirekte adressierung! Du greifst auf die Adresse zu die im AR 1 steht mit dem Offset 0.0!

________________________________________
Wenn der Pointer für den Speicherort nicht indirekt generiert wird, dann wird immer bei der Adresse 0 begonnen und ich möchte aber sagen von wo der Speicherbereich beginnt wo die Daten abgespeichert werden. möchte mit einem DB mehrere Mittelwertbildungen abdecken.

Der Index arbeitet schon noch richtig aber der Pointer beginnt trotzdem bei Adresse 0!
 
________________________________________
Wenn der Pointer für den Speicherort nicht indirekt generiert wird, dann wird immer bei der Adresse 0 begonnen und ich möchte aber sagen von wo der Speicherbereich beginnt wo die Daten abgespeichert werden. möchte mit einem DB mehrere Mittelwertbildungen abdecken.

Der Index arbeitet schon noch richtig aber der Pointer beginnt trotzdem bei Adresse 0!

Hast du die Kommentare gelesen und verstanden die ich bei den Beispielen dazugeschrieben habe?
 
Hast du die Kommentare gelesen und verstanden die ich bei den Beispielen dazugeschrieben habe?


OK, das stimmt - aber ich brauche den offset mit null nicht! oder ich habe es nicht verstanden?
das behebt das problem auch nicht - leider!;)
den bei einem neustart, wenn im Index_Ringspeicher 0 drinnen steht und ich sage die daten beginnen bei adresse 100 dann wird der db von adresse 0 - 100 genauso mit dem real_in wert überschrieben.
und ganu das möchte ich verhindern, da ich mit einem zweiten fc auf diesen bereich schreibe und zugreife.

Offset: P#100.0 beginnt der Pointer natürlich bei 100.0.
jetzt gebe ich bei datenanfang die adresse 200 an und der speicherort ist bei 300 und der mittelwert wird ab 200 gebildet?
 
Zuletzt bearbeitet:
Zuviel Werbung?
-> Hier kostenlos registrieren
habe dein programm jetz nicht angesehen, muss hier grad erst alles neu installieren auf der neuen mühle....

aber nur zum thema mittelwerbildung eine kleine anregung:

M=LM+((Z-LM)/N)

M=Mittelwert
LM=Letzter Mittelwert
Z=Messwert
N=Anzahl der Messungen

man spart dadurch rechenzeit und mem da ich nur den letzten mittelwert (LM) und die anzahl der messungen (N) speichern muss (aus dem buch "c für die automatisierungstechnik")

mfg, harry

vielleicht machst du die sache zu kompliziert?

habe mit einen schönen fc gemacht der mir mittel, min und max wert ausgibt und eingänge für trigger und reset hat - aber leider komme ich da gerade nicht dran...
 
habe dein programm jetz nicht angesehen, muss hier grad erst alles neu installieren auf der neuen mühle....

aber nur zum thema mittelwerbildung eine kleine anregung:



vielleicht machst du die sache zu kompliziert?

habe mit einen schönen fc gemacht der mir mittel, min und max wert ausgibt und eingänge für trigger und reset hat - aber leider komme ich da gerade nicht dran...

Ist das nicht eine "Signalglättung" ,ein schöner Einzweiler.
beim anfahren der anlage braucht es ewig bis der wirkliche mittelwert erreicht ist, wenn die anzahl zu hoch ist, oder?
aber ich werde es nochmals ansehen - danke
 
Dein Index_Ringspeicher sollte eine IN_OUT Variable sein.
Den Offset von deinem Pointer könntest du auch von Außen über eine IN Variable angeben.

zb:
L #Index
L #Offset_Index
+D
SLD 3
LAR 1
L #Real_IN
T DBD [AR1,P#0.0]
 
Zuviel Werbung?
-> Hier kostenlos registrieren
ein paar bausteine die dir weiterhelfen findest du auf meiner hp im download unter sps/s7
guckst du mal filo_lifo.zip und db_auswerten.zip


 
Habe diverse Programmteile vom Forum zu einem Ringpuffer zusammengefügt. Soweit funktioniert es ja aber es gibt ein Problem.

Wenn Du nicht unbedingt mit einem Ringpuffer arbeiten musst, dann helfen Dir vielleicht die beiden folgenden Bausteine weiter.

Der FC100 FILO liest Werte im Datenformat REAL ein und speichert die Werte in einem DB:

Code:
FUNCTION FC 100 : INT
TITLE =FILO-Speicher
AUTHOR : KAI
FAMILY : SPSFORUM
NAME : FILO
VERSION : 1.0
 
VAR_INPUT
  SPEICHER : POINTER ;  
  LAENGE : INT ;    
  WERT : REAL ; 
END_VAR
VAR_TEMP
  DB_REGISTER : WORD ;  
  AR1_REGISTER : DWORD ;    
  DB_NUMMER : WORD ;    
  BEREICHSZEIGER : DWORD ;  
  ZWISCHENWERT : REAL ; 
  SCHLEIFE : INT ;  
  ZAEHLER : REAL ;  
END_VAR
BEGIN
NETWORK
TITLE =DB-Register und Adressregister AR1 sichern
 
      L     DBNO; // DB-Register
      T     #DB_REGISTER; 
 
      TAR1  #AR1_REGISTER; // AR1-Register
 
NETWORK
TITLE =FILO-Speicher
 
      L     P##SPEICHER; // POINTER
      LAR1  ; 
 
      L     W [AR1,P#0.0]; // DB-Nummer
      T     #DB_NUMMER; 
 
      AUF   DB [#DB_NUMMER]; 
 
      L     D [AR1,P#2.0]; // Bereichszeiger
      LAR1  ; 
 
      L     #WERT; // Wert
      T     #ZWISCHENWERT; // Wert => Zwischenwert
 
      L     #LAENGE; // Länge
M01:  T     #SCHLEIFE; // Schleife
 
      L     D [AR1,P#0.0]; // Wert
      L     #ZWISCHENWERT; // Zwischenwert
      T     D [AR1,P#0.0]; // Zwischenwert => Wert
      TAK   ; 
      T     #ZWISCHENWERT; // Wert => Zwischenwert 
 
      L     P#4.0; 
      +AR1  ; 
 
      L     #SCHLEIFE; // Schleife
      LOOP  M01; 
 
NETWORK
TITLE =DB-Register und Adressregister AR1 wiederherstellen
 
      AUF   DB [#DB_REGISTER]; // DB-Register
 
      LAR1  #AR1_REGISTER; // AR1-Register
 
END_FUNCTION

Der FC110 MITTELWERT bildet aus den im DB gespeicherten Werten einen Mittelwert im Datenformat REAL nach folgender Formel:

M = LM + ( (Z - LM ) / N)

M = Mittelwert
LM = Letzter Mittelwert
Z = Messwert
N = Anzahl der Messungen

Code:
FUNCTION FC 110 : INT
TITLE =Mittelwert
//Mittelwert
//
//M = LM + ((Z - LM) / N)
//
//M  = Mittelwert
//LM = Letzter Mittelwert
//Z  = Wert
//N  = Anzahl Werte
//   
//Beispiel:
// 
//Man hat einen Mittelwert, der aus 10 Werten gebildet wird. Wenn jetzt ein 
//neue Wert dazu addiert wird, hat man 11 Werte. Also muss 1/10 des
//Mittelwertes subtrahiert werden, damit man insgesamt wieder 10 Werte hat.
//   
AUTHOR : KAI
FAMILY : SPSFORUM
NAME : FILO
VERSION : 1.0
 
VAR_INPUT
  SPEICHER : POINTER ;    
  LAENGE : INT ;    
END_VAR
VAR_OUTPUT
  MITTELWERT : REAL ;   
END_VAR
VAR_TEMP
  DB_REGISTER : WORD ;  
  AR1_REGISTER : DWORD ;    
  DB_NUMMER : WORD ;    
  BEREICHSZEIGER : DWORD ;  
  ZWISCHENWERT : REAL ; 
  SCHLEIFE : INT ;  
  ZAEHLER : REAL ;  
END_VAR
BEGIN
NETWORK
TITLE =DB-Register und Adressregister AR1 sichern
 
      L     DBNO; // DB-Register
      T     #DB_REGISTER; 
 
      TAR1  #AR1_REGISTER; // AR1-Register
 
NETWORK
TITLE =Mittelwert
 
      L     P##SPEICHER; // POINTER
      LAR1  ; 
 
      L     W [AR1,P#0.0]; // DB-Nummer
      T     #DB_NUMMER; 
 
      AUF   DB [#DB_NUMMER]; 
 
      L     D [AR1,P#2.0]; // Bereichszeiger
      LAR1  ; 
 
      L     0.000000e+000; 
      T     #ZWISCHENWERT; // Letzter Mittelwert
 
      L     1.000000e+000; 
      T     #ZAEHLER; // Anzahl Werte
 
      L     #LAENGE; // Länge
M01:  T     #SCHLEIFE; // Schleife
 
      L     D [AR1,P#0.0]; // Wert
      L     #ZWISCHENWERT; // Letzter Mittelwert
      -R    ; 
      L     #ZAEHLER; // Anzahl Werte
      /R    ; 
      L     #ZWISCHENWERT; // Letzter Mittelwert
      +R    ; 
      T     #ZWISCHENWERT; // Mittelwert
 
      L     #ZAEHLER; // Anzahl Messungen
      L     1.000000e+000; 
      +R    ; 
      T     #ZAEHLER; // Anzahl Messungen
 
      L     P#4.0; 
      +AR1  ; 
 
      L     #SCHLEIFE; // Schleife
      LOOP  M01; 
 
      L     #ZWISCHENWERT; // Mittelwert
      T     #MITTELWERT; // Mittelwert
 
NETWORK
TITLE =DB-Register und Adressregister AR1 wiederherstellen
 
      AUF   DB [#DB_REGISTER]; // DB-Register
 
      LAR1  #AR1_REGISTER; // AR1-Register
 
END_FUNCTION

Gruß Kai
 

Anhänge

  • OB1.pdf
    5,3 KB · Aufrufe: 270
  • FC100.pdf
    4,3 KB · Aufrufe: 244
  • FC110.pdf
    4,7 KB · Aufrufe: 234
  • DB200.pdf
    2,5 KB · Aufrufe: 187
  • Filo.zip
    33,9 KB · Aufrufe: 254
eine Frage

Hallo und guten Tag
Ich habe mir die beiden Bausteinen von Kai in mein Programm übertragen.
CPU Typ : 314-1AF10-0AB0.
Die CPU geht in stop und meldet: Bereichsfehler beim lesen
Ursache:
Sie haben bei der bereichsübergreifenden registerindirekten Adressierung einen unzulässigen Operandenbereich verwendet. Die Bereichskennung der Zugriffsadresse (Bit 24 -31) ist unzulässig.
Behebung:
Verwenden Sie einen Pointer mit korrekter Bereichskennung.

den Stop habe ich mit OB121 abgefangen, damit die Maschine weiter produzieren kann

Bei einer CPU 318 (Vipa 315)funktionieren die beiden Bausteine wunderbar.

womit könnte das zusammen hängen?

der_iwan
 
Hallo
Ich habe genau wie im Beispiel von Kai 10 Werte.

Es sind bei beiden CPU ist die gleichen Bausteine.

der_iwan
 
Sorry ... da habe ich dann auch keine gute Idee mehr.
Welche Programmzeile wird denn angemeckert, wenn du den beschriebenen Fehler bekommst ?
Was macht dein Programm sonst noch so ?

Gruß
Larry
 
Zurück
Oben