Forum: Digitale Signalverarbeitung / DSP / Machine Learning Messwerte glätten


von Bastian G. (Gast)


Lesenswert?

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

von Karl H. (kbuchegg)


Lesenswert?

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.

von AC/DC (Gast)


Lesenswert?

Rauschen vom Messsignal ausfiltern?

von Gast (Gast)


Lesenswert?

Addiere einfach z.B. 16 Messwerte und mache dann ein Rechtsshift um 4 
Stellen. Da kommt der Controller auch nicht in schwitzen ;)

Gruß

von Michael G. (linuxgeek) Benutzerseite


Lesenswert?

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? ;)

von I_ H. (i_h)


Lesenswert?

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.

von Wolfgang Mües (Gast)


Lesenswert?

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.

von Matt (Gast)


Lesenswert?

>Eine exponentielle Glättung ist sicher zu langsam.

http://www.ibrtses.com/embedded/exponential.html

von Stephan (Gast)


Lesenswert?

ich bevorzuge die gleitende Mittelwertbildung.
Wert = Wert(alt) *3 + Wert (neu)
      --------------------------
                4

danach wird Wert zu wert (alt)

Voila

von Läubi .. (laeubi) Benutzerseite


Lesenswert?

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...

von Bastian G. (Gast)


Lesenswert?

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.

von Bastian G. (Gast)


Angehängte Dateien:

Lesenswert?

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.

von Kai G. (runtimeterror)


Lesenswert?

>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.

von eProfi (Gast)


Lesenswert?

@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).

von Gast (Gast)


Lesenswert?

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.

von Läubi .. (laeubi) Benutzerseite


Lesenswert?

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.

von H_S (Gast)


Lesenswert?

Wie wäre es mit einem FIR Filter?

von eProfi (Gast)


Lesenswert?

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
Noch kein Account? Hier anmelden.