Hallo Leute,
ich habe folgendes Problem:
Ich habe folgende Funktion
float GetGravitationValueX()
{
float fCountsX;
char cCommandX;// local 8 Bit variable
switch(bSelfTestVTI)
{
case 0:
cCommandX = READ_X_CHANNEL_VTI;
break;
case 1:
cCommandX = SELFTEST_X_CHANNEL;
break;
case 2:
cCommandX = MEAS; //After selftest first set to zero
break;
}
fCountsX = (float)readsca (cCommandX);
//calculate a gravitation value
fCountsX = (fCountsX - 1024.0)/819.0;
if(fCountsX>1)
{
fCountsX = 1;
}else if(fCountsX<-1){
fCountsX = -1;
}
return fCountsX;
}
Ich lese einen Wert dieser wird anschließend umgewandelt als
Gravitations Wert und zurück gegeben.
Anschließend wird dieser Wert in folgender Funktion verarbeitet:
void mainVTI()
{
fGraValueX = GetGravitationValueX();
//calculates angle of x-axis inclination
fDecimValueX = asin(fGraValueX) * 57.29582790;// 180 / 3.14159;
fDecimValueX = fDecimValueX * 100;
}
Hier wird ein Winkel berechnet und fDecimValueX übergeben. Anschließend
soll diese Variable über das CANopen Protokoll weiter verarbeitet
werden.
Hier mein Problem:
Der asin() wird nicht korrekt berechnet obwohl ich einen korrekten Wert
fGraValueX über die Funktion GetGravitationValueX() geliefert bekomme.
Ich bekomme einen sehr kleinen Wert ca. 10E-28.
Das merkwürdige ist das wenn ich den code in einer funktion habe als
etwa so:
void mainVTI()
{
float fCountsX;
char cCommandX;// local 8 Bit variable
switch(bSelfTestVTI)
{
case 0:
cCommandX = READ_X_CHANNEL_VTI;
break;
case 1:
cCommandX = SELFTEST_X_CHANNEL;
break;
case 2:
cCommandX = MEAS; //After selftest first set to zero
break;
}
fCountsX = (float)readsca (cCommandX);
//calculate a gravitation value
fGraValueX = (fCountsX - 1024.0)/819.0;
if(fGraValueX>1)
{
fGraValueX = 1;
}else if(fGraValueX<-1){
fGraValueX = -1;
}
fDecimValueX = asin(fGraValueX) * 57.29582790;// 180 / 3.14159; //
calculates angle of x-axis inclination
fDecimValueX = fDecimValueX * 100;
}
funktioniert es.
Hat da jemand eine Idee woran das liegen könnte?
fDecimValueX = asin(fGraValueX) * 57.29582790;
Welchen Wert gibst Du bei fGraValueX ein (bitte debuggen), und welchen
Wert bekommst Du raus für:
fDecimValueX = asin(fGraValueX)
und für
fDecimValueX = asin(fGraValueX) * 57.29582790;
und für:
fDecimValueX = asin(fGraValueX) * 57.29582790f;
(f hinten an der Konstanten)
Kannst du mal ein paar Werte ausdumpen.
Interessant sind die Werte vor und nach
fDecimValueX = asin(fGraValueX) * 57.29582790;// 180 / 3.14159;
Also: Welchen Wert hat fGraValueX und was ergibt sich daraus
für fDecimalValueX. Ideal waere es, wenn fGraValueX mal in ein
paar Schritten den Wertebereich von -1 bis +1 durchlaufen
könnte.
Ansonsten: math.h ist includiert?
Sorry, ist eine bescheuerte Frage, aber ansonsten fällt mir
auf Anhieb gar nichts ein, was da schief gehen könnte. Das
Einzige ist: Es ist keine Dekleration von asin sichtbar und
der Compiler geht davon aus, dass asin() einen int
zurückliefert.
[quote]
fDecimValueX = asin(0.0073260069) * 57.29582790;
fDecimValueX = 9,2469674E-030 (merkwürdig)
fDecimValueX = asin(0.0073260069) * 57.29582790;
fDecimValueX = 5,2981264E-028
[/quote]
Das gibt's nicht. gleicher Eingabewert, anderer Ausgabewert!? Wie
debuggst Du die Werte?
Lass mal das *57.xx weg und schau nur, ob asin gute Werte für 0,
M_PI/2, M_PI usw gibt. Probier auch mal, ob die Zuweisung an double den
richtigen Wert ergäbe.
Sorry der oberste ist
fDecimValueX = asin(0.0073260069);
fDecimValueX = 9,2469674E-030 (merkwürdig)
Ich habe jetzt alles aus der Funktion rausgeschmißen.
Also:
void mainVTI()
{
fDecimValueX = asin(3.14/2);
}
fDecimValueX ist eine globale float Variable;
Ich gehe über die main() direkt in die mainVTI() und der asin() liefert
mir schlechte Werte. Ich glaubt das nicht
Hast recht, das war nicht besonders gut.
Ich habe aber auch wilkürlich Werte zwischen -1 und 1 eingegeben und
der asin() wird nicht korrekt berrechnet. Ich habe mal den asin()
selbst berechnet:
float MyAsin( float x )
{
float 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;
}
so funktioniert es einwandfrei.
Da stimmt doch etwas mit dem asin() nicht.
Ich verwende den AT90CAN128. Zum programmieren den ICCAVR.
Jo, hast recht. Allerding konvergiert diese Berechnung nicht so schön
gegen -1 und 1. Dadurch ist mein Winkelbereich nicht so schön. Komme
max bis 72° bis 75°(Auch bedingt durch Toleranzen des Sensors).
Ich habe das mal mit acos() versucht. Es gillt acos(x)=pi/2-asin(x)
fDecimValueX = (3.14/2 - acos(X))* 57.29582790f;
Siehe da es funktioniert.
Ich verstehe nicht warum er den asin() nicht richtig berechnet.
Der hat da irgendwie einen integer mit d'rin. Schau dir mal den
generierten ASM code an und verlgeiche ihn mit dem von der
acos-Lösung.
(Kann man irgendwie einstellen, dass der original-code noch als
Kommentar dabei ist)