Forum: Mikrocontroller und Digitale Elektronik asin funktion Programmieren


von Sebastian (Gast)


Lesenswert?

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

von Karl heinz B. (heinzi)


Lesenswert?

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.

von Barti (Gast)


Lesenswert?

Nur ein Tipp: Hast Du das nur interessehalber programmiert? Wenn es auf
Geschwindigkeit ankommt nimmt man bei kleinen Mikrocontrollern gern
Sinus-Tabellen. Geht schneller.

von Sebastian (Gast)


Lesenswert?

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

von Rahul (Gast)


Lesenswert?

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ß.

von Sebastian (Gast)


Lesenswert?

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

von Rahul (Gast)


Lesenswert?

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.

von sackgesicht (Gast)


Lesenswert?

/++ 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.

von Karl H. (kbuchegg)


Lesenswert?

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'.

von Unbekannter (Gast)


Lesenswert?

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
Noch kein Account? Hier anmelden.