My team’s been trying to use the gyroscope sensor on our robot, but we’ve been having problems with the accuracy. We are aware of the drifting problem, and thanks to the forums we have gotten rid of it through coding. However, even without the drift the gyro seems to be very inaccurate. The value it returns always seems to be off by about 10 percent. So if we turn it by 90 degrees, it returns 1000. Is this a problem that everyone has, or is it specific to our particular gyro?
We would appreciate any insight anyone might give to help us get accurate values.
-How are you handling the drift in code - Copying the code into "
" tags would be best (look for the # icon in the editor, that's for code)
-What language are you using
-How do you have it configured if using easyC
-Are you initializing it properly (in either language)
I would suspect implementation of drift handling code or initialization. The drift isn't really that bad (usually about 1/10th of a degree per second) unless you saturate the gyro, at which point there's nothing you can do.
I first do initiation similar to the RobotC example:
SensorType[gyroPort] = sensorNone;
wait1Msec(500);
//Reconfigure Analog Port 2 as a Gyro sensor and allow time for ROBOTC to calibrate it
SensorType[gyroPort] = sensorGyro;
wait1Msec(2000);
Whenever I use the gyro, I first set the input equal to zero:
SensorValue[gyroPort] = 0;
Then I can just read the value:
while(SensorValue[gyroPort] < desiredDegrees)
{
//rotate the robot
}
And here is our “Turn” testing code. For now, we’re just writing the gyro value on an LCD line:
void Turn(int degrees){
int goal = degrees * 10;
int proportional = goal;
float integral = 0;
float derivative = 0;
int lastGyro = 0;
int lastDriftGyro = 0;
float speed;
float Kp = 0;
float Ki = 0;
float Kd = 0;
ClearTimer(T1);
ClearTimer(T2);
SensorValue[in1] = 0;
float driftRate = 10.0; //drift rate of gyro in tenths of a degree per second
int gyroError = 0;
int gyroValue = getGyro();
while(true){//(abs(goal) > abs(getGyro())){
clearLCDLine(0);
displayLCDPos(0,0);
displayNextLCDNumber(gyroValue, 3);
if(time1(T2) > 500){
if(abs((1000.0*((float)(getGyro())
-(float)(lastDriftGyro))/(float)time1(T2))) <= driftRate){
gyroError += lastDriftGyro - getGyro();
}
lastDriftGyro = getGyro();
ClearTimer(T2);
}
gyroValue = getGyro() + gyroError;
// Code to drive the motors to turn
}
int getGyro(){
int gyro = SensorValue[in1];
if(gyro < 0){
gyro += 3600;
}
if(gyro > 1800) {
return -1*(gyro-3600);
}
else {
return(-1*gyro);
}
}
We found that the gyro was drifting badly, just sitting in place. Once we added the code above, (based on other postings on the forum), we found that the drift has been eliminated.
However, when we turn the robot 90 or 180 or 270 or 360, we get readings that are roughly 10% too high. For example, if we manually turn the robot a full 360, our LCD tells us that we are at -363.
Our programmer says that even if we comment out the “fix the drift” code, we are still seeing values coming back from the gyro that are off by roughly 10% (too high).
You could try changing the value of SensorScale] to something slightly different. I think the default is 130, perhaps try 120 or 140 and see how this affects the calibration.
Sorry, I should have been more clear. We are outputting the value directly from the gyro - which is in tenths of degrees. So, the -363 is roughly ten percent of the expected rotation of 3600 (tenths).
I’ll mention the SensorScale to our programmer and see if that helps.
I don’t have the code on hand, but we managed to get an incredibly stable and precise gyro reading, although it wasn’t representative of any degrees (as in you can’t really tell it to go x number of degrees, it just requires some guess and check) by using one of the recommended methods of eliminating drift. I also find that in a practical scenario, you will not be “reading” the gyro for more than a few seconds, so sacrificing a little bit of drift for accurate readings was preferred. I think my SensorScale is set to about 400 or something, and its readings are accurate and precise. I have it set to eliminate any drift of 5 or less, and it keeps it stable enough to produce and accurate reading for about 10-15 seconds, and then it begins to drift. Good Luck! When my team next meets I can post some code but at the moment I don’t have it on me.
One thing I might point out is that this gyro has a nonlinearity spec of ± 1% FS relative to a best fit straight line (BFSL). Full scale for this gyro is 1000 deg/s. I interpret this to mean that the deviation at any point on the gyro transfer function curve can be off by 10 deg/s from the BFSL. This is the worst case spec , but you could have a gyro with this kind of error. So lets say you make a full turn in 1 second or 360 degs/s rate. If you happen to be on a peak nonlinearity point, then the gyro could be off by 10 deg at the end of the turn and still be within spec.
This type of error can be calibrated out but RobotC does not provide this capability. Also…
The gyro also has a noise spec and a A/D sampling error that combine to give around .28 deg/sec rms per sample. (ref blog post) This gives a random walk rms angle deviation of sqrt(Tdt).28 where T is fhe integration time and dt is the update interval. If you integrate for 4 seconds and the gyro is updated at 100 hz then the rms error after 4 seconds would be .056 degrees. In 16 seconds it would be .112 degrees rms. So this is not a significant contributor to the error in short intervals.
I am a little disappointed that Vex did not provide a better scale factor to reduce the nonlinearity effects, or at least provide for a programmable scale factor.