Diskussion:AVR Arithmetik/Sinus und Cosinus (CORDIC)

Aus der Mikrocontroller.net Artikelsammlung, mit Beiträgen verschiedener Autoren (siehe Versionsgeschichte)
Wechseln zu: Navigation, Suche

Hallo,

wieviel Zeit und Platz kostet es, eine lineare Interpolation in der Tabelle zu machen. Ich habe mal in Freepascal zur Simulation mit single gerechnet:auf 16 Bit beschränkt: sintable[i] := int(sin(pi/2 *i/TABZAHL) *65536) /65536; und eine Tabelle mit 64 Einträgen = 128 Byte gewählt, welche auf dem AVR ja im 0.16 Format sein könnte, da nur Werte von 0000..FFFF(= 0,9999847) gebraucht werden. Linear interpoliert ergibt sich eine Genauigkeit von 13 Bit.

const
  TABZAHL = 64;
  DeltaWinkel = 90 / TABZAHL;
  rezDeltaWinkel = 1/ DeltaWinkel;
...
//i Position des  Wertes in der Tabelle 
i := int(Winkel*rezDeltaWinkel);// Ganzzahl
frak :=  Winkel*rezDeltaWinkel-i;//frak= [0..1[

sinLinearNaeh :=(sintable[i+1]-sinTable[i])*frak+sinwert;

Das braucht sicher keine 280 Takte, sodass es insgesamt schneller als die Berechnung mittels Cordic sein müsste um sinus und cosinus zu bestimmen.

Gruß Horst P.S. Quadratisch interpoliert reicht eine Tabelle mit 17 Plätzen (-1..16)

  
a := sintable[i];
b := sintable[i+1] /2;
c := sintable[i-1] /2;
sinLinearNaeh :=(2*b-a)*frak+a;
sinquadratNaeh := ((b+c-a)*frak + b-c)*frak+a;
Eine lineare Interpolation erscheint mir sinnvoll. Mit einem Stützstellenabstand δ ergibt sich ein absoluter Fehler von ca.
[math]\tfrac 1{16} \delta^2 f''[/math]
Sollen Werte von 0 bis π/2 in die Tabelle, dann braucht man bei einem absoluen Fehler von höchstens 2-15 also mindestens
[math]16\pi\sqrt{2} \approx 72[/math]
Stützstellen.
Mit einer quadratischen Interpolation wird man m.E. nicht glücklich. Stolperstein sind die Überläufe in den Zwischenergebnissen. Die sind unproblematisch, solange das Endergebnis nahe genug am korrekten Wert ist, was man aber nicht bzw. nur mit großem Aufwand feststellen kann. Wenn als Ergebnis aufgrund eines Überlaufs 1 anstatt −1 (oder 0 anstatt 1) herauskommt, muss das korrigietr werden. Beim CORDIC hab ich das so gelöst, daß ich den Algorithmus für /alle/ Eingabewerte durchlaufen ließ und mich für die vorliegende Wahl von CORDIC_SCALE_IN, CORDIC_SCALE_OUT, etc. davon überzeugte, daß es für keine Eingabe einen Überlauf gibt.
Eine Ausgabe im 1.15 Q-Format find ich sinnvoller als 0.16, weil man diese Darstellung einfacher negieren kann, was in sehr vielen Anwendungen gefordert sein wird. Aus diesem Grunde sollte man dann auch den Wert 0x8000 aussparen (was bei der CORDIC-Implementierung der Fall ist) weil dieser Wert nicht negierbar ist. --Gjlayde 09:23, 23. Jul. 2009 (CEST)

Nichtfunktionalitätsmeldung Atmega88

Leider funktioniert die lib nicht auf Anhieb mit Atmega88:

avr-gcc    -c -o cordic-asm.o cordic-asm.S
cordic-asm.S: Assembler messages:
cordic-asm.S:44: Error: illegal opcode movw for mcu avr2
cordic-asm.S:50: Error: illegal opcode lpm for mcu avr2
cordic-asm.S:50: Error: postincrement not supported
cordic-asm.S:51: Error: illegal opcode lpm for mcu avr2
...
avr-gcc -v:
Using built-in specs.
Target: avr
configured with: ../gcc-4.3.3/configure --enable-win32-registry=WinAVR-20100110 --with-gmp=/usr/local --with-mpfr=/usr/local --prefix=/c/WinAVR --target=avr --e
nable-languages=c,c++,objc --with-dwarf2 --enable-doc --disable-shared --disable-libada --disable-libssp --disable-nls --with-pkgversion='WinAVR 20100110' --wit
h-bugurl='URL:http://sourceforge.net/tracker/?atid=520074&group_id=68108&func=browse'
Thread model: single
gcc version 4.3.3 (WinAVR 20100110)
Für einen ATmaga88 ist der Schalter -mmcu=atmega88 anzugeben, damit der Compiler auch Code für diesen µC-Typ erzeugt und die richtigen Bibliotheken/Header verwendet. --Gjlayde 15:36, 24. Jun. 2010 (UTC)