Ich versuche zum ersten mal einen einfachen Tiefpass auf einem 32bit ARM
Cortex M3 (LPC1766) zu realisieren. Ich erhoffe mir, dass mal jemand
drüber schaut ob irgendwo logische Fehler sind oder der Code so
überhaupt richtig lauffähig ist und seine Funktion erfüllt.
Dabei bin ich nach dem Buch "Signalverarbeitung" von Martin Meyer
vorgegangen.
Dort wird mit der bilinearen Transformation
und der bekannten Übertragungsfunktion eines analogen Tiefpasses
der Frequenzgang möglichst gut angenähert. Man erhält wie im Buch
beschrieben dann
Die Grenzfrequenz und Abastrate will ich später zum rumspielen
verändern. Ich substituiere
und stelle daraus die Differenzengleichung auf
Zurücktransformiert:
Umstellen nach y[n]
Ich habe nun mal etwas Pseudocode erstellt, der diesen Filter
realisieren soll. Ich habe jedoch noch nicht auf eventuelle Überläufe
geachtet. Dazu muss ich mir erst noch angucken welche Genauigkeit ich
bei den Koeffizienten brauche bzw. wie sich diese überhaupt auf den
Freuquenzgang auswirken.
1 | uint16 uiSample = ReadADU(); //12Bit Messwert, Offset bei (2^12)/2 = 2048
|
2 | uiSample = uiSample>>2; //10Bit DA-Wandler
|
3 |
|
4 | int16 iOutput[2]; //letzter[0] und vorletzter[1] Filteroutput (y[n] und y[n-1])
|
5 |
|
6 | int8 b[2] = {b0, b1}; //Koeffizienten, Fixkomma mit einer Nachkommastelle, z.B. -0.7 ^= -7
|
7 | int8 a[2] = {a0, a1}; // b0=b1=1, a0=1+tau, a1=1-tau
|
8 |
|
9 | int16 iBuffer[2]; // x[n] und x[n-1]
|
10 |
|
11 | //Weiterrücken im Buffer
|
12 | iBuffer[1] = iBuffer[0];
|
13 |
|
14 | //Sample einfügen, aber bitte mit Vorzeichen
|
15 | iBuffer[0] = (int16)uiSample;
|
16 |
|
17 | //letzter ist nun vorletzter
|
18 | iOutput[1] = iOutput[0];
|
19 |
|
20 |
|
21 | //Na dann mal los, hoffentlich ohne Überlauf
|
22 | //Nachkommastelle wieder rausrechnen mit Faktor/Divisor 10
|
23 | for (int i = 0; i<2; i++) //1. Schritt
|
24 | {
|
25 | iOutput[0] = iOutput[0] + (b[i]*iBuffer[i])/10;
|
26 | }
|
27 |
|
28 | iOutput[0] = iOutput[0] - (a[1]*iOutput[1])/10; //2. Schritt
|
29 | iOutput[0] = (iOutput[0]*10)/a[0]; //3. Schritt
|
30 |
|
31 |
|
32 | uint16 IchBinGefiltert= (uint16)iOutput[0]; //fertig
|
Ich habe überlegt ob es nicht sinnvoll wäre den Offset vorher
rauszurechnen und später wieder drauf zu addieren. Naja erstmal sehen
was ihr meint.
Gruß
Maddin