@sebmadgwick, or anyone how want to reply
hello,
i'm trying to replicate the method you suggested to calibrate a gyro, which i belive is similar to this one:
https://www.edn.com/design/sensors/4363 ... gyroscopes
please correct me if i'm wrong.
repeat this procedure for every axes
A) to obtain raw
bias error correction offset:
1) read the raw values with the gyro not moving (is it better to avarage many values), do the same thing reversing gyro to opposite position
2) the bias is half the avarage of the sum of values collected for both directions
-- so the raw value now will be = readvalue - bias
B) to obtain
scale factor:
1) install the gyro on a board which can rotate 90 degrees (call this real_rotation_angle)
2) while rotating the gyro clockwise, collect raw values (-bias) at fixed time interval (let's suppose 10ms)
3) to obtain the cumulative rotation angle (call this calculated_rotation_angle), integrate collected values. to do this sum values and multiply for the fixed intervall time
4) repeat point 2 and 3 rotating anticlockwise
-- scale factor for clockwise and anticlockwise should be real_rotation_angle / calculated_rotation_angle, then avarage the scale factor for both direction to obtain the scale factor.
-- given this, the converted values (deg/sec) from gyro should be
conv_value = (rawvalue-bias)*scalefactor
i'm sorry for my poor english, hope you can understaind
above some code that implements this method (on l3g4200d), i've to build a better table to test, doing 90degrees rotation "by hand" give me values similar to datasheet (i.e. 0.07 scale factor for 2000deg/sec)
Code: Select all//define timer for calibration
#define GYROCAL_TIMERINT ISR(TIMER0_OVF_vect) //the timer interrupt
#define GYROCAL_TIMERINIT TCCR0B |=(1<<CS02)|(1<<CS00); //init timer
#define GYROCAL_TIMERSTART TIMSK0 |= (1<<TOIE0); //start timer
#define GYROCAL_TIMERSTOP TIMSK0 &= ~(1<<TOIE0); //stop timer
#define GYROCAL_TIMERFREQ 61 //timer frequency is freq = FCPU / (prescaler * 256)
#define gyrocal_getrawdata(gxraw, gyraw, gzraw) l3g4200d_getrawdata(gxraw, gyraw, gzraw);//gyro get raw data function
//volatile variable for offset and cumulative angles
volatile double gyrocal_anglex = 0;
volatile double gyrocal_angley = 0;
volatile double gyrocal_anglez = 0;
volatile double gyrocal_oggsetx = 0;
volatile double gyrocal_oggsety = 0;
volatile double gyrocal_oggsetz = 0;
//calibration timer
GYROCAL_TIMERINT {
int16_t gxraw = 0;
int16_t gyraw = 0;
int16_t gzraw = 0;
//read raw values
gyrocal_getrawdata(&gxraw, &gyraw, &gzraw);
gxraw = (gxraw-(double)gyrocal_oggsetx);
gyraw = (gyraw-(double)gyrocal_oggsety);
gzraw = (gzraw-(double)gyrocal_oggsetz);
//add this to local variable to process
gyrocal_anglex += gxraw;
gyrocal_angley += gyraw;
gyrocal_anglez += gzraw;
}
int main(void) {
//init gyro and uart....
..........
//calibrate gyro
GYROCAL_TIMERINIT;
GYROCAL_TIMERSTOP;
for(;;) {
uint8_t o = 0;
uint8_t calibsamples = 200;
int32_t gxrawt = 0;
int32_t gyrawt = 0;
int32_t gzrawt = 0;
double biasx = 0;
double biasy = 0;
double biasz = 0;
double biasxC = 0;
double biasyC = 0;
double biaszC = 0;
double biasxA = 0;
double biasyA = 0;
double biaszA = 0;
uart_puts("1) leave gyro in a stable positition to obtain bias\r\n");
_delay_ms(1000);
//read raw values
for(o=0; o<calibsamples; o++) {
gyrocal_getrawdata(&gxraw, &gyraw, &gzraw);
gxrawt += gxraw;
gyrawt += gyraw;
gzrawt += gzraw;
_delay_ms(1);
}
//avarage raw values
gyrocal_oggsetx = gxrawt/(double)calibsamples;
gyrocal_oggsety = gyrawt/(double)calibsamples;
gyrocal_oggsetz = gzrawt/(double)calibsamples;
_delay_ms(1000);
//now check scale factor
uart_puts("2) rotate 90 degress anticlockwise the gyro...\r\n");
//reset angles
gyrocal_anglex = 0;
gyrocal_angley = 0;
gyrocal_anglez = 0;
//read angle using timer
GYROCAL_TIMERSTART;
_delay_ms(5000);
GYROCAL_TIMERSTOP;
//integrate angles to get cumulative angle
biasxA = gyrocal_anglex * 1/GYROCAL_TIMERFREQ;
biasyA = gyrocal_angley * 1/GYROCAL_TIMERFREQ;
biaszA = gyrocal_anglez * 1/GYROCAL_TIMERFREQ;
uart_puts(" read bias offsets:\r\n");
uart_puts(" cumulative raw x: "); dtostrf(biasxA, 3, 5, itmp); uart_puts(itmp); uart_puts("\r\n");
uart_puts(" cumulative raw y: "); dtostrf(biasyA, 3, 5, itmp); uart_puts(itmp); uart_puts("\r\n");
uart_puts(" cumulative raw z: "); dtostrf(biaszA, 3, 5, itmp); uart_puts(itmp); uart_puts("\r\n");
uart_puts("\r\n");
_delay_ms(1000);
//now check scale factor
uart_puts("3) rotate 90 degress clockwise the gyro...\r\n");
//reset angles
gyrocal_anglex = 0;
gyrocal_angley = 0;
gyrocal_anglez = 0;
//read angle using timer
GYROCAL_TIMERSTART;
_delay_ms(5000);
GYROCAL_TIMERSTOP;
//integrate angles to get cumulative angle
biasxC = gyrocal_anglex * 1/GYROCAL_TIMERFREQ;
biasyC = gyrocal_angley * 1/GYROCAL_TIMERFREQ;
biaszC = gyrocal_anglez * 1/GYROCAL_TIMERFREQ;
uart_puts(" read bias offsets:\r\n");
uart_puts(" cumulative raw x: "); dtostrf(biasxC, 3, 5, itmp); uart_puts(itmp); uart_puts("\r\n");
uart_puts(" cumulative raw y: "); dtostrf(biasyC, 3, 5, itmp); uart_puts(itmp); uart_puts("\r\n");
uart_puts(" cumulative raw z: "); dtostrf(biaszC, 3, 5, itmp); uart_puts(itmp); uart_puts("\r\n");
uart_puts("\r\n");
_delay_ms(1000);
//calculate the suggestd scale factor for each direction, and avarage values
uart_puts("4) results:\r\n");
//suggested bias
uart_puts(" suggested bias offsets:\r\n");
uart_puts(" x: "); dtostrf(gyrocal_oggsetx, 3, 5, itmp); uart_puts(itmp); uart_puts("\r\n");
uart_puts(" y: "); dtostrf(gyrocal_oggsety, 3, 5, itmp); uart_puts(itmp); uart_puts("\r\n");
uart_puts(" z: "); dtostrf(gyrocal_oggsetz, 3, 5, itmp); uart_puts(itmp); uart_puts("\r\n");
uart_puts(" suggested scale factor:\r\n");
biasx = ((90 / biasxA) + (-90 / biasxC)) / 2;
biasy = ((90 / biasyA) + (-90 / biasyC)) / 2;
biasz = ((90 / biaszA) + (-90 / biaszC)) / 2;
uart_puts(" gain x: "); dtostrf(biasx, 3, 5, itmp); uart_puts(itmp); uart_puts("\r\n");
uart_puts(" gain y: "); dtostrf(biasy, 3, 5, itmp); uart_puts(itmp); uart_puts("\r\n");
uart_puts(" gain z: "); dtostrf(biasz, 3, 5, itmp); uart_puts(itmp); uart_puts("\r\n");
uart_puts("\r\n");
uart_puts("\r\n");
_delay_ms(3000);
}
}