Zuviel Werbung? - > Hier kostenlos beim SPS-Forum registrieren

Results 1 to 10 of 10

Thread: B&R Steuerung Mittelwert von Analogwerten bilden (Strukturierter Text)

  1. #1
    Join Date
    15.09.2020
    Posts
    2
    Danke
    1
    Erhielt 0 Danke für 0 Beiträge

    Beitrag


    Zuviel Werbung?
    -> Hier kostenlos registrieren
    Hallo zusammen,

    ich habe folgendes Problem.

    Ich lese einen analogen Messtaster über den Analogeingang meiner B&R Steuerung (X20 CP 1382) aus. Dazu habe ich dem Eingang eine Variable zugewiesen, die den aktuellen Analogwert speichert. Dieser wird dann mit Hilfe einer VC4 Visualisierung, die man auch in Automation Studio erstellen kann, ausgegeben. Jedoch ist der umgerechnete Wert inkonstant, d.h. er springt immer etwas hin und her da der Analogwert unstetig ist.

    Jetzt wollte ich, um den Wert konstanter zu machen, den Mittelwert bilden. Wie mache ich das am besten? Ich brauche ja eine Art "Data Buffer" (z.B. ein INT Array) um mehrere Analogwerte in einem Zyklus zu speichern, aber ich weiß nicht wie genau ich das umsetzten soll (Bin noch ein Anfänger). Vor allem wie schaffe ich es, dass ich sagen wir mal 15 Werte in diesem Buffer abspeichere. Denke mal dass eine for-Schleife auch gebraucht wird. Der Ansatz ist da, aber ich weiß nicht wie ich das am besten bei einer Steuerung umsetzten soll.

    Jede Hilfe ist willkommen und falls ihr mehr Infos braucht grad schreiben, ist mein erster Beitrag hier.

    Gruß
    Bastud
    Attached Images Attached Images
    Reply With Quote Reply With Quote B&R Steuerung Mittelwert von Analogwerten bilden (Strukturierter Text)  

  2. #2
    Join Date
    23.06.2009
    Location
    Sassnitz
    Posts
    15,847
    Danke
    1,299
    Erhielt 4,659 Danke für 3,771 Beiträge

    Default

    Quote Originally Posted by Bastud View Post
    Jetzt wollte ich, um den Wert konstanter zu machen, den Mittelwert bilden. (...) Ich brauche ja eine Art "Data Buffer" (z.B. ein INT Array) um mehrere Analogwerte in einem Zyklus zu speichern
    Einen Mittelwert erhält man nicht, indem man einen Wert mehrmals im Zyklus speichert, sondern man muß in mehreren Zyklen den Wert in einen Puffer speichern. Der Puffer muß so groß sein über wieviele Zyklen man den Mittelwert bilden will.

    Eine Schleife braucht man nicht für das Speichern, nur einen Ringpuffer zum Einspeichern je eines Wertes in jedem Zyklus. Über die Werte des Ringpuffers kann dann der Mittelwert berechnet werden - hier bietet sich eine Schleife an, um die Summe über alle Elemente des Puffers zu bilden.
    Code:
    buff : ARRAY[0..9] OF REAL;  //Ringpuffer für 10 Werte
    buffindex : UINT;  // Ringpuffer Füllzeiger
    i : UINT;
    sum : REAL;
    avg : REAL;  // Mittelwert
    
    //neuen Wert in Ringpuffer schreiben, ältester Wert verschwindet dabei (wird überschrieben)
    buffindex := (buffindex + 1) MOD 10;  // Ringpuffer-Füllzeiger auf das nächste Element setzen
    buff[buffindex] := New_value;         // aktuellen Wert in Ringpuffer schreiben
    
    //Mittelwert über Pufferwerte berechnen
    sum := 0.0;
    FOR i := 0 TO 9 DO
      sum := sum + buff[i];
    END_FOR;
    
    avg := sum / 10.0;
    Eine Glättung kann man auch ohne Schleife erreichen, einen Beispielcode für einen gleitenden Mittelwert kannst Du bei OSCAT finden im FUNCTION_BLOCK FT_AVG
    (und Beispiel Ringpuffer)

    Einen Glättung kann man auch ohne Puffer-Array für das Merken der vorherigen Werte erreichen, indem man z.B. 10 Werte addiert und beim Hinzufügen eines neuen Wertes den bisherigen Mittelwert (10% der Summe) abzieht und den neuen Wert dazu addiert. Allerdings werden bei dieser Glättung große Wertesprünge nur langsam abgebaut. Das Prinzip kann man vereinfacht implementieren mit dieser Formel:

    Smooth_value := Smooth_value * 0.9 + New_value * 0.1;


    PS:
    IF resValue < 0.0 OR resValue = 0.0 THEN resValue := 0.0;
    kann man einfacher schreiben
    IF resValue <= 0.0 THEN ...
    oder hier reicht auch
    IF resValue < 0.0 THEN ...

    Harald
    Es ist immer wieder überraschend, wie etwas plötzlich funktioniert, sobald man alles richtig macht.

    FAQ: Linkliste SIMATIC-Kommunikation über Ethernet

  3. Folgender Benutzer sagt Danke zu PN/DP für den nützlichen Beitrag:

    Bastud (17.09.2020)

  4. #3
    Bastud is offline Neuer Benutzer
    Themenstarter
    Join Date
    15.09.2020
    Posts
    2
    Danke
    1
    Erhielt 0 Danke für 0 Beiträge

    Default

    Hallo Harald,

    erstmal danke für die schnelle Antwort. Den Code habe ich schonmal verstanden.

    Ich bin mir nicht sicher in welchen Programmabschnitt ich den Code packen muss. Der Teil mit dem Ringpuffer hätte ich in den Cyclic.st geschrieben, aber wenn ich die For-schleife für die Mittelwertbildung da auch rein schreibe klappt es nicht so wie es soll.

    Ich muss der Steuerung ja auch irgendwie sagen, dass Sie nach 10 Zyklen den Mittelwert bilden soll oder?

    Gruß
    Bastud

  5. #4
    Join Date
    23.06.2009
    Location
    Sassnitz
    Posts
    15,847
    Danke
    1,299
    Erhielt 4,659 Danke für 3,771 Beiträge

    Default

    Der Mittelwert kann und sollte immer dann neu berechnet werden wenn ein neuer Wert in den Puffer geschrieben wurde (also in jedem Zyklus). Das Speichern in den Ringpuffer und das Mittelwert berechnen also am besten direkt nacheinander machen. Es sei denn, der Mittelwert wird seltener abgefragt und verarbeitet - dann braucht er natürlich nur vor der Verarbeitung neu berechnet werden.

    Wenn Du von mehreren Signalen dessen Mittelwert haben willst, dann braucht jedes Signal seinen eigenen Ringpuffer. Am besten einen FB mit Ringpuffer schreiben und für jedes Signal eine eigene Instanz des FB anlegen.

    Harald
    Es ist immer wieder überraschend, wie etwas plötzlich funktioniert, sobald man alles richtig macht.

    FAQ: Linkliste SIMATIC-Kommunikation über Ethernet

  6. #5
    Join Date
    25.06.2017
    Location
    Oerlinghausen
    Posts
    2,925
    Danke
    317
    Erhielt 550 Danke für 461 Beiträge

    Default

    Quote Originally Posted by Bastud View Post
    Ich muss der Steuerung ja auch irgendwie sagen, dass Sie nach 10 Zyklen den Mittelwert bilden soll oder?
    Das darfst Du doch selbst entscheiden, ob Du z.B.
    - jedesmal, wenn ein neuer Wert hinzugekommen ist, den Mittelwert über die jeweils letzten 10 Werte bildest oder
    - erst dann, wenn 10 neue Werte hinzugekommen sind, den Mittelwert über die letzten 10 - noch nicht bereits zum Teil verwursteten - Werte bilden möchtest.

    Wenn Du allerdings nach der Methode "neuer_Mittelwert := (n * letzter_Mittelwert + neuer_Wert)/(n+1)" mittelst, stellt sich Deine Frage eigentlich gar nicht!?

  7. #6
    Join Date
    03.05.2015
    Location
    Schweiz
    Posts
    7
    Danke
    0
    Erhielt 1 Danke für 1 Beitrag

    Default

    Hallo Bastud,

    B&R bietet für solche Anwendungen auch fix-fertige Bibliotheken an. Schau dir doch mal den FUB MTFilterMovingAverage aus der Bibliothek MTFilter an. Der Einsatz dieser Bibliothek ist gratis.

    MTFilterMovingAverage.jpg

    Sollte genau das bieten, was du benötigst.

    Liebe Grüsse
    Ulumulu1510

  8. #7
    Join Date
    03.05.2015
    Location
    Schweiz
    Posts
    7
    Danke
    0
    Erhielt 1 Danke für 1 Beitrag

    Default

    Quote Originally Posted by Heinileini View Post
    Wenn Du allerdings nach der Methode "neuer_Mittelwert := (n * letzter_Mittelwert + neuer_Wert)/(n+1)" mittelst, stellt sich Deine Frage eigentlich gar nicht!?
    Dieser Code ist leider kein korrekter gleitender Mittelwert. Eher entspricht dies einem Tiefpass.

    Folgendes Beispiel macht dies deutlich:
    1. Initialisiere n := 2 soll Mittelwert über 3 Werte ergeben, neuer_Mittelwert := 0
    2. neuer_Wert := 9'000 -> neuer_Mittelwert = 3'000 -> Vergleichsrechnung: (0 + 0 + 9'000) / 3 = 3'000 -> stimmt
    3. neuer_Wert := 0 -> neuer_Mittelwert = 2'000 -> Vergleichsrechnung: (0 + 9000 + 0) / 3 = 3'000 -> stimmt nicht
    4. neuer_Wert := 0 -> neuer_Mittelwert = 1'333 -> Vergleichsrechnung: (9000 + 0 + 0) / 3 = 3'000 -> stimmt nicht
    5. neuer_Wert := 0 -> neuer_Mittelwert = 888 -> Vergleichsrechnung: (0 + 0 + 0) / 3 = 0 -> stimmt nicht


    Liebe Grüsse
    Ulumulu1510

  9. #8
    Join Date
    22.03.2007
    Location
    Detmold (im Lipperland)
    Posts
    12,422
    Danke
    422
    Erhielt 2,543 Danke für 2,114 Beiträge

    Default

    @Ulumulu:
    wenn du das Beispiel von Heinrich korrekt angewendet hättest dann hätte es auch die korrekten Werte erbracht ...
    Sorry ... kein Foto für dich ...

  10. #9
    Join Date
    25.06.2017
    Location
    Oerlinghausen
    Posts
    2,925
    Danke
    317
    Erhielt 550 Danke für 461 Beiträge

    Default

    Quote Originally Posted by Ulumulu1510 View Post
    Dieser Code ist leider kein korrekter gleitender Mittelwert. Eher entspricht dies einem Tiefpass.
    Korrekt! Das ist eine "Glättung mit sparsamen Mitteln", ohne Array, ohne FIFO. Für viele Zwecke gut geeignet, aber kein Mittelwert über eine gegebene Anzahl von Messungen.
    Dafür ist MehrAufwand nicht vermeidbar.

    Man kann ein wenig vereinfachen, wenn ...
    - die Anzahl der Werte, über die gemittelt werden soll, immer gleich bleibt und
    - man die Summe der Messwerte in den nächsten Zyklus rettet,
    folgendermassen rechnen:
    Code:
    i := (i+1) mod n ; // n: Anzahl der zu mittelnden Werte; i: Index 0..(n-1)
    WertZuvor := Wert[i] ;
    Wert[i] := WertAktuell ;
    Summe := Summe - WertZuvor + WertAktuell ;
    MittelWert := Summe / n ;
    D.h. man muss nicht beim Eintreffen eines neuen Wertes alle Werte des Array in einer Schleife neu aufsummieren.
    Allerdings hat diese Abkürzung einen Haken: Zu Beginn muss man doch einmalig die Summe aller ArrayElemente bilden 1), um den Wert in Summe zu "synchronisieren".
    Vorteilhaft ist das Verfahren, wenn über eine hohe Anzahl von Werten gemittelt werden muss und sich die Anzahl SchleifenDurchläufe störend auf die ZyklusZeit auswirken würde.

    PS:
    1) Initialisieren aller ArrayElemente und von Summe mit 0 tut's natürlich auch.
    Last edited by Heinileini; 15.10.2020 at 15:03.

  11. #10
    Join Date
    04.01.2015
    Posts
    79
    Danke
    0
    Erhielt 19 Danke für 18 Beiträge

    Default


    Zuviel Werbung?
    -> Hier kostenlos registrieren
    Du kannst auch in der Konfiguration des Analogeingangs die Filterstufe einstellen.
    Beschreibung siehe Seite 37.
    https://download.br-automation.com/B...ime=1602926852

    Das entspricht auch der obengenannten Formel. Nur wird die CPU durch die Berechnung nicht belastet.

    Code:
    Formel für die Berechnung des Eingangswerts: Wert neu = Wert alt - Wert alt/Filterstufe + Eingangswert/Filterstufe
    Last edited by roger34; 17.10.2020 at 12:46.

Similar Threads

  1. Ein Messwert Mittelwert bilden
    By sde628 in forum CODESYS und IEC61131
    Replies: 6
    Last Post: 30.11.2017, 16:39
  2. Sonstiges B&R MpRecipe in strukturierter text
    By alainbk in forum Simatic
    Replies: 0
    Last Post: 27.10.2017, 22:24
  3. SIEMENS LOGO, Mittelwert von Analogwerten
    By mkatmkat in forum Sonstige Steuerungen
    Replies: 6
    Last Post: 22.07.2016, 11:57
  4. Mittelwert von zehn Temperaturen bilden
    By husox81 in forum Simatic
    Replies: 2
    Last Post: 22.11.2010, 16:03
  5. Mittelwert bilden (von zb 5 SPS-Zyklen)
    By Matthias O. in forum Simatic
    Replies: 3
    Last Post: 05.01.2007, 15:21

Tags for this Thread

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •