Forum: Mikrocontroller und Digitale Elektronik Mittelwert sinnvoll bilden


von Christian S. (mueke)


Lesenswert?

Halo Leute,
ich absolviere zurzeit ein Praktikum. Hier frage ich nun einen Sensor 
(PYD1998) ab (ca jede 15ms). Dieser gibt mir einen digitalen Wert 
(14bit) aus. Aus diesem Wert möchte ich nun einen gleitenden Mittelwert 
bilden. Zur Verfügung steht aber nur ein PIC12F675, zu programmieren in 
Assembler (C Overhead zu groß). Zurzeit mache ich das nach folgendem 
Schema:

(Alter Wert + Neuer Wert) / 2

Dieses ist aber nicht genau genug, da der Wert des Sensors bei 
Erfasssung einer Person größere Sprünge macht. Der Mittelwert folgt mir 
dem Signal zu schnell.

Hat jemand ne Idee, was man hier fü nen Algorithmus nehmen kann, der 
auch in Assembler auf den "kleinen" PIC passt?

MfG
Muecke

von Ralph (Gast)


Lesenswert?

Der Algorithmus ist schon der Richtige.
Nimm 4 , 8 oder 16 Werte.
Welcher Wert für dich der Beste, ist musst du selbst bestimmen.

Wenn du ANSI C nimmst und auf Bibliotheken verzichtest, wird der C 
Overhead sehr klein.

Also zb eine Ausgabe nicht mit PRINTF sondern mit direkter Zuweisung in 
den Ausgangsbuffer schreiben.

von Christian S. (mueke)


Lesenswert?

Danke schön,
aber das würde doch auch bedeuten, dass ich bei 16 Werten, jeden Wert in 
einer Variablen speichern müsste. Das wären in meinem Fall ja 
16Variablen a 16bit, also 32 Byte...
Oder bekommt man das auch kleiner hin?

MfG
Muecke

von Ralph (Gast)


Lesenswert?

Du musst halt sehen wieviel Ram du dafür verwenden kannst. Das ist einer 
der Punkte die du berücksichtigen musst, um die optimalen Parameter zu 
bestimmen.
Eventuell reichen ja auch schon 4 Werte ==> 8 Byte

Das Ergebnis einer solchen Praktikumsarbeit kann aber auch sein, das der 
verfügbare µC für die Aufgabe nicht geeignet ist.
Mit Begründung 1.; 2.; ........
Sowie einer Alternative, sprich einem geeigneten µC.

Dazu muss aber die ganze Aufgabenstellung, und nicht nur der 
beschriebene Ausschnitt herangezogen werden.

von Hannes L. (hannes)


Lesenswert?

Beitrag "Re: Mittelwert berechnung"

Ist zwar für AVR und ADC, aber anhand der Kommentare sicher auf Dein 
System und Deinen Sensor übertragbar.

...

von Joe (Gast)


Lesenswert?

>> Das wären in meinem Fall ja 16Variablen a 16bit

Du denkst falsch, du brauchst nur 2 Variablen. Der jeweils neue ADC Wert 
sowie den Mittelwert.

adc_summe += adc_wert;

Nen Schleifchen drumherum und gut ist.

von Rene (Gast)


Lesenswert?

Gleitender Mittelwert - ist leider Schrott. Versuch den exponentiellen 
Mittelwert.
http://www.ibrtses.com/embedded/exponential.html

von Thomas (kosmos)


Lesenswert?

Hallo, habe leider keine Ahnung was dein Sensor macht? Misst er die 
Wärmeaussendung eines Objektes? Was willst du genau damit feststellen 
nur ob jemand vorbeiläuft oder auch andere Sachen z.B. wie warm das 
Objekt ist wie weit weg usw?

Könnte mir vorstellen dein dein Wert zu stark schwankt weil man beim 
vorbeilaufen mit einem Körperteil näher am Objekt ist als mit einem 
anderen. Probier doch einfach mal nciht alle 15mSek sondern vieleicht 
alle 100mSek zu messen oder mit noch größeren Abständen so das du nur 
einen Wert in der Zeit erhälts wo du sonst 10 Werte bekommst.

Du kannst aber auch das Signals des Sensors mittels eine regelbaren 
Widerstand in Reihe und danach einen Kondensator zur Masse dämpfen, oder 
muss das ganze in Software geschehen.

Aber man muss schon wissen was du genau vorhast, also erklär mal deine 
Aufgabenstellung genauer.

von yalu (Gast)


Lesenswert?

Was du offensichtlich suchst, ist ein Tiefpassfilter in Software
(würde der Sensor keine Digital- sondern Analogwerte ausgeben,
könntest du das Filter natürlich auch hardwaremäßig realisieren).

Die meisten Softwarefilter bilden eine gewichtete Summe über die
letzten n (FIR, finite impulse response) oder alle (IIR, infinite
impulse response) Messwerte. Die Summe der Gewichte ist i. Allg.
gleich 1, so dass bei konstanten Messwerten genau dieser Wert als
Ergebnis herauskommt.

Der (gleichgewichtete) gleitende Mittelwert ist die einfachste Form
eines FIR-Filters. Dabei werden die letzten k Messwerte jeweils mit
dem Faktor 1/k gewichtet:


Dazu müssen natürlich die letzten k Werte gespeichert werden, es sei
denn, es reicht dir aus, den Mittelwert nur nach jedem k-ten
Messzyklus auszugeben. Dann kannst du da so machen, wie Joe
vorgeschlagen hat.

Die exponentielle Mittelung (s. Rene) ist hingegen die einfachste Form
eines IIR-Filters. Dabei unterscheiden sich die Gewichte aufeinander
folgender Messwerte um einen konstanten Faktor c:


Der Faktor 1-c sorgt dafür, dass die (unendliche) Summe der Gewichte
gleich 1 ist. Die unendliche Summe kann man einfacher rekursiv
hinschreiben:


Mit dem Faktor c kann eingestellt werden, wie stark das Filter auf
Änderungen der Messwerte reagiert (c=1: überhaupt nicht, c=0: in
voller Höhe).

Durch andere geeignete Wahl der Gewichte kann praktisch jede
Filtercharakteristik realisiert werden. Da es dir aber nicht darum
geht, ganz bestimmte Frequenzbereiche scharf auszuschneiden, sondern
die Werte einfach irgendwie zu glätten, sollte einer der beiden
Vorschläge ausreichend sein.

Die exponentielle Mittelung ist vor allem dann einfacher zu
realisieren, wenn mit jedem Messwert ein gefilteter Wert als Ergebnis
herauspurzeln soll, da außer dem letzten Messwert und dem Mittelwert
nichts gespeichert werden muss.

Ein Nachteil besteht darin, dass - insbesondere bei großem c - ein
grober Ausreißer in den Messwerten das Ergebnis u. U. über sehr lange
Zeit verfälscht, da sein Einfluss zwar exponentiell abnimmt, aber nie
ganz verschwindet. Bei der gleitenden Mittelung verschwindet der
Einfluss nach k Messungen vollständig.

Wird der Mittelwert nur alle k Messwerte benötigt, ist die Implemen-
tierung der gleitenden Mittelung genauso einfach wie die der
exponentielle Mittelung.

Um die Divisionen für den µC zu vereinfachen, wählt man für k
sinnvollerweise Zweierpotenzen bzw. für c die Kehrwerte von
Zweierpotenzen, so dass die Divisionen durch Schiebeoperationen
realisiert werden können.

von Zeusi (Gast)


Lesenswert?

Hi,

>>Dazu müssen natürlich die letzten k Werte gespeichert werden, ...

äh nÖ,..

klar ist wie das arithmetische mittel gebildet wird,..
daher braucht man prinzipiell nur
3
zu Speicherende werte,..

1)  k
2)  arithmetisches mittel
3)  neuer wert

damit man im µC nicht immer hin und her rechnen muss sind natürlich 4 
besser:

4) summe aller elemente =(arith. mittel. * k)

nochmal schön:

der ablauf:

man bekommt einen neuen wert
addiert diesen zu gespeicherten Summe auf:
jetzt will man das mittel haben , ok:

super, jetzt kann man damit machen was man will, achtung ein neuer wert 
schleicht sich an =>

ich denke das prinzip ist verstanden, du brauchst also
nur
k
die summe
den wert
um dein problem zu lösen,..

TIPP:

wenn du kein bock auf umständige division hast, addiere erst 2 neue 
werte auf und dan diviere mit nen shift nach rechts (damit umgehst du 
die division mit "krummen" divisoren), ...

ich hoffe ich habe geholfen,..

grüüüße

von Zeusi (Gast)


Lesenswert?

oh,.. das mit den schiebeoperationen hat yalu schon gesagt, kommt davon 
das man das nur überfliegt sry g

von Michael G. (linuxgeek) Benutzerseite


Lesenswert?

Versuche es mal mit dem geometischen Mittelwert, der reagiert nicht so 
stark auf Ausreisser:

von pic-assambler (Gast)


Lesenswert?

Wie Setzt man Solche formeln in pic-assambler Um??

von yalu (Gast)


Lesenswert?

@Zeusi:

Was du beschreibst (wenn ich das richtig verstanden habe), ist die
Berechnung des Mittelwerts über alle bisherigen Messwerte. Dazu
braucht man die Einzelwerte in der Tat nicht zu speichern.

Allerdings liefert dieses Verfahren nicht unbedingt das gewünschte
Ergebnis, das der Einfluss eines Messwerts auf das Ergebnis mit jeder
neuen Messung geringer wird. Dies bedeutet, dass das Ergebnis mit
wachsender Laufzeit des Verfahrens immer langsamer auf Änderungen der
Messungen reagiert.

Das "gleitend" im gleitenden Mittelwert bezieht sich auf das
mitlaufende Zeitfenster konstanter Breite k, innerhalb dessen die
Messungen gemittelt werden. Alle Messwerte, die älter als die letzen k
sind, werden bei der Mittelung nicht mehr berücksichtigt. Damit ist
das Verhalten des Verfahrens unabhängig von der Laufzeit.

Das Aufsummieren der letzten k Werte kann effizient dadurch erreicht
werden, dass in jedem Messschritt der Messwert x(n) zur Summe addiert
und der Messwert x(n-k) von der Summe subtrahiert wird. Damit x(n-k)
zum aktuellen Zeitpunkt noch bekannt ist, müssen aber die letzten k
Werte gespeichert werden.

@Michael G.:

> Versuche es mal mit dem geometischen Mittelwert, der reagiert nicht
> so stark auf Ausreisser:

Stimmt. Nur muss dann OP Christian auch noch eine Wurzelfunktion in
seinen PIC quetschen :-)

Übrigens bin ich begeistert, dass du den Index "geom" in der Formel in
aufrechten Buchstaben geschrieben hast. Das machen nicht viele.

@pic-assembler:

> Wie Setzt man Solche formeln in pic-assambler Um??

Ich stehe eher auf AVRs, außerdem bin ich sehr faul und lasse die
Umsetzung lieber den C-Compiler erledigen ;-)

von pic-assambler (Gast)


Lesenswert?

> Ich stehe eher auf AVRs, außerdem bin ich sehr faul und lasse die
> Umsetzung lieber den C-Compiler erledigen ;-)

Im Ersten beitrag Wurde aber Eindeutig von asm Geschrieben. Demnach 
Gehen eure Hochwissenschaftlichen antworten an der frage Vorbei.

von Karl H. (kbuchegg)


Lesenswert?

pic-assambler wrote:
> Wie Setzt man Solche formeln in pic-assambler Um??

Indem man seinen Fundus an Rechenfunktionen durchkramt und
die passenden so kombiniert und abändert, dass
* die Registerbelegungen passen
* die gewünschte Formel berechnet wird.

von Karl H. (kbuchegg)


Lesenswert?

pic-assambler wrote:
>> Ich stehe eher auf AVRs, außerdem bin ich sehr faul und lasse die
>> Umsetzung lieber den C-Compiler erledigen ;-)
>
> Im Ersten beitrag Wurde aber Eindeutig von asm Geschrieben. Demnach
> Gehen eure Hochwissenschaftlichen antworten an der frage Vorbei.

Seit wann hängt der Gültigkeitsbereich einer Formel von der
Programmiersprache ab, in der sie implementiert wird?

von pic-assambler (Gast)


Lesenswert?

> Seit wann hängt der Gültigkeitsbereich einer Formel von der
> Programmiersprache ab, in der sie implementiert wird?

Der gültigkeitsbereich Nicht, aber die realisierbarkeit bei Knappen 
ressourcen.

von Di P. (drpepper) Benutzerseite


Lesenswert?

Wie wäre es mit folgendem Weg (Beispiel mit Fensterbreite von 4 Werten, 
lässt sich natürlich beliebig verändern)?

Mittelwert = Summe(k0 .. k3)/4

Neuer Messwert: k4
-> Mittelwert = (3*Mittelwert + k4)/4

Neuer Messwert: k5
-> Mittelwert = (3*Mittelwert + k5)/4

usw...

Hierbei soll die Gleichung "Mittelwert = (3*Mittelwert + k4)/4" 
natürlich im algorithmischen und nicht im mathematischen Sinne gesehen 
werden.

von rene (Gast)


Lesenswert?

Fuer knappe resourcen kommt eigentlich nur das exponentielle mittel in 
Frage. Siehe http://www.ibrtses.com/embedded/exponential.html
Ein Bisschen Schieben und Addieren.

von Di P. (drpepper) Benutzerseite


Lesenswert?

Mehr ist es bei mir ja auch nicht (Bei Fensterbreiten von 2,4,8,16 usw. 
ist die Division ja auch nur ein Bitshift).

von Andreas S. (andreas) (Admin) Benutzerseite


Lesenswert?

Eine Alternative zu Tiefpassfiltern ist der Medianfilter. Liefert bei 
manchen Anwendungen bessere Ergebnisse und kommt ohne Multiplikationen 
aus.

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.