Hallo, mein Controller liest von 10 Kanälen 16-Bit Messwerte mit ca. 10 Hz ein. Die Messwerte sind mit ca. 4 Bit ziemlich verrauscht. Mit 3 Hz soll ein geglätteter Messwert ausgegeben werden. Welche Methode wäre dafür geeignet (ausreichend schnell, aber ressourcenschonend)? Eine long Variable pro Kanal zum aufaddieren und anschließender Division scheint mir zu ressourcenintensiv. Eine exponentielle Glättung ist sicher zu langsam. Was gäbe es noch für Möglichkeiten? Grüße, Bastian
Bastian G. wrote: > Hallo, > > mein Controller liest von 10 Kanälen 16-Bit Messwerte mit ca. 10 Hz ein. > Die Messwerte sind mit ca. 4 Bit ziemlich verrauscht. Mit 3 Hz soll ein > geglätteter Messwert ausgegeben werden. > Welche Methode wäre dafür geeignet (ausreichend schnell, aber > ressourcenschonend)? > Eine long Variable pro Kanal zum aufaddieren und anschließender Division > scheint mir zu ressourcenintensiv. Du kriegst von Atmel kein Geld zurück, wenn sich der µC langweilt. Bei deinen Timing Werten kann der µC zwischendurch noch ein paar hundert teuflisch schwierige quadratische Gleichungen (tm) lösen ehe er vor Langeweile ins Koma fällt.
Addiere einfach z.B. 16 Messwerte und mache dann ein Rechtsshift um 4 Stellen. Da kommt der Controller auch nicht in schwitzen ;) Gruß
Bastian G. wrote: > Eine long Variable pro Kanal zum aufaddieren und anschließender Division > scheint mir zu ressourcenintensiv. > Eine exponentielle Glättung ist sicher zu langsam. Da sieht man mal wieder was heute fuer Vorstellungen von Rechenleistung bestehen. Unter 64Bit bei 3GHz geht garnix... ne? ;)
Nimm 2^n Werte und du brauchst nur logisch zu schieben. Bei 10ksps die der Atmel locker mitmacht kannst du pro Kanal 1024 Samples aufnehmen und hast immernoch 10Hz. Und wenn du den ADC Interrupt benutzt hast du sogar noch massig Rechenzeit für andere Dinge über. Ach ja, und die Genauigkeit wird am Ende wohl eher bei 12..14 Bit liegen.
Du könntest die Abtastrate im Eingang auf 12 Hz hochdrehen, Dann kannst Du 4 Messwerte addieren und das Ergebnis durch 4 teilen. Durch 4 teilt man durch Schieben um 2 bit nach rechts (in C der Operator ">>"). Wenn Du die long-Variable vermeiden willst, kannst Du auch vor dem Addieren jeden einzelnen Messwert durch 4 teilen. Dadurch verlierst Du Genauigkeit, aber bei 4 bit Rauschen ist das vielleicht nicht so wichtig.
>Eine exponentielle Glättung ist sicher zu langsam. http://www.ibrtses.com/embedded/exponential.html
ich bevorzuge die gleitende Mittelwertbildung. Wert = Wert(alt) *3 + Wert (neu) -------------------------- 4 danach wird Wert zu wert (alt) Voila
man kann auch sehr schön folgendes machen bei Kontinuierlichen Sachen die sich nicht sprunghaft ändern (geschwindigkeit, temperatur...) WERT_neu/2 + Wert_alt1/4 + Wert_alt2/8 + Wert_alt3/8 to be continued...
Danke schonmal für eure Anregungen! Diesmal benutze ich keinen Atmel, sondern einen Freescale MC9S12. Hätte ich erwähnen sollen. Die Messwerte kommen über den I2C Bus, nicht von den internen ADCs. Was die Prozessorauslastung hochtreibt ist allerdings das kontinuierliche Senden von Messwerten über die serielle Schnittstelle. Die Routinen dazu sind nicht optimal (Polling statt IRQ), lassen sich jetzt aber nicht mehr ändern. @Matt: Danke für den Link. Ich hatte diesen schon in einem älteren Posting gefunden und mal mit Excel durchgerechnet. Erschien mir auf den ersten Blick aber, selbst mit N = 0,25, sehr langsam.
Im Anhang ein kleiner Vergleich verschiedener Methoden. Sehr gut, da schnelle Reaktion auf Änderungen, gefällt mir die Variante von Läubi. Allerdings müssen pro Kanal 4 Werte gespeichert werden. Bei 10 Kanälen ist das nicht wenig.
>Allerdings müssen pro Kanal 4 Werte gespeichert werden. Bei >10 Kanälen ist das nicht wenig. Irgendwo wirst du wohl Prioritäten setzen müssen. Qualität vs. Speicherbedarf vs. Rechenaufwand. Ich bevorzuge Stephans Methode. Ist schnell implementiert und liefert gute Resultate. Bei deinen Messwerten reicht ggf. schon folgende Glättung: Wert = Wert(alt) + Wert (neu) -------------------------- 2 Das reagiert noch einen Ticken schneller und braucht kaum Speicher.
@Stephan und Kai: ich verwende eine ähnliche, aber bessere Methode: Aver = Aver + ADC - (Aver >> x); Das hat zur Folge, dass Aver auf den 2^x-fachen Wert von ADC ansteigt. Entweder ich rechne gleich mit Aver weiter, oder teile ihn durch 2^x (und runde) in dem Augenblick, in dem ich ihn brauche (was in der Regel seltener als die Abtastrate ist). Wenn ADC 16 Bit hat, bleibt nichts anderes als für Aver 24 oder 32 bit zu verwenden. Oder wie Wolfgang schrieb, kannst Du es auch so machen: Aver = Aver + (ADC >> y) - (Aver >> x); Aver ist dann im Bereich ADC * (2^(x-y)) Bei z.B. x = y = 2 reichen dann auch für Aver 16 Bit aus. Da war ich auch schonmal versucht, sowas zu schreiben, um einen Shift zu sparen: Aver = Aver + ((ADC - Aver) >> x); Aber der Effekt ist nicht wie erwünscht, Aver ist dann immer einen Tick zu klein. Eine andere Methode wäre ein echter Digitalfilter (Tiefpass FIR oder IIR) ala Bessel, Butterworth, Tschebyscheff.... Der reagiert schnell auf Änderungen und filtert trotzdem gut. Ansonsten empfehle ich immer, die Ursache zu suchen und weniger an den Symptomen zu doktern: Vermutlich hast Du eine Gnd-Schleife oder ähnliches, also ein Analog-Problem. Auch die digitalen Signale (SDA und SCL) können die Wandlung beeinflussen. Da würde ich mal jeweils auf der Treiberseite einen Dämpfungswiderstand (10-82 Ohm) einfügen. Welche Sprache? Um welche Signale handelt es sich? Welche Wandler verwendest Du? Habe mit der ADS125x-Familie (24 Bit Delta-Sigma) sehr gute Erfahrung gemacht (mit erhöhtem externen Aufwand 18 echte Bits bei 100 Hz).
Hallo, die Form xk+1 = (a*uk+1 + b*xk)/(a+b) ist die zeitdiskrete Form eines Tiefpassfilters erster Ordnung. xk+1 = a*uk+1 + (1-a)*xk mit 0<=a<=1 als "Filterzeitkonstante". Wenn a=1 kein Filter, wenn a=0 alles gefiltert (alles tot). Man kann also mit a spielen und so das Filter anpassen.
Bastian G. wrote: > Im Anhang ein kleiner Vergleich verschiedener Methoden. > Sehr gut, da schnelle Reaktion auf Änderungen, gefällt mir die Variante > von Läubi. Allerdings müssen pro Kanal 4 Werte gespeichert werden. Bei > 10 Kanälen ist das nicht wenig. Ich benutz das um die Digitalanzeige meines Tachos vorm "zittern" zu bewahren, klappt ganz gut, allerdings noch mit einer Stufe mehr. Und 40Werte a 16bit sind gerade mal 80bytes Ram das ist auch noch nicht soooo viel.
Ich habe nochmal nachgerechnet, auch das Filter von Autor: Stephan (Gast) Datum: 15.05.2008 08:20 ich bevorzuge die gleitende Mittelwertbildung. Wert(alt) *3 + Wert (neu) Wert = --------------------------- 4 danach wird Wert zu wert (alt) erreicht übrigens auch nie den Eingangswert. Das ganze hatten wir übrigens erst vor kurzem: Beitrag "Re: Digitales Filter"
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.