# KOP Gyro Lag

My team is experiencing a problem with the gyro included in the KOP this year. It appears to have a lag of almost a second after any large turn. For example, if we make a 90 degree turn and print out the gyro value each 26ms loop, the gyro will think it’s still turning for 30-40 loops after the turn has stopped and motors have been set to neutral. The gyro value will be around 75 (on a 0-255 scale) and gradually return to neutral, but it will not reach neutral until almost a second after the robot has stopped turning.

This is a big problem because we intend to use the gyro to allow the robot to maintain a straight heading during autonomous mode. Basically, we store a neutral rate before we start moving, then slow down either the left or right motors when the gyro value deviates from that rate to counteract any deviation from a 0 heading.

This works perfectly if we just tell the robot to go straight. But if we tell it to turn left and then go straight, it will make a large turn to the right. This is because, for about one second after the left turn, the gyro will still say we are turning left. The robot will then attempt to “correct” for this by slowing down the right motor, but since the robot isn’t really turning left, it will actually turn right.

We are using IFI’s default code right now, but we tried converting everything over to Kevin’s latest code to see if that would help. Unfortunately, it didn’t. For about one second after a fast turn, Kevin’s gyro code reports a turn rate of over 1,000 tenths of degrees per second. Yes, I know, that’s way over the 800 tenths of degrees per second limit of the gyro.

We’re thinking our problem is that we are saturating the 80 dps gyro, and that is making it do weird things. So, our plan is to go buy the ADXRS300 and be done with it. We aren’t 100% sure saturation is our problem, however, and we don’t want to spend \$70 just to find out that it still doesn’t work.

So, here’s our question: can anyone here who has the ADXRS300 confirm that it does not have the lag problems described above? (or recommend another gyro that doesn’t have the problems described above)

Thanks,
Josh - Team 339 programmer

2 things:

1. I believe the lag you are seeing is related to your print out rather than true lag. Output to screen takes more time than the slow loop, so what you are seeing as output happened a while ago. When you are outputing a dynamic value every loop, the buffer backs up. You could try adding a counter and just print every 10 loops or so.

2. The 80 deg/sec gyro is ok if you just want to use it to help drive straight, but it is hard to turn the robot that slow. I would definitely go with the 300 deg/sec gyro. Again lag issues you are observing aren’t originating from from the gyros themselves so that isn’t an issue.

I thought this too, but the robot itself seems to be affected by this lag. As I described in my previous post, when told to go straight after a left turn, the robot makes a large “correction” to the right. This indicates to me that gyro is telling the robot that it is still turning left when in fact it is not.

I also doubt the printout is my problem because I am using another printout as a reference. Every single slow loop, I print out a counter called “time tic” so I know how many slow loops have passed by. When the robot turns, it does so using gear tooth sensors, and prints out a message when the turn is finished and motors have been set to 230 each again (for another straight run). After that message, the gyro value printout (which also prints every loop) indicates the robot is turning for the next 30-40 time tic printouts.

Yes, it is true that all of these printouts are delayed. But the “turn finished” prinout would also experience the same delay. Regardless, there are still 30-40 loops between the end of a turn and when the gyro stops reporting a turn.

yeah this years KOP can only measure 80 deg per second(as opposed to last years 150). . . read your sensor manual . . . . yeah kinda sucks.

Just for fun try slowing down your printf’s and see if that has any affect. If not then you have another chunk of code that is lagging. The gyros don’t lag. Are you using any for loops? Any other loops?

3Here’s an example of what my terminal windows looks like after I get after telling the robot to turn, then go straight. This isn’t actually code - it’s what prints out into the terminal window. First, it does the turn, and the gyro value reflects that:

``````Autonomous State = Turn
Loop Number = 1
Gyro Value = 75
Left Motor = 127, Right Motor = 230
Autonomous State = Turn
Loop Number = 2
Gyro Value = 75
Left Motor = 127, Right Motor = 230
Autonomous State = Turn
Loop Number = 3
Gyro Value = 75
Left Motor = 127, Right Motor = 230
Autonomous State = Turn
Loop Number = 4
Gyro Value = 75
Left Motor = 127, Right Motor = 230
``````

This continues until the robot has turned 90 degrees, as determined by the gear tooth sensors (and I can confirm by watching it that that works):

``````Autonomous State = Turn
Loop Number = 32
Gyro Value = 75
Left Motor = 127, Right Motor = 230
Autonomous State = Turn
Loop Number = 33
Gyro Value = 75
Left Motor = 127, Right Motor = 230
Autonomous State = Turn
Loop Number = 34
Gyro Value = 75
Left Motor = 127, Right Motor = 230
TURN DONE
``````

Now that the turn is done, I go into another function that tells the robot to go straight, using the gyro to make corrections to the motor speeds. In that function, the printouts say:

``````Autonomous State = Straight
Loop Number = 35
Gyro Value = 75
Left Motor = 230, Right Motor = 230
Autonomous State = Straight
Loop Number = 36
Gyro Value = 75
Left Motor = 230, Right Motor = 190
Autonomous State = Straight
Loop Number = 37
Gyro Value = 75
Left Motor = 230, Right Motor = 160
Autonomous State = Straight
Loop Number = 38
Gyro Value = 75
Left Motor = 230, Right Motor = 140
Autonomous State = Straight
Loop Number = 39
Gyro Value = 75
Left Motor = 230, Right Motor = 127
Autonomous State = Straight
Loop Number = 40
Gyro Value = 75
Left Motor = 230, Right Motor = 127
Autonomous State = Straight
Loop Number = 41
Gyro Value = 75
Left Motor = 230, Right Motor = 127
``````

That continues for about forty loops, when the gyro finally notices that we aren’t turning anymore:

``````Autonomous State = Straight
Loop Number = 75
Gyro Value = 80
Left Motor = 230, Right Motor = 127
Autonomous State = Straight
Loop Number = 76
Gyro Value = 95
Left Motor = 230, Right Motor = 150
Autonomous State = Straight
Loop Number = 77
Gyro Value = 115
Left Motor = 230, Right Motor = 180
Autonomous State = Straight
Loop Number = 78
Gyro Value = 127
Left Motor = 230, Right Motor = 230
``````

Now, the robot thinks it’s going straight and stops correcting the motors. Of course, it’s actually way off course, since it “corrected” for 30 tics in which the gyro reported a left turn that wasn’t actually happening.

Note that I was putting that into my own words since I didn’t save the terminal printouts and can’t get new ones right now. The gyro value actually varied between 72 and 78 during the turn.

I can slow down the printouts, but I don’t see how that would help. Yes, all of the printouts are delayed. In fact, we get a red light of death if we run autonomous mode for too long with those printouts on (serial buffer overflows). But all of the prinouts should be affected by the same delay. The fact remains that, for forty tics after the turn stops, the gyro reports that we are still turning.

The only way the printouts could be the problem is if they were somehow slowing down the ADC but not the rest of the code. I’ll try slowing down the printouts to once every ten loops tomorrow (we’re taking today off), but I doubt it will help.

I think the problem is related to us exceeding the gyro’s 80 dps range during the turn, but like I said, we don’t want to buy the 300 dps version only to find out that it has the same lag.

What exactly happens when you exceed the gyro’s range? Will it simply report its maximum range and then go back down when you stop turning? Or will it get “stuck” at its maximum range for about a second?

And no, we aren’t using any other loops in our code except the master 26.2ms loop. We used to use a while loop to do atuonomous, but we fixed that. There are a few floating point operations, but nothing too complicated.

When you max out a gyro it just gives the max rate until it drops below the max again. There is no lag in the gyro output itself. What it sends is what it sees at that instant. It’d need to be able to store information in order to even remember what any lag was.

However, that doesn’t mean code on the RC couldn’t introduce a lag in the readings, but I too, doubt it.
None of our gyro’s have ever exhibited a lag. We use 300 deg/sec gyro’s on the robot, but other gyro’s in demonstrations.

The gyro values in your sample printout seem very odd. Where exactly are you getting your gyro values from and what do they represent?

Our code for getting the gyro value says the following:

``````unsigned char ucGyroValue = (Get_Analog_Value(rc_ana_in01))  >> 2
``````

Basically, we are getting the analog value from the RC and shifting it two bits to get a value between 0 and 255. I thought maybe the shifting was the problem, but I also encountered the lag with Kevin’s gyro code, which doesn’t shift.

The thing is, only a turn triggers the lag. Like I said, if we tell the robot to go straight, it does just fine. If we print out the gyro value in main.c every loop, it prints a constant neutral or something very close to neutral when the robot is stationary. If we manually nudge the robot, the printed gyro value changes instantly with almost no lag at all. But if we make a sharp turn during autonomous, the value lags considerably.

In case it matters, we are calling a separate function to calculate motor corrections. It gets the gyro value, calculates a motor correction percentage, and return the correction percentage to the caller.

Here’s the entire function if it matters. There is one fabs but from what I’ve read that shouldn’t be a problem if we only use it once.

``````
static float fCorrectMotorsForOutOfAlignmentGyro (
eDecreaseWhichMotorEnum *peDecreaseWhichMotor) // tells the calling function which
// which motor needs the adjustment on
{
unsigned int uiGyroValue = GET_ANALOG_VALUE(GYRO_INPUT);
// The analog value from the gyro at present
float fPercentageOfChangeToMotors = 1.0;           // The number that will be multiplied by the current motor speed to slow
// it down for a correction (i.e. 0.99 will slow down the motor by 1%)
// Positive values indicate we are too far right. Negative values indicate we
// are too far left
//-------------------------------------
// if the caller didn't pass in the correct
// argument type, simply return a NO_CHANGE
// value.  Preset the change goes to the
// LEFT motor
//-------------------------------------
*peDecreaseWhichMotor = DECREASE_LEFT_MOTOR;
if (peDecreaseWhichMotor == NULL)
return (fPercentageOfChangeToMotors);
//--------------------------------------------------------------------------------
// Depending on the direction we are turning, increase or decrease our total
//--------------------------------------------------------------------------------
iGyroTotalError = iGyroTotalError + (uiGyroValue - iGetGyroStartingValue());

//--------------------------------------------------------------------------------
// Calculate the percentage of change based on how far off we are (gyro error) and our constant
// motor correction curve valuee (FACTOR and CURVE)
//--------------------------------------------------------------------------------
fPercentageOfChangeToMotors = 1.0 -
MIN((MOTOR_CORRECTION_FACTOR * fabs(iGyroTotalError / MOTOR_CORRECTION_CURVE)), 1.0);
//-------------------------------------
// if we are drifting to the left
// then we need to let the called
// functions know by denoting that we
// want the RIGHT motor to be decreased
//-------------------------------------
if(iGyroTotalError < 0)
*peDecreaseWhichMotor = DECREASE_RIGHT_MOTOR;

# define DEBUG
# ifdef DEBUG
printf("The gyro value is %d." EOL, (int)uiGyroValue);
printf("The gyro error is %d." EOL, (int)iGyroTotalError);
printf("The percentage of change %d.%d" EOL, (int)fPercentageOfChangeToMotors, (int)FLOAT_FRAC_PART(fPercentageOfChangeToMotors));
# endif // DEBUG
# undef DEBUG
return (fPercentageOfChangeToMotors);
} // end fCorrectMotorsForOutOfAlignmentGyro
``````

GET_ANALOG_VALUE is a macro we wrote that gets an analog value and shifts it two bits.

You’ll notice the function has an accumulator, iGyroTotalError, which keeps track of how far off of a zero heading we are. The robot will actually try to turn back to a zero heading based on this value.

iGetGyroStartingValue() gets the gyro neutral value, which we measure right before we start autonomous mode.

MOTOR_CORRECTION_FACTOR and MOTOR_CORRECTION_CURVE are defines that control how large the corrections to the motors are.

EOL is a define we made that inserts whatever this years “go to the next line of the terminal screen” command happens to be. Sometimes it’s \r, sometimes it’s
, sometimes it’s
…so we just made a macro to avoid having to change every single printf statement if the command changes again.

Can you zip up your build directory and e-mail it to me? Also, make sure you’ve plugged the gyro into channel one. If you plug it into a different channel than specified in gyro.h, the ADC can still read residual charge from the sample-and-hold capacitor if that input is floating. How is the gyro wired? Perhaps it’s output driver is weak and having a tough time driving the capacitance of the cabling? Ideally, the cable should be as short as possible.

-Kevin

Just did some searching and it look like I’m not crazy after all.

I’m trying to implement a closed loop controller with the KOP

Gyro, and it seems to have a major flaw !!!

The initial symptoms were that if you locked the current heading when the operator stoped turning the bot (joystic returns to detent), the controller would steer the robot BACK about 30 degrees.

I initially suspected my code, but finally I had to start looking at the actual Gyro input. By just wiring the Gyro to a stand-alone RC unit on analog channel 1, I could display the gyro angle whenever it changed.

If I spin the gyro, the heading starts changing immediatly, but when I stop it, the heading changes continue on for almost another SECOND. Once again I suspected my software (maybe overflowing the serial port), so I changed the input to a pot so I could simulate gyro input.

That is exactly the problem I am having, and this guy has the same problem with last year’s gyro, too.

And here’s one of the responses:

The KOP

gyro has a maximum number of degrees it can turn in one second before it ‘overflows’ and loses accuracy. To the best of my knowledge, this value is ~85 degrees in one second for the KOP
gyro. If you try turning 180 degrees in one second, you will overflow the sensor and drastically lose accuracy. (This is the same as exceeding the +1G acceleration on the accelerometer.)

For use of the gyro with our drive-train on our robot this year, we purchased an additional gyro with a maximum turn-rate of 300 degrees in one second from Spark Fun Electronics. (Which has tons of great sensors, BTW.) Seeing how our drive-train this year is geared for 9 ft/sec at 85% of the CIM

motor free speed, the increased turning-rate of this additional gyro was much appreciated.

Which is what leads me to believe that the 300 dps gyro would solve our problem.

Any thoughts?

Sure. I’ll send you our version that uses your code. We also have a version that uses IFI

’s base code. Both exhibited the gyro lag problem.

The topic that I linked to above tells me it isn’t an ADC problem, since the person who posted that topic tested the same analog input with a POT and there was no lag at all.

You should test your setup with a potentiometer too (I suspect it will react much faster). Because what you describe sounds like a classic capacitive drive problem, I strongly suspect your gyro cannot drive the capacitance it’s output driver is “seeing”. This can be due to a defective gyro and/or the cabling presents a capacitive load that is too high for the gyro to drive. Either way, this is not normal behavior as the angular change should be nearly instantaneous.

-Kevin

How much cabling is too much? We’re just using one standard-length PWM

cable that came from the KOP
. Is that too much? What would you suggest we do next?

I just tried a really short cable and it didn’t help. We still have the same 1 second lag. I think we’re just going to order a new ADXRS300 having eliminated all other potential sources of the problem.