Hallo, ich versuche gerade mal eine asin funktion zu Programmieren, in der GCC Lib habe ich für den AVR folgendes gefunden: /*---------------------------------------------------------------------- ------ asin(x) = pi/2 - (1 - x)^2 (P0 + x(P1 + x(P2 + x(P3 + x(P4 + x(P5 + x(P6 + x(P7)))))))) * * P0 : 1.57079 63050 [3FC90FDA] * P1 : -0,21459 88016 [BE5BBFCA] * P2 : 0.08897 89874 [3DB63A9E] * P3 : -0.05017 43046 [BD4D8392] * P4 : 0.03089 18810 [3CFD10F8] * P5 : -0.01708 81256 [BC8BFC66] * P6 : 0.00667 00901 [3BDA90C5] * P7 : -0.00126 24911 [BAA57A2C] */ ich habe das so implementiert: const float P0= 1.57079; const float P1= -0.21459; const float P2= 0.08897; const float P3= -0.05017; const float P4= 0.03089; const float P5= -0.01708; const float P6= 0.00667; const float P7= -0.00126; float Asin(float winkel){ float result= _PI/2; float temp= P7; temp *= winkel; temp += P6; temp *= winkel; temp += P5; temp *= winkel; temp += P4; temp *= winkel; temp += P3; temp *= winkel; temp += P2; temp *= winkel; temp += P1; temp *= winkel; temp += P0; temp *= winkel; temp *= ((1-winkel) * (1-winkel)); //(1-x)^2 result -= temp; //pi/2 - --> return(result); } leider kommt da nur müll bei raus, kann mir vielleicht jemand etwas auf die sprünge helfen? Sebastian
liegt vielleicht daran, dass man in asin keinen Winkel hineinstopft, sondern ein Winkel (in Radianten) herauskommt. Die Umsetzung der Formel sieht auf den ersten Blick gut aus. Ob die Formel stimmt hab ich allerdings nicht geprueft.
Nur ein Tipp: Hast Du das nur interessehalber programmiert? Wenn es auf Geschwindigkeit ankommt nimmt man bei kleinen Mikrocontrollern gern Sinus-Tabellen. Geht schneller.
ne das muss ich implemtieren da ich einen compiler bentze der das nicht kann, aber ich mit winkeln rechnen muss. Das mann in RAD rechen muss ist klar, sagt ja auch der C Standart. Aber 0,707 als eingang müsse so 0,785~ rauskommen, --> 45°. Aber die kommen nicht raus das sind irgendwas um die 1.5... . Ich habe die Formel von oben einfach mal in C++ (Win) eingegeben und da kommt das gleiche falsche ergebniss raus. Ich will für modellbau 2 servos synchron steuen, die liegen aber in Variablen winklen zueinander. Oben ist sogar noch ein keiner fehler drinn: temp += P0; temp *= winkel; <-- FALSCH, ist zuviel aber die funktion geht immer noch nicht. Hat jemand vielleicht ne idee wie man das sonst noch so machen kann? Und wie implementiert man am besten sqrt(), also wurzel 2, ich kann ja auch pow(n, 1/2); nehmen, nur ist das wesentlich auffwendiger zur laufzeit. Sebastian
Könntest du vielleicht einfach mal dein Problem / deine Aufgabe formulieren (das mit den Servos). Ich denke, dass für Servos wegen der geringen Auflösung keine asin-Funktion programmiert werden muß.
Es geht darum: eine frei beweglich steuerdüse mit flachem ausftritt soll in 2 richtungen gesteuert werden. Wenn 2 servos gegeneinander drehen dann dreht sich die düse um die z Achse. Wenn beide servos jetzt im mit dieser verschränkung in die gleiche richtung drehen kann man um die X Achse schwenken. Das problem ist: man muss eine kompensation der wege machen da sich die hebel der Sevos im kreis bewegen, aber eine lineare bewegung ausgeführt werden soll, dazu die winkelfunktionen. Um den gleichen X weg zu fahren müssen beide Servos unterschiedliche winkel fahren. Und das wollte ich halt in echtzeit berechnen und keine tabellen nehmen, wenn man was am system andert (mechanik) dann muss man alle tabellen neu machen, so muss man nur die abstände neu eingeben. Die Mechanik dazu funktioniert, jetzt muss halt nur noch der Controller programmiert werden. Sebastian
So wie ich deine Mechanik verstehe, steckt deine Düse in etwas einem Differntial ähnlichen Aufbau: Wenn die Drehrichtung gleich ist, dann schwenkt die Düse (Geradeausfahrt). Wenn es einen Drehzahlunterschied gibt, dann verdreht sich die Düse (Differentialkorb dreht sich; Kurvenfahrt). Wie sollen denn drehende Bewegungen ohne eine Längenänderung eine lineare Bewegung ausführen? Das erinnert mich an einen Sinus-Antrieb... Da die Änderung der Kompenation des Antriebs ja eigentlich nur bei Änderung der Mechanik auftritt, solltest du doch den Weg der Tabelle gehen, was die Geschwindigkeit wesentlich erhöhen würde.
/++ zitat Und das wollte ich halt in echtzeit berechnen und keine tabellen nehmen, wenn man was am system andert (mechanik) dann muss man alle tabellen neu machen, /-- zitat Warum sollte sich eine asin-Tabelle ändern, wenn du was an deinem System machst? Der asin(0.707) ist immer 0,785... egal wie du dein System verbiegst.
Nach einigem googeln hab ich eine Reihenentwicklung fuer Asin gefunden wildegg.com/papers/WrongTrig.pdf Die Funktion sieht dann so aus double MyAsin( double x ) { double Result = x + 1.0/6.0 * x*x*x + 3.0/40.0 * x*x*x*x*x + 5.0/112.0 * x*x*x*x*x*x*x + 35.0/1152.0 * x*x*x*x*x*x*x*x*x + 63.0/2816.0 * x*x*x*x*x*x*x*x*x*x*x; return Result; } (Das Anwenden des Horner-Schemas zur Vereinfachung der Berechnung der Potenzen bleibt als Uebung fuer den Leser). Ich hab aber auch noch weiteres gefunden: Meist wird nicht so eine Entwicklung benutzt, den die konvergiert nur schlecht. Meist wird stattdessen ein ganz simples Newton Verfahren angewendet (zusammen mit einer Reihenentwicklung fuer Sinus). Mit dem koennte man dann auch die Wurzel berechnen: myweb.lmu.edu/dmsmith/MComp89.pdf Aber ehrlich: Du solltest Dir die Verwendung von Tabellen noch mal gruendlich ueberlegen. Grade da Du das Ganze in 'Echtzeit' brauchst. Das da ist alles andere als 'schnell mal eben berechnet'.
Aus dem Bronstein: x^3 1*3 x^5 1*3*5 x^7 arcsin x = x + ----- + --------- + ----------- + ... 2*3 2*4*5 2*4*6*7 1*3*5 ... (2n-1) x^(2n+1) + --------------------------- + ... 2*4*6 ... (2n) (2n+1) Naja, das ganze kannst Du natürlich ausfaktorisieren...
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.