Forum: Mikrocontroller und Digitale Elektronik Quadratischer Mittelwert IIR höherer Ordnung möglich?


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von Karl (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Ich habe ein Signal von 50Hz, welches mit 2.5kHz abgetastet wird. Von 
diesem Signal soll der quadratische Mittelwert gefiltert werden, um 
daraus RMS zu berechnen.

Entsprechend dieses Beitrages 
Beitrag "Re: quadratischer mittelwert" mache ich das nach 
der Formel, genaugenommen ein digitaler Tiefpass:

y(k+1)=((n-1)*y(k)+x(k+1)*x(k+1))/n

Umgesetzt habe ich das mit:

yqsum = yqsum - (yqsum + N/2) / N + vneu * vneu
yrms = sqrt(yqsum / N)

Damit wird in yqsum der um N vergrößerte Mittelwert zwischengespeichert, 
damit die Bits nicht abgeschnitten werden.

Funktioniert soweit, aber die Werte schwanken bei N = 256 noch um etwa 
1% des Messwertes. Was auch gut mit der Simulation der Daten 
übereinstimmt. Diesen Ripple könnte ich jetzt verhindern, indem ich N 
erhöhe, dazu müsste ich allerdings auf N = 4096 oder höher gehen, was 
zum einen den Tiefpass sehr langsam macht, zum anderen meine 32bit-Summe 
sprengt. Mit 64bit wird dann die Rechnung wieder zu langsam, um die 
Werte rechtzeitig abarbeiten zu können.

Die Lösung wäre jetzt ein Filter höherer Ordnung. Kann man sowas digital 
implementieren?

Eine Erhöhung der Messfrequenz oder ein "echter" Mittelwertfilter mit 
Ringbuffer sind nicht möglich, weil 10 Kanäle abgearbeitet werden und 
dafür weder Speicher noch Taktrate ausreichen.

von A. S. (achs)


Bewertung
0 lesenswert
nicht lesenswert
Naja, ein Tiefpass läuft der Sinuswelle halt nach. Lösen kannst Du das 
nur mit RAM (mut fifo über ganze Perioden Mitteln), oder über viele 
Perioden.

Die erste Methode kostet zwar RAM, aber spart Rechenzeit.

Die Alternative: über ganze Perioden mitteln und nur diese Ergebnisse 
exponentiell glätten. Also 25 oder 50 Zyklen nur quadr. addieren.

von Possetitjel (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Karl schrieb:

> Ich habe ein Signal von 50Hz, welches mit 2.5kHz
> abgetastet wird. Von diesem Signal soll der
> quadratische Mittelwert gefiltert werden, um daraus
> RMS zu berechnen.
>
> Entsprechend dieses Beitrages
> Beitrag "Re: quadratischer mittelwert" mache ich das
> nach der Formel, genaugenommen ein digitaler Tiefpass:
> [...]

Warum?

Du hast aufgrund der 50Hz offenbar ein periodisches Signal;
also integriere doch einfach genau über eine Periode (bzw.
über eine GANZE Anzahl von Perioden).
Fünf Vollwellen (=100ms) bieten sich an; das sind gerade
250 Abtastwerte.

von Karl (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Possetitjel schrieb:
> Du hast aufgrund der 50Hz offenbar ein periodisches Signal;
> also integriere doch einfach genau über eine Periode (bzw.
> über eine GANZE Anzahl von Perioden).
> Fünf Vollwellen (=100ms) bieten sich an; das sind gerade
> 250 Abtastwerte.

Habe ich auch schon überlegt, aber Bedenken: Was passiert, wenn die 
Frequenzen nicht genau übereinstimmen? Gibt das dann nicht eine 
Schwebung im Ausgangssignal?

Ich müßte also eine PLL der Abtastfrequenz auf das Abtastsignal machen.

Zweites Problem: Division durch 250 ist deutlich zweiraubender als 
Division durch 256. Aber ich könnte vielleicht versuchen meine 
Abtastfrequenz etwas anzupassen, so dass 256 Messwerte = 5 Perioden 
sind.

von Dergute W. (derguteweka)


Bewertung
0 lesenswert
nicht lesenswert
Moin,

Karl schrieb:
> Die Lösung wäre jetzt ein Filter höherer Ordnung. Kann man sowas digital
> implementieren?

Klar kann man das machen. Bloss machen halt IIR Filter gerne Malheur 
wegen Rundung und Uebersteuerung. Daher werden Filter hoeherer Ordnung 
gerne als Kettenschaltung von Filtern mit max. 2. Ordnung realisiert.
Ein ganz simpler Schritt in diese Richtung waer', wenn du einfach das 
Ergebnis aus deinem Filter in ein weiteres, gleich aufgebautes Filter 
gibst.

Gruss
WK

von Possetitjel (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Karl schrieb:

> Possetitjel schrieb:
>> Du hast aufgrund der 50Hz offenbar ein periodisches Signal;
>> also integriere doch einfach genau über eine Periode (bzw.
>> über eine GANZE Anzahl von Perioden).
>> Fünf Vollwellen (=100ms) bieten sich an; das sind gerade
>> 250 Abtastwerte.
>
> Habe ich auch schon überlegt, aber Bedenken: Was passiert,
> wenn die Frequenzen nicht genau übereinstimmen?

Nicht sehr viel.


> Gibt das dann nicht eine Schwebung im Ausgangssignal?

Ja, klar.
Hast Du mal versucht, die Größe der Auswirkung abzuschätzen?


> Zweites Problem: Division durch 250 ist deutlich
> zweiraubender als Division durch 256.

Sicher.
Aber Division durch 256 und anschließendes Multiplizieren
mit 1.024 ist nicht so kompliziert.

Und -- nein, man braucht dazu nicht zwingend Fließkommazahlen.


> Aber ich könnte vielleicht versuchen meine Abtastfrequenz
> etwas anzupassen, so dass 256 Messwerte = 5 Perioden sind.

Das geht natürlich auch.

von Wolfgang (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Karl schrieb:
> Zweites Problem: Division durch 250 ist deutlich zweiraubender als
> Division durch 256.

Wer zwingt dich denn zu einer Abtastfrequenz von 2,5kHz?
Was spricht gegen 2,56kHz?

von Karl (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Dergute W. schrieb:
> Ein ganz simpler Schritt in diese Richtung waer', wenn du einfach das
> Ergebnis aus deinem Filter in ein weiteres, gleich aufgebautes Filter
> gibst.

Was dem elektronischen Äquivalent von zwei hintereinander geschalteten 
RC-Tiefpässen entspräche?

Der doppelte Speicherbedarf wäre hier im Gegensatz zum Ringbuffer kein 
Problem, die Rechnerei dürfte sich auch auf 32 Bit beschränken und die 
Ausführungszeit würde sich knapp verdoppeln... mal probieren.

Possetitjel schrieb:
> Ja, klar.
> Hast Du mal versucht, die Größe der Auswirkung abzuschätzen?

Die Simulation sagt, bei 50.2Hz und 50 Werten pro Periode 0.4% Ripple, 
das ist so viel wie der Tiefpass mit N = 1024 bringt.

Possetitjel schrieb:
> Das geht natürlich auch.

Hab das gerade mal durchgerechnet: 256 Werte x 2 Byte x 7 Kanäle (es 
werden 10 Kanäle gemessen, aber nur 7 gespeichert) bekomme ich nicht in 
den Ram, 128 Werte gehen.

Aktuell habe ich 50 Messungen pro Periode: Um auf 2^n zu kommen müsste 
ich auf 32 Messungen pro Periode runtergehen, hätte dann 4 Perioden im 
Buffer. Würde halt Auflösung verschenken.

Oder auf 64 Messungen hochgehen, das wird aber seeeehr knapp mit dem 
AD-Wandler.

von Karl (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Verdammte Axt! Ich brauche gar keinen riesigen Ringbuffer. Ich brauche 
auch keinen gleitenden Mittelwert.

Ich brauche nur einen kleinen Ringbuffer, in den der ADC die Daten 
schiebt und der alle paar msec ausgewertet wird. Die Werte quadriere und 
summiere ich, zähle dabei mit und wenn 50 Werte zusammen sind, bilde ich 
aus der Summe einmal den Mittelwert.

Dann habe ich zwar nur 50 Werte pro Sekunde, aber das reicht allemal. 
Über die schiebe ich noch ein IIR mit N = 16 oder 32 und komme unter 
0.1% Ripple. Die Frequenz darf halt nicht mehr als 0.2Hz abweichen.

Sollte doch gehen, oder?

von Dergute W. (derguteweka)


Bewertung
0 lesenswert
nicht lesenswert
Moin,

Karl schrieb:
> Sollte doch gehen, oder?

Sollte schon. Zumindest hab ich das auch schon gemacht; da tast' ich im 
AVR mit 32kSamples/sec ein Audiosignal ab, jag's durch eine Filterbank 
und summiere so die Momentanpegel der einzelnen Frequenzbaender auf, um 
sie danach anzuzeigen...

Beitrag ""LED-Spectrumanalyzer"software ohne Fouriertransformation"

Gruss
WK

Beitrag #5320358 wurde von einem Moderator gelöscht.
von Karl (Gast)


Bewertung
0 lesenswert
nicht lesenswert
c-hater schrieb im Beitrag #5320358:
> Schwachsinn (zumindest zur Hälfte)...

Hach Gottchen, was bist Du denn für ein Troll?

Possetitjel schrieb:
> Aber Division durch 256 und anschließendes Multiplizieren
> mit 1.024 ist nicht so kompliziert.

Ich habe es jetzt mit einem periodischen Mittelwertfilter und einem 
nachgeschalteten Tiefpass gelöst.

Die Divison 32 Bit / 50 in Asm optimiert braucht 20µsec, die 
Quadratwurzel nochmal ähnlich. Damit kann ich leben.

von A. S. (achs)


Bewertung
0 lesenswert
nicht lesenswert
Karl schrieb:
> Ich brauche nur einen kleinen Ringbuffer,

Das ist ja schön, wenn Du die Antworten hier umsetzt, aber erklär doch 
mal, wozu Du dann den Ringbuffer einbaust? Er spart Dir doch keine 
Rechenzeit.

von Karl (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Achim S. schrieb:
> wozu Du dann den Ringbuffer einbaust? Er spart Dir doch keine
> Rechenzeit.

Nö, aber der ADC wird per ISR alle 40usec bedient. Die ISR möchte ich so 
kurz wie möglich halten, also wirklich nur Wert auslesen, dem passenden 
Kanal zuordnen, neuen Kanal setzen und nächste Wandlung fertigmachen. 
Die wird dann im Timer-Interrupt gestartet.

Im Hauptprogramm habe ich dann genug Zeit, die bisherigen Werte auf 
gültigen Bereich zu prüfen, zu skalieren und zu mitteln. Auch werden 
mehrere Kanäle miteinander verrechnet (Offset...), was in der ISR nicht 
möglich wäre, weil ich da nur immer den Wert des aktuellen Kanals habe.

Die Berechnung erfolgt über etwa 10 Werte, wobei es auch nicht schlimm 
ist wenn mal mehr Werte auflaufen, weil gerade ins Display geschrieben 
wird. Die Werte müssen nur so schnell abgearbeitet werden, dass der 
Buffer nicht vollläuft, sprich der Write-Pointer den Read-Pointer 
einholt.

von A. S. (achs)


Bewertung
0 lesenswert
nicht lesenswert
Karl schrieb:
> Nö, aber der ADC wird per ISR alle 40usec bedient. Die ISR möchte ich so
> kurz wie möglich halten, also wirklich nur Wert auslesen, dem passenden
> Kanal zuordnen, neuen Kanal setzen und nächste Wandlung fertigmachen.
> Die wird dann im Timer-Interrupt gestartet

Ich kenne ja Dein Programm nicht, und betrifft auch nicht die 
Fragestellung, aber es ist (bei >> 8Bitter) relativ unwahrscheinlich, 
dass Y+=adc*adc mehr Zeit braucht, als der Eintrag in einen 
interruptfesten Fifo (inclusive der Sperrzeit zum Auslesen, die gehört 
ja dazu!).

Wenn Du die Summe geschickt wählst (im Takt Deiner Main-Loop), dann 
kannst Du sogar auf jedes blockieren verzichten (und mit 
Spiegelvariablen arbeiten).

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]
  • [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.