Autonomous Code help

Recently, our teams are running into some obstacles with programming. Unfortunately, I’m not much of a programmer. Can you guys please review this code? We wont have access to a compiler for a while.

This is what we’re trying to do
-Get the lift to raise at the start of the match
-trigger a sensor with a bumper switch and Bump a large ball and return to the tile
-Trigger a sensor with a bumper switch and Bump a second large ball, return to the tile while opening the funnels and lower lift(the part im worried about)
-Drive forward, enclose the funnels on the bump buckies
-close funnels to set up driver control

If you can check part of the code, we should be able to figure out the rest

//raise lift at the start of the match. 3 motors are on lift
motor[LeftLift]   = -127;
motor[RightLift1] = 127;
motor[RightLift2] = 127;
wait1Msec(1500)

While 1==1
{

		motor[LeftLift]   = -16;	//The robot maintains lift position for the duration of autonomous
		motor[RightLift1] = 16;
		motor[RightLift2] = 16;

	if (SensorType[Bump1] == 1)	//If 1st bumper switch is pushed by driver, robot goes forward, pushes large ball, and returns
		{
			motor[FrontRight]	=	-127; 
			motor[FrontLeft]	=	127;
			motor[BackRight]	=	-127;
			motor[backLeft]		=	127;
			wait1Msec(1500)

			//slow down 
			motor[FrontRight]	=	-10;
			motor[FrontLeft]	=	10;
			motor[BackRight]	=	-10;
			motor[backLeft]		=	10;
			wait1Msec(500)
			
			//return to tile
			motor[FrontRight]	=	127;
			motor[FrontLeft]	=	-127;
			motor[BackRight]	=	127;
			motor[backLeft]		=	-127;
			wait1Msec(1250)
		}

 	if (SensorType[Bump2] == 1)	//If 2nd bumper switch is pushed by driver, robot goes forward, pushes large ball, returns, opens funnels + lowers lift
		{
			motor[FrontRight]	=	-127; 
			motor[FrontLeft]	=	127;
			motor[BackRight]	=	-127;
			motor[backLeft]		=	127;
			wait1Msec(2000)

			//slow down 
			motor[FrontRight]	=	-10;
			motor[FrontLeft]	=	10;
			motor[BackRight]	=	-10;
			motor[backLeft]		=	10;
			wait1Msec(500)
			
			//return to tile + open funnels
			motor[Funnel]		=	-127;
			motor[FrontRight]	=	127;
			motor[FrontLeft]	=	-127;
			motor[BackRight]	=	127;
			motor[backLeft]		=	-127;
			wait1Msec(800)

			//Continue returning to tile + stop opening Funnels
			motor[FrontRight]	=	127;
			motor[FrontLeft]	=	-127;
			motor[BackRight]	=	127;
			motor[backLeft]`	=	-127;
			motor[LeftLift]  	=	30;
			motor[RightLift1]	= 	-30;
			motor[RightLift2]	= 	-30;
			wait1Msec(1100)			
		}

 	if (SensorType[Bump3] == 1)	//If 3rd bumper switch is pushed by driver, robot goes forward, gathers buckies, and retracts funnels 
		{	
			motor[FrontRight]	=	-127; 
			motor[FrontLeft]	=	127;
			motor[BackRight]	=	-127;
			motor[backLeft]		=	127;
			wait1Msec(2000)
			
			//open funnels to push in buckies
			motor[Funnel]		=	-127;
			wait1Msec(500)
			
			//close funnels to set up driver control
			motor[Funnel]		=	127;
			wait1Msec(1250)			
		}
}

this is something extra i’m trying to do, but i’m no sure if my logic is sound. I’m trying to make the next task start by declaring a variable. Then, by pressing the button an additional time, the next task will be executed.

int X = 0

if (SensorType[BumpX] == 1)
	{
		X = X+1
	}

if(X=1)
	{
		first task
	}


if(X=2)
	{
		Second task
	}

if(X=3)
	{
		Third task
	}

Your if’s should probably be while’s. In autonomous you are typically looking to do a procedural set of things rather than a set of choices. Maybe you do want to mx it up and this will work fine for that. It should technically work, but if you hit button 1 again, it would execute that button 1 subroutine of actions again and that is probably not what you want. However, if you saw something was happening with the other robot that would make button 2 set not work well, then you have it coded correctly.

Generally you want to wait until the button is pressed and do a specific task.

instead of:


if (SensorType[Bump1] == 1)
{
   //stuff you had it doing for that button that could be executed each time you bcame back though the while loop

For procedurally going through autonomous, you typically do it using while loops (and take out the while (1==1) part, just process straight through once in autonomous). Using this method you could use Bump 1 for all three parts:


while (SensorType[Bump1] != 1)
{
     wait1Msec(50);
}
//stuff goes after the while loop for button 1 for the first set of actions


while (SensorType[Bump2] != 1)
{
     wait1Msec(50);
}
//stuff goes after the while loop for button 2 for the second set of actions


while (SensorType[Bump3] != 1)
{
     wait1Msec(50);
}
//stuff goes after the while loop for button 3 for the third set of actions

Hey there! From my vague understanding of programming, it looks like you are on the right track.

I would create functions for your Drive, Lift, Intake, etc. Here are a couple you can use on your robot (you may need to switch the - signs, and stuff for them to work).

Drive Function:

void Drive(int speed, int time)
{
         motor[FrontRight] = -speed; 
	 motor[FrontLeft]	= speed;
	 motor[BackRight]	= -speed;
	 motor[BackLeft] = speed;
	 
         wait1Msec(time);
   
         motor[FrontRight] = 0; 
	 motor[FrontLeft]	= 0;
	 motor[BackRight]	= 0;
	 motor[BackLeft] = 0;
}

To call that function in autonomous you would do (inside your while loop)


Drive(127, 5000);

That would make your robot drive straight at full speed for 5 sec. You could then do:


Drive(-127, 5000);

to drive backwards for 5 sec.

Lift Function:

void Lift(int speed, int time)
{
	motor[LeftLift]   = -speed;
	motor[RightLift1] = speed;
	motor[RightLift2] = speed;
	
	wait1Msec(time);
	
	motor[LeftLift]   = 0;
	motor[RightLift1] = 0;
	motor[RightLift2] = 0;
}

It would call it the same way as the drive function:


Lift(127, 5000);


Lift(-127, 5000);

Intake Function:

void Intake(int speed, int time)
{
	motor[Funnel] = speed;
	
	wait1Msec(time);
	
	motor[Funnel] = 0;
}

Now you have those functions, that will clean things up in autonomous. You can do random stuff like this:


Drive(127, 3000); //Drive forward at full power for 3sec
Intake(63, 1500); //Intake at half power for 1.5 sec
Lift(127, 3000); //Lift arm at full power for 3sec
Drive(63, 2000); //Drive forward at half power for 2sec
Intake(-127, 1000); //Outtake at full power for 1sec

That is basic. If you want to get your lift moving, while you drive forward, you can do that pretty easy. You need to create tasks for the lift. Here are 3 tasks I made for the lift (using your code):

task ArmToBar()
    {
	while(true)
	    {
	    Lift(127, 3000);
	    wait1Msec(20);
	    }
    }

task ArmToStash()
    {
	while(true)
	    {
	    Lift(127, 5000);
	    wait1Msec(20);
	    }
    }

Now you can have your drive working while you lift is raising. Here is what you would do to call those tasks:


Drive(127, 3000); //Drive forward at full power for 3sec
Intake(63, 1500); //Intake at half power for 1.5 sec
StartTask(ArmToStash); //Arm starts lifting to stash (ArmToStash task is called)
Drive(-63, 2000); //Drive backward at half power for 2sec
Intake(-127, 1000); //Outtake at full power for 1sec
StopTask(ArmToStash);
Lift(-127, 5000); //Arm goes to bottom and rests

That is some stuff you can do. Now for autonomous, if you have multiple buttons (like us last year, we had 4-5) this is how we set up our autonomous code. We created Autonomous as a function:

void Main_Autonomous()
{
while(SensorValue(Left1) == 0 && SensorValue(Left2) == 0)

		{
		 //Do nothing while none of the buttons are pressed
 		}

  if(SensorValue(Left1) == 1)
		{
		 //When left button 1 is pressed, do the code in here
	  }

	else if (SensorValue(Left2) == 1)
		{
		 //When left button 2 is pressed, do the code in here
		}
}

So while the buttons are not pressed, it doesn’t do anything, but when Left1 is pressed, it will start preforming the code inside the brackets. Another thing we created and used was a ResumeButton. Basically we could put in some functions and tasks then enter:


ResumeButton();

Once it hit that line of code, it would stop. It would then wait until the button was pressed to resume the code. Here is the code for the resume button:

void ResumeButton()
{
  while(!SensorValue[Right2]
    wait1Msec(5);
}

This is an example of how you can use it:

Drive(127, 3000); //Drive forward at full power for 3sec
Intake(63, 1500); //Intake at half power for 1.5 sec
StartTask(ArmToStash); //Arm starts lifting to stash (ArmToStash task is called)
ResumeButton(); //waits until button is pressed to continue on
Drive(-63, 2000); //Drive backward at half power for 2sec
Intake(-127, 1000); //Outtake at full power for 1sec
StopTask(ArmToStash);
Lift(-127, 5000); //Arm goes to bottom and rests

Hopefully this makes sense. I just threw the code together real quick, so you will have to change some things (motor names, sensor names, etc.). Hopefully this helps you!

Edit: I threw what you had written at the top and put it (mostly) into an autonomous routine. Here is what I have.


void Main_Autonomous()
{
while(SensorValue(Left1) == 0 && SensorValue(Left2) == 0)

		{
		 //Do nothing while none of the buttons are pressed
 		}

  if(SensorValue(Left1) == 1) //Middle Zone Autonomous
		{
		  Drive(127, 1500); //Knocks large ball off barrier
		  wait1Msec(100);
		  Drive(-10, 500); //slows down robot a tad
		  wait1Msec(100);
		  
		  Drive(-127, 1250); //Goes back to starting tile and waits for Resume Button to be pressed
		  ResumeButton();
		  
		  Drive(127, 2000); //drives forward for 2sec
		  wait1Msec(100);
		  Drive(-10, 500); //slows robot down
		  wait1Msec(100);
		  
		  StartTask(Intake800); //Funnel opens while driving back to tile
		  StartTask(Arm1100); //Starts Arm1100 function 
		  Drive(-127, 1900); //ROBOT HEADS TO TILE
		  StopTask(Intake800); //Stops intake 800 task once it reaches the starting tile
		  ResumeButton(); //Robot is at the tile waiting to go to next task
		  
		  Drive(127, 2000); //Robot goes full power forward for 2 sec when the button is pressed
		  Intake(-127, 500); //Opens funnel 
		  wait1Msec(100);
		  Intake(127, 1250); //Closes funnel and auto is done
		  
	  }

	else if (SensorValue(Left2) == 1) //Hanging Zone Autonomous
		{
		 
		}
}

I have attached the ROBOTC document for you to look through and edit as you want!

I would invest in a potentiometer, and at least two encoders. These will help make your autonomous 110% better. You can make consistent but reliable autonomous programs. Timing all depends on your battery, so always test timed autonomous on a full battery.
2425.c (2.87 KB)

This is where things get conceptually vague. I know code goes from top to bottom, left to right, but when while loops are present, I don’t know if code would continue down or stop at the while.

Does this mean that when while loops are executed once the robot moves on to the next set of code (as indicated by when bump = 0 [aka bump != 1])?:confused:

From there, things get even vaguer as whiles show up after whiles and other commands(the next set task) shows up. Cause wouldn’t that mean that there’s no block of white space and when bump = 1, the task becomes the mix of all 3 tasks?

Thanks Jesse for your sophisticated approach. Currently, I understand what voids are, and how much more useful it will be to use them for the future, but I lack the detail orientation to do this at the moment. When time frees up, I’ll dissect what you write:(

In this situation the code would get stuck in the while loop, but you could solve that with a break command at the end of the code in the while loop.

I agree!

My advice is to use the resume function that Jesse323Z used, but then have each different step in a void loop, so that your code looks like this…


void Main_Autonomous()
{
while(SensorValue(Left1) == 0 && SensorValue(Left2) == 0)

		{
		 //Do nothing while none of the buttons are pressed
 		}

  if(SensorValue(Left1) == 1) //Middle Zone Autonomous
		{
		  Step1(); // go forward, knock large ball off, and return to start

		  ResumeButton(); //wait to go to next task

		  Step2();// drives forward, opens funnel, lifts the arm and returns to start

		  ResumeButton(); //wait to go to next task

		  Step3(); // go forward, opens funnel, and close funnel
}

	else if (SensorValue(Left2) == 1) //Hanging Zone Autonomous
		{

		}
}

I am curious what your robot looks like, how you got three motors to lift the arm, not two of four, and what your funnel looks like, please post pictures!

Visit Facebook!

So you clean your code up even more (at least in the autonomous portion) by using Step functions. That is cool. We might use that.

Not the OP, but we had a 3 motor scissor lift earlier in the season. It used a gearbox split the power and drive two linear slides, one attached to each side of the lift. The pictures are under 127X on the website, posted a couple of months back if you wanted to see what it looked like. I can’t imagine the process would be any more difficult on an N-Bar or Chain Bar lift, if someone was inclined to make one.

Can I have a rationale please. . . I’m still trying to learn code

I HAVE FAILED U!!!. It’s not like I post a weekly update or anything. . . If you go to my signature, you can see weekly updates, stats, strategies, the facebook update, and videos of the robot in action

We just hooked up the gearboxes together
http://www.hydrarobotics.com/uploads/9/0/7/5/9075173/2396320_orig.jpg

Back to code stuff. I’d like to thank everyone for the help I’ve received. I was able to borrow a compiler, so I’ll see how things turn out tomorrow.

Hi, I’m Lucy, the programmer for 9090C. (And I’m using my coach’s account bc vexforum won’t activate mine lol)

From my understanding, you are trying to activate different sections of your autonomous program using a bumper switch. Although the people who have already replied provided really good answers, I wanted to share something new.

I saw that most everyone puts the test case for the bumper switch within their main autonomous. However, I created a user function specifically for bumper switch activation, and it’s worked out really well.

I use RobotC, so the bumper switch SensorValue] is 0 but becomes 1 upon pushing.

void bumper()
{
     int bump = 0; //0 is default for RobotC
     while( true ) //infinite loop
     {
          bump = SensorValue BumperButton ];
          if( bump == 1 ) //is pushed
          {
               break;
          }
     }
}

So for the code in your main autonomous, you can use this method whenever you need an activation. So here’s an example of some pseudocode.

task autonomous()
{
     //first part of your program, probably drive forward and lift or intake, blah blah blah
     //return to starting tile to await activation via bumper switch
     **bumper();**
     //second part of your program, drive around, do victory circles, lalala
     **bumper();**
     //third part of your program, drive over the bump, steal opponents' buckyballs, do cartwheels, whatever
}

The great thing about this is that you don’t have to write and rewrite if statements every time… I know. I’m really lazy, but they say that laziness is another word for efficiency. Even if you add another bumper switch, you can easily modify the code by added an “or” function.

I’m answering your question thinking that you’re asking about a bumper for procedural purposes as Team80_Giraffes said. If you’re going for a set of choices as Jesse323Z indicated, I’d invest in a potentiometer (highly recommended) or some jumpers (I never see anyone use them anymore but they’re awesome!).

I also recommend creating user functions for your various chassis, lift, etc. tasks. Jesse323Z had some great example code.

Remember, laziness is another word for efficiency!!

Hopefully this helps! Feel free to reply or PM if you have questions. My coach will (hopefully) redirect to me.

So I tried team 80’s autonomous method, and for some reason, the bumper sensor isn’t responding. I didn’t attempt jesse’s yet since I know i’m not skilled enough to do that, and lucy, it looks simple enough, but I’m confused by the “break”. is that what ur supposed to put for a process?

“break” is just a way of ending the loop early, in the case of Lucy’s bumper function, as soon as the loop ends the function will return to where it was called from. Take a look at Cody’s tutorials, even though he’s pitching them for PROS, so far they are just as applicable to ROBOTC and ConVEX.

playlist for Cody’s tutorials

Welcome, Lucy. Thanks for posting your code. The only small change I would make is giving a little time back to the operating system by adding some delay each time around the loop.

void bumper()
{
     int bump = 0; //0 is default for RobotC
     while( true ) //infinite loop
     {
          bump = SensorValue BumperButton ];
          if( bump == 1 ) //is pushed
          {
               break;
          }
     
     // small delay
     wait1Msec(10);
     }
}

This allows you function to “play nice” with other tasks that may be running. wait1Msec(10); will slow the loop down to “only” 100 times per second, plenty fast enough for checking a bumper switch.

Yup, this way it can return to your autonomous and proceed with the rest of your code.

Will do! Thank you, jpearman!

I have not read this thread entirely because class is about to end, so forgive me if this has been said, but couldn’t you have the while loop based on the sensor value? Plus less typing!

This would look like…

void bumper()
{
     int bump = SensorValue[BumperButton];
     while( bump == 1) //infinite loop
     {
       // Task here
       wait1Msec(10); //small delay still included
     }
}

I think this just another way of achieving the same task I believe.

While I believe your code is also correct, I don’t think it applies to my logic because I don’t want my bumper function to be specific to any task. For example, (if I’m understanding you correctly) if I use your code above, I would not be able to call this function every time I wanted to activate the bumper because I might have different tasks each time I push it.

Like I posted above, my main autonomous code would go something like this:

task autonomous()
{
     //first part of your program, probably drive forward and lift or intake, blah blah blah
     //return to starting tile to await activation via bumper switch
     bumper();
     //second part of your program, drive around, do victory circles, lalala
     bumper();
     //third part of your program, drive over the bump, steal opponents' buckyballs, do cartwheels, whatever
}

The purpose of my user function is to halt the autonomous until I press the bumper-- then it can return to my autonomous task and continue on. Hopefully that makes sense.

-Lucy

I think Drbayer meant to include line 6.
The following code should do the same thing as your code, Lucy.

void bumper()
{
    int bump = SensorValue[BumperButton];
    while( bump == 1 )
    {
         bump = SensorValue[BumperButton]; // LINE 6 
         wait1Msec(10); //small delay still included
    }
}

Of course, it could also be done even shorter, but it’s a matter of personal preference. :slight_smile:

void bumper()
{
    while( !SensorValue[BumperButton] )
        wait1Msec(10); //while not pressed
}

Oh! My misunderstanding. Thanks for clearing that up, JoeTPR. :slight_smile:

-Lucy