Forum: Digitale Signalverarbeitung / DSP / Machine Learning IIR auf DsPic mit Koeffizient > 1


von Rupert (Gast)


Lesenswert?

Ich bin dabei einen IIR-Filter zweiter Ordnung auf einem dsPIC 30F6010 
zu programmieren und würde dabei gerne das von Microchip programmierte 
Beispiel CE001 
(http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=2620) 
benutzen.
Die IIRTransposed-Funktion benötigt dabei die 5 Filter-Koeffizienten 
({b0, b1, a1, b2,a2}) in Fractional-1.15. Da a1 aber -1.8937941 ist, 
müsste ich theoretisch durch 2 dividieren. Nur verbietet sich mir das, 
weil dabei ja auch a0 durch zwei dividiert würde und folglich die 
Funktion von einem falschen a0 ausgehen würde (immer noch 1 statt neu 
0.5).

Weiss da jemand, wie ich da vorgehen muss?

von die ??? (Gast)


Lesenswert?

Du kannst den Filter getrost mit Koeffizienten füttern die skaliert 
sind. Das drückt sich lediglich in einem Verstärkungsfaktor aus. Die '1' 
(a_0) steht im zeitdiskreten Bereich schließlich für den Koeffizienten 
des "Ausgangs" y_k - ob dieser "Ausgang" nun auf 1 oder 0.5 bezogen wird 
ist egal. Mach dir den Spaß und transformiere

1
        b_0 + b_1 * z^-1 + b_2 * z^-2
2
H(z) = -------------------------------
3
         1 + a_1 * z^-1 + a_2 * z^-2

und anschließend

1
        b_0 + b_1 * z^-1 + b_2 * z^-2
2
H(z) = -------------------------------
3
        0.5 + a_1 * z^-1 + a_2 * z^-2

in den zeitdiskreten Bereich und bilde die Differenzengleichung, so 
sieht man es imho am besten.

von Rupert (Gast)


Angehängte Dateien:

Lesenswert?

Vielen Dank schon mal. Leider verstehe ich es trotzdem noch nicht so 
ganz.
Da a0 ja der Koeffizient für den Ausgang ist, soll ich dann folglich am 
Schluss noch durch 2 dividieren (resp. shift rechts um 1 bit)?
Konkret:
IRTransposedStruct-Type hat ja da als letztes Argument "int finalShift". 
Kommt da also eine 1 rein?

Zudem tue ich mich echt schwer, das oben verlinkte Beispiel (und auch 
die darin vorkommende Funktionen) zu verstehen. Ich habe deshalb mal auf 
eigene Faust versucht, die Funktionen anzuwenden. Wäre schön, wenn sich 
das mal jemand anschauen könnte. Denn funktionieren tut es (wie 
erwartet) leider nicht. Die Beschreibung der Funktionen findet man unter 
"5.15       IIRTransposed" in der angehängten Datei.


#include "dsp.h"
[...]

fractional Coeff[5] = {258, 0,-31028, -258, 15869};
fractional d1[2] = {0,0};
fractional d2[2] = {0,0};
fractional Source, Dest;

IIRTransposedStruct BandPass =
{0, Coeff, 0xFF00, d1, d2, 1};
[...]

IIRTransposedInit (&BandPass);
fractional test = *IIRTransposed (16, &Source, &Dest, &BandPass);


Ich muss ehrlich eingestehen, dass ich nicht wirklich viel verstehe. 
Weder was es mit diesem X-Data / Y-Data auf sich hat, noch was unter 
numSamps (1. Argument für IIRTransposed) verstanden wird (ich habe 16 
eingegeben, weil im Beispiel von Microchip 256 steht, wobei dort 
irgendwie alle 16 16-bit A/D Result Buffer verwendet werden (ich brauche 
deren nur einen).
Wäre wirklich super, wenn da jemand was Konstruktives dazu schreiben 
könnte, denn ich bin arg am verzweifeln (Die Uhr tickt.)

von die ??? (Gast)


Lesenswert?

Rupert wrote:
> soll ich dann folglich am Schluss noch durch 2 dividieren (resp. shift
> rechts um 1 bit)?

Nein, du verstärkst zum Schluss wieder. Links-Shift.


> IRTransposedStruct-Type hat ja da als letztes Argument "int finalShift".
> Kommt da also eine 1 rein?

Wenn du vorher mit 1/2 normiert hast dann macht es natürlich Sinn den 
"Ausgang" am Ende wieder mit 2 zu denormieren - ergo finalShift = 1. Zum 
probieren geht auch 0, die Werte sind dann entsprechend kleiner.


> Ich habe deshalb mal auf eigene Faust versucht, die Funktionen anzuwenden.

Das ist gut. Ein paar Gedanken:

1
#include "dsp.h"
2
3
/* Aufpassen bei der Reihenfolge. Es kommt vor, */
4
/* dass die Koeffizienten nicht der Reihe nach */
5
/* abgelegt werden, sondern durcheinander -> Doku */
6
fractional Coeff[5] = {258, 0,-31028, -258, 15869};
7
8
/* OK */
9
fractional d1[2] = {0,0};
10
11
/* OK */
12
fractional d2[2] = {0,0};
13
14
/* OK, _ein_ Sample rein und _ein_ Sample raus */
15
fractional Source, Dest;
16
17
/* Liegen die Koeffizienten in der Data-Code-Sektion? */
18
IIRTransposedStruct BandPass = {0, Coeff, 0xFF00, d1, d2, 1};
19
20
/* Nur einmal aufrufen, niemals im laufenden Betrieb */
21
IIRTransposedInit (&BandPass);
22
23
/* Nicht gut! 16 sollte hier 1 sein, dein Samplearray ist nur 1 tief */
24
fractional test = *IIRTransposed (16, &Source, &Dest, &BandPass);


> Ich muss ehrlich eingestehen, dass ich nicht wirklich viel verstehe.
> Weder was es mit diesem X-Data / Y-Data auf sich hat

Ich kenne den DSPic nicht, aber wie es mir scheint sind X-Data/Y-Data 
Speicherbereiche die per Code-Page-Schalter eingestellt werden können. 
Die Koeffizienten dürfen im X-Data-Bereich oder im Programmspeicher 
abgelegt sein (daher der Wert coeffsPage). Die Delaylines dürfen 
ausschließlich im Y-Data-Bereich abgelegt werden.

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.