PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Variablen ändern sich durch Berechnung anderer Variablen



Amri
03.05.2013, 18:30
Hallo,

ich möchte mit einem 3-Achs-Gyroskop und 3-Achs-Beschleunigungssensor eine Lageerkennung programmieren. Allerdings geht irgendetwas in meiner Messdatenverarbeitung schief. Es sieht irgendwie nach einer falschen Typumwandlung oder einem Überlauf aus, ich kann mir aber nicht erklären, was da passiert.

Der Programmablauf:
In einem Timer-Interrupt messe ich die Werte von Gyroskop und Beschleunigungssensor (16 Bit, signed). Die Werte werden aufsummiert (in 32-Bit-Integer) und nach 25 Durchgängen wird die Summe durch 25 geteilt.
Danach werden die Gyroskop-Messungen per Komplementärfilter mit den Beschleunigungsdaten verrechnet, was genau da gemacht wird sollte hier nicht relevant sein.
Um alles nachvollziehen zu können lasse ich mir dann sowohl die Rohmessdaten, als auch die berechneten Winkel ausgeben.
Die gesamte ISR habe ich ganz unten eingefügt.

Jetzt passiert folgendes: Ab und zu liegen einzelne Messwerte des Beschleunigungsmessers (accx, accy, accz) weit außerhalb des Messbereichs (z.B. -100130). Das ist zwar rein formal möglich, da der 16-Bit-Messwert aufgrund der Summierung in einer 32-Bit-Variablen liegt, aber logisch ist es nicht. Denn die Summe aus 25 16-Bit-Werten geteilt durch 25 muss ja wieder einen 16-Bit-Wert ergeben.

Hier ein Beispiel einer Messdatenfolge (in diesem Fall accz):


-670
-654
-670
-652
-689
-673
-671
-652
-84539
-662
-651
-678
-656
-690


Was mich jetzt verwirrt:
Sobald ich den folgenden Codeabschnitt auskommentiere, gibt es keine "Fehlmessungen" mehr.


int16_t winkelx_acc = atan2((double)accy,(double)accz)*573;
int16_t winkely_acc = atan2((double)-accx,(double)accz)*573;
int16_t winkelz_acc = atan2((double)accy,(double)accx)*573;

int8_t dt = 5;
winkelx = (95*(winkelx + (gyrox*10/131 * dt)/100) + (5*(winkelx_acc)))/100;
winkely = (95*(winkely + (gyroy*10/131 * dt)/100) + (5*(winkely_acc)))/100;
winkelz = (95*(winkelz + (gyroz*10/131 * dt)/100) + (5*(winkelz_acc)))/100;


Offenbar haben die Variablen accx, accy und accz erst nach diesen Rechnungen ihren fehlerhaften Wert. Aber warum? Eigentlich werden sie ja nur ausgelesen...


Hier noch die gesamte ISR und die globalen Variablen:


volatile uint16_t durchlauf;
volatile int32_t accx,accy,accz;
volatile int32_t gyrox,gyroy,gyroz;

volatile int16_t winkelx,winkely,winkelz;


ISR(TIMER0_OVF_vect)
{
TCNT0 = TIMER0_START;

durchlauf++;

accx += read_acc_x();
accy += read_acc_y();
accz += read_acc_z();

gyrox += read_gyro_x();
gyroy += read_gyro_y();
gyroz += read_gyro_z();

if(durchlauf>=25)
{

durchlauf = 0;

accx /= 25;
accy /= 25;
accz /= 25;

gyrox /= 25;
gyroy /= 25;
gyroz /= 25;

int16_t winkelx_acc = atan2((double)accy,(double)accz)*573;
int16_t winkely_acc = atan2((double)-accx,(double)accz)*573;
int16_t winkelz_acc = atan2((double)accy,(double)accx)*573;

int8_t dt = 5;
winkelx = (95*(winkelx + (gyrox*10/131 * dt)/100) + (5*(winkelx_acc)))/100;
winkely = (95*(winkely + (gyroy*10/131 * dt)/100) + (5*(winkely_acc)))/100;
winkelz = (95*(winkelz + (gyroz*10/131 * dt)/100) + (5*(winkelz_acc)))/100;

printf("%li,%lu,%li,%li,%li,%li,%li,%li,%i,%i,%i\r\n",temperatur,druck,accx,accy,accz,gyrox,gyroy,gyroz ,winkelx,winkely,winkelz);


accx = 0;
accy = 0;
accz = 0;

gyrox = 0;
gyroy = 0;
gyroz = 0;
}
}


Hat jemand eine Idee, wo diese Messwerte herkommen?