Forum: Mikrocontroller und Digitale Elektronik asin() Probrlem


von Efthi (Gast)


Lesenswert?

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?

von Gernot F. (gernotfrisch)


Lesenswert?

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)

von Efthi (Gast)


Lesenswert?

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.

von Karl heinz B. (kbucheg)


Lesenswert?

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.

von Karl heinz B. (kbucheg)


Lesenswert?

Ignoriere mein letzter Posting.
Das ist lange Zeit hängen geblieben.

von Gernot F. (gernotfrisch)


Lesenswert?

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

von Efthi (Gast)


Lesenswert?

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

von Uwe Nagel (Gast)


Lesenswert?

jetzt kann garnichts mehr gehen, da die asin()-Funktion nur für Werte
zwischen -1 und +1 definiert ist.

von Efthi (Gast)


Lesenswert?

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.

von Gernot F. (gernotfrisch)


Lesenswert?

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

von Efthi (Gast)


Lesenswert?

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.

von Gernot F. (gernotfrisch)


Lesenswert?

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)

von Efthi (Gast)


Lesenswert?

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

von Gernot F. (gernotfrisch)


Lesenswert?

da scheint tatsächlich ein bug in asin sein...

von Efthi (Gast)


Lesenswert?

hast du evntl. einen fertigen asin() den ich nutzen könnte?
Ich hab schon zuviel Zeit mit dem scheiß verloren.

von Gernot F. (gernotfrisch)


Lesenswert?


von Efthi (Gast)


Lesenswert?

super, dank dir

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.