Multiple Auton's

I was wondering of a way to do multiple auton modes. Please if you have any proven information let me know either in a PM or Email [email protected] .

I tired having a switch to make a digital input on the Robot Controler trigger a different auton mode by grounding the Signal (To make it a 1) with such code as:

(I forgot the actual name for the digital inputs so lets say dig 1 & dig 2)

if (dig1 = 1)
{
/Auton mode here/
}

else if (dig2 =1)
{
/* other Auton Mode/*
}

else
{
/do nothing /
}

Can someone tell me why this theory wouldnt work ??
Does anyone have an auton mode that has a switch to change between modes that I can look at and pick apart. Thankyou

Make sure you realize that = is the assignment operator in C and == is the equality test. Therefore, you’d have to say:


if (auto_selector_switch == 0)
  Do_Auto_0 ();
...

Sure, this would work. The only thing you need for multiple auton’s to work is some method to select which auto program you want to run. You can have a switch on the RC or the OI. Just chose the program based on its value.

Joe, your theory should work just fine. We also used switches to customize our autonomous mode. We could use switches to determine which side of the field we started on, what path to drive, and whether to do it in high gear or low gear. It was all configurable on the field, so our autonomous mode selection was a match-time decision, often based on who was lined up opposite from us.

The code is pretty much what you have above, albeit much uglier. This is an earlier copy that wasn’t cleaned up.

Cheers!


void User_Autonomous_Code(void)
{	
	static unsigned int auton_status = 0;
	static unsigned char left_set; // left motor speed set-point
	static unsigned char right_set; // right motor speed set-point
	static unsigned int counter; // used to take snapshot of clock for dead-reckoning moves
	unsigned int pressure;
	
	
  while (autonomous_mode)   /* DO NOT CHANGE! */
  {
    if (statusflag.NEW_SPI_DATA)      /* 26.2ms loop area */
    {
        Getdata(&rxdata);   /* DO NOT DELETE, or you will be stuck here forever! */
		
		relay2_fwd=1; //turns brake off.....

		if (Clock > Old_Clock) // Old_Clock and Clock are serviced by the IR Timer - this line ensures a new IR cycle has occured
		{
			Old_Clock = Clock;
			switch (auton_status)
			{
				case 0: 
					Left_Encoder_Count = 0;
					counter = Clock;
					left_set = 127;
					right_set = 127;
					relay2_fwd = 1;
					if (rc_dig_in10)
					{ 
						relay5_fwd=1;
					}
					else
					{
						relay5_fwd=0;
					}
					auton_status++;
					break;
			
			case 1:

		
		if (rc_dig_in11)

		{ 
			if ((Clock - counter) < 384) //this stops the robot in low gear right in front of the goal
					
					{
						left_set = 255;
						right_set = 225;//fudge factor
					}
				
					else 
					{
						left_set = 127;
						right_set = 127;
					    counter = Clock;
					}
					break;
		}

	
	

		if (rc_dig_in12)
		
		{	
			if ((Clock - counter) < 460) //this makes the robot hit the goal and go straight 3/4 of the way
					{
						left_set = 255;
						right_set = 225;//fudge factor
					}
				
					else 
					{
						left_set = 127;
						right_set = 127;
						counter = Clock;
					}
					break;

		}


		if (rc_dig_in13)

		{
				if ((Clock - counter) < 576) // rush down to the other end of the feild hitting the goal HIGH GEAR
					{
						left_set = 255;
						right_set = 255;
					}
				
					else 
					{
						left_set = 127;
						right_set = 127;
						counter = Clock;
					}
					break;
		}


		if (rc_dig_in14)

		{
				if ((Clock - counter) < 396) //stop beside the mobile goal,
						
						left_set = 225;
						right_set = 225;
					}
				
					else 
					{
						left_set = 127;
						right_set = 127;
					   	counter = Clock;
						auton_status=2;
					}
					break;
				
				case 2:
				
				if ((Clock - counter) < 15) //turn to face right back at you.
					{
						left_set = 0;
						right_set = 255;
					}
				
					else 
					{
						left_set = 127;
						right_set = 127;
					   	counter = Clock;
						auton_status=3;
					}
					break;
			
				case 3:
				
				if ((Clock - counter) < 10) //positions itself behind the goal
					{
						left_set = 255;
						right_set = 225;
					}
				
					else 
					{
						left_set = 127;
						right_set = 127;
						counter = Clock;
						auton_status=4;
					}
					break;

				case 4:
		
				if ((Clock - counter) < 15) //positions itself behind the goal
					{
						left_set = 0;
						right_set = 225;
					}
				
					else 
					{
						left_set = 127;
						right_set = 127;
					    	counter = Clock;
						auton_status=5;
					}
					break;
				
				case 5:
		
				if ((Clock - counter) < 384) //positions itself behind the goal
					{
						left_set = 255;
						right_set = 225;
					}
				
					else 
					{
						left_set = 127;
						right_set = 127;
					    	counter = Clock;
					}
					break;
				
		
		}

		
			}
		}
		
		// Carol's cubic transfer function that desensitizes small movements, but still allows full speed
		temp_p1_y = (signed long)left_set - 128;
	    pwm01 = (unsigned char)(((temp_p1_y * temp_p1_y * temp_p1_y)  >> 14) + 128);
  		temp_p2_y = (signed long)right_set - 128;
  		pwm02 = (unsigned char)(((temp_p2_y * temp_p2_y * temp_p2_y)  >> 14) + 128); 
		
		

// Run compressor
		  pressure = Get_Analog_Value(rc_ana_in16);
		  
		  if (pressure < 800)
		  	relay6_fwd = 1;
		  else if (pressure > 925)
		  	relay6_fwd = 0;

		// Get all 6 drive motors working together		
		pwm03 = pwm01;
  		pwm05 = pwm01;
  		pwm04 = pwm02;
  		pwm06 = pwm02;
        Putdata(&txdata);   /* DO NOT DELETE, or you will get no PWM outputs! */
    }
  }

We had the following code to use 2 pots on the OI to set the aunonomous mode.

Basically, we had 6 varieties of Auton (0-5). We had up to 15 steps per auton program (0-15). We could set the max number of steps as well as set the particular program.

The way it works is that your robot has to be not in AUTONOMOUS MODE, DISABLED and the OI has to be in USER MODE.

After that, you either are looking at the codes or you are setting the codes.

For our OI, we had two software disable switches in addition to the disable from the competition port (OIW_Enable_Sw and OIA_Enable_Sw). We used these switches to decide if we were in the “view autonomous” mode or the “set autonomous” mode. If both of these switches are in the “enabled” state, the program is in the “viewing” mode. If one or both switch is disabled, then the program is in the “setting” mode.

One pot sets the program number (OIW_RHW_Pot), the other sets the number of steps (OIA_Extra_Pot).

The display is as follows XXY where XX is the number of steps the particular program will run and Y is the auton program number – I use this format because the number of steps is greater then 10 and the number of auton programs is not AND I need to have the entire number (XXY) be less than 255 or it would not display properly on the 3 digit display on the OI.

It is harder to explain than to use.

Below is the code fragment of where we set the codes we use in autonomous mode to select which program runs and how far it runs.

Finally, we also set these numbers to a safe condition upon reset so that we could simply cancel autonomous mode by simply hitting robot reset.

Joe J.

if (!Enabled && user_display_mode && !autonomous_mode)
{
if (OIW_Enable_Sw == 0 || OIA_Enable_Sw == 0)
{

[indent]if ((OIA_Extra_Pot >> 4) < 16) auton_stop_cnt = OIA_Extra_Pot >> 4 ;
else auton_stop_cnt = 15 ;
if ((OIW_RHW_Pot >> 5) < 6) auton_prog_no = OIW_RHW_Pot >> 5 ;
else auton_prog_no = 5 ;
}
User_Mode_byte = (auton_stop_cnt *10) + auton_prog_no;
[/indent]}

Here are two ways teams I helped accomplished it this year.

  1. Use a BCD style rotary switch available from Digi-Key (hooked to digital input pins 15-18 in this case). 16 choices using 4 digital input pins or 8 choices using 3 pins. The extra selections were used for diagnostic software rather than have so many autonomous programs.

static unsigned int swtc; //set equal to the switch input
 
swtc = PORTJ>>4; // Auto select switch 0-15
switch(swtc) 
{
	case 0: 
	default:
		AUTO_0();
		break;
 
	case 1: 
		AUTO_1();
		break;
…
}

  1. Use a regular Radioshack style mechanical rotary switch. In this case a 6-position switch hooked to digital input pins 11-16.

if (!rc_dig_in11)
{
	 Auto_1();
}
else if (!rc_dig_in12)
{
	 Auto_2();
}
...
else
{
	 Auto_1();
}

That’s surprisingly similar to ours. I guess ours is a dumbed down version, but it’s worked almost flawlessly the past two years.

Ours has a selector switch (10 position I think) where we select the autonomous program that we want to run. That coupled with the R/L switch on the robot selects the waypoint list that will get executed. While the robot is DISABLED and not in USER MODE, the RC is constantly taking the value of the OI auton selector and assigning pointers to the correct list (actually an array in memory, but that doesn’t matter). Once the driver goes into USER MODE, we lock in the autonomous program and any changes to the selector switch are ignored. The OI display follows XYZ, where X is 0 for right, 1 for left; Y is the program number; Z is the current waypoint number in the program.

I said it’s been almost flawless because at Nationals in 2003 we failed to run autonomous in one of our qualification matches. One of the field crew members hit our OI select button and took us out of USER MODE after the drivers locked us in. No one noticed so no one re-locked us in. Apparently we needed to be in USER MODE in 2003 for us to run auto so we just sat there for 15 seconds.

We used 5 switches on the OI: 1 for side select, 4 for auton select. Each of the 4 switches represents a bit. We set a variable with these values in Process_Data_From_Master_uP() (which got me to notice the bug in main.c).

For Auton, we do this:

//...
while (autonomous_mode)   /* DO NOT CHANGE! */
{
 // Do instructions
 switch (AUTON_MODE)
 {
  case 0:
   //Do nothing
   break;
  case 1:
   Auton_1(); break;
  case 2:
   Auton_2(); break;
  case 3:
   Auton_3(); break;
  //...
 }
 if (statusflag.NEW_SPI_DATA)      /* 26.2ms loop area */
 {
  Getdata(&rxdata);   //DO NOT DELETE, or you will be stuck here forever!   
  Putdata(&txdata);   // DO NOT DELETE, or you will get no PWM outputs!
  Generate_PWMs(pwm13, pwm14, pwm15, pwm16);
 }
 Process_Data_From_Local_IO();
}// End Loop

Then, we wrote the Auton’s in seperate files.

I thinkthat this is a great thread. I think that it brings up another good point. Innovation First does a great job, but in some ways they have no idea what we, the users of their stuff, really need.

I am going to start a new thread that will be a title something like "what should the “Default Code REALLY include?” Of course, one thing it should include is an easy way to select auton programs.

Look for the thread, coming soon to a forum near you…

Joe J.

wow those are great solutions what we have is alo0ng the lines of:

 |rc_dig_in_01| + |rc_dig_in_02 << |+ |rc_dig_in_03 <<|

or something along those lines, it creates a 3 digit binary number that has 8 options, 0-7,what it does is sets digin 1 as the 1’s place, digin 2 as the 10’s place3 and digin 3 as the 100’s place, so we have options of 000,001,010,011,100,101,110,111, and we have a case set afeter that with our autonomous modes, in retrospect its a bit confusing for some people tyo understand, and a rotary selector would have een nice

wait…
we were talking about this during our meeting today, and we didn’t think that switches on the OI (vs on the robot) would work.
this is because i didnt think that your robot would recieve data from the OI during autonomous mode. (its autonomous, why would you get the data?)

altho, we did think it possible that it gets data once in the beginning, and could read the switches then.

can someone clear us up on this?
thanks,
~Stephanie
Team 1351

Yeah, I was under the impression that you may not (can not?) access information from the OI during autonomous mode. :confused:

The OI switches and joysticks can be read by the robot any time autonomous mode is not active. It’s no trouble to constantly read the value of a selector switch into a variable while auton_mode is false, and use that variable when auton_mode is true.

We liked having lots of autonomous options last year. Instead of eating up a bunch of switch inputs on the OI, we used a rotary switch to select between taps in a string of resistors and connected that to one of the joystick _aux inputs. The code saw an analog value, compared it against a collection of programmed low/high limits, determined which switch position had been selected, and stored a number representing that position in a global variable.

We’ll be doing something similar this year.

Someone should sticky this. I know I will be refering back to it as soon as we actually have a working bot.

You are correct. Data generated by the OI is not transmitted to the RC during autonomous mode. The field control system disables the transmission of any data from the OI during this period.

-dave

yay thank you!!!
~Stephanie
Team 1351

OK, my question: Is any data transmitted at all when the robot is disabled. eg. data is transmitted but ignored because the “disabled” flag is set?

Edit:

http://www.chiefdelphi.com/forums/showthread.php?t=23519 seems to be on point but has anyone confirmed the ability for this year?

Nothing is different in the data communication in disabled mode except for the actual “disabled” flag. Unless your code specifically checks that flag, the data is transmitted and acted on by the robot just as when the robot is enabled. The dashboard sees the pwm outputs being commanded, the user and LED control bytes come through unharmed, etc. The only real difference is that the master processor in the RC turns off all the actual output pins.

(Dave Lavery overstated the case when he said the data transmission from the OI is disabled during autonomous mode. The OI still sends data, but it is read by the robot code as all being inactive – joysticks at center, all switches off, etc.)

Awesome, thanks!