SparkFun Forums 

Where electronics enthusiasts find answers.

Have questions about a SparkFun product or board? This is the place to be.
By monstrum
#95885
What's the easiest way to calibrate a gyroscope, without using specialized hardware.
I guess you need some form of platform rotating at constant speed. But, then you'd also need to know the platforms exact speed.
Have anyone tried using a 2 or 3 axis accelerometer as a reference? If you rotate the platform perpendicular to the ground, you could easily measure its angle, but would it be precise enough to be of any use?
By MichaelN
#95898
That would be an accurate way to measure the rotation, but might be overkill.

You could just use a optical means to measure the rotation (segmented / colored wheel with optical sensors), which would remove the need for vertical orientaion. If you're trying to check the sensitivity of the gyro to accelerations in different axes, you would need to do this anyway, since you'd need to be able to orient the platform in different directions.

If you can find an old record turntable, that might make a good platform to use, although you'd probably want to add a speed control of some kind. The challenge would be getting the data from the gyro on the rotating platform into your computer - if your device has wireless it would of course be easy.
By monstrum
#95899
Well, the "platform" is a UAV, so it can't be used for the calibration purpose.

I'm also very certain if a "hand-held" approach would yield usable results.
By MichaelN
#95900
monstrum wrote:Well, the "platform" is a UAV, so it can't be used for the calibration purpose.
Presumably you have a wireless link, so maybe you can just mount the electronics on the turntable?
monstrum wrote:I'm also very certain if a "hand-held" approach would yield usable results.
Not sure what you mean by that...
By monstrum
#95901
Sure, I have both wireless link and logging-capability, so there would be no problem mounting it anywhere.

The problem is that I don't have a turntable. What I meant by my question was if it would be consistent enough if I just spun the sensors by hand.

Perhaps something more refined needs to be manufactured, like a real table driven by some motor. The problem seems to be getting low enough rotation speed. The gyros will saturate at somewhere around 150 deg/s, so it should be close to, but absolutely not higher than that.
By MichaelN
#95909
Use an old record player with a "leading edge" light dimmer (<$20 at the hardware store) to adjust speed.

I don't think turning something by hand will be of any use for calibration.

The most important calibration is the setting of the "zero" rotation, which should be performed automatically (at least) every time the unit is switched on, and preferably any time the UAV is known to be stationary.
By sebmadgwick
#96351
A simple and effective method to calibrate the gyroscope gain is to:
- Log the gyroscope output as you turn through a measured/constrained rotation (e.g. 180 degrees) over a short period of time. (Keep rotations monotonic)
- Integrate the logged output with a starting guess of the gain to yield the calculated angle of rotation.
- Ad hoc tune this gain until your calculated angle of rotation equals your measured angle of rotation.

To really improve your calibration process:
- Compile a data set of many repetitions featuring a range of angular velocities.
- Automate the ad hoc process with MATLAB optimisation toolbox for example.

Methods such as using a record player may only enable the accurate calibration at 1 or 2 known magnitudes (assumes truly linear) and is unlikely to be representative of the motion within the intended application.
By monstrum
#96355
That actually sounds like a very good way. I already got the log running so it's really just about analyzing this in Matlab.
By ScottH
#118063
You get five (or 7) points with a record player. Zero, 33 1/3 rpm, 45rpm. Turn the gyro upside down for two more points. a 78 rpm record player adds two more points. This is what I do.
-Scott
sebmadgwick wrote:A simple and effective method to calibrate the gyroscope gain is to:
- Log the gyroscope output as you turn through a measured/constrained rotation (e.g. 180 degrees) over a short period of time. (Keep rotations monotonic)
- Integrate the logged output with a starting guess of the gain to yield the calculated angle of rotation.
- Ad hoc tune this gain until your calculated angle of rotation equals your measured angle of rotation.

To really improve your calibration process:
- Compile a data set of many repetitions featuring a range of angular velocities.
- Automate the ad hoc process with MATLAB optimisation toolbox for example.

Methods such as using a record player may only enable the accurate calibration at 1 or 2 known magnitudes (assumes truly linear) and is unlikely to be representative of the motion within the intended application.
By sebmadgwick
#122009
A report, video and source code are available for the method I suggested above:
http://www.x-io.co.uk/node/8#automated_calibration

Although the study uses servos to rotate the gyro, there is no reason why this cannot be done by hand. In this way the method enables the calibration of gyroscopes without the need for any extra equipment.
By sebmadgwick
#123795
I thought I would share some findings regarding 'turn table' vs. 'integration' gyroscope calibration.

I fixed the ITG-3200 to a newly purchased turntable and allowed it to rotate 10 times so that it turned precisely 3600˚ (±0.2˚) at 45 RPM. By sampling the output at 256 Hz I was able to integrate the coupled body rates to yield to measured angle rotated, free from alignment errors. When using the datasheet sensitivity values, the measured angle was 3599˚; indicating an overall sensitivity error of 0.28% !

Using the now validated datasheet sensitivity values, I observed the turntable angular velocity to be 276˚/s when rotated at 45 RPM. We know that 45 RPM should be 270˚/s and that our measurement error is approx 0.28%; therefore an observed turntable angular velocity error of 100*(276/270 - 1) = 2.22% can only be accountable by the turn table itself.

These results are repeatable. The conclusions are:
1) The ITG-3200 datasheet sensitivity calibration values are far more accurate than one might expect.
2) Turntable angular velocities may be far less accurate than required. (Note that my turntable was low quality)
3) An integration based calibration approach can be extremely accurate provided the user accounts for (a) the sensor bias and (b) the random walk that occurs when integrating mean zero noise.
By hozone
#151834
@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);
	}
}