Hallo, mein Ziel ist es atan() zu berechnen, das ganze jedoch ohne Fließkommaarithmetik. Mir genügen zwei Nachkommastellen, also von -90.00° bis +90.00° in 0.01° Schritten. Die in der avr-libc enthaltene atan() funktion verwendet Fließkommazahlen, und das wollte ich vermeiden. Wie würdet ihr das lösen? Eine look up Tabelle im Flash? Oder eine Annäherung? (z.b. http://de.wikipedia.org/wiki/Arctan#N.C3.A4herungsweise_Berechnung ) Was haltet ihr hier für sinnvoll? Es kommt vor allem auf die Schnelligkeit an, RAM und Flash sind eigentlich genügend vorhanden (16kb bzw 128kb) Vielen Dank für eure Hilfe
Hallo Versuch es doch mal mit einer Taylorreihe. Gruß Joachim
john schrieb: > -90.00° bis +90.00° in 0.01° Schritten. Dann wären es als LUT aber auch schon 180°/0,01° = 18.000 Werte! arctan(pi/2) - artan(-pi/2)= 2,00 also müsste ein Byte pro Wert reichen, dann wären es 18kByte. Evtl. könnte man es für verschiedene Bereiche linearisieren und dann je nach dem in was für einem Bereich man ist mit der dementsprechenden Gleichung berechnen? Ein anderes Stichwort ist CORDIC. Grüße
john schrieb: > Es kommt vor allem auf die > Schnelligkeit an, Nenn doch mal ne Hausnummer: 1ms 10ms 1µs ?
Hallo, > Versuch es doch mal mit einer Taylorreihe. Die Taylorreihe habe ich mir schon auf der Wikipedia angesehen, nur ich glaube diese Berechnung dauert auf einem AVR recht lange... >> -90.00° bis +90.00° in 0.01° Schritten. > > Dann wären es als LUT aber auch schon 180°/0,01° = 18.000 Werte! > arctan(pi/2) - artan(-pi/2)= 2,00 also müsste ein Byte pro Wert reichen, > dann wären es 18kByte. Eine Lookup Tabelle von 18kb wäre ja noch im Rahmen, ich habe sowieso recht viel Flash übrig... > john schrieb: >> Es kommt vor allem auf die >> Schnelligkeit an, > > Nenn doch mal ne Hausnummer: 1ms 10ms 1µs ? Das ganze (und noch einiges mehr) muss mit ca 400Hz laufen, das heißt ich habe ca 2.5ms zeit. Aber wie gesagt muss da noch einiges mehr berechnet werden... Takt des AVR ist 20MHz Ich habe gerade mal auf Basis der Nährungsfunktionen in der Wikipedia eine kurze Funktion geschrieben:
1 | int16_t _arctan(double x) |
2 | {
|
3 | if(-1 <= x && x <= 1) // |x| <= 1 |
4 | {
|
5 | return (int16_t)((57.2958*x) / (0.28*x*x + 1)); |
6 | }
|
7 | else if(x > 1) // x > 1 |
8 | {
|
9 | return (int16_t)(90 - (57.2958*x) / (x*x + 0.28)); |
10 | }
|
11 | else // x < 1 |
12 | {
|
13 | return (int16_t)(-(90 - (57.2958*x) / (x*x + 0.28))); |
14 | }
|
15 | }} |
16 | }
|
Ganz um die Fließkommazahlen komme ich so aber nicht herum... Wie finde ich heraus, wie viele Takte die Funktion benötigt? Viele Grüße
john schrieb: > Das ganze (und noch einiges mehr) muss mit ca 400Hz laufen, das heißt > ich habe ca 2.5ms zeit. Aber wie gesagt muss da noch einiges mehr > berechnet werden... Takt des AVR ist 20MHz Dann hast Du genug Zeit, um die atan()-Funktion der .lib zu verwenden. Ich würde die Rechenzeit auf 200-300µs schätzen; probiere es doch einfach aus, wielange 10000 Aufrufe brauchen.
Wie probiere ich das am besten aus? Einen Timer so einstellen, dass er jede µs um eins hochzählt, und danach schauen wie weit er gezählt hat?
Machs doch so wie schon geschrieben wurde: Setze einen Pin auf HIGH, warte kurz, setze den Pin auf LOW und führe ein paar hundert mal atan() aus und setze danach den Pin gleich danach wieder auf HIGH. Die Zeit dazwischen kann man schön mit nem Oszi am Pin messen. Dann kannst du ja leicht berechnen wie lange du gebraucht hast für einen ablauf. Falls du kein Oszi hast: Mach es tausende bis hunderttausende Male, und stoppe die Zeit "per Hand".
john schrieb: > Hallo, > > mein Ziel ist es atan() zu berechnen, das ganze jedoch ohne > Fließkommaarithmetik. Mir genügen zwei Nachkommastellen, also von > -90.00° bis +90.00° in 0.01° Schritten. Versteh ich nicht. Bei atan ist doch die Ausgabe ein Winkel, nicht die Eingabe. Der Definitionsbereich von atan ist ganz |R. > Wie würdet ihr das lösen? Eine look up Tabelle im Flash? Oder eine > Annäherung? Würd ich mal versuchen wie beschrieben in http://www.mikrocontroller.net/articles/AVR_Arithmetik/Sinus_und_Cosinus_(Lineare_Interpolation%29 Das dauert weniger als 80 Ticks für Sinus (inclusive CALL+RET) und bringt einen Absolutfehler < 1e-4 bei 300 Byte Flash-Verbrauch. Allerdings musst du das natürlich auf atan anpassen. Hinweis: * atan' <= 1 * atan(-x) = -atan(x) * atan(x) lässt sich einfach durch atan(1/x) darstellen Die Berechnung braucht's alsu nur für Werte 0 <= x <= 1. Ansonsten würd mir noch CORDIC einfallen. XXX schrieb: > Versuch es doch mal mit einer Taylorreihe. Nö, Taylor ist notorisch schlecht, vor allem hat man mit Überläufen etc zu kämpfen. Falls eine lineare Interpolation nicht ausreicht, nimm ein Polynom höheren Grades. Aber: Die Auswertung machst du nicht als Anfang einer Potenzreihe, sondern du stellst das Polynom zur Basis der Bernsteinpolynome dar und wertest nach de-Casteljau aus. Gute Stützstellen zu finden und gute Polynome sind ne Hausaufgabe ;-)
john schrieb: > Ganz um die Fließkommazahlen komme ich so aber nicht herum... Prinzipiell kann man ziemlich alles auch mit Festkommazahlen machen; zumindest solange man die jeweiligen Wertebereiche im Blick hat.
Hallo, http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&p=530476 atan ~2100-2400 cycles oder mit Unterscheidung zwischen mit oder ohne Hardwaremultiplizierer http://www.nongnu.org/avr-libc/user-manual/benchmarks.html
Johann L. schrieb: > Gute Stützstellen zu finden und gute Polynome sind ne Hausaufgabe ;-) Man kann davon ausgehen, dass die Compiler-Bauer ihre Hausaufgaben gemacht haben! john schrieb: > Wie probiere ich das am besten aus? Schreib Dein Programm und bring es zum Laufen. Dann setzt Du Deine Zykluszeit von 2,5ms auf 1ms. Du wirst sehen, es funktioniert immer noch. Dann gehst Du wieder auf 2,5ms zurück und weißt, dass Du keine Probleme mit dem Timing hast.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.