Forum: Mikrocontroller und Digitale Elektronik Fixpointzahl für Sinus


von Graph Oszillo (Gast)


Lesenswert?

Hallo,

ich habe ein Problem mit, wie im Titel schon erwähnt, mit Fikommazahlen. 
Ich verwende das Luminary LMS38962 Microcontroller Board von TI. Dabei 
verwende ich die miteglieferte DriverLib. In dieser ist eine Funktion 
für den Sinus definiert. Allerdings wird für die Berechnung dieser ein 
Fixkommawert des Datentyps unsigned long benötigt (0.32). Dieser gibt 
den Winkel in Prozent an, also 2*pi = 100% = 0.999999999...
Soviel ich aber weiß (vielleicht ist dieses vermeintliche Wissen falsch) 
werden die Werte aber als Gleitkomma (also mit Mantisse und Exponent) 
abgespeichert.

Leider bin ich nicht in der Lage den Gleitkommawert in einen 
Fixkommawert umzuwandeln, oder direkt einen solchen zu erzeugen (wär 
noch viel besser). Habe schon die ganze Allwissende Müllhalde 
abgeklappert, jedoch ohne Erfolg.

Ich hoffe ihr könnt mir weiterhhelfen.

mfg Graph Oszillo

von Werner (Gast)


Lesenswert?

Graph Oszillo schrieb:
> Leider bin ich nicht in der Lage den Gleitkommawert in einen
> Fixkommawert umzuwandeln

Woran scheitert es denn?
Auf einem µC ist es oft vorteilhaft Fixkommazahlen auf Basis vom 
2er-System zu verwenden. Welche Auflösung brauchst du für deine 
Fixkommazahlen?

von Christian K. (Firma: Atelier Klippel) (mamalala)


Lesenswert?

Uh, Ernsthaft?

Also, nehmen wir mal das Dezimalsystem. Was ergibt sich aus:

0,09 + 0,01?

Und nun mal das Hexadezimalsystem. Was ergibt sich aus:

0x0F + 0x01?

Da der Wertbereich deiner Angabe nach sich auf 0,0 - 0,999~ erstreckt, 
sagen wir mal bis 1,0, und Du nun 32 Bit hast... Wenn die 32 Bit nun die 
Nachkommastellen angeben, so ist das 0xFFFFFFFF was dann 0.999~ 
entsprechen soll. Dieser Hex-Wert entspricht dezimal 4.294.967.295. Die 
1,0 wäre dann 4.294.967.296 oder in Hex 100000000. Klickt es nun?

Anders ausgedrückt: Du dividierst den Fixed-Point von "0,32" Bit ganz 
einfach durch 4.294.967.296 um einen Fließkommawert im Bereich 0,0 - 
0,999~ zu erhalten. Wenn Du aber den Wertbereich 0,0 - 1,0 haben willst, 
dann dividierst Du ganz einfach durch 4.294.967.295.

Grüße,

Chris

Edit: Oder wenn Du den 32-Bit Fixed-Point Wert haben willst dann 
dividierst Du die 4.294.967.296 oder 4,294,967,295 einfach durch den 
Fließkommawert (der den Bereich 0,0 bis 0,999~ oder 1,0 haben muss).

von Thomas E. (thomase)


Lesenswert?

Das ist genau das Gleiche wie beim Ergebnis eines AD-Wandlers. Da ist 
die Zahl nur nicht so groß.

10-Bit-ADC skaliert auf Uref:
U = Uref * ADC_Value / 2^10 (=1024)

Dein Sinus skaliert auf 1:
sin = (1 * )Value / 2^32 (= s.o.)

Oder auf 255 zur Ausgabe auf einen 8-Bit DA-Wandler
DA-Value = 255 * Value / 2^32

mfg.

von Werner (Gast)


Lesenswert?

Wieso braucht man eigentlich eine Tabelle mit dem Typ unsigned long, 
wenn man Zahlen aus dem Bereich 0,000 .. 0,999 - also drei Stellen im 
Dezimalsystem -  als Fixkommawerte ablegen möchte. Um die Zahlen 
darzustellen, reichen 10-Bit, d.h. 22-Bit sind völlig nutzlos.

Welche Genauigkeit muß denn die Tabelle nun wirklich haben, d.h. wie 
sauber muß der Sinus sein?

von Thomas E. (thomase)


Lesenswert?

Werner schrieb:
> Welche Genauigkeit muß denn die Tabelle nun wirklich haben, d.h. wie
> sauber muß der Sinus sein?
So sauber wie möglich. Also unendlich viele Werte. Wie bei Analog.
Das geht aber digital nicht. Das ist immer endlich. Also rechnet man auf 
einem 32-Bit-Rechner auch mit 32 Bit. Damit rechnet er sowieso.
Und zwar solange  wie möglich. Das Umrechnen in eine Dezimalzahl ist 
erst der letzte Schritt und nur für uns. Rechnen kann der Controller 
besser binär. Und die Rundungsfehler bleiben bei 32 Bit klein.

Auf einem 8-Bitter, wo das zum zeitaufwendigen K(r)ampf wird, überlegt 
man sich, ob man so viele Werte wirklich braucht, wenn man sie z.B. auf 
einen 10-Bit DAC ausgeben will.

mfg.

von Christian K. (Firma: Atelier Klippel) (mamalala)


Lesenswert?

Thomas Eckmann schrieb:
> Auf einem 8-Bitter, wo das zum zeitaufwendigen K(r)ampf wird, überlegt
> man sich, ob man so viele Werte wirklich braucht, wenn man sie z.B. auf
> einen 10-Bit DAC ausgeben will.
>
> mfg.

Wobei man auch da beachten muss das es in gewissen Situationen ein paar 
gute Tricks gibt. Viele µC haben einen Hardware-Multiplier, also eine 
Einheit die in meistens einem Takt eine Multiplikation machen kann. 
Damit kann man aber auch auch eine Division machen. Natürlich nur unter 
gewissen Bedingungen.

Grüße,

Chris

von Christian K. (Firma: Atelier Klippel) (mamalala)


Lesenswert?

Werner schrieb:
> Wieso braucht man eigentlich eine Tabelle mit dem Typ unsigned long,
> wenn man Zahlen aus dem Bereich 0,000 .. 0,999 - also drei Stellen im
> Dezimalsystem -  als Fixkommawerte ablegen möchte. Um die Zahlen
> darzustellen, reichen 10-Bit, d.h. 22-Bit sind völlig nutzlos.
>
> Welche Genauigkeit muß denn die Tabelle nun wirklich haben, d.h. wie
> sauber muß der Sinus sein?

Falls Du dich damit auf mein Beispiel beziehst dann beachte bitte das 
ich nicht drei Nachkommastellen angegeben habe, sondern z.B. 0,999~, 
wobei das ~ dann "unendlich" repräsentiert.

Grüße,

Chris

von Werner (Gast)


Lesenswert?

Thomas Eckmann schrieb:
> So sauber wie möglich. Also unendlich viele Werte. Wie bei Analog.

"So sauber wie möglich" kann kein Mensch bezahlen und ist meistens nicht 
wirklich nötig.

Was hat die Sauberkeit des Sinus mit "Analog" und "unendlich viele 
Werte" zu tun. Als Kriterium würde man eher sowas wie SNR oder Dämpfung 
der Oberwellen erwarten. Aber vielleicht kann sich unser Graph mal zu 
seinem Problem äußern.

von Graph Oszillo (Gast)


Lesenswert?

Vielen Dank an alle!

Von mir aus müsste der Wert nicht mal auf drei Nachkommastellen genau 
sein, da ich diesen nur auf dem 128x96 Pixel großen Display zeichnen 
werde. Allerdings rechnet diese Sinusfunktion sowieso keine Werte selbst 
aus. Sie hat die Werte eines viertel Sinus (90°) in einem Array als 0.16 
Fixpoint unsigned short gespeichert, und legt diese Kurve mehrmals 
aneinander. Ausgegeben wird ein 16.16 Fixpoint Long.

Bezüglich der Umwandlung hätte ich noch eine Frage: Wenn ich einen 16.16 
Fixpoint wieder auf Floatingpoint umwandeln will, muss ich dann einfach 
durch 2^16 dividieren?

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.