arduimu at higher integration rate; returns corrected gyro values

This commit is contained in:
Gautier Hattenberger
2011-04-13 18:16:20 +02:00
parent a935c23572
commit 4a9e5b142b
6 changed files with 38 additions and 118 deletions
+1 -1
View File
@@ -6,7 +6,7 @@
</header> </header>
<init fun="ArduIMU_init()"/> <init fun="ArduIMU_init()"/>
<periodic fun="ArduIMU_periodic()" freq="60"/> <periodic fun="ArduIMU_periodic()" freq="60"/>
<periodic fun="ArduIMU_periodicGPS()" freq="8"/> <periodic fun="ArduIMU_periodicGPS()" freq="4"/>
<event fun="ArduIMU_event()"/> <event fun="ArduIMU_event()"/>
<makefile target="ap"> <makefile target="ap">
<file name="ins_arduimu_basic.c"/> <file name="ins_arduimu_basic.c"/>
@@ -31,29 +31,9 @@ float read_adc(int select)
float temp; float temp;
if (SENSOR_SIGN[select]<0){ if (SENSOR_SIGN[select]<0){
temp = (AN_OFFSET[select]-AN[select]); temp = (AN_OFFSET[select]-AN[select]);
if (abs(temp)>900) {
#if PRINT_DEBUG != 0
Serial.print("!!!ADC:1,VAL:");
Serial.print (temp);
Serial.println("***");
#endif
#if PERFORMANCE_REPORTING == 1
adc_constraints++;
#endif
}
return constrain(temp,-900,900); //Throw out nonsensical values return constrain(temp,-900,900); //Throw out nonsensical values
} else { } else {
temp = (AN[select]-AN_OFFSET[select]); temp = (AN[select]-AN_OFFSET[select]);
if (abs(temp)>900) {
#if PRINT_DEBUG != 0
Serial.print("!!!ADC:2,VAL:");
Serial.print (temp);
Serial.println("***");
#endif
#if PERFORMANCE_REPORTING == 1
adc_constraints++;
#endif
}
return constrain(temp,-900,900); return constrain(temp,-900,900);
} }
} }
@@ -61,8 +41,8 @@ float read_adc(int select)
//Activating the ADC interrupts. //Activating the ADC interrupts.
void Analog_Init(void) void Analog_Init(void)
{ {
ADCSRA|=(1<<ADIE)|(1<<ADEN); ADCSRA|=(1<<ADIE)|(1<<ADEN);
ADCSRA|= (1<<ADSC); ADCSRA|= (1<<ADSC);
} }
// //
@@ -80,8 +60,8 @@ ISR(ADC_vect)
high = ADCH; high = ADCH;
if(analog_count[MuxSel]<63) { if(analog_count[MuxSel]<63) {
analog_buffer[MuxSel] += (high << 8) | low; // cumulate analog values analog_buffer[MuxSel] += (high << 8) | low; // cumulate analog values
analog_count[MuxSel]++; analog_count[MuxSel]++;
} }
MuxSel++; MuxSel++;
MuxSel &= 0x07; //if(MuxSel >=8) MuxSel=0; MuxSel &= 0x07; //if(MuxSel >=8) MuxSel=0;
@@ -23,25 +23,11 @@ void Normalize(void)
renorm= 1. / sqrt(renorm); renorm= 1. / sqrt(renorm);
#if PERFORMANCE_REPORTING == 1 #if PERFORMANCE_REPORTING == 1
renorm_sqrt_count++; renorm_sqrt_count++;
#endif
#if PRINT_DEBUG != 0
Serial.print("???SQT:1,RNM:");
Serial.print (renorm);
Serial.print (",ERR:");
Serial.print (error);
Serial.println("***");
#endif #endif
} else { } else {
problem = TRUE; problem = TRUE;
#if PERFORMANCE_REPORTING == 1 #if PERFORMANCE_REPORTING == 1
renorm_blowup_count++; renorm_blowup_count++;
#endif
#if PRINT_DEBUG != 0
Serial.print("???PRB:1,RNM:");
Serial.print (renorm);
Serial.print (",ERR:");
Serial.print (error);
Serial.println("***");
#endif #endif
} }
Vector_Scale(&DCM_Matrix[0][0], &temporary[0][0], renorm); Vector_Scale(&DCM_Matrix[0][0], &temporary[0][0], renorm);
@@ -53,25 +39,11 @@ void Normalize(void)
renorm= 1. / sqrt(renorm); renorm= 1. / sqrt(renorm);
#if PERFORMANCE_REPORTING == 1 #if PERFORMANCE_REPORTING == 1
renorm_sqrt_count++; renorm_sqrt_count++;
#endif
#if PRINT_DEBUG != 0
Serial.print("???SQT:2,RNM:");
Serial.print (renorm);
Serial.print (",ERR:");
Serial.print (error);
Serial.println("***");
#endif #endif
} else { } else {
problem = TRUE; problem = TRUE;
#if PERFORMANCE_REPORTING == 1 #if PERFORMANCE_REPORTING == 1
renorm_blowup_count++; renorm_blowup_count++;
#endif
#if PRINT_DEBUG != 0
Serial.print("???PRB:2,RNM:");
Serial.print (renorm);
Serial.print (",ERR:");
Serial.print (error);
Serial.println("***");
#endif #endif
} }
Vector_Scale(&DCM_Matrix[1][0], &temporary[1][0], renorm); Vector_Scale(&DCM_Matrix[1][0], &temporary[1][0], renorm);
@@ -83,23 +55,11 @@ void Normalize(void)
renorm= 1. / sqrt(renorm); renorm= 1. / sqrt(renorm);
#if PERFORMANCE_REPORTING == 1 #if PERFORMANCE_REPORTING == 1
renorm_sqrt_count++; renorm_sqrt_count++;
#endif
#if PRINT_DEBUG != 0
Serial.print("???SQT:3,RNM:");
Serial.print (renorm);
Serial.print (",ERR:");
Serial.print (error);
Serial.println("***");
#endif #endif
} else { } else {
problem = TRUE; problem = TRUE;
#if PERFORMANCE_REPORTING == 1 #if PERFORMANCE_REPORTING == 1
renorm_blowup_count++; renorm_blowup_count++;
#endif
#if PRINT_DEBUG != 0
Serial.print("???PRB:3,RNM:");
Serial.print (renorm);
Serial.println("***");
#endif #endif
} }
Vector_Scale(&DCM_Matrix[2][0], &temporary[2][0], renorm); Vector_Scale(&DCM_Matrix[2][0], &temporary[2][0], renorm);
@@ -170,23 +130,18 @@ void Drift_correction(void)
Integrator_magnitude = sqrt(Vector_Dot_Product(Omega_I,Omega_I)); Integrator_magnitude = sqrt(Vector_Dot_Product(Omega_I,Omega_I));
if (Integrator_magnitude > ToRad(300)) { if (Integrator_magnitude > ToRad(300)) {
Vector_Scale(Omega_I,Omega_I,0.5f*ToRad(300)/Integrator_magnitude); Vector_Scale(Omega_I,Omega_I,0.5f*ToRad(300)/Integrator_magnitude);
#if PRINT_DEBUG != 0
Serial.print("!!!INT:1,MAG:");
Serial.print (ToDeg(Integrator_magnitude));
Serial.println("***");
#endif
} }
} }
/**************************************************/ /**************************************************/
void Accel_adjust(void) void Accel_adjust(void)
{ {
Accel_Vector[1] += Accel_Scale(speed_3d*Omega[2]); // Centrifugal force on Acc_y = GPS_speed*GyroZ Accel_Vector[1] += Accel_Scale(speed_3d*Omega[2]); // Centrifugal force on Acc_y = GPS_speed*GyroZ
Accel_Vector[2] -= Accel_Scale(speed_3d*Omega[1]); // Centrifugal force on Acc_z = GPS_speed*GyroY Accel_Vector[2] -= Accel_Scale(speed_3d*Omega[1]); // Centrifugal force on Acc_z = GPS_speed*GyroY
} }
/**************************************************/
/**************************************************/
void Matrix_update(void) void Matrix_update(void)
{ {
Gyro_Vector[0]=Gyro_Scaled_X(read_adc(0)); //gyro x roll Gyro_Vector[0]=Gyro_Scaled_X(read_adc(0)); //gyro x roll
@@ -202,7 +157,6 @@ void Matrix_update(void)
Accel_adjust(); //Remove centrifugal acceleration. Accel_adjust(); //Remove centrifugal acceleration.
#if OUTPUTMODE==1
Update_Matrix[0][0]=0; Update_Matrix[0][0]=0;
Update_Matrix[0][1]=-G_Dt*Omega_Vector[2];//-z Update_Matrix[0][1]=-G_Dt*Omega_Vector[2];//-z
Update_Matrix[0][2]=G_Dt*Omega_Vector[1];//y Update_Matrix[0][2]=G_Dt*Omega_Vector[1];//y
@@ -212,17 +166,6 @@ void Matrix_update(void)
Update_Matrix[2][0]=-G_Dt*Omega_Vector[1];//-y Update_Matrix[2][0]=-G_Dt*Omega_Vector[1];//-y
Update_Matrix[2][1]=G_Dt*Omega_Vector[0];//x Update_Matrix[2][1]=G_Dt*Omega_Vector[0];//x
Update_Matrix[2][2]=0; Update_Matrix[2][2]=0;
#else // Uncorrected data (no drift correction)
Update_Matrix[0][0]=0;
Update_Matrix[0][1]=-G_Dt*Gyro_Vector[2];//-z
Update_Matrix[0][2]=G_Dt*Gyro_Vector[1];//y
Update_Matrix[1][0]=G_Dt*Gyro_Vector[2];//z
Update_Matrix[1][1]=0;
Update_Matrix[1][2]=-G_Dt*Gyro_Vector[0];
Update_Matrix[2][0]=-G_Dt*Gyro_Vector[1];
Update_Matrix[2][1]=G_Dt*Gyro_Vector[0];
Update_Matrix[2][2]=0;
#endif
Matrix_Multiply(DCM_Matrix,Update_Matrix,Temporary_Matrix); //a*b=c Matrix_Multiply(DCM_Matrix,Update_Matrix,Temporary_Matrix); //a*b=c
@@ -235,16 +178,11 @@ void Matrix_update(void)
} }
} }
/**************************************************/
void Euler_angles(void) void Euler_angles(void)
{ {
#if (OUTPUTMODE==2) // Only accelerometer info (debugging purposes)
roll = atan2(Accel_Vector[1],Accel_Vector[2]); // atan2(acc_y,acc_z)
pitch = -asin((Accel_Vector[0])/(double)GRAVITY); // asin(acc_x)
yaw = 0;
#else
pitch = -asin(DCM_Matrix[2][0]); pitch = -asin(DCM_Matrix[2][0]);
roll = atan2(DCM_Matrix[2][1],DCM_Matrix[2][2]); roll = atan2(DCM_Matrix[2][1],DCM_Matrix[2][2]);
yaw = atan2(DCM_Matrix[1][0],DCM_Matrix[0][0]); yaw = atan2(DCM_Matrix[1][0],DCM_Matrix[0][0]);
#endif
} }
@@ -1,24 +1,28 @@
//*****I2C Output************************************************************ //*****I2C Output************************************************************
void fill_I2C_message() {
void requestEvent(){
#if PRINT_DEBUG != 0
Serial.println("Sending IMU Data");
#endif
// Message Array : Roll; Pitch; YaW; GyroX; GyroY; GyroZ; ACCX; ACCY; ACCZ // Message Array : Roll; Pitch; YaW; GyroX; GyroY; GyroZ; ACCX; ACCY; ACCZ
// Float Number is multipited with 10000 and converted to an Integer, for sending via I2C. // Float Number is multipited with 10000 and converted to an Integer, for sending via I2C.
// Resolution for angles: 12, rates: 12, accel:10 (from pprza BFP math lib) // Resolution for angles: 12, rates: 12, accel:10 (from pprza BFP math lib)
I2C_Message_ar[0] = int(roll*(1<<12)); I2C_Message_ar[0] = int(roll*(1<<12));
I2C_Message_ar[1] = int(pitch*(1<<12)); I2C_Message_ar[1] = int(pitch*(1<<12));
I2C_Message_ar[2] = int(yaw*(1<<12)); I2C_Message_ar[2] = int(yaw*(1<<12));
I2C_Message_ar[3] = int(Gyro_Vector[0]*(1<<12)); I2C_Message_ar[3] = int(Omega_Vector[0]*(1<<12));
I2C_Message_ar[4] = int(Gyro_Vector[1]*(1<<12)); I2C_Message_ar[4] = int(Omega_Vector[1]*(1<<12));
I2C_Message_ar[5] = int(Gyro_Vector[2]*(1<<12)); I2C_Message_ar[5] = int(Omega_Vector[2]*(1<<12));
I2C_Message_ar[6] = int((9.81*Accel_Vector[0]/GRAVITY)*(1<<10)); I2C_Message_ar[6] = int((9.81*Accel_Vector[0]/GRAVITY)*(1<<10));
I2C_Message_ar[7] = int((9.81*Accel_Vector[1]/GRAVITY)*(1<<10)); I2C_Message_ar[7] = int((9.81*Accel_Vector[1]/GRAVITY)*(1<<10));
I2C_Message_ar[8] = int((9.81*Accel_Vector[2]/GRAVITY)*(1<<10)); I2C_Message_ar[8] = int((9.81*Accel_Vector[2]/GRAVITY)*(1<<10));
}
void requestEvent(){
#if PRINT_DEBUG != 0
Serial.println("Sending IMU Data");
#endif
fill_I2C_message();
byte* pointer; byte* pointer;
pointer = (byte*) &I2C_Message_ar; pointer = (byte*) &I2C_Message_ar;
Wire.send(pointer, 18); Wire.send(pointer, 18);
@@ -51,6 +55,7 @@ void receiveEvent(int howMany){
void printdata(void){ void printdata(void){
#if PRINT_I2C_MSG == 1 #if PRINT_I2C_MSG == 1
fill_I2C_message();
Serial.print("Time "); Serial.print("Time ");
Serial.print(millis()); Serial.print(millis());
Serial.print("; Roll "); Serial.print("; Roll ");
@@ -89,8 +94,7 @@ void printdata(void){
Serial.print (",AN4:"); Serial.print (",AN4:");
Serial.print(read_adc(4)); Serial.print(read_adc(4));
Serial.print (",AN5:"); Serial.print (",AN5:");
Serial.print(read_adc(5)); Serial.println(read_adc(5));
Serial.print (",");
#endif #endif
#if PRINT_DCM == 1 #if PRINT_DCM == 1
@@ -111,8 +115,7 @@ void printdata(void){
Serial.print (",EX7:"); Serial.print (",EX7:");
Serial.print(convert_to_dec(DCM_Matrix[2][1])); Serial.print(convert_to_dec(DCM_Matrix[2][1]));
Serial.print (",EX8:"); Serial.print (",EX8:");
Serial.print(convert_to_dec(DCM_Matrix[2][2])); Serial.println(convert_to_dec(DCM_Matrix[2][2]));
Serial.print (",");
#endif #endif
#if PRINT_EULER == 1 #if PRINT_EULER == 1
@@ -123,8 +126,7 @@ void printdata(void){
Serial.print(",YAW:"); Serial.print(",YAW:");
Serial.print(ToDeg(yaw)); Serial.print(ToDeg(yaw));
Serial.print(",IMUH:"); Serial.print(",IMUH:");
Serial.print((imu_health>>8)&0xff); Serial.println((imu_health>>8)&0xff);
Serial.print (",");
#endif #endif
#if PRINT_GPS == 1 #if PRINT_GPS == 1
@@ -141,6 +143,7 @@ void printdata(void){
gps_messages_sent++; gps_messages_sent++;
#endif #endif
} }
Serial.println("");
#endif #endif
} }
@@ -174,7 +177,7 @@ void printPerfData(long time)
Serial.print(gps_messages_sent,DEC); Serial.print(gps_messages_sent,DEC);
Serial.print(",imu:"); Serial.print(",imu:");
Serial.print((imu_health>>8),DEC); Serial.print((imu_health>>8),DEC);
Serial.print(",***"); Serial.println(",***");
// Reset counters // Reset counters
mainLoop_count = 0; mainLoop_count = 0;
@@ -30,9 +30,6 @@
/*For debugging propurses*/ /*For debugging propurses*/
#define PRINT_DEBUG 0 //Will print Debug messages #define PRINT_DEBUG 0 //Will print Debug messages
//OUTPUTMODE=1 will print the corrected data, 0 will print uncorrected data of the gyros (with drift), 2 will print accelerometer only data
#define OUTPUTMODE 1
#define PRINT_I2C_MSG 0 //Will print the I2C output buffer #define PRINT_I2C_MSG 0 //Will print the I2C output buffer
#define PRINT_DCM 0 //Will print the whole direction cosine matrix #define PRINT_DCM 0 //Will print the whole direction cosine matrix
#define PRINT_ANALOGS 0 //Will print the analog raw data #define PRINT_ANALOGS 0 //Will print the analog raw data
@@ -49,7 +46,7 @@ int I2C_Message_ar[9];
// *** NOTE! To use ArduIMU with ArduPilot you must select binary output messages (change to 1 here) // *** NOTE! To use ArduIMU with ArduPilot you must select binary output messages (change to 1 here)
#define PRINT_BINARY 0 //Will print binary message and suppress ASCII messages (above) #define PRINT_BINARY 1 //Will print binary message and suppress ASCII messages (above)
// *** NOTE! Performance reporting is only supported for Ublox. Set to 0 for others // *** NOTE! Performance reporting is only supported for Ublox. Set to 0 for others
#define PERFORMANCE_REPORTING 1 //Will include performance reports in the binary output ~ 1/2 min #define PERFORMANCE_REPORTING 1 //Will include performance reports in the binary output ~ 1/2 min
@@ -70,10 +67,9 @@ int I2C_Message_ar[9];
#define ToDeg(x) (x*57.2957795131) // *180/pi #define ToDeg(x) (x*57.2957795131) // *180/pi
// LPR530 & LY530 Sensitivity (from datasheet) => 3.33mV/º/s, 3.22mV/ADC step => 1.03 // LPR530 & LY530 Sensitivity (from datasheet) => 3.33mV/º/s, 3.22mV/ADC step => 1.03
// Tested values : 0.96,0.96,0.94 #define Gyro_Gain_X 1.0 //X axis Gyro gain
#define Gyro_Gain_X 0.92 //X axis Gyro gain #define Gyro_Gain_Y 1.0 //Y axis Gyro gain
#define Gyro_Gain_Y 0.92 //Y axis Gyro gain #define Gyro_Gain_Z 1.0 //Z axis Gyro gain
#define Gyro_Gain_Z 0.94 //Z axis Gyro gain
#define Gyro_Scaled_X(x) x*ToRad(Gyro_Gain_X) //Return the scaled ADC raw data of the gyro in radians for second #define Gyro_Scaled_X(x) x*ToRad(Gyro_Gain_X) //Return the scaled ADC raw data of the gyro in radians for second
#define Gyro_Scaled_Y(x) x*ToRad(Gyro_Gain_Y) //Return the scaled ADC raw data of the gyro in radians for second #define Gyro_Scaled_Y(x) x*ToRad(Gyro_Gain_Y) //Return the scaled ADC raw data of the gyro in radians for second
#define Gyro_Scaled_Z(x) x*ToRad(Gyro_Gain_Z) //Return the scaled ADC raw data of the gyro in radians for second #define Gyro_Scaled_Z(x) x*ToRad(Gyro_Gain_Z) //Return the scaled ADC raw data of the gyro in radians for second
@@ -84,7 +80,7 @@ int I2C_Message_ar[9];
//#define Kp_YAW 2.5 //High yaw drift correction gain - use with caution! //#define Kp_YAW 2.5 //High yaw drift correction gain - use with caution!
#define Ki_YAW 0.00005 #define Ki_YAW 0.00005
#define ADC_WARM_CYCLES 75 #define ADC_WARM_CYCLES 100
#define FALSE 0 #define FALSE 0
#define TRUE 1 #define TRUE 1
@@ -268,7 +264,10 @@ void loop() //Main Loop
{ {
timeNow = millis(); timeNow = millis();
if((timeNow-timer)>=20) // Main loop runs at 50Hz // 20 -> Main loop runs at 50Hz
// 5 -> Main loop runs at 200Hz
// Max measured duty time around 3ms
if((timeNow-timer)>=5)
{ {
timer_old = timer; timer_old = timer;
timer = timeNow; timer = timeNow;
+1 -1
View File
@@ -132,7 +132,7 @@ void ArduIMU_event( void ) {
estimator_p = arduimu_rates.p; estimator_p = arduimu_rates.p;
ardu_ins_trans.status = I2CTransDone; ardu_ins_trans.status = I2CTransDone;
RunOnceEvery(15, DOWNLINK_SEND_AHRS_EULER(DefaultChannel, &arduimu_eulers.phi, &arduimu_eulers.theta, &arduimu_eulers.psi)); //RunOnceEvery(15, DOWNLINK_SEND_AHRS_EULER(DefaultChannel, &arduimu_eulers.phi, &arduimu_eulers.theta, &arduimu_eulers.psi));
RunOnceEvery(15, DOWNLINK_SEND_IMU_GYRO(DefaultChannel, &arduimu_rates.p, &arduimu_rates.q, &arduimu_rates.r)); RunOnceEvery(15, DOWNLINK_SEND_IMU_GYRO(DefaultChannel, &arduimu_rates.p, &arduimu_rates.q, &arduimu_rates.r));
RunOnceEvery(15, DOWNLINK_SEND_IMU_ACCEL(DefaultChannel, &arduimu_accel.x, &arduimu_accel.y, &arduimu_accel.z)); RunOnceEvery(15, DOWNLINK_SEND_IMU_ACCEL(DefaultChannel, &arduimu_accel.x, &arduimu_accel.y, &arduimu_accel.z));
} }