-         

Seite 1 von 2 12 LetzteLetzte
Ergebnis 1 bis 10 von 15

Thema: Immer noch Probleme mit der gleitenden Mittelung

  1. #1
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    23.12.2004
    Ort
    Ulm
    Alter
    30
    Beiträge
    136

    Immer noch Probleme mit der gleitenden Mittelung

    Anzeige

    Hallo,

    vielleicht erinnert ihr euch an die Diskussion über gleitende Mittel im Sommer. In meinem letzten Projekt konnte ich durch einige Tricks die Sache in den Griff bekommen. Im aktuellen jedoch bin ich dringend darauf angewiesen einen anständigen Messwert zu bekommen. Allerdings habe ich die Geschichte von der theoretischen Seite her immer noch nicht ganz verdaut.


    Konkret habe ich ein stark schwankendes analoges Messsignal eines Drucksensors welches größere Schwankungen aufweist wie mein Delta zwischen unterer und oberer Schaltschwelle ist.
    Bei einem ADC Wert von 300 möchte ich einen Ausgang schalten der bis zum ADC Wert 200 aktiv bleibt. Mein Messwert schwankt jedoch beinahe über diesen ganzen Bereich. Das entsteht durch die seltsame Messmethode. Es handelt sich um eine Füllstandsmessung einer Abwassergrube eines Einödhofes. Bei einem bestimmten Pegel pumpt eine Tauchpumpe den Grubeninhalt in die Kanalisation der nächsten Ortschaft. Um den Füllstand zu messen wird ein Luftschlauch der in der Grube mündet durch eine Membranpumpe mit einem Druck beaufschlagt. Dieser Druck wird mittels Drucksensor ausgewertet. Dadurch, dass die Luftblasen in der sehr hochviskosen Flüssigkeit aufsteigen baut sich immer ein sehr hoher Druck auf, der dann sobald die Luftblase aufsteigt blitzartig in den Keller sinkt. Das erklärt mein schlechtes Signal.
    Diese Messmethode hat einerseits den Vorteil, dass niemand in die Grube steigen muss um dort z.B. auf dem Boden einen Drucksensor anzubringen, zum anderen wird bei dieser sehr inhomogenen Beschaffenheit des Inhaltes wahrscheinlich auch nicht jede Art der Füllstandsmessung funktionieren. Ich hoffe ich konnte mein Problem einigermaßen gut in Worte fassen und ihr könnt euch ein Bild davon machen.

    Nun habe ich schon viele Möglichkeiten versucht um diesen Messwert in den Griff zu bekommen, allerdings noch keine zufriedenstellende Lösung gefunden. Einige von euch(u.a. Manf, Recycle) haben sich sehr viel Mühe gegeben mir die gleitende Mittelung zu erklären, ich habe jedoch noch nicht komplett verstanden wie es genau funktionieren kann, dass mit dem Bascom Code von recycle auf der ersten Seite des nachfolgend genannten Threads eine solche gleitende Mittelung realisiert wird.
    http://www.roboternetz.de/phpBB2/viewtopic.php?t=49678

    Manf hat damals geschrieben, dass dieses Vorgehen eine exponentiell über der Zeit abnehmende Gewichtung der vorgehenden Werte ermöglicht. Wie kommt das zustande? Recycle verwendet lediglich Subtraktion/Addition und eine Divison durch die Anzahl der Werte über die gemittelt werden soll. Mir ist nicht ganz klar woher der exponentielle Charakter kommt.

    Nichtsdestotrotz habe ich den Code von Recycle übernommen und getestet. Es ist eine deutliche Glättung der Werte festzustellen.
    Jedoch auch eine Art Sprungfunktion. Es hat sich der Mittelwert 250 eingestellt. Mein tatsächlich gemessener ADC Wert pendelte zwischen 195 und 260. Sobald der ADC Wert kurzzeitig auf unter 200 fiel hat recycles Funktion den Mittelwert auf 200 gesetzt. Dieser änderte sich erst wieder wenn der ADC Wert zufällig einen Peak über 250 hatte. Dann sprang der Mittelwert wieder auf seinen ursprünglichen Wert von 250.
    Woher diese Charakteristik rührt kann ich mir nicht vorstellen.

    Tabellarisch:

    IST-Wert / Mittelwert
    220 / 250
    210 / 250
    250 / 250
    199 / 200
    230 / 200
    240 / 200
    251 / 250
    240 / 250
    245 / 250
    198 / 200
    230 / 200
    255 / 250

    Ich hoffe diese Tabelle konnte die zugegeben nicht ganz glückliche Beschreibung des Problems "Sprungfunktion" verdeutlichen.


    Das ist meine Funktion zur gleitenden Mittelung von o.g. Thread Seite 1 aus Recycles Beitrag übernommen:

    Code:
    const Anzahl = 50
    
    Function Mittelung(aw As Integer) As Integer
    
    Local Zaehler As Integer
    Local Temp As Integer
    Local Mittelwert As Single
    Local Mittelwert_int As Integer
    
    For Zaehler = 1 To Anzahl
          Temp = Mittelwert / Anzahl
          Mittelwert = Mittelwert - Temp
          Temp = Aw / Anzahl
          Mittelwert = Mittelwert + Temp
          Mittelwert_int = Mittelwert
          Mittelung = Mittelwert
    Next Zaehler
    End Function
    Kann sich jemand dieses Verhalten erklären, bzw mir einiges Tipps geben wie ich meinen Messwert in den Griff bekomme? Oder ist die Funktion so vielleicht nicht richtig umgesetzt?

    Unter Wikipedia gibt es einiges zum Thema "Gleitendes Mittel" zu finden. Die Beispiele sind jedoch immer auf Logistik, Lagerhaltung bzw Aktiencharts bezogen. Ich habe noch keinen Weg gefunden die dort genannte Funktion auf mein Problem zu übertragen.

    Bis zum heutigen Tage war diese ganze Steuerung mit einer elektromechanischen Druckdose mit dem selbenMessprinzip realisiert. Diese hat jedoch den Dienst quittiert. Weil ich nun vermeiden möchte, dass die erwähnte Membranpumpe rund um die Uhr läuft möchte ich die Steuerung mittels Atmel und MPX5100 realisieren und die Pumpe nur einige Male pro Tag zum aufbauen des Messdrucks einschalten. Dazu kommt, dass der Hersteller kein Interesse mehr daran hat die bereits "schon" 10 Jahre alte Steuerung zu reparieren (sprich eine neue Druckdose zu verkaufen).

    Als Notlösung denke ich bereits schon an eine mechanische Glättung meines Signals mittels Druckbehälter zum Ausgleichen der Druckschwankungen. Die Methode finde ich zwar keineswegs elegant, liegt mir als Maschinenbaustudent jedoch etwas näher .


    Vielen Dank allen die sich die Zeit genommen haben diesen langen Beitrag zu lesen.


    Ich freue mich auf Eure Resonanz


    Gruss


    Florian.

  2. #2
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    29.01.2004
    Beiträge
    2.441
    Hallo Florian,
    könnte sein, dass mein Beispielcode nicht völlig korekt war. Ich habe ihn zwar ausprobiert, aber nicht allzu gründlich.

    In deinem Code fällt mir aber 2 Dinge auf:

    a) Du mittelst nur über 50 Werte. Das wird für deinen Zweck viel zu wenig sein

    b) Du rechnest ziemlich viel mit Integer Werten und das ist bei Divisionen nicht so toll.

    Temp = Aw / Anzahl
    Temp ist bei dir ein Integer. D.h. für alle Aw <50 kommt da 0 raus.
    Bis Aw = 99 bleibt Temp dann 1 und springt bei Aw= 100 auf 2.....

    Bei Temp = Mittelwert / Anzahl gilt dasselbe.

    Das verusacht vermutlich deine sprunghaften Änderungen des Mittelwertes

  3. #3
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    23.12.2004
    Ort
    Ulm
    Alter
    30
    Beiträge
    136
    Ich meine ich hätte das mit den Integervariablen so von dir übernommen und habe mich auch schon gewundert. Darum habe ich dann testweise alles mit Singlevariablen gemacht, auch die Funktion als Single angelegt. Damit hatte ich beim Mittelwert immer xxx.0. Somit dachte ich mir:

    1. hast du immer ,0 und
    2. hast du das ja von Recycle abgeschrieben.
    Also muss Integer doch okay sein und habs wieder auf Integer geändert

    Werde ich jetzt aber wieder auf Single zurückverändern. Was schätzt du über wieviele Werte ich mitteln sollte? Sehe ich es richtig, dass der Einfluss der Messwerte gegenüber dem bisherigen Mittelwert an Bedeutung gewinnt, je größer ich dieses Fenster (const Anzahl=...) wähle?

  4. #4
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    29.01.2004
    Beiträge
    2.441
    Was schätzt du über wieviele Werte ich mitteln sollte?
    Das hängt
    a) davon ab, wie schnell du die Messwerte erfasst und
    b) wie schnell die Schwankungen in der Grube sind.

    Du mittelst ja im Prinzip über die Zeit, der Microcontroler macht vermutlich sehr viele Messungen in kurzer Zeit, das "Blubbern" in der Grube verursacht aber eine recht langsame Schwankung.


    Sehe ich es richtig, dass der Einfluss der Messwerte gegenüber dem bisherigen Mittelwert an Bedeutung gewinnt, je größer ich dieses Fenster (const Anzahl=...) wähle?
    Nein, eigentlich genau umgekehrt. Je grösser die Anzahl der gemittelten werte, desto kleiner die Bedeutung eines einzelnen Wertes.


    Ich finde den alten Post nicht mehr, dein Link oben funktioniert bei mir nicht.
    Habe mein Beipiel aber mal in Bascom aufgemacht und da habe ich Temp as Single deklariert.

    Als Integer habe ich eigentlich nur Mittelwert_int deklariert.
    Das diente in meinem Beispiel nur dazu, den Mittelwert ohne die vielen Nachkommastellen über Print auszugegeb, damit man etwas leichter erkennen kann wie sich der Wert ändert.

  5. #5
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    20.07.2009
    Ort
    Wien
    Beiträge
    131
    nur so als schnelle idee, ohne den alten thread gelesen zu haben: ist nicht der spitzenwert des drucks bei deiner meßmethode eigentlich das wesentliche, weil das der druck ist, der zum überwinden des gegendrucks der grube notwendig ist? könnte es sein, daß du mit dem mittelwert auf dem holzweg bist?

    cm.

  6. #6
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    23.12.2004
    Ort
    Ulm
    Alter
    30
    Beiträge
    136
    Habe im ersten Beitrag nun den Link zum alten Post korrigiert. Hier nochmal:
    http://www.roboternetz.de/phpBB2/viewtopic.php?t=49678

    Du hattest recht, in deinem Programm stimmten die Datentypen. Kann noch nicht sagen ob dieses sprungverhalten dadurch jetzt behoben wurde. Aber ich schätze schon.
    Ich mittle momentan über 250 Werte. Der Mega8 (Takt 3686400 Hz) liest in jedem Zyklus einmal den Wert vom ADC. Wenn ich jedoch über 250 Werte das gleitende Mittel bestimme verbringt der AVR natürlich sehr viel Zeit in dieser For Schleife (For Zaehler=1 to Anzahl). Somit schätze ich die Anzahl der Messungen bei Anzahl=250 so auf 5-8 pro Sekunde.

    Das gleitende Mittel hängt aber trotzdem sehr stark am aktuellen Wert. Eine spürbare Glättung kann ich kaum feststellen. Der ADC schwankt vielleicht im Bereich von 80, der Mittelwert um 50-60.

    Daran, dass der Mittelwert ungeeignet ist und ich vielmehr die Spitzenwerte ausfltern sollte habe ich noch gar nicht gedacht. Aber klingt nicht ganz unlogisch. Bin mir jedoch im Moment nicht sicher ob das eine gute Möglichkeit wäre.

    Florian.

  7. #7
    Erfahrener Benutzer Fleißiges Mitglied Avatar von wawa
    Registriert seit
    18.12.2007
    Ort
    Berlin
    Alter
    67
    Beiträge
    164
    hallo Florian,

    ich bin wie cmock der Meinung, dass du den Spitzenwert messen musst, bevor die Blase den Schlauch verlaesst. Du steigerst ueber die Zeit den Druck im Schlauch, bis er die Hoehe des Druckes der Fluessigkeit erreicht, dann loesst sich eine Blase und dein Druck im Schlauch faellt ein wenig.
    Der hoechste Messwert ist also die Entsprechung fuer den Fuellstand der Grube.
    !! uebrigens - tolle Idee !!

    gruss wawa

  8. #8
    Erfahrener Benutzer Robotik Visionär
    Registriert seit
    26.11.2005
    Ort
    bei Uelzen (Niedersachsen)
    Beiträge
    7.942
    Ob man jetzt den Spitzenwert, oder den unteren Wert nimmt ist relativ egal. Der Spitzenwert des Drucks entspricht etwa der Flüssigkeitssäule mit Rohr+Blase, der mindestwert ist etwa der Druck wenn sich gerade eine Blase gelöst hat, also das was dem reinen Rohr entspricht.

    Die Zeit für die Mittelung bzw. die Zahl der werte sollte so groß sein, dass mehr als eine Blase in der Zeit aufsteigt.

    Die Mittelung so wie vorgeschlagen ist schin nicht schlecht. Auch wenn man keine explizite Exponentialfunktion drin hat, bekommt man ein2 exponetiell abnehmende Wichtung. Der neue Wert kommt dazu, und alle alten Werte werden in der Wichtung um einen konstanten Faktor (hier 1- 1/Anzahl) reduziert. Für jeden Schritt den ein Wert zurückliegt kommt einmal der Faktor dazu. Der Wert der N Schritte zurückliegt hat damit noch ein Gewicht von (1-1/Anzahl)^N.

    Damit die Rechnung funktioniert muß die Auflösung der zahlen so groß sein, dass (1-1/anzahl) nicht wieder auf 1 gerundet wird.

  9. #9
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    23.12.2004
    Ort
    Ulm
    Alter
    30
    Beiträge
    136
    Genau. Korrekterweise, wenn ich den Druck bestimmen wollen würde, müsste ich den Spitzenwert nehmen. Da es mir jedoch auf keinen Zahlenwert ankommt spielt es keine Rolle. Mir geht es lediglich um zwei Schaltschwellen.

    1-1/Anzahl...Ab wann wird eine Single Variable auf 1 aufgerundet? Sollte ich von diesem Punkt des Aufrundens möglichst weit wegbleiben, oder besser diesen gerade so nicht erreichen?

    Egal welchen Wert zwischen 50 und 5000 ich für Anzahl nehme, eine merkliche Verbesserung des Signals erreiche ich dadurch nicht. Der Prozessor ist mit größerwerdender Anzahl nur länger mit der Mittelung beschäftigt, so dass er nicht mehr sonderlich oft vom ADC lesen kann.

    Habt ihr eine Idee wie ich diesem Schwanken noch entgegenwirken könnte?

  10. #10
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    08.12.2005
    Beiträge
    535
    Florian,

    einen gleitenden Mittelwert stelle ich mir immer wie eine Warteschlange vor: Jedesmal, wenn ein neuer Messwert dazukommt, rückt die ganze Schlange einen Schritt voran und der erste (also der älteste) Messwert fällt aus der Schlange heraus. In die neue freie Stelle am anderen Ende der Schlange wird der neue Messwert eingeschrieben. Danach werden alle Werte in der Schlange zusammengezählt und durch die Schlangenlänge (Anzahl) dividiert - das ist dann der neue Mittelwert.

    Der erste Schritt zur Vereinfachung besteht darin, dass man eine Variable MessWertSumme einführt, die gross genug ist, um den Wert Anzahl*maximaler_Messwert ohne Überlauf aufzunehmen. Diese Variable wird ganz am Anfang mit Null initialisiert. Jedesmal, wenn ein neuer Messwert dazukommt, bleibt das Schlangenballett dasselbe. Aber statt die Summe über alle Werte in der Schlange zu bilden, bildet man die Differenz zwischen dem Messwert, der aus der Schlange herausgefallen ist, und dem neuen und zählt diese Differenz zu MessWertSumme dazu. Um den gleitenden Mittelwert zu berechnen, braucht man jetzt nur noch MessWertSumme durch die Anzahl zu dividieren. Damit ist jetzt überflüssig geworden, die zeitraubende Summe über alle Werte der Schlange zu berechnen .

    Die zweite Vereinfachung besteht darin, die ganze Schlange wegzulassen, weil man annimmt, dass die einzelnen Messwerte in der Schlange sich sowieso nicht so sehr vom Mittelwert unterscheiden. Wenn jetzt ein neuer Messwert ankommt, wird davon der alte Mittelwert abgezogen und die Differenz zu MittelWertSumme dazuaddiert. Den neuen Mittelwert bekommt man wieder, indem man MittelWertSumme durch Anzahl dividiert. Damit hat man auch noch den Speicherplatz für die Warteschlange und den Zeitaufwand für das Schlangenballett gespart .

    Der Code dazu könnte so aussehen:
    Code:
    $sim
    $crystal = 16000000
    $regfile = "m16def.dat"
    $baud = 38400
    
    Dim Messwert As Integer : Messwert = 512
    Const Anzahl = 50                                           ' Anzahl Messwerte
    
    Dim MessWSumme As Single
    Dim Mittelwert As Single
    Dim Mittelwert_int As Integer
    Dim Temp As Single
    
    REM der nachfolgende Teil ist IMHO überflüssig 
    
    REM Dim Zaehler As Word : Zaehler = 0
    
    REM While Mittelwert < 511
    REM   Incr Zaehler
    REM   Temp = Mittelwert / Anzahl
    REM   Mittelwert = Mittelwert - Temp
    REM   Temp = Messwert / Anzahl
    REM   Mittelwert = Mittelwert + Temp
    REM   Print Zaehler ; ": " ; Mittelwert
    REM Wend
    
    REM 'Print Zaehler ; ": " ; Mittelwert
    
    MessWertSumme = 0
    Mittelwert = 0
    
    Do
       Input "Neuer Messwert: " , Messwert
       Temp =  Messwert-Mittelwert
       MessWSumme = MessWertSumme+Temp
       Mittelwert = MessWertSumme/Anzahl
       Mittelwert_int = Mittelwert
       Print "Neuer Mittelwert: " ; Mittelwert_int
    
    Loop
    End
    Was meinst Du dazu?

    mare_crisium

Seite 1 von 2 12 LetzteLetzte

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •