Forum: Mikrocontroller und Digitale Elektronik arm_cmplx_mag_q31 Wie wird diese Funktion richtig genutzt?!


von hochsitzcola (Gast)


Lesenswert?

Ich möchte mit einem STM32F103 den Betrag eines Vektors in einer 
zeitkritischen Routine berechnen.
In den CMSIS libraries gibt es dafür die Funktion arm_cmplx_mag_q31()
https://www.keil.com/pack/doc/CMSIS/DSP/html/group__cmplx__mag.html

Aber wie benutze ich die?! Mit Festkommas bin ich nicht sattelfest :-)
Als Beispiel kann das klassische "Maurerdreieck dienen.
1
q31_t complex_voltage[2] = {3000, 4000};
2
q31_t result[2];
3
arm_cmplx_mag_q31(complex_voltage,result,1);

hier würde ich jetzt als result[0] gerne 5000 rausbekommen.
Leider habe ich keine Beispiele gefunden, die mich zum richtigen 
Ergebnis geführt hätten.

Die Funktion arm_sqrt_q31 habe ich mit diesem Beispiel dazu gebracht, 
sinnvolle Werte zurückzugeben.
https://github.com/DD4WH/Teensy-SDR-Rx/blob/master/AM_demod.cpp

Weiß jemand wie man arm_cmplx_mag_q31 richtig anwendet?

Gruß
hochsitzcola

von Jim M. (turboj)


Lesenswert?

Die Funktion ist eigentlich ziemlich übersichtlich:
1
 /* C[0] = sqrt(A[0] * A[0] + A[1] * A[1]) */ 
2
    real = *pSrc++; 
3
    imag = *pSrc++; 
4
    acc0 = (q31_t) (((q63_t) real * real) >> 33);   // [1]
5
    acc1 = (q31_t) (((q63_t) imag * imag) >> 33); 
6
    /* store the result in 2.30 format in the destination buffer. */ 
7
    arm_sqrt_q31(acc0 + acc1, pDst++);

Bei Werten von 4000 und 5000 kommt bei der Quadrierung [1] allerdings 
0(Null) heraus.

Abhilfe: Wertebereich vernünftig wählen, d.h. anders skalieren. Zum 
Bleistift die 3000 und die 4000 vorher mit 1024 multiplizieren.

von c-hater (Gast)


Lesenswert?

Jim M. schrieb:

> Bei Werten von 4000 und 5000 kommt bei der Quadrierung [1] allerdings
> 0(Null) heraus.

Nicht bei der Quadrierung, sondern bei der Skalierung der 
Zwischenergebnisse auf FP 4.28...

@TO: die Routine erwartet die Eingabe im 1.31-Festkommaformat und 
liefert das Ergebnis mit FP 2.30, bist du dir dessen bewusst?

von hochsitzcola (Gast)


Lesenswert?

OK, da spuckt also das rightshift 33 in die Suppe. Wenn die 
Eingangswerte groß genug sind, geht es tatsächlich. Da das Ergebnis als 
2.30 berechnet wird, braucht es beim zurückshiften eine Stelle weniger, 
um wieder auf 1.31 zu kommen. So kommt für temp5 auf jeden der 
gewünschte Wert 5000 raus :-)
Vielen Dank!
Komisch finde ich nur, das es keinen Hinweis in der 
Funktionsbeschreibung gibt, daß die Eingangswerte eine mindestgröße 
haben müssen...

1
q31_t complex_voltage[2] = {3000<<10, 4000<<10};
2
q31_t result[2];
3
arm_cmplx_mag_q31(complex_voltage,result,1);
4
temp5=(result[0]>>9)+1;

Gruß
hochsitzcola

von c-hater (Gast)


Lesenswert?

hochsitzcola schrieb:

> Komisch finde ich nur, das es keinen Hinweis in der
> Funktionsbeschreibung gibt, daß die Eingangswerte eine mindestgröße
> haben müssen...

Müssen sie ja auch nicht haben. Alles bis herunter zu 0 funktioniert 
ganz hervorregend und liefert ein Ergebnis, was im Rahmen der lt. Doku 
erwartbaren Genauigkeit korrekt ist.

Die Verfasser der Doku gehen halt davon aus, dass jemand, der 
Fixed-Point-Routinen verwendet, auch in der Lage ist, deren 
Implikationen zu begreifen.

Tatsächlich benutzt du sie ja nicht "as intended", sondern 
zweckentfremded. Das ist OK, solange man weiß, was man tut. Du weißt das 
nicht, also solltest du es lernen. Und zwar, bevor du es tust...

Das hier ist nämlich noch ziemlich einfach zu überschauen. Es gibt 
reichlich Operationen, die nicht so einfach zu verstehen sind. Und auch 
nicht so einfach zweckenentfremded zu benutzen...

von hochsitzcola (Gast)


Lesenswert?

c-hater schrieb:
> Tatsächlich benutzt du sie ja nicht "as intended", sondern
> zweckentfremded. Das ist OK, solange man weiß, was man tut. Du weißt das
> nicht, also solltest du es lernen. Und zwar, bevor du es tust...

wenn die Menschen immer erst alles hätten verstehen wollen, bevor sie es 
getan haben, würden wir wahrscheinlich noch auf den Bäumen hocken :-)
Aber du hast natürlich recht, wenn man etwas verstanden hat, tut man 
sich deutlich leichter in der Anwendung :-)

Gruß
hochsitzcola

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.