How to loop peices of code forever?

Hello I am a programmer for my school’s robotics team and engineering class and i ran into a code problem. A team project is to program a claw bot that when a button is pressed it will follow a line with encoders and with the claw bot grab a box line track backwards and let go of the box, it is supposed to do this forever when the button at the beginning is pressed. Not only that but when a button is pressed while its looping it will do this task one more time before ending the program. So my problem is that i can’t get the code to run forever when the button is pressed, what happens is that the line track moves forever and never moves on to the next step. Here is how my code looks below.

PS: I know i didn’t include the part when the button is pressed again it runs one more time. It’s not included because that’s not the problem.

#pragma config(Sensor, in1, pot, sensorPotentiometer)
#pragma config(Sensor, in3, LineLeft, sensorLineFollower)
#pragma config(Sensor, in4, LineRight, sensorLineFollower)
#pragma config(Sensor, in5, LineCenter, sensorLineFollower)
#pragma config(Sensor, dgtl1, touch, sensorTouch)
#pragma config(Sensor, dgtl2, Encoder, sensorQuadEncoder)
#pragma config(Sensor, dgtl7, Encoder2, sensorQuadEncoder)
#pragma config(Motor, port2, arm, tmotorServoContinuousRotation, openLoop)
#pragma config(Motor, port3, elbow, tmotorServoContinuousRotation, openLoop)
#pragma config(Motor, port7, rightMotor, tmotorServoContinuousRotation, openLoop, reversed)
#pragma config(Motor, port8, leftMotor, tmotorServoContinuousRotation, openLoop)
//!!Code automatically generated by ‘ROBOTC’ configuration wizard !!//

task main()
{

if(SensorValue(touch) == 0)
{
motor[arm] = 0;
}

if(SensorValue(touch) == 1)

{

 while(true)// i also tried  while(1 == 1)

 {
 	motor[elbow] = -63;
	wait1Msec(1500);
}

motor[elbow] = 0;
wait1Msec(100);

int threshold = 2000;

SensorValue[Encoder] = 0;

while(SensorValue[Encoder] < 210)
{

if(SensorValue(LineRight) &gt; threshold)
{
  // counter-steer right:
  motor[leftMotor]  = 50;
  motor[rightMotor] = 0;
}
// CENTER sensor sees dark:
if(SensorValue(LineCenter) &gt; threshold)
{
  // go straight
  motor[leftMotor]  = 30;
  motor[rightMotor] = 30;
}


if(SensorValue(LineLeft) &gt; threshold)
{
  // counter-steer left:
  motor[leftMotor]  = 0;
  motor[rightMotor] = 50;
}

}
}

  {
  motor[arm] = 63;
  wait1Msec(2000);

  motor[elbow] = 63;
	wait1Msec(200);

  motor[rightMotor] = 0;
  motor[leftMotor] = 0;
  wait1Msec(1000);

motor[arm] = -63;
  wait1Msec(1800);

  motor[elbow] = -63;
	wait1Msec(2500);

	motor[elbow] = 0;
  wait1Msec(1000);

  motor[rightMotor] = -43;
  motor[leftMotor] = -43;
  wait1Msec(500);

}

int threshold = 2000;

SensorValue[Encoder] = 0;

while(SensorValue[Encoder] > -450)
{

if(SensorValue(LineRight) &gt; threshold)
{
  // counter-steer right:
  motor[leftMotor]  = -50;
  motor[rightMotor] = 0;
}
// CENTER sensor sees dark:
if(SensorValue(LineCenter) &gt; threshold)
{
  // go straight
  motor[leftMotor]  = -30;
  motor[rightMotor] = -30;
}


if(SensorValue(LineLeft) &gt; threshold)
{
  // counter-steer left:
  motor[leftMotor]  = 0;
  motor[rightMotor] = -50;
}

}

}

In your code, you have

while(true)// i also tried while(1 == 1)
{
	motor[elbow] = -63;
	wait1Msec(1500);
}

so you’re on the right track. Both while(true) and while(1 == 1) will work (because 1 == 1 evaluates to true so it’s just a more indirect way of writing the same thing).

However, the block of code inside the while(true) loop is the only thing that will run forever. So at the moment, your elbow motor will run forever, but not the rest of the code.

You should change your code so that the while(true) { … } surrounds the entirety of the code that you want to run forever.

You may want to posibly try this, I changed some things that might make it work a little better(or fail miserably):

#pragma config(Sensor, in1, pot, sensorPotentiometer)
#pragma config(Sensor, in3, LineLeft, sensorLineFollower)
#pragma config(Sensor, in4, LineRight, sensorLineFollower)
#pragma config(Sensor, in5, LineCenter, sensorLineFollower)
#pragma config(Sensor, dgtl1, touch, sensorTouch)
#pragma config(Sensor, dgtl2, Encoder, sensorQuadEncoder)
#pragma config(Sensor, dgtl7, Encoder2, sensorQuadEncoder)
#pragma config(Motor, port2, arm, tmotorServoContinuousRotation, openLoop)
#pragma config(Motor, port3, elbow, tmotorServoContinuousRotation, openLoop)
#pragma config(Motor, port7, rightMotor, tmotorServoContinuousRotation, openLoop, reversed)
#pragma config(Motor, port8, leftMotor, tmotorServoContinuousRotation, openLoop)
//*!!Code automatically generated by 'ROBOTC' configuration wizard !!*//

int threshold = 2000;
void lineFollower(int speed);

task main()
{
	while(true)
	{

		if(SensorValue(touch) == 0)
		{
			motor[arm] = 0;
		}

		if(SensorValue(touch) == 1)
		{
			motor[elbow] = -63;
			wait1Msec(1500);
			motor[elbow] = 0;			

			SensorValue[Encoder] = 0;
			while(SensorValue[Encoder] < 210)
			{
				lineFollower(60);
			}

			motor[arm] = 63;  // Brackets were wraped around this, is there suposed to be a loop or somthing here?
			wait1Msec(2000);

			motor[elbow] = 63;
			wait1Msec(200);

			motor[rightMotor] = 0;
			motor[leftMotor] = 0;
			wait1Msec(1000);

			motor[arm] = -63;
			wait1Msec(1800);

			motor[elbow] = -63;
			wait1Msec(2500);

			motor[elbow] = 0;
			wait1Msec(1000);

			motor[rightMotor] = -43;
			motor[leftMotor] = -43;
			wait1Msec(500);
		}

		SensorValue[Encoder] = 0;

		while(SensorValue[Encoder] > -450)
		{
			lineFollower(-60);
		}
	}
}

void lineFollower(int speed)  // Can help clean up your code and make it easier to read
{

	if(SensorValue(LineRight) > threshold && SensorValue(LineCenter) > threshold)
	{ // Added a slight turn to have a bit of a gentler correction when the robot is not that far off the line
		motor[leftMotor] = speed;
		motor[rightMotor] = (speed / 2);
	}
	else if(SensorValue(LineLeft) > threshold && SensorValue(LineCenter) > threshold)
	{
		motor[leftMotor] = 0;
		motor[rightMotor] = (speed / 2);
	}
	else if(SensorValue(LineCenter) > threshold)
	{
		motor[leftMotor] = speed;
		motor[rightMotor] = speed;
	}
	else if(SensorValue(LineRight) > threshold)
	{
		motor[leftMotor] = speed;
		motor[rightMotor] = 0;
	}
	else if(SensorValue(LineLeft) > threshold)
	{
		motor[leftMotor] = 0;
		motor[rightMotor] = speed;
	}
	else
	{
		motor[leftMotor] = 0;
		motor[rightMotor] = 0;

	}
}

Yes I did put the while(true) brackets around the entire code, still it only moved the arm and line tracked forward forever. The code above me only went backwards forever. I can’t believe these small problems sometimes.

Your code will keep line tracking while SensorValue[Encoder] < 210 in the forward-moving phase and SensorValue[Encoder] > -450 in the backward-moving phase. How did you arrive at these conditions? Are you sure that Encoder counts in the positive direction when you’re moving forward, and the negative direction when moving backward?

This should do more what you want maybe? Wait untill the button is pressed, move arm, follow line, move stuff around, reverse on line, wait for button again.

I also changed the encoders to an absulate value comparison so it wont matter if you have the tick calculations wrong.

#pragma config(Sensor, in1, pot, sensorPotentiometer)
#pragma config(Sensor, in3, LineLeft, sensorLineFollower)
#pragma config(Sensor, in4, LineRight, sensorLineFollower)
#pragma config(Sensor, in5, LineCenter, sensorLineFollower)
#pragma config(Sensor, dgtl1, touch, sensorTouch)
#pragma config(Sensor, dgtl2, Encoder, sensorQuadEncoder)
#pragma config(Sensor, dgtl7, Encoder2, sensorQuadEncoder)
#pragma config(Motor, port2, arm, tmotorServoContinuousRotation, openLoop)
#pragma config(Motor, port3, elbow, tmotorServoContinuousRotation, openLoop)
#pragma config(Motor, port7, rightMotor, tmotorServoContinuousRotation, openLoop, reversed)
#pragma config(Motor, port8, leftMotor, tmotorServoContinuousRotation, openLoop)
//*!!Code automatically generated by 'ROBOTC' configuration wizard !!*//

int threshold = 2000;
void lineFollower(int speed);
void stopAllMotors();

task main()
{
	while(true)
	{

		if(SensorValue(touch) == 0)
		{
			stopAllMotors();
		}

		if(SensorValue(touch) == 1)
		{
			motor[elbow] = -63;
			wait1Msec(1500);
			motor[elbow] = 0;

			SensorValue[Encoder] = 0;
			while(abs(SensorValue[Encoder]) < 210)
			{
				lineFollower(60);
			}

			motor[arm] = 63;  // Brackets were wraped around this, is there suposed to be a loop or somthing here?
			wait1Msec(2000);

			motor[elbow] = 63;
			wait1Msec(200);

			motor[rightMotor] = 0;
			motor[leftMotor] = 0;
			wait1Msec(1000);

			motor[arm] = -63;
			wait1Msec(1800);

			motor[elbow] = -63;
			wait1Msec(2500);

			motor[elbow] = 0;
			wait1Msec(1000);

			motor[rightMotor] = -43;
			motor[leftMotor] = -43;
			wait1Msec(500);

			SensorValue[Encoder] = 0;

			while(abs(SensorValue[Encoder]) < 450)
			{
				lineFollower(-60);
			}
		}
	}
}

void lineFollower(int speed)  // Can help clean up your code and make it easier to read
{

	if(SensorValue(LineRight) > threshold && SensorValue(LineCenter) > threshold)
	{ // Added a slight turn to have a bit of a gentler correction when the robot is not that far off the line
		motor[leftMotor] = speed;
		motor[rightMotor] = (speed / 2);
	}
	else if(SensorValue(LineLeft) > threshold && SensorValue(LineCenter) > threshold)
	{
		motor[leftMotor] = 0;
		motor[rightMotor] = (speed / 2);
	}
	else if(SensorValue(LineCenter) > threshold)
	{
		motor[leftMotor] = speed;
		motor[rightMotor] = speed;
	}
	else if(SensorValue(LineRight) > threshold)
	{
		motor[leftMotor] = speed;
		motor[rightMotor] = 0;
	}
	else if(SensorValue(LineLeft) > threshold)
	{
		motor[leftMotor] = 0;
		motor[rightMotor] = speed;
	}
	else
	{
		motor[leftMotor] = 0;
		motor[rightMotor] = 0;

	}
}

void stopAllMotors()
{
		motor[leftMotor] = 0;
		motor[rightMotor] = 0;
		motor[elbow] = 0;
		motor[arm] = 0;	
}

That code works but I think you misunderstand what i meant. I need this code to run forever once the button is pressed, once i press the button i can’t press it again. The code has to keep running the same task once I press the button and the only reason I press the button again would be to end the while loop and stop the code.

I think your description of what you want is unclear. You’re using the phrase “loop forever”, but you also say you want to “run it once more and stop”. What is it that you want the robot to do repeatedly – is it the entire process of shuttling along the line moving boxes from one end to the other? Will you ever want to give any other commands besides “start” and “stop after you drop the next box”?

“The entire process of shuttling along the line moving boxes from one end to the other” Yes, So in the code should start up when a button is pressed and when it is the process should be looping forever.

I don’t know your level of knowledge so I can give you an appropriately tailored answer. My first thought is that this should be implemented as a state machine without any delays in it. The “start” state would do nothing, and would move to the “follow the line forward” when it sees the button press. When not in the “start” state I’d have the program continually check to see whether the button has just been pressed, and set a “prepare to stop” flag if so. If the flag is set, the final “drop the block” state would transition either to a “halted” state or back to the “start” state if you want to be able to start it up again.

Doing it sequentially with delays, as in the originally posted code, will make detecting the second button press very difficult.

Last edit Im going to do

#pragma config(Sensor, in1, pot, sensorPotentiometer)
#pragma config(Sensor, in3, LineLeft, sensorLineFollower)
#pragma config(Sensor, in4, LineRight, sensorLineFollower)
#pragma config(Sensor, in5, LineCenter, sensorLineFollower)
#pragma config(Sensor, dgtl1, touch, sensorTouch)
#pragma config(Sensor, dgtl2, Encoder, sensorQuadEncoder)
#pragma config(Sensor, dgtl7, Encoder2, sensorQuadEncoder)
#pragma config(Motor, port2, arm, tmotorServoContinuousRotation, openLoop)
#pragma config(Motor, port3, elbow, tmotorServoContinuousRotation, openLoop)
#pragma config(Motor, port7, rightMotor, tmotorServoContinuousRotation, openLoop, reversed)
#pragma config(Motor, port8, leftMotor, tmotorServoContinuousRotation, openLoop)
//*!!Code automatically generated by 'ROBOTC' configuration wizard !!*//

int threshold = 2000;
bool continueRunning = true;
void lineFollower(int speed);
void stopAllMotors();
task checkForButtonPress();

task main()
{
	while(true)
	{

		if(SensorValue(touch) == 0)
		{
			stopAllMotors();
		}

		if(SensorValue(touch) == 1)
		{
			while(SensorValue(touch) == 1) // Wait for release
			{
			}
			StartTask(checkForButtonPress);
			while(continueRunning)
			{
				motor[elbow] = -63;
				wait1Msec(1500);
				motor[elbow] = 0;

				SensorValue[Encoder] = 0;
				while(abs(SensorValue[Encoder]) < 210)
				{
					lineFollower(60);
				}

				motor[arm] = 63;  // Brackets were wraped around this, is there suposed to be a loop or somthing here?
				wait1Msec(2000);

				motor[elbow] = 63;
				wait1Msec(200);

				motor[rightMotor] = 0;
				motor[leftMotor] = 0;
				wait1Msec(1000);

				motor[arm] = -63;
				wait1Msec(1800);

				motor[elbow] = -63;
				wait1Msec(2500);

				motor[elbow] = 0;
				wait1Msec(1000);

				motor[rightMotor] = -43;
				motor[leftMotor] = -43;
				wait1Msec(500);

				SensorValue[Encoder] = 0;

				while(abs(SensorValue[Encoder]) < 450)
				{
					lineFollower(-60);
				}
			}
		}
	}
}

void lineFollower(int speed)  // Can help clean up your code and make it easier to read
{

	if(SensorValue(LineRight) > threshold && SensorValue(LineCenter) > threshold)
	{ // Added a slight turn to have a bit of a gentler correction when the robot is not that far off the line
		motor[leftMotor] = speed;
		motor[rightMotor] = (speed / 2);
	}
	else if(SensorValue(LineLeft) > threshold && SensorValue(LineCenter) > threshold)
	{
		motor[leftMotor] = 0;
		motor[rightMotor] = (speed / 2);
	}
	else if(SensorValue(LineCenter) > threshold)
	{
		motor[leftMotor] = speed;
		motor[rightMotor] = speed;
	}
	else if(SensorValue(LineRight) > threshold)
	{
		motor[leftMotor] = speed;
		motor[rightMotor] = 0;
	}
	else if(SensorValue(LineLeft) > threshold)
	{
		motor[leftMotor] = 0;
		motor[rightMotor] = speed;
	}
	else
	{
		motor[leftMotor] = 0;
		motor[rightMotor] = 0;

	}
}

void stopAllMotors()
{
	motor[leftMotor] = 0;
	motor[rightMotor] = 0;
	motor[elbow] = 0;
	motor[arm] = 0;
}

task checkForButtonPress()
{continueRunning = true;
	while(true)
	{
		if(SensorValue(touch) == 1)
			continueRunning = false;

	}
}

Hey Kevin that Code almost works, It line follows back and fourth forever like its supposed to and stops when i press the button a second time. The only problem is that the arm keeps moving forever while its line tracking and the arm gets stuck because it never stops its first task. I’m trying to explain it right, the arm commands are supposed to stop once their done running for the time its given then switch to line following forward then move the arm a little you know to pick up the little box then switch to line following backwards.

I tried putting the commands inside where the line follower is because I thought since the line follower is working then the arm will too but the arm never stopped moving. :confused:

When I program in VEX, RobotC, I create a main loop. This loop will execute until it is killed somehow, or the break statement is used. Basically, you have an infinite loop (while(true) {…}) and that holds all your code.

In this loop, you only execute the command ONCE. Basically, the program loop will constantly check all inputs. If it notices any of the inputs high, for example, using a joystick, the program branches into another function, that runs the mechanism once. For servos, this is different. You assign a servo a position and it will stay there. You only signal the servo when you change positions (or not).

This way, everything will run together constantly.

It is sad that the VEX cortex does not support threading or tasks :(. It would be nice to run tasks parallel to each other. Does anyone by chance know how to bypass RobotC and actually access C10 (I think that’s what it runs)? We are doing VEX robotics in eng. class, but I want to do things that are a bit harder!

There’s quite a bit of confusion here, let me try to clear it up:

There is no inherent support for Tasks native to any processor, really. Tasks are almost always implemented by an operating system running on top of the processor, which runs a scheduler to schedule tasks when they are ready (on embedded systems they are usually scheduled by time rate). This is not a function of the processor hardware. However, there are ways to do tasks without an OS. Many micros have timers, which can be used for a number of things, including generating an interrupt request when they expire. This can be used to create a task by running code in the interrupt service routine. I usually see this used for very fast tasks, such as the OS kernel, but in basic systems it can be used to run fast code directly.

The Cortex has an ARM Cortex processor, so naturally it would run ARM opcodes. There is no real ‘language’ assigned to opcodes except the assembly language, which just gives meaningful names to opcodes (e.g. load, store, … operations). C is a high level language on top of that, with a compiler that takes the C code and compiles it into opcodes for the particular processor family (in this case, ARM opcodes). As long as you can find a compiler to generate the opcodes for your processor, the language is usable.

RobotC does not actually use C standard code, it’s quite bad with it (but it’s gotten a lot better over the years). RobotC compiles using an internal compiler to RobotC bytecode, which is then run on a virtual machine on the Cortex. So, on the Cortex, the RobotC bytecode (opcodes) is executed by the RobotC interpreter, which is written in some language which was compiled into ARM opcodes. RobotC itself does have tasks, you can have many parallel threads, but you can’t control the task rate precisely.