How to end an auto mode after gyro gets out of deadband

Hey all,

In my code, i have a gyroscope that gets read from the adc.c and gyro.c where when it gets off the deadband the robot would stop auto mode. But when the gyro gets put back into position (within the deadband) it would keep executing from where it started. Any ideas?

My guess is you’re just doing a direct comparison to the gyro value to determine if you should run autonomous or not. You might want to have a flag that gets set to on when the gyro goes out of the deadband, but it never gets reset. Then have the autonomous only execute when that flag is off.

Could you show us the portion of code controlling autonomous from the gyro?

Just to keep weird things like this from happening, our code has a global flag (called auto_done) that is set once the autonomous mode is completed. If the flag is set, the autonomous code won’t do anything.

I dont understand the logic behind your implementation?

The gyro measures the rate of turn of the sensor (degrees rotation per second). On which axis are you going to mount the gyro sensor with the intent that any rotation on that axis will cause auton mode to end

but then to restart (continue) auton mode when the rotation stops ?!

My guess is that they don’t want to fire if they have been knocked off angle from the target, but would like to start firing again if their robot once again faces the target.

If so, I’d suggest not ending autonomous mode and trying to start it again, instead modify your autonomous so that each cycle a check is done to determine if you should be firing or not:

<get update from gyro>

if (<gyro in accepted range>)
{ <fire>
} else
{ <don’t fire>
}

So that each time the sensor data is updated, the check will be done again.

I’m fairly new at this, so my apologies if I’m off base here.

I’ve got a better guess. They want the robot to stop moving if it get whacked by another bot, and start again after the gyro settles down. and the robot stops going nuts. In that case, the check for the gyro condition comes before all other auto code. Like thus:

User_Autonomous()
{

gyro state reading goes here

if(gyro in good state)
{
good gyro code goes here
including all counter incrementing, auto mode switching, etc.
}
else
{
code to run if gyro is crazy goes here
could be an alternate automode or something else
stopping motors, etc.
}

}

That’s much more pseudo than it is code, of course. You could get fancy and set a flag such that the gyro has to be sane for X loops for it to enter the good auto code. With the above code, the execution could jump into the good auto loop if you happen to catch the gyro fluctuating through a good value.


#define KP		1
#define KI		0
#define KD		0
#define WANTED_HEADING	0
#define WANTED_OUTPUT_SPEED		80 //-127 to 127
#define SHOOTING_DEADBAND		20 //4 degree deadband. 20 tenths of a degree = 2 degrees. -2 to 2 = 4 total degrees.

cur_heading = Get_Gyro_Angle();

error = WANTED_HEADING - cur_heading; //if you want the robot to drive straight in auto mode, line up robot, then turn on. cur_heading will be 0 and 0-0=0.
sumError += error;
dError = last_error - error;

if(sumError > 100){
	sumError = 100;
}else if(sumError < -100){
	sumError = -100;
}

//Calculate individual outputs
pOut = error * KP; //proportional gain
iOut = sumError * KI; //integral gain
dOut = dError * KD; //differential gain

//Add for total PID output signal
pidOut = pOut + iOut + dOut;

//limit pidOUT so total output value is in range (0,254)
if(pidOut > 126){
	pidOut = 126;
}else if(pidOut < -127){
	pidOut = -127;
}

//To drive straight, subtract output from either side of the drivebase..
//this should work if pwm01 is left side and pwm02 is right side.
pmw01 = 127 + WANTED_OUTPUT SPEED - pidOut;
pwm02 = 127 + WANTED_OUTPUT SPEED + pidOut;

//Lastly, do other stuff.
if(error >= -SHOOTING_DEADBAND && error <= SHOOTING_DEADBAND){
	Shoot(); //Put whatever you want the robot to "do" here.
}

This will utilize a PID feedback control system to steer and control the shooting of your robot.

This will work the best, but you must know how to tune this piece of code to work with your robot. If you choose to follow this road, please read (in full) this page:
http://www.embedded.com/2000/0010/0010feat3.htm
(it wasnt loading for me… heres the google cached page)

and this CD paper: http://www.chiefdelphi.com/media/papers/1823?

ok, but the gyro doesnt tell you at what angle you are pointing, it tells the the rate at which the robot is turning

so if the robot turns for any reason it would stop - any reason includes any offset in your drive motors that might cause the robot to not go exactly straight

then when the robot has stopped turning it will start moving again? that doesnt make much sense.

the same for Kevins suggestion - if another robot taps you sideways a little whats the point in shutting the robot down, then starting up again when you stop turning? Either way you have been knocked off your path.

My guess (another guess!) from the names of the files they are using (adc.c and gyro.c) is that they are using the Kevin Watson gyro code, which uses the rate information to determine a relative angle.

This is all getting highly speculative now though… more information from 968 would make it easier for us all to help :slight_smile:

Well there’s a maximum rate limit of 80deg per second that the gyro will measure. Certainly you can’t trust it to integrate the rate and reliably determine your angular position if it’s near this maximum or fluctuating wildly. And if it’s pegged at the maximum, then you can’t trust it at all or your integrated angle at any time after that. So I was figuring that if it hit the maximum, or maybe 75% of the maximum, you’d shut your motors down and hope like heck it’d settle down to a trustable value, then start back up again and continue on your merry way. Probably better than forging blindly ahead and hoping for the best.

This is more along the lines of what we want to happen. Once we get hit and the gyro senses rotation, we want the robot to just stop.

Let’s say that you have a good initial value for your neutral point, and that you can handle the case where each sample bounces around that point a bit ie. you have a stable value for zero rotation. You don’t necessarily want to stop for a minor disturbance, such as small irregularities in the carpet, so pick a +/- threshold away from you neutral point, and some time threshold of persistence - (9 passes ~1/4sec?) If you exceed those two thresholds, together, then set a latch variable that stomps on the chassis pwms and sets them to 127.
Then you can turn the two threshold “knobs” to get the behavior you are looking for.

Eric

If you are going through the trouble to read the gyro, and see that your robot is turning when you dont want it to

then instead of having your robot throw up its arms and give up in the middle of auton mode, why not take that same information, feed it to your motor control system, and use that error signal to zero out the turn rate and keep the robot on its original heading?

The gyro chip is very sensitive, as soon as it detects the slightest bit of turn rate you can have your robot fight back to stay straight on its path.

You’ve come this far, take the last step: close the loop (PID feedback is a beautiful thing!)

In fact, if you design in gyro feedback steering for auton mode, you can leave it engaged for driver mode as well - then all your driver has to do is point the robot with the joystick - if anything pushes it off the drivers intended course then the *robot itself * will fight back against the outside force to maintaing the drivers desired heading.

So true Ken! We’ve been using the gyro feedback for yaw rate stabilization and heading since 2004 and have found it to be VERY effective :cool:

Shameless plug, read my PID whitepaper linked in my signature for an introduction to the math and programming behind PID, if you have any specific questions feel free to catch me via PM or email, always happy to help.

Thanks for all the replies…

We know how to write a PID loop but, thats not what were looking for. What im actually trying to do is to totally kill the autonomous mode after the gyro gets out of the deadband in code, but once it goes back into the dead band, the code was once again running. I need to stop the bot once it gets out of the dead band and make sure its going to not re execute while its back into the deadband.

Getting it still??
Heres what I have in my code so far.



	autoCalculator++;
	gyroTimer++; // this will rollover every ~1000 seconds

	if(gyroTimer == 1)
	{
		// start a gyro bias calculation
		Start_Gyro_Bias_Calc();
	}

	if(gyroTimer == 2)
	{
		// terminate the gyro bias calculation
		Stop_Gyro_Bias_Calc();

		// reset the gyro heading angle
		Reset_Gyro_Angle();

		printf("Done\r");
	}


	//	if(i >= 30 && j >= 65)
	if(gyroTimer >= 3)
	{
		temp_gyro_bias = Get_Gyro_Bias();
		temp_gyro_rate = Get_Gyro_Rate();
		temp_gyro_angle = Get_Gyro_Angle();
		printf("Gyro Angle: %d
", (int)temp_gyro_angle);
		//i = 0;

	}

	// AUTONO STUFF GOES HERE!!	
					gyroAuto = temp_gyro_angle;
				gyroAutoCalc = temp_gyro_angle - gyroAuto;
				
				if(ActivateGyro == 1)
				{
					if(setauto == !2 && gyroAuto < 24 && gyroAuto > -24)
					{
						setauto = 1;
					}
					else
					{
						setauto = 2;
					}
				}
				else
				{
					setauto = 1;
				}

When it goes into setauto = 2, the bot stops. But why would it re execute?

I didn’t look closely at the rest of the logic, but this line is wrong. You probably mean

if(setauto != 2...

How’s 'bout something like this:


   .
   .
   .
   static unsigned char LatchEndAuto = 0;   /* ...or declare it global */
   int gyroThreshold = 24  ; /* ...or whatever */

   if( !LatchEndAuto)
   {
      if ( (gyroauto < -gyroThreshold) || 
           (gyroauto > gyroThreshold )   )
           LatchEndAuto = 1 ;
   }
    .
    .
    .

   /* put this at the end of your auto code */
    if(LatchEndAuto)
   {
      LeftSideChassisPWM  =  127 ;
      RightSideChassisPWM =  127 ;
   }
   

Eric