PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : asin durch inverse LUT?



XBert
06.01.2010, 20:47
Hi,
ich hab mich mal zur berechnung des cos/sin an das folgende tutorial gehalten und
würde jetzt gerne wissen wie ich mit der selben tabelle die inversen funktionen (arcus sinus reicht da ja acos=90°-asin) dazu berechne.
Hier das Tutorial: http://www.mikrocontroller.net/articles/AVR_Arithmetik/Sinus_und_Cosinus_(Lineare_Interpolation)

und hier mein Versuch:



int16_t linasin(int16_t input)
{
uint8_t neg = input<0?1:0;

input &= ~(1 << 15); //=abs()
for (uint8_t i = 0; i < 91; i++) {
if (input >= linsin_tab[i] && input < linsin_tab[i +1]) {
uint16_t data0 = linsin_tab[i+1] - linsin_tab[i];
uint16_t data1 = input - linsin_tab[i];
int16_t res = i * 256 + 256 * data1 / data0;
return neg ? -res :res;
}
}
}

MFG XBert

XBert
07.01.2010, 16:26
Hi,
ich hab das ganze doch noch hinbekommen; falls jemand ebenfalls darauf stoßen sollte, hier ist des Source-Code;
allerdings ist noch zu klären warum das Ergebnis an manchen stellen so weit vom soll-wert abweicht; (+-1 ist ok da ich durch 2^15 dividiere und nicht durch 2^15-1);
Ausgabe:


std | diy
sin(30°): 16384 | 16385
asin(0.5): 7680 | 7547
asin(0.7): 11373 | 11373
asin(0.3): 4469 | 4468

und der Source-Code:


nt16_t linasin(int16_t input)
{
uint8_t neg = input<0?1:0;
uint16_t _input = abs(input);
//input &= ~(1 << 15); //=abs()
for (uint8_t i = 0; i < 91; i++) {
uint16_t data1 = pgm_read_word(&linsin_tab[i]);
uint16_t data0 = pgm_read_word(&linsin_tab[i+1]);
if (_input >= data1 && _input < data0) {
data0 -= data1;
data1 = _input - data1;
int16_t res = i * 256 + 256 * data1 / data0;
return neg ? -res :res;
}
}
return 0;
}

MFG