Forum: Mikrocontroller und Digitale Elektronik PT1 Filter Erklärung


von NeuerProgrammierer (Gast)


Lesenswert?

Hallo Leute,

ich möchte bei einem Mikrocontroller Langzeitwerte der AD-Wandler durch 
den PT1 Filter schicken. Diesen Code habe ich aus einen anderen Beitrag 
hier im Forum entnommen.

Kann mir einer den unteren Code etwas erklären ?

unsigned long mittelwert(unsigned long newval)
{
static short n = 0;
static unsigned long avgsum = 0;

if (n<128) {
n++;
avgsum += newval;
return avgsum/n;
}else {
avgsum -= avgsum/128;
avgsum += newval;
return avgsum/128;   }
}

Gruss

Sebi

von Ein Gast (Gast)


Lesenswert?

NeuerProgrammierer schrieb:
> Kann mir einer den unteren Code etwas erklären ?

Der erste Teil deiner If-Schleufe wird beim Start des Filter benötigt. 
Danach läuft es als ganz normales IIR-Filter.

von Michael (Gast)


Lesenswert?

Und was bitte ist eine If-Schleife?

von Bronco (Gast)


Lesenswert?

NeuerProgrammierer schrieb:
> ich möchte bei einem Mikrocontroller Langzeitwerte der AD-Wandler durch
> den PT1 Filter schicken. Diesen Code habe ich aus einen anderen Beitrag
> hier im Forum entnommen.

Das ist aber kein PT1-Filter.

Ein PT1-Filter sieht in etwas so aus:

Ausgang = Speicher = Speicher*(1.0 - Faktor) + Eingang * Faktor;
mit Faktor = 0.0 bis 1.0

Über den Faktor wird die Gewichtung zwischen Eingang und Speicher 
eingestellt, d.h. welchen Einfluß der Eingangswert auf den Speicher und 
damit den Ausgang hat.
Je kleiner der Faktor desto träger das Ding, weil ein neuer Eingangswert 
nur einen kleinen Einfluß auf den Speicher hat.

PT1 bedeutet übrigens, daß der Speicher die Tiefe 1 hat.

von Michael R. (dj_motionx)


Lesenswert?

Michael schrieb:
> Und was bitte ist eine If-Schleife?

Ein Dauerbrenner aber immer wieder gut
http://www.if-schleife.de/
hi hi hi

Sie dir mal auf Wikipedia den Absatz Zeitdiskretes PT1-Glied an. Genau 
so kannst das dann implementieren.

L.g.

von NeuerProgrammierer (Gast)


Lesenswert?

Ich habe diesen C-Code aus der Seite von Lothar Miller gefunden. Er ist 
übrigens denke mal Moderator hier im Forum.

http://www.lothar-miller.de/s9y/archives/25-Filter-in-C.html

Da hat er diesen Code als dem PT1 genannt..!?

von Floh (Gast)


Lesenswert?

> Das ist aber kein PT1-Filter.
Doch, ist es. Es ist nur nicht auf 1 normiert.

von NeuerProgrammierer (Gast)


Lesenswert?

Floh schrieb:
> Doch, ist es. Es ist nur nicht auf 1 normiert.

Was kann ich daraus verstehen? :)

von eProfi (Gast)


Lesenswert?

Du kannst die if-Abfrage auch weglassen und den Filter auf einen Wert 
initialisieren:
avgsum = 128 * "initwert" ;

Ich würde das Filtern und das Berechnen des Endwertes trennen, denn oft 
muss viel öfter gefiltert werden, als man den Endwert braucht.

Warum Lothar im 2. Beispiel statt 128 dann 100 verwendete (mit dem 
Hinweis, der Compiler kann konstanten besser optimieren)?!?

Achte immer auf die Wertebereiche, bei einem 10Bit-ADC-Wert und /64 
reichen 16 Bits für die Summe.

von NeuerProgrammierer (Gast)


Lesenswert?

In der main funktion habe ich zum schluss eine warteschleife von 10ms 
und schicke jeden zehnten AD-Wert in das Filter. Sodass für einen Wert 
10x10ms=100ms benötigt wird.

Habe eine Filterstärke von 128 sodass das komplette 100ms x 128 = 
12,8sekunden dauert den langzeit mittelwert zu berechnen.

Wenn ich aber anstatt 128 eine Filterstärke von 512 funktioniert es 
nicht mehr...! Was könnte das Problem sein ? Vllcht Überlauf??

von Bronco (Gast)


Lesenswert?

Floh schrieb:
> Doch, ist es. Es ist nur nicht auf 1 normiert.
Das Verhalten bei "leerem" Speicher (der Teil in der "if-Schleife") 
entspricht nicht dem PT1-Filter.

von Wolfgang (Gast)


Lesenswert?

Bronco schrieb:
> Das ist aber kein PT1-Filter.
>
> Ein PT1-Filter sieht in etwas so aus:
>
> Ausgang = Speicher = Speicher*(1.0 - Faktor) + Eingang * Faktor;
> mit Faktor = 0.0 bis 1.0

Wie recht du hast - zumindest mit der Gleichung. Wenn mich meine 
Rechenkenntnisse nicht ganz verlassen haben, läßt sich der C-Algorithmus

NeuerProgrammierer schrieb:
> avgsum -= avgsum/128;   (1)
> avgsum += newval;       (2)
> return avgsum/128;   }  (3)

wunderbar wie folgt umformen:
Ersetzt man avgsum/128 durch Speicher (4), so ergibt sich
1
  Ausgang = Speicher      (3)  
2
  avgsum = (avgsum - avgsum/128) + Eingang  (1 in 2)     
3
  Speicher*128 = (Speicher*128 - Speicher) + Eingang     (mit 4)
4
  Speicher = Speicher*(1-1/128) + Eingang / 128        (/128)
Wählen wir Faktor = 1/128 landen wir bei
  Ausgang = Speicher = Speicher * (1.0 - Faktor) + Eingang * Faktor

q.e.d.

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.