www.mikrocontroller.net

Forum: Digitale Signalverarbeitung / DSP Messwerte glätten


Autor: Bastian G. (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: AC/DC (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Rauschen vom Messsignal ausfiltern?

Autor: Gast (Gast)
Datum:

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

Gruß

Autor: Michael G. (linuxgeek) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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? ;)

Autor: I_ H. (i_h)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Wolfgang Mües (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Matt (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Eine exponentielle Glättung ist sicher zu langsam.

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

Autor: Stephan (Gast)
Datum:

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

danach wird Wert zu wert (alt)

Voila

Autor: Läubi .. (laeubi) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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...

Autor: Bastian G. (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Bastian G. (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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.

Autor: Kai G. (runtimeterror)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: eProfi (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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).

Autor: Gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Läubi .. (laeubi) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: H_S (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wie wäre es mit einem FIR Filter?

Autor: eProfi (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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"

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.