While Loop

I’m not sure what the following code means, I’m trying to teach some kids about programming, and they asked what it means. I don’t know how to answer their question. What does the while loop do, and what are the wasted resources. Also, does it matter if it is before or after the autonomous code?
Thanks!

while(1) {
vex::task::sleep(100);//Sleep the task for a short amount of time to prevent wasted resources.
}

1 Like

It means that you are being nice, and let your hardworking V5 brain to catch some :zzz: and save battery juice. :battery:

I am sure other more knowledgeable people could explain it with technical details that will make more sense.

3 Likes

This basically means that the code inside the curly braces will run forever. Since the while loop is unable to compare the 1 to anything to see if it is false, the code will run forever. This is an infinite loop. The sleep task does exactly what the comment says. The sleep command will just wait, then continue executing the code. In this case, there is no other code so the sleep code will continue running until you can change that. @Illyana is right about the wasted resources it lets your processor catch up and save some battery. When I do have it, I usually tune it down to maybe 2 milliseconds. I like precision and speed. If this code is in the autonomous task, then do NOT put it before your auton code. That would cause your auton code to not run. Infinite loops like these are used in driver control so that the controller gets checked continuously. Something like

while(1) {

Drive.spin(directionType::fwd, Controller1.Axis3.value(),velocityUnits::pct)
vex::task::sleep(100);//Sleep the task for a short amount of time to prevent wasted resources.
}

If I still remember the VCS and VexCode syntax

5 Likes

And, in case if you are looking for even more nitty-gritty technical details …

VexOS uses cooperative scheduler, which means that, unless one tasks yields the CPU, other tasks couldn’t run.

In the first, non-competition example, main() task starts sensorMonitoringTask(). However, VexOS will let it run only when the main loop makes a system call that yields the CPU, like vex::task::sleep(). If main task never calls such function the second task will never get to run and vice versa.

int sensorMonitoringTask()
{
   while(1) { // loop forever
    // do something useful ...
    vex::task::sleep( 10 );
   }
}

int main()
{
    vex::task task1(sensorMonitoringTask); // this will start task

    while(1) // main user interface loop
    {
      if( button1.pressing() )
      {
         // display something, run some motors, ...
      }
      vex::task::sleep(10); // yield time to other tasks
    }
}

For VRC robots, when you want them to obey competition switch, that controllers must be plugged into during the matches, you will need to follow special template:

vex::competition Competition; // https://help.vexcodingstudio.com/#cpp/namespacevex/classvex_1_1competition/autonomous

// Autonomous Task - This task is used to control your robot during the autonomous phase of a VEX Competition.
void autonomous( void )  {
    // run robot forward for 3 seconds and kick the ball
}

//  User Control Task - This task is used to control your robot during the user control phase of a VEX Competition. 
void usercontrol( void ) {
  while (1){ // main loop
   // check for user input
   // run some motors
   vex::task::sleep(10); // yield time to other tasks
  }
}

int main() { // Program gets control here
  // if necessary run the pre-autonomous functions, like starting sensorMonitoringTask(), 
  
  //Set up callbacks for autonomous and driver control periods.
  Competition.autonomous( autonomous );
  Competition.drivercontrol( usercontrol );

  //Prevent main from exiting with an infinite loop.                         
  while(1) { // this essentially does nothing, but yields time to other tasks. 
     vex::task::sleep(100);//Sleep the task for a short amount of time to prevent wasted resources.
  }    
}
1 Like

Almost, as long as you call some sort of API method, the other task will run. In the example, the call to button1.pressing() would allow that.

@jpearman, that’s funny, because I spent many minutes thinking if I should mention that detail about API calls or not.

On one hand you want to explain behavior of the scheduler as simply as possible (don’t mention).
On another hand you want to explain it as accurate as possible, so people are not surprised (do mention).
You also want to encourage students to think about scheduling explicitly and write vex::task::sleep() in their loops (don’t mention).
But at the same time we want them to learn how real operating systems work, where interrupts could happen at any time (do mention).

By the time I was reading manual pages for vex::thread::priority and refreshing my memory about mutex vs semaphore, I figured out I am overthinking it way too much. :smile:

So, at the end, I just linked to your post. I understand that allowing scheduler to preempt current thread when API function is called makes it easier to implement and helps porting legacy RobotC code where virtual machine could switch tasks at any time.

However, if in the future some of the calls into vex:: classes are going to be implemented as inlineable member variable access methods, then that rule may no longer hold true and it would be easier if students are accustomed to including explicit calls to vex::task::sleep() in their loops.