MPU6050 - Hilfe bei Winkelbestimmung

Gast #5490275
Lesenswert?
• ▲
▼
Hallo allerseits. Ich versuche aus dem Gyroskop und Accelerometer im 
MPU6050 die Winkel abzuleiten. Habe dazu folgendes Programm aus dem 
Netz:
1
#include <Wire.h>
2

3
int gyro_x, gyro_y, gyro_z;
4
int angle_pitch_buffer, angle_roll_buffer;
5
int temp;
6
int count = 0;
7

8
long gyro_x_cal, gyro_y_cal, gyro_z_cal;
9
long acc_x, acc_y, acc_z, acc_total_vector;
10
long loop_timer;
11
long acc_x_average, acc_y_average, acc_z_average;
12

13
long gyro_x_offset = 0;
14
long gyro_y_offset = 0;
15
long gyro_z_offset = 0;
16

17
long acc_x_offset = 0; // 10
18
long acc_y_offset = 0; // 180
19
long acc_z_offset = 0; // -225
20

21
boolean set_gyro_angles;
22
boolean toggle;
23

24
float angle_roll_acc, angle_pitch_acc;
25
float angle_pitch, angle_roll;
26
float angle_pitch_output, angle_roll_output;
27

28
void setup() 
29
{
30
  Wire.begin();                                                        //Start I2C as master
31

32
  Serial.begin(115200);
33
  
34
  setup_mpu_6050_registers();                                          //Setup the registers of the MPU-6050 
35

36
  Serial.println("Calibrating gyro");
37
  
38
  for(int cal_int = 0; cal_int < 500 ; cal_int ++)
39
  {                                                                    //Read the raw acc and gyro data from the MPU-6050 for 500 times
40
    read_mpu_6050_data();                                             
41
    gyro_x_cal += gyro_x;                                              //Add the gyro x offset to the gyro_x_cal variable
42
    gyro_y_cal += gyro_y;                                              //Add the gyro y offset to the gyro_y_cal variable
43
    gyro_z_cal += gyro_z;                                              //Add the gyro z offset to the gyro_z_cal variable
44
    delay(3);                                                          //Delay 3us to have 250Hz for-loop
45
  }
46

47
  pinMode(8, OUTPUT);
48
  pinMode(9, OUTPUT);
49
  pinMode(10, OUTPUT);
50
    
51
  // divide by 500 to get avarage offset
52
  gyro_x_cal /= 500;                                                 
53
  gyro_y_cal /= 500;                                                 
54
  gyro_z_cal /= 500;                                                 
55
  
56
  Serial.begin(115200);
57
  
58
  loop_timer = micros();                                               //Reset the loop timer
59
}
60

61
void loop(){
62

63
  read_mpu_6050_data();   
64
  
65
  //Subtract the offset values from the raw gyro values
66
  gyro_x -= gyro_x_cal;                                                
67
  gyro_y -= gyro_y_cal;                                                
68
  gyro_z -= gyro_z_cal;
69
  acc_x += acc_x_offset;
70
  acc_y += acc_y_offset; 
71
  acc_z += acc_z_offset;                                               
72
         
73
  //Gyro angle calculations . Note 0.0000611 = 1 / (250Hz x 65.5)
74
  angle_pitch += gyro_x * 0.0000611;                                   //Calculate the traveled pitch angle and add this to the angle_pitch variable
75
  angle_roll += gyro_y * 0.0000611;                                    //Calculate the traveled roll angle and add this to the angle_roll variable
76
  
77
  //0.000001066 = 0.0000611 * (3.142(PI) / 180degr) The Arduino sin function is in radians
78
  angle_pitch += angle_roll * sin(gyro_z * 0.000001066);               //If the IMU has yawed transfer the roll angle to the pitch angel
79
  angle_roll -= angle_pitch * sin(gyro_z * 0.000001066);               //If the IMU has yawed transfer the pitch angle to the roll angel
80
  
81
  //Accelerometer angle calculations
82
  acc_total_vector = sqrt((acc_x*acc_x)+(acc_y*acc_y)+(acc_z*acc_z));  //Calculate the total accelerometer vector
83
  
84
  //57.296 = 1 / (3.142 / 180) The Arduino asin function is in radians
85
  angle_pitch_acc = asin((float)acc_y/acc_total_vector)* 57.296;       //Calculate the pitch angle
86
  angle_roll_acc = asin((float)acc_x/acc_total_vector)* -57.296;       //Calculate the roll angle
87
  
88
  angle_pitch_acc -= -2.04;                                            //Accelerometer calibration value for pitch
89
  angle_roll_acc -= 0.38;                                              //Accelerometer calibration value for roll
90

91
  if(set_gyro_angles)
92
  {                                                                    //If the IMU is already started
93
    angle_pitch = angle_pitch * 0.9996 + angle_pitch_acc * 0.0004;     //Correct the drift of the gyro pitch angle with the accelerometer pitch angle
94
    angle_roll = angle_roll * 0.9996 + angle_roll_acc * 0.0004;        //Correct the drift of the gyro roll angle with the accelerometer roll angle
95
  }
96
  
97
  else
98
  {                                                                    //At first start
99
    angle_pitch = angle_pitch_acc;                                     //Set the gyro pitch angle equal to the accelerometer pitch angle 
100
    angle_roll = angle_roll_acc;                                       //Set the gyro roll angle equal to the accelerometer roll angle 
101
    set_gyro_angles = true;                                            //Set the IMU started flag
102
  }
103
  
104
  //To dampen the pitch and roll angles a complementary filter is used
105
  angle_pitch_output = angle_pitch_output * 0.9 + angle_pitch * 0.1;   //Take 90% of the output pitch value and add 10% of the raw pitch value
106
  angle_roll_output = angle_roll_output * 0.9 + angle_roll * 0.1;      //Take 90% of the output roll value and add 10% of the raw roll value
107

108
  acc_x_average += acc_x;
109
  acc_y_average += acc_y;
110
  acc_z_average += acc_z;
111
  count++;
112
  
113
  if(count == 100)
114
  {  
115
  Serial.print(acc_x_average/100);
116
  Serial.print("\t");
117
  Serial.print(acc_y_average/100);
118
  Serial.print("\t");
119
  Serial.print(acc_z_average/100);
120
  Serial.print("\t\t");
121
  Serial.print(angle_pitch_output);
122
  Serial.print("\t");
123
  Serial.println(angle_roll_output);
124
  count = 0;
125
  acc_x_average = 0;
126
  acc_y_average = 0;
127
  acc_z_average = 0;
128
  }
129
  
130
  
131
  // half frequency output
132
  toggle = !toggle; if(!toggle) { PORTB |= (1 << PB2); } else { PORTB &= ~(1 << PB2); }
133

134
  if(angle_pitch_output <= 90.1 && angle_pitch_output >= 89.9) { digitalWrite(8, HIGH); } else { digitalWrite(8, LOW); }
135
  if(angle_roll_output <= 90.1 && angle_roll_output >= 89.9) { digitalWrite(9, HIGH); } else { digitalWrite(9, LOW); }
136

137
  while(micros() - loop_timer < 4000);                                 //Wait until the loop_timer reaches 4000us (250Hz) before starting the next loop
138
  
139
  loop_timer = micros();//Reset the loop timer 
140
}
141

142

143

144

145
void setup_mpu_6050_registers()
146
{
147
  //Activate the MPU-6050
148
  Wire.beginTransmission(0x68);                                        //Start communicating with the MPU-6050
149
  Wire.write(0x6B);                                                    //Send the requested starting register
150
  Wire.write(0x00);                                                    //Set the requested starting register
151
  Wire.endTransmission();                                             
152
  //Configure the accelerometer (+/-8g)
153
  Wire.beginTransmission(0x68);                                        //Start communicating with the MPU-6050
154
  Wire.write(0x1C);                                                    //Send the requested starting register
155
  Wire.write(0x10);                                                    //Set the requested starting register
156
  Wire.endTransmission();                                             
157
  //Configure the gyro (500dps full scale)
158
  Wire.beginTransmission(0x68);                                        //Start communicating with the MPU-6050
159
  Wire.write(0x1B);                                                    //Send the requested starting register
160
  Wire.write(0x08);                                                    //Set the requested starting register
161
  Wire.endTransmission();                                             
162
}
163

164
void read_mpu_6050_data()
165
{                                                                       //Subroutine for reading the raw gyro and accelerometer data
166
  Wire.beginTransmission(0x68);                                        //Start communicating with the MPU-6050
167
  Wire.write(0x3B);                                                    //Send the requested starting register
168
  Wire.endTransmission();                                              //End the transmission
169
  Wire.requestFrom(0x68,14);                                           //Request 14 bytes from the MPU-6050
170
  while(Wire.available() < 14);                                        //Wait until all the bytes are received
171
  acc_x = Wire.read()<<8|Wire.read();                                  
172
  acc_y = Wire.read()<<8|Wire.read();                                  
173
  acc_z = Wire.read()<<8|Wire.read();                                  
174
  temp = Wire.read()<<8|Wire.read();                                   
175
  gyro_x = Wire.read()<<8|Wire.read();                                 
176
  gyro_y = Wire.read()<<8|Wire.read();                                 
177
  gyro_z = Wire.read()<<8|Wire.read();                                 
178
}

Der MPU6050 liegt flach auf meinem Schreibtisch (Werte driften kaum) und 
nach einer kurzen Zeit kippe ich die Y-Achse um 90 °:

GyX GyY  GyZ    X    Y
-33 -174 4349  -0.04 0.14
-32 -174 4353  -0.05 0.13
-33 -173 4350  -0.06 0.14
-31 -175 4354  -0.06 0.14
-31 -173 4355  -0.07 0.14
-31 -173 4349  -0.08 0.14
-32 -174 4352  -0.08 0.14
-33 -173 4349  -0.08 0.13
-32 -174 4353  -0.09 0.13
-33 -175 4354  -0.10 0.13
-33 -178 4351  -0.11 0.13
-31 -173 4351  -0.12 0.12
-33 -172 4353  -0.12 0.13
-33 -173 4355  -0.12 0.14
-31 -173 4354  -0.13 0.14
-34 -173 4350  -0.12 0.16
-95 -168 4365  0.00 4.45
-1750 -184 3795  -0.97 42.07
-3658 -260 1730  -1.08 79.78
-4082 -287 431  -1.35 88.81
-4057 -270 56  -1.50 89.84
-4055 -270 30  -1.35 89.83
-4056 -272 14  -1.40 90.09 << ab hier 90 Grad gedreht
-4055 -272 -8  -1.41 89.91
-4056 -278 -3  -1.41 89.45
-4058 -267 28  -1.38 89.19
-4055 -269 32  -1.33 89.04
-4060 -267 27  -1.34 88.89
-4054 -266 32  -1.36 88.77
-4058 -264 32  -1.37 88.65
-4056 -266 32  -1.38 88.55
-4053 -263 34  -1.40 88.44
-4055 -265 36  -1.43 88.33
-4052 -268 40  -1.45 88.21
-4058 -265 40  -1.45 88.12
-4056 -264 34  -1.46 88.04
-4056 -267 34  -1.47 87.93
-4057 -266 36  -1.49 87.86
-4057 -266 36  -1.49 87.79
-4058 -265 37  -1.51 87.71
-4056 -267 37  -1.53 87.65
-4056 -269 34  -1.56 87.58
-4057 -268 36  -1.57 87.52
-4055 -269 37  -1.58 87.46
-4056 -267 35  -1.58 87.40
-4055 -267 38  -1.58 87.33
-4054 -267 37  -1.58 87.28
-4057 -266 40  -1.58 87.24
-4059 -266 40  -1.60 87.19
-4057 -266 37  -1.59 87.14
-4058 -264 34  -1.59 87.09
-4056 -266 37  -1.58 87.05
-4058 -265 33  -1.60 87.01
-4056 -263 36  -1.61 86.97
-4057 -265 39  -1.60 86.93
-4057 -265 37  -1.61 86.89
-4056 -266 36  -1.61 86.85
-4059 -264 37  -1.62 86.81
-4056 -266 32  -1.62 86.76
-4058 -265 41  -1.61 86.73
-4057 -267 41  -1.60 86.69
-4058 -267 39  -1.61 86.65
-4056 -266 40  -1.62 86.61

Mein Problem ist, dass ein gekippter Sensor sofort anfängt zu driften 
(siehe Messwerte). Weiß jemand, an welcher Stelle der Drift zustande 
kommt?

Antwort schreiben

Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt. Bitte hier nur auf die ursprüngliche Frage antworten, für neue Fragen einen neuen Beitrag erstellen.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.