ROBOT LCD

We seem to have a lot of questions this year on how to use the LCD to select different autonomous routines for your robot. I’m going to present several examples, each of which is going to increase in complexity, the first three of which are here, there may be more later.

Most code that uses the LCD to allow autonomous selection has common features.

  1. Choices are presented to the user, these can be simple or a complex series of menus.
  2. The code must monitor button presses and releases on the LCD display.
  3. The code must be aware of the competition state so that the autonomous task may run.

Item 2 is one of the most basic functions that the code must perform. A user will press an LCD button, this is detected and causes the code to take some action, the code then must generally wait for the button to be released so the action does not happen multiples times in quick succession. To help simplify the LCD selection code I decided to create a wrapper for this most basic function that combines LCD button press detection and also waiting for button release. It also needs to be aware of the competition state so that it does not block (that means wait in a loop forever). This function is saved in its own file and “included” in the code for the three demo’s, here is the function.

// Wrap code with definition so it's not included more than once
#ifndef  _GETLCDBUTTONS
#define  _GETLCDBUTTONS

// Some utility strings
#define LEFT_ARROW  247
#define RIGHT_ARROW 246
static  char l_arr_str[4] = { LEFT_ARROW,  LEFT_ARROW,  LEFT_ARROW,  0};
static  char r_arr_str[4] = { RIGHT_ARROW, RIGHT_ARROW, RIGHT_ARROW, 0};

/*-----------------------------------------------------------------------------*/
/*  This function is used to get the LCD hutton status but also acts as a      */
/*  "wait for button release" feature.                                         */
/*  Use it in place of nLcdButtons.                                            */
/*  The function blocks until a button is pressed.                             */
/*-----------------------------------------------------------------------------*/

// Little macro to keep code cleaner, masks both disable/ebable and auton/driver
#define vexCompetitionState (nVexRCReceiveState & (vrDisabled | vrAutonomousMode))

TControllerButtons
getLcdButtons()
{
    TVexReceiverState   competitionState = vexCompetitionState;
    TControllerButtons  buttons;
    
    // This function will block until either
    // 1. A button is pressd on the LCD
    //    If a button is pressed when the function starts then that button
    //    must be released before a new button is detected.
    // 2. Robot competition state changes
    
    // Wait for all buttons to be released
    while( nLCDButtons != kButtonNone ) {
        // check competition state, bail if it changes
        if( vexCompetitionState != competitionState )
            return( kButtonNone );
        wait1Msec(10);
        }
    
    // block until an LCD button is pressed
    do  {
        // we use a copy of the lcd buttons to avoid their state changing
        // between the test and returning the status
        buttons = nLCDButtons;
        
        // check competition state, bail if it changes
        if( vexCompetitionState != competitionState )
            return( kButtonNone );

        wait1Msec(10);
        } while( buttons == kButtonNone );

    return( buttons );
}

#endif  // _GETLCDBUTTONS

The functionality of this code, in pseudo code form, is as follows.

Wait for all buttons to be released unless
    the robot is enabled which causes exit

Wait for a button press unless
   the robot is enabled which causes exit

return the pressed button

Demo 1

This allows selection of one of three autonomous routines, the three LCD buttons are used to make that selection. The code separates the display of the choices and selected routine from the selection of that routine.

/*-----------------------------------------------------------------------------*/
/*  LCD autonomous demo 1                                                      */
/*  Copyright (c) 2013 James Pearman                                           */
/*  This is unlicensed software - you may modify and use as you wish           */
/*-----------------------------------------------------------------------------*/

//Competition Control and Duration Settings
#pragma competitionControl(Competition)

#include "Vex_Competition_Includes.c"   //Main competition background code...do not modify!

// Include the lcd button get utility function
#include "getlcdbuttons.c"

// global hold the auton selection
static int MyAutonomous = 0;

/*-----------------------------------------------------------------------------*/
/*  Display autonomous selection                                               */
/*-----------------------------------------------------------------------------*/
void
LcdSetAutonomous( int value )
{
    // Simple selection display
    if( value == 0 ) {
        displayLCDString(0, 0, "auton 0");
        displayLCDString(1, 0, "[00]   01    02 ");
        }
    if( value == 1 ) {
        displayLCDString(0, 0, "auton 1");
        displayLCDString(1, 0, " 00   [01]   02 ");
        }
    if( value == 2 ) {
        displayLCDString(0, 0, "auton 2");
        displayLCDString(1, 0, " 00    01   [02]");
        }
        
    // Save autonomous mode for later
    MyAutonomous = value;
}

/*-----------------------------------------------------------------------------*/
/*  Select one of three autonomous choices                                     */
/*-----------------------------------------------------------------------------*/

void
LcdAutonomousSelection()
{
    TControllerButtons  button;
    
    // Clear LCD and turn on backlight
    clearLCDLine(0);
    clearLCDLine(1);
    bLCDBacklight = true;
    
    // diaplay default choice
    LcdSetAutonomous(0);
    
    while( bIfiRobotDisabled )
        {
        // this function blocks until button is pressed
        button = getLcdButtons();    
        
        // Display and select the autonomous routine
        if( button == kButtonLeft )
            LcdSetAutonomous(0);
        
        if( button == kButtonCenter )
            LcdSetAutonomous(1);
        
        if( button == kButtonRight )
            LcdSetAutonomous(2);
        
        // Don't hog the cpu !
        wait1Msec(10);
        }
}

void pre_auton()
{
    bStopTasksBetweenModes = true;

    LcdAutonomousSelection();
}


task autonomous()
{
    switch( MyAutonomous ) {
        case    0:
            // run auton code
            break;
        
        case    1:
            // run some other auton code
            break;
        
        default:
            break;
        }
}

task usercontrol()
{
    while (true) {
        wait1Msec(10);
        }
}

A global called MyAutonomous stores the selected choice, you would run a different autonomous routine depending if it was 0, 1 or 2. The selection function is called in pre_auton() and will run until the robot is enabled, it does not run again unless the cortex is power cycled.

Demo 2 will be in the next post

The three programs are attached as a zip file so you don’t have to cut and paste from the forum.

Lee!

1 Like