Selecting Autonomous with LCD (ROBOTC)

One of the great features of the VEX LCD screen is that it can be used to select multiple autonomous modes.  However, figuring out how to do so appears to stump many programmers.  In this post, I’ll explain how to write an autonomous selection program in ROBOTC.

Some things to know first:
When I hear “select something” I start thinking of a switch command based on a number:

switch (var){
case 1:
  //Something
  break;
case 2:
  //Something
  break;
//etc...
}

Where var is an integer or long variable.  The switch onstruct is basically a shorthand way of writing a bunch of if statements.  If the variable’s value is 1, the first case is executed, if the value is 2, the second is executed, etc.

Something else to keep in mind is that the pre_auton() function in the competition template will run as soon as the VEXnet remote connects with the Cortex.  The autonomous task runs as soon as the field control system tells it to do so.

The Idea:
The most important part of writing a program is deciding how to break it up.  In this case, we can set a integer variable to designate which autonomous mode we want to run (autonomous 1 could be a red alliance program, and autonomous 2 could be blue, etc).  We know that pre_auton will always run before the autonomous task.  This seems like a great place to set the autonomous number variable.
We can use a switch to run a specific autonomous code.  This should be in the autonomous task.

So now our (pseudo)code looks like this:

int autonNumber = 0; //holds num to run (GLOBAL)

void pre_auton(){
  //Set autonNumber based on LCD
}

task autonomous(){
  switch(autonNumber){
    case 1: //Automode 1
    break;
    case 2: //Automode 2
    break;
case 3: //Automode 3
    default: //Do nothing
    break;
  }
}

Setting autonNumber
We want to use the LCD to set the autonomous number.  If you are unfamiliar with the commands for the LCD, I suggest you read over this post.  If we press the right button, we want autonNumber to be incremented.  If we press the left button, we want autonNumber to be decremented.  If we press the center button, we’ve selected that program number.  Because we want to be constantly checking for button presses, we should put this in a loop–a while loop is best suited to this task.

So, here’s the psuedocode for this (only typing the pre_auton function; the rest is the same as above):

void pre_auton(){
  while(nLCDButtons != 2){ //While center not pressed
    if(nLCDButtons == 0) //No button pressed
      wait1Msec(10); //Do nothing
    else{ //Some button was pressed
      if(nLCDButtons == 1){
        autonNumber--; //Decrement if left press
      }
      else if(nLCDButtons == 4){
        autonNumber++; //Increment if right press
      }
      //Update display
      while(nLCDButtons != 0){//Wait for release
        wait1Msec(10); //Wait for multitasking.
      }
    }
  }
}

Notice the last loop?  That prevents the processor from looping through multiple times for a single button press.

Now, there is one issue with this–if autonNumber is 0, and you press the left button, you end up with -1.  Conversely, there is no upper limit to autonNumber.  This will become a bit of a problem later when we display the mode selected.

User Interface
Now we need to find a way of displaying the currently selected autonomous mode.  I like to do this through a string array.  I will call this autoNames[].  The length of the array will be a 0-based constant, autoCount.  (0-based meaning that if there are four autonomous modes, the value of autoCount is 3: 0, 1, 2, 3)

To update the LCD, we will simply display the autonNumber index of autoNames[].

We don’t want an array-out-of-bounds error, so we’ll only increment/decrement the autonNumber if we aren’t on one of the bounds of the array.

Code:

void pre_auton(){
  const int autoCount = 3;
  string autoNames[autoCount + 1] = {"None", "Mode 1", "Mode 2", "Mode 3"};
  displayLCDCenteredString(0, autoNames[0]); //first mode to display
  
  while(nLCDButtons != 2){ //While center not pressed
    if(nLCDButtons == 0) //No button pressed
      wait1Msec(10); //Do nothing
    else{ //Some button was pressed
      
      if((nLCDButtons == 1)&&(autoMode > 0)){
        autonNumber--; //Decrement if left press
      }
      else if((nLCDButtons == 4)&&(autoMode < autoCount)){
        autonNumber++; //Increment if right press
      }
      
      //Update display
      clearLCDLine(0);
      displayLCDCenteredString(0, autoNames[autonNumber]);
      
      while(nLCDButtons != 0){//Wait for release
        wait1Msec(10); //Wait for multitasking.
      }
    }
  }
}

…and that should do it!

Posted in Robot Programming, ROBOTC, Tutorial, VEX

Twitter