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_tcomplex_voltage[2]={3000,4000};
2
q31_tresult[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
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.
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?
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...
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...
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
Eine eigene Frage?
Dieser Thread ist über 5 Jahre alt.
Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.