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)
Hi, Wert über Sensor: Für fDecimValueX = asin(fGraValueX) fGraValueX = 0,0073260069 fDecimValueX = 9,2469681E-032 (merkwürdig) und für fDecimValueX = asin(fGraValueX) * 57.29582790; fGraValueX = 0,0061050057 fDecimValueX = 4,4150687E-028 (merkwürdig) und für: fDecimValueX = asin(fGraValueX) * 57.29582790f; fGraValueX = -0,0061050057 fDecimValueX = -4,4150687E-028 (merkwürdig) Fester Wert für fGraValueX = 0,0073260069: fDecimValueX = asin(0.0073260069) * 57.29582790; fDecimValueX = 9,2469674E-030 (merkwürdig) fDecimValueX = asin(0.0073260069) * 57.29582790; fDecimValueX = 5,2981264E-028 fDecimValueX = asin(0.0073260069) * 57.29582790f; fDecimValueX = 5,2981264E-028 (merkwürdig) Hoffe du kannst was mit anfangen.
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
jetzt kann garnichts mehr gehen, da die asin()-Funktion nur für Werte zwischen -1 und +1 definiert ist.
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.
1 | float MyAsin( float x ) |
2 | { |
3 | float Result = x |
4 | + 1.0/6.0 * x*x*x |
5 | + 3.0/40.0 * x*x*x*x*x |
6 | + 5.0/112.0 * x*x*x*x*x*x*x |
7 | + 35.0/1152.0 * x*x*x*x*x*x*x*x*x |
8 | + 63.0/2816.0 * x*x*x*x*x*x*x*x*x*x*x; |
9 | return Result; |
10 | } |
Da kannst Du viele Multiplikationen rauswerfen, wenn Du x weiter multimplizierst:
1 | float xx = x*x; |
2 | float Result = 0; |
3 | x*=xx; |
4 | Result+= 1.0/6.0 * x; |
5 | x*=xx; |
6 | Result+=3.0/40.*x; |
7 | ... |
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)
Hi, ASM code mit asin() (0334) fDecimValueX = asin(X) * 57.29582790f;//180 / 3.14159; // calculates angle of x-axis inclination 04FA 8108 LDD R16,Y+0 04FB 8119 LDD R17,Y+1 04FC 812A LDD R18,Y+2 04FD 813B LDD R19,Y+3 04FE 940E0D28 CALL _asin 0500 0118 MOVW R2,R16 0501 0129 MOVW R4,R18 0502 E80C LDI R16,0x8C 0503 E010 LDI R17,0 0504 940E08E1 CALL lpm32 0506 925A ST R5,-Y 0507 924A ST R4,-Y 0508 923A ST R3,-Y 0509 922A ST R2,-Y 050A 940E0BEA CALL fpmule2 050C 9310043D STS fDecimValueX+1,R17 050E 9300043C STS fDecimValueX,R16 0510 9330043F STS fDecimValueX+3,R19 0512 9320043E STS fDecimValueX+2,R18 0514 9624 ADIW R28,4 0515 9508 RET ASM code mit acos() (0335) fDecimValueX = (3.14/2 - acos(X))* 57.29582790f; 0504 8108 LDD R16,Y+0 0505 8119 LDD R17,Y+1 0506 812A LDD R18,Y+2 0507 813B LDD R19,Y+3 0508 940E0C50 CALL _acos 050A 0118 MOVW R2,R16 050B 0129 MOVW R4,R18 050C E900 LDI R16,0x90 050D E010 LDI R17,0 050E 940E08F5 CALL lpm32 0510 0138 MOVW R6,R16 0511 0149 MOVW R8,R18 0512 E80C LDI R16,0x8C 0513 E010 LDI R17,0 0514 940E08F5 CALL lpm32 0516 925A ST R5,-Y 0517 924A ST R4,-Y 0518 923A ST R3,-Y 0519 922A ST R2,-Y 051A 940E0A2D CALL fpsub2x 051C 0183 MOVW R16,R6 051D 0194 MOVW R18,R8 051E 940E0C0C CALL fpmule2 0520 9310043D STS fDecimValueX+1,R17 0522 9300043C STS fDecimValueX,R16 0524 9330043F STS fDecimValueX+3,R19 0526 9320043E STS fDecimValueX+2,R18 0528 9624 ADIW R28,4 0529 9508 RET kann auf den ersten Blick nichts auffallendes erkennen
hast du evntl. einen fertigen asin() den ich nutzen könnte? Ich hab schon zuviel Zeit mit dem scheiß verloren.
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.