How To Program LCD Display (ROBOTC)

  1. 4 years ago

    JesseCRN

    6 Oct 2013 Indianapolis, IN 323Z

    We just purchased an LCD Display this year, and want to know how to use it.

    We would like to display our robot batteries voltage, we also would like to scroll through multiple autonomous routines and be able to select them.

    Can we see sample code, or something? What other cool things do you use your LCD screen for?

    (Off topic: What should we use our extra lexan for on our robot?)

  2. Ephemeral_Being

    6 Oct 2013 Gilbert, Arizona N/A

    The RobotC Blog has an example of one way to write LCD code to do both of those things. I don't like the way they did their menu system because it leaves redundant code all over the program and won't let you choose a program to run during intialization, but it will almost work. Their battery code is almost exactly the way I would write it, though. If you're using a Power Expander, it might be worth looking into the High Resolution Analog Input that will allow you to get that battery's charge level, too.

    http://www.robotc.net/blog/2012/05/18/advanced-applications-with-the-vex-lcd/

    I've got a version of RobotC running on a different computer now, and I'll port the code I wrote last night over minus the battery levels if I can ever figure out their LCD Menu commands. I don't want to do the math for that right now, but the other thing is really easy. Give me 10 minutes, and I'll see what I can do.

    EDIT: Okay, I don't use RobotC. Ever. But I think that this code should work. If there are errors, it's in how I tracked button presses from the LCD Screen and/or initialized it. Sorry. I've written exactly zero lines of code in RobotC before, and this was the best I could do from their (quite honestly unhelpful) documentation and help page. If someone else could take a look, that would be great.

    #pragma platform(VEX)
    
    //Competition Control and Duration Settings
    #pragma competitionControl(Competition)
    #pragma autonomousDuration(20)
    #pragma userControlDuration(120)
    #pragma config(UART_Usage, UART1, uartVEXLCD, baudRate19200, IOPins, None, None)
    //Variable that will carry between modes
    int Program;
    
    #include "Vex_Competition_Includes.c"   //Main competition background code...do not modify!
    
    /////////////////////////////////////////////////////////////////////////////////////////
    //
    //                          Pre-Autonomous Functions
    //
    // You may want to perform some actions before the competition starts. Do them in the
    // following function.
    //
    /////////////////////////////////////////////////////////////////////////////////////////
    
    void pre_auton()
    {
      // Set bStopTasksBetweenModes to false if you want to keep user created tasks running between
      // Autonomous and Tele-Op modes. You will need to manage all user created tasks if set to false.
      bStopTasksBetweenModes = true;
    	//Leave this value alone
    	int lcdScreenMin = 1;
    	//This keeps track of which program you want to run
    	int lcdScreen = 1;
    	//Change this value to be the maximum number of programs you want on the robot
    	int lcdScreenMax = 4;
    	//Turns on the Backlight
    	bLCDBacklight = true; 
    	
    	//Copied from someone's sample code because the documentation for RobotC won't tell me anything useful
    	//These should logically work, but I'm not 100% sure
    	const short leftButton = 1;
    	const short centerButton = 2;
    	const short rightButton = 4;
    
    	while (vrDisabled == 1) { //Ensures this code will run ONLY when the robot is disabled
    		if (nLCDButtons == leftButton) { //Scrolls to the left
    			if (lcdScreenMin == lcdScreen) {
    				lcdScreen = lcdScreenMax;
    				wait1Msec(250);
    			} else {
    				lcdScreen --;
    				wait1Msec(250);
    			}
    		}
    		if (nLCDButtons == rightButton) { //Scrolls to the right
    			if (lcdScreenMax == lcdScreen) {
    				lcdScreen = lcdScreenMin;
    				wait1Msec(250);
    			} else {
    				lcdScreen++;
    				wait1Msec(250);
    			}
    		}
    		if (lcdScreen == 1 && Program != 1) {
    			displayLCDCenteredString (0, "Program"); //Name the first program here
    			displayLCDCenteredString (1, "1"); //Name the first program here
    			if (nLCDButtons == centerButton) {
    				Program = lcdScreen; //Sets the Program to the one on-screen
    				displayLCDCenteredString (0, "Autonomous Has");
    				displayLCDCenteredString (1, "Been Selected!");
    				wait1Msec(1500);
    			}
    		} else if (lcdScreen == 1 && Program == 1) {
    			displayLCDCenteredString (0, "Program"); //We use brackets to mark which program we have chosen
    			displayLCDCenteredString (1, "[1]"); //So that while we're scrolling, we can have one marked
    		} else if (lcdScreen == 2 && Program != 2) {
    			displayLCDCenteredString (0, "Program"); //Name the second program here
    			displayLCDCenteredString (1, "2"); //Name the second program here
    			if (nLCDButtons == centerButton) {
    				Program = lcdScreen; //Sets the Program to the one on-screen
    				displayLCDCenteredString (0, "Autonomous Has");
    				displayLCDCenteredString (1, "Been Selected!");
    				wait1Msec(1500);
    			}
    		} else if (lcdScreen == 2 && Program == 2) {
    			displayLCDCenteredString (0, "Program"); //We use brackets to mark which program we have chosen
    			displayLCDCenteredString (1, "[2]"); //So that while we're scrolling, we can have one marked
    		} else if (lcdScreen == 3 && Program != 3) {
    			displayLCDCenteredString (0, "Program"); //Name the third program here
    			displayLCDCenteredString (1, "3"); //Name the third program here
    			if (nLCDButtons == centerButton) {
    				Program = lcdScreen; //Sets the Program to the one on-screen
    				displayLCDCenteredString (0, "Autonomous Has");
    				displayLCDCenteredString (1, "Been Selected!");
    				wait1Msec(1500);
    			}
    		} else if (lcdScreen == 3 && Program == 3) {
    			displayLCDCenteredString (0, "Program"); //We use brackets to mark which program we have chosen
    			displayLCDCenteredString (1, "[3]"); //So that while we're scrolling, we can have one marked
    		} else if (lcdScreen == 4 && Program != 4) {
    			displayLCDCenteredString (0, "Program"); //Name the fourth program here
    			displayLCDCenteredString (1, "4"); //Name the fourth program here
    			if (nLCDButtons == centerButton) {
    				Program = lcdScreen; //Sets the Program to the one on-screen
    				displayLCDCenteredString (0, "Autonomous Has");
    				displayLCDCenteredString (1, "Been Selected!");
    				wait1Msec(1500);
    			}
    		} else if (lcdScreen == 4 && Program == 4) {
    			displayLCDCenteredString (0, "Program"); //We use brackets to mark which program we have chosen
    			displayLCDCenteredString (1, "[4]"); //So that while we're scrolling, we can have one marked
    		}
    	}
    
    }
    
    
    /////////////////////////////////////////////////////////////////////////////////////////
    //
    //                                 Autonomous Task
    //
    // This task is used to control your robot during the autonomous phase of a VEX Competition.
    // You must modify the code to add your own robot specific commands here.
    //
    /////////////////////////////////////////////////////////////////////////////////////////
    
    task autonomous()
    {
    	if(Program == 1){
    		//Put your second program in here
    	}
    	else if(Program == 2){
    		//Put your second program in here
    	}
    	else if(Program == 3){
    		//Put your third program in here
    	}
    	else if(Program == 4){
    		//Pur your fourth program in here
    	}
      // .....................................................................................
      // Insert user code here.
      // .....................................................................................
    
    	AutonomousCodePlaceholderForTesting();  // Remove this function call once you have "real" code.
    }
    
    /////////////////////////////////////////////////////////////////////////////////////////
    //
    //                                 User Control Task
    //
    // This task is used to control your robot during the user control phase of a VEX Competition.
    // You must modify the code to add your own robot specific commands here.
    //
    /////////////////////////////////////////////////////////////////////////////////////////
    
    task usercontrol()
    {
    	// User control code here, inside the loop
    
    	while (true)
    	{
    	  // This is the main execution loop for the user control program. Each time through the loop
    	  // your program should update motor + servo values based on feedback from the joysticks.
    
    	  // .....................................................................................
    	  // Insert user code here. This is where you use the joystick values to update your motors, etc.
    	  // .....................................................................................
    
    	  UserControlCodePlaceholderForTesting(); // Remove this function call once you have "real" code.
    	}
    }
  3. sbdrobotics

    6 Oct 2013 Rockwall, TX 4080

    Here is a "skeleton" I did for one of my teams to use. It works fine, it will ask you to choose an autonomous and then will display voltages after autonomous mode is over or during driver control mode.

    I will bet you a dollar JPearman has something much cleaner and more impressive, but this will work.

    #include "Vex_Competition_Includes.c"   //Main competition background code...do not modify!
    
    //LCD Display code.
    const short leftButton = 1;
    const short centerButton = 2;
    const short rightButton = 4;
    //Declare count variable to keep track of our choice
    	int count = 0;
    //Wait for Press--------------------------------------------------
    void waitForPress()
    {
    	while(nLCDButtons == 0){}
    	wait1Msec(5);
    }
    //----------------------------------------------------------------
    
    //Wait for Release------------------------------------------------
    void waitForRelease()
    {
    	while(nLCDButtons != 0){}
    	wait1Msec(5);
    }
    
    //
    
    /////////////////////////////////////////////////////////////////////////////////////////
    //
    //                          Pre-Autonomous Functions
    //
    // You may want to perform some actions before the competition starts. Do them in the
    // following function.
    //
    /////////////////////////////////////////////////////////////////////////////////////////
    
    void pre_auton()
    {
    
    
    	//------------- Beginning of User Interface Code ---------------
    	//Clear LCD
    	clearLCDLine(0);
    	clearLCDLine(1);
    	//Loop while center button is not pressed
    	while(nLCDButtons != centerButton)
    	{
    		//Switch case that allows the user to choose from 4 different options
    		switch(count){
    		case 0:
    			//Display first choice
    			displayLCDCenteredString(0, "Red Left");
    			displayLCDCenteredString(1, "<		 Enter		>");
    			waitForPress();
    			//Increment or decrement "count" based on button press
    			if(nLCDButtons == leftButton)
    			{
    				waitForRelease();
    				count = 3;
    			}
    			else if(nLCDButtons == rightButton)
    			{
    				waitForRelease();
    				count++;
    			}
    			break;
    		case 1:
    			//Display second choice
    			displayLCDCenteredString(0, "Red Right");
    			displayLCDCenteredString(1, "<		 Enter		>");
    			waitForPress();
    			//Increment or decrement "count" based on button press
    			if(nLCDButtons == leftButton)
    			{
    				waitForRelease();
    				count--;
    			}
    			else if(nLCDButtons == rightButton)
    			{
    				waitForRelease();
    				count++;
    			}
    			break;
    		case 2:
    			//Display third choice
    			displayLCDCenteredString(0, "Blue Left");
    			displayLCDCenteredString(1, "<		 Enter		>");
    			waitForPress();
    			//Increment or decrement "count" based on button press
    			if(nLCDButtons == leftButton)
    			{
    				waitForRelease();
    				count--;
    			}
    			else if(nLCDButtons == rightButton)
    			{
    				waitForRelease();
    				count++;
    			}
    			break;
    		case 3:
    			//Display fourth choice
    			displayLCDCenteredString(0, "Blue Right");
    			displayLCDCenteredString(1, "<		 Enter		>");
    			waitForPress();
    			//Increment or decrement "count" based on button press
    			if(nLCDButtons == leftButton)
    			{
    				waitForRelease();
    				count--;
    			}
    			else if(nLCDButtons == rightButton)
    			{
    				waitForRelease();
    				count = 0;
    			}
    			break;
    		default:
    
    			count = 0;
    
    			break;
    
    		}
    	}
    
    }
    
    /////////////////////////////////////////////////////////////////////////////////////////
    //
    //                                 Autonomous Task
    //
    // This task is used to control your robot during the autonomous phase of a VEX Competition.
    // You must modify the code to add your own robot specific commands here.
    //
    /////////////////////////////////////////////////////////////////////////////////////////
    
    task autonomous()
    {
     	//Clear LCD
    	clearLCDLine(0);
    	clearLCDLine(1);
    	//Switch Case that actually runs the user choice
    	switch(count){
    	case 0:
    		//If count = 0, run the code correspoinding with choice 1
    		displayLCDCenteredString(0, "Red Left");
    		displayLCDCenteredString(1, "is running!");
    		wait1Msec(250);						// Robot waits for 250 milliseconds
    
    //Insert "Red Left" autonommous code here.
    
    
    
    		break;
    	case 1:
    		//If count = 1, run the code correspoinding with choice 2
    		displayLCDCenteredString(0, "Red Right");
    		displayLCDCenteredString(1, "is running!");
    		wait1Msec(250);						// Robot waits for 250 milliseconds
    
    // Insert "Red Right" autonomous code here.
    		
    	
    		break;
    	case 2:
    		//If count = 2, run the code correspoinding with choice 3
    		displayLCDCenteredString(0, "Blue Left");
    		displayLCDCenteredString(1, "is running!");
    		wait1Msec(250);						// Robot waits for 250 milliseconds
    		
    // Insert "Blue Left" autonomous code here.
    
    
    		break;
    		
    	case 3:
    		//If count = 3, run the code correspoinding with choice 4
    		displayLCDCenteredString(0, "Blue Right");
    		displayLCDCenteredString(1, "is running!");
    		wait1Msec(250);						// Robot waits for 250 milliseconds
    
    		// Insert "Blue Right" autonomous code here.
    		
    		break;
    	default:
    		displayLCDCenteredString(0, "No valid choice");
    		displayLCDCenteredString(1, "was made!");
    		break;
    	}}
    
    /////////////////////////////////////////////////////////////////////////////////////////
    //
    //                                 User Control Task
    //
    // This task is used to control your robot during the user control phase of a VEX Competition.
    // You must modify the code to add your own robot specific commands here.
    //
    /////////////////////////////////////////////////////////////////////////////////////////
    
    task usercontrol()
    {
    	// User control code here, inside the loop
    
    
    	   while(1 == 1)
      {
        //Remote Control Commands go here.
       
      
    
     
        
       
        {
    	bLCDBacklight = true;									// Turn on LCD Backlight
    	string mainBattery, backupBattery;
    
    {
    		clearLCDLine(0);											// Clear line 1 (0) of the LCD
    		clearLCDLine(1);											// Clear line 2 (1) of the LCD
    
    		//Display the Primary Robot battery voltage
    		displayLCDString(0, 0, "Primary: ");
    		sprintf(mainBattery, "%1.2f%c", nImmediateBatteryLevel/1000.0,'V'); //Build the value to be displayed
    		displayNextLCDString(mainBattery);
    
    		//Display the Backup battery voltage
    		displayLCDString(1, 0, "Backup: ");
    		sprintf(backupBattery, "%1.2f%c", BackupBatteryLevel/1000.0, 'V');	//Build the value to be displayed
    		displayNextLCDString(backupBattery);
    
    		//Short delay for the LCD refresh rate
    		wait1Msec(100);
    	}
    }
    
      }
    }
  4. Ephemeral_Being

    6 Oct 2013 Gilbert, Arizona N/A

    @sbdrobotics Here is a "skeleton" I did for one of my teams to use. It works fine, it will ask you to choose an autonomous and then will display voltages after autonomous mode is over or during driver control mode.

    I will bet you a dollar JPearman has something much cleaner and more impressive, but this will work.

    #include "Vex_Competition_Includes.c" //Main competition background code...do not modify! //LCD Display code. const short leftButton = 1; const short centerButton = 2; const short rightButton = 4; //Declare count variable to keep track of our choice int count = 0; //Wait for Press-------------------------------------------------- void waitForPress() { while(nLCDButtons == 0){} wait1Msec(5); } //---------------------------------------------------------------- //Wait for Release------------------------------------------------ void waitForRelease() { while(nLCDButtons != 0){} wait1Msec(5); } // ///////////////////////////////////////////////////////////////////////////////////////// // // Pre-Autonomous Functions // // You may want to perform some actions before the competition starts. Do them in the // following function. // ///////////////////////////////////////////////////////////////////////////////////////// void pre_auton() { //------------- Beginning of User Interface Code --------------- //Clear LCD clearLCDLine(0); clearLCDLine(1); //Loop while center button is not pressed while(nLCDButtons != centerButton) { //Switch case that allows the user to choose from 4 different options switch(count){ case 0: //Display first choice displayLCDCenteredString(0, "Red Left"); displayLCDCenteredString(1, "< Enter >"); waitForPress(); //Increment or decrement "count" based on button press if(nLCDButtons == leftButton) { waitForRelease(); count = 3; } else if(nLCDButtons == rightButton) { waitForRelease(); count++; } break; case 1: //Display second choice displayLCDCenteredString(0, "Red Right"); displayLCDCenteredString(1, "< Enter >"); waitForPress(); //Increment or decrement "count" based on button press if(nLCDButtons == leftButton) { waitForRelease(); count--; } else if(nLCDButtons == rightButton) { waitForRelease(); count++; } break; case 2: //Display third choice displayLCDCenteredString(0, "Blue Left"); displayLCDCenteredString(1, "< Enter >"); waitForPress(); //Increment or decrement "count" based on button press if(nLCDButtons == leftButton) { waitForRelease(); count--; } else if(nLCDButtons == rightButton) { waitForRelease(); count++; } break; case 3: //Display fourth choice displayLCDCenteredString(0, "Blue Right"); displayLCDCenteredString(1, "< Enter >"); waitForPress(); //Increment or decrement "count" based on button press if(nLCDButtons == leftButton) { waitForRelease(); count--; } else if(nLCDButtons == rightButton) { waitForRelease(); count = 0; } break; default: count = 0; break; } } } ///////////////////////////////////////////////////////////////////////////////////////// // // Autonomous Task // // This task is used to control your robot during the autonomous phase of a VEX Competition. // You must modify the code to add your own robot specific commands here. // ///////////////////////////////////////////////////////////////////////////////////////// task autonomous() { //Clear LCD clearLCDLine(0); clearLCDLine(1); //Switch Case that actually runs the user choice switch(count){ case 0: //If count = 0, run the code correspoinding with choice 1 displayLCDCenteredString(0, "Red Left"); displayLCDCenteredString(1, "is running!"); wait1Msec(250); // Robot waits for 250 milliseconds //Insert "Red Left" autonommous code here. break; case 1: //If count = 1, run the code correspoinding with choice 2 displayLCDCenteredString(0, "Red Right"); displayLCDCenteredString(1, "is running!"); wait1Msec(250); // Robot waits for 250 milliseconds // Insert "Red Right" autonomous code here. break; case 2: //If count = 2, run the code correspoinding with choice 3 displayLCDCenteredString(0, "Blue Left"); displayLCDCenteredString(1, "is running!"); wait1Msec(250); // Robot waits for 250 milliseconds // Insert "Blue Left" autonomous code here. break; case 3: //If count = 3, run the code correspoinding with choice 4 displayLCDCenteredString(0, "Blue Right"); displayLCDCenteredString(1, "is running!"); wait1Msec(250); // Robot waits for 250 milliseconds // Insert "Blue Right" autonomous code here. break; default: displayLCDCenteredString(0, "No valid choice"); displayLCDCenteredString(1, "was made!"); break; }} ///////////////////////////////////////////////////////////////////////////////////////// // // User Control Task // // This task is used to control your robot during the user control phase of a VEX Competition. // You must modify the code to add your own robot specific commands here. // ///////////////////////////////////////////////////////////////////////////////////////// task usercontrol() { // User control code here, inside the loop while(1 == 1) { //Remote Control Commands go here. { bLCDBacklight = true; // Turn on LCD Backlight string mainBattery, backupBattery; { clearLCDLine(0); // Clear line 1 (0) of the LCD clearLCDLine(1); // Clear line 2 (1) of the LCD //Display the Primary Robot battery voltage displayLCDString(0, 0, "Primary: "); sprintf(mainBattery, "%1.2f%c", nImmediateBatteryLevel/1000.0,'V'); //Build the value to be displayed displayNextLCDString(mainBattery); //Display the Backup battery voltage displayLCDString(1, 0, "Backup: "); sprintf(backupBattery, "%1.2f%c", BackupBatteryLevel/1000.0, 'V'); //Build the value to be displayed displayNextLCDString(backupBattery); //Short delay for the LCD refresh rate wait1Msec(100); } } } }

    What does that do if you press the left button on the first screen, or the right button on the fourth screen? The reason I rewrote the code instead of just using the one on the RobotC Blog was that I didn't expect it to loop from screen 1 to 4 when the left button was pressed. I'm not familiar with "case," and don't know what it does. If that works, then the only thing the code I wrote does differently is to mark which program was selected, and allow the user to keep scrolling through menus afterwords.

  5. sbdrobotics

    6 Oct 2013 Rockwall, TX 4080

    @Ephemeral_Being What does that do if you press the left button on the first screen, or the right button on the fourth screen? The reason I rewrote the code instead of just using the one on the RobotC Blog was that I didn't expect it to loop from screen 1 to 4 when the left button was pressed. I'm not familiar with "case," and don't know what it does. If that works, then the only thing the code I wrote does differently is to mark which program was selected, and allow the user to keep scrolling through menus afterwords.

    Yours may well work better, I believe we were posting at the same time, your post was not there when I hit the reply button. I am not a programmer, I just keep hacking until I find something that works and then run with it. :D

    I would expect an example from someone who truly knows how to program to work smoother and look much cleaner than the crude examples I provide which are usually pieced together from sample programs.

  6. edjubuh

    6 Oct 2013 V5 Beta Moderator West Lafayette, IN

    I've quickly bashed together the LCD Menu system I will likely be using this year. I've tested it on a real robot (not the emulator), and it's working. I've included three selections: alliance color, alliance position, and routine to run. The first two are plain-ol' shmlain-ol left button means left and right button means right. The routine to run cycles through 5 routines to select (easy to change to be more or less). It also has a timeout feature, and will skip all remaining selections to be made if a timeout happens. All values have a default pseudo-null value, so you can use the psuedo-null value to detect a timeout during autonomous. I've attached the code and copied below:

    #pragma config(UART_Usage, UART1, uartVEXLCD, baudRate19200, IOPins, None, None)
    #pragma config(UART_Usage, UART2, uartNotUsed, baudRate4800, IOPins, None, None)
    //*!!Code automatically generated by 'ROBOTC' configuration wizard               !!*//
    
    typedef enum 
    {
    	noButton = 0,
    	leftButton = 1,
    	centerButton = 2,
    	rightButton = 4
    } sLCDButtons;
    
    typedef enum
    {
    	left = -1,
    	right = 1,
    	nullPosition = 0,
    } pAlignments;
    
    typedef enum
    {
    	blue = -1,
    	red = 1,
    	nullColor = 0
    } pAllianceColors;
    
    #define numberOfRoutines 5
    
    
    
    void LCDWaitForRelease ()
    {
    	while(nLCDButtons != noButton) wait1Msec(100);
    }
    //The enterLCDButton function will look for and wait for a button to be pressed, and returns that button's name
    sLCDButtons enterLCDButton ( bool useLeft, bool useCenter, bool useRight, int timeoutSec = 10)
    {
    	ClearTimer(T1);
    	bool quit = false;
    	sLCDButtons returnButton = noButton;
    
    	while(!quit)
    	{
    		if(useLeft && nLCDButtons == leftButton)
    		{
    			quit = true;
    			LCDWaitForRelease();
    			returnButton = leftButton;
    		}
    		else if(useCenter && nLCDButtons == centerButton)
    		{
    			quit = true;
    			LCDWaitForRelease();
    			returnButton = centerButton;
    		}
    		else if(useRight && nLCDButtons == rightButton)
    		{
    			quit = true;
    			LCDWaitForRelease();
    			returnButton = rightButton;
    		}
    		else if(time1[T1] > (timeoutSec * 1000))
    		{
    			quit = true;
    			returnButton = noButton;
    		}
    	}
    	return returnButton;
    }
    
    void displayLCDAlignedString(int nLine, pAlignments align, const string textToDisplay)
    {
    	int rightPosition = 16-strlen(textToDisplay);
    	writeDebugStreamLine("%i", rightPosition);
    	switch(align)
    	{
    	case left: displayLCDString(nLine,0,textToDisplay); break;
    	case right: displayLCDString(nLine,rightPosition, textToDisplay); break;
    	}
    }
    
    
    task main()
    {
    	bLCDBacklight = true;
    	sLCDButtons retrievedButton = noButton;
    
    	/* INFORMATION TO BE DETERMINED */
    	pAllianceColors allianceColor = nullColor;
    	pAlignments alliancePosition = nullPosition;
    	int routineToRun = -1;
    
    	displayLCDCenteredString(0,"Loading..."); // random loading screen becase we can
    	clearLCDLine(1);
    	wait1Msec(100);
    
    	displayLCDCenteredString(0,"Alliance Color?");
    	displayLCDAlignedString(1,left,"Blue");
    	displayLCDAlignedString(1,right,"Red");
    	retrievedButton = enterLCDButton(true,false,true);
    	switch(retrievedButton)
    	{
    	case leftButton:
    		allianceColor = blue;
    		displayLCDCenteredString(0,"Selected:");
    		displayLCDCenteredString(1,"BLUE");
    		break;
    	case rightButton:
    		allianceColor = red;
    		displayLCDCenteredString(0,"Selected:");
    		displayLCDCenteredString(1,"RED");
    		break;
    	default:
    		allianceColor = nullColor;
    		displayLCDCenteredString(0,"Error Selecting");
    		displayLCDCenteredString(1,"Terminating"); //Your code would "terminate" the selection process, or you could say "defaulting" if you have a default autonomous
    		break;
    	}
    	wait10Msec(50);
    	clearLCDLine(0);
    	clearLCDLine(1);
    	retrievedButton = noButton;
    
    	if(allianceColor != nullColor)
    	{
    		displayLCDCenteredString(0,"Alliance Pos?");
    		char leftArrow = 200;
    		char rightArrow = 199;
    		string leftText; sprintf(leftText, "%c Left", leftArrow);
    		string rightText; sprintf(rightText, "Right %c", rightArrow);
    		displayLCDAlignedString(1,left,leftText);
    		displayLCDAlignedString(1,right,rightText);
    		retrievedButton = enterLCDButton(true,false,true);
    		switch(retrievedButton)
    		{
    		case leftButton:
    			alliancePosition = left;
    			displayLCDCenteredString(0,"Selected:");
    			displayLCDCenteredString(1,"LEFT");
    			break;
    		case rightButton:
    			alliancePosition = right;
    			displayLCDCenteredString(0,"Selected:");
    			displayLCDCenteredString(1,"RIGHT");
    			break;
    		default:
    			alliancePosition = nullPosition;
    			displayLCDCenteredString(0,"Error Selecting");
    			displayLCDCenteredString(1,"Terminating");
    			break;
    		}
    		wait10Msec(50);
    		clearLCDLine(0);
    		clearLCDLine(1);
    		retrievedButton = noButton;
    
    		if(alliancePosition != nullPosition)
    		{
    			bool quit = false;
    			int selectedRoutine = (numberOfRoutines/2);
    
    			displayLCDCenteredString(0,"Select Routine");
    			while(!quit)
    			{
    				switch(selectedRoutine) {
    				case 1:
    					displayLCDCenteredString(1,"<    R1    >");
    					break;
    				case 2:
    					displayLCDCenteredString(1,"<    R2    >");
    					break;
    				case 3:
    					displayLCDCenteredString(1,"<    R3    >");
    					break;
    				case 4:
    					displayLCDCenteredString(1,"<    R4    >");
    					break;
    				case 5:
    					displayLCDCenteredString(1,"<    R5    >");
    					break;
    				default:
    					displayLCDCenteredString(1,"ERROR");
    					break;
    				}
    				retrievedButton = enterLCDButton(true,true,true);
    				switch(retrievedButton) {
    				case leftButton:
    					if(selectedRoutine <= 1) selectedRoutine = numberOfRoutines;
    					else selectedRoutine--;
    					break;
    				case rightButton:
    					if(selectedRoutine >= numberOfRoutines) selectedRoutine = 1;
    					else selectedRoutine++;
    					break;
    				case centerButton:
    					routineToRun = selectedRoutine;
    					quit = true;
    					break;
    				}
    			}
    			displayLCDCenteredString(0,"Selected:");
    			switch(routineToRun)
    			{
    			case 1:
    				displayLCDCenteredString(1,"R1");
    				break;
    			case 2:
    				displayLCDCenteredString(1,"R2");
    				break;
    			case 3:
    				displayLCDCenteredString(1,"R3");
    				break;
    			case 4:
    				displayLCDCenteredString(1,"R4");
    				break;
    			case 5:
    				displayLCDCenteredString(1,"R5");
    				break;
    			default:
    				displayLCDCenteredString(1,"ERROR");
    				break;
    			}
    			wait1Msec(500);
    			
    			displayLCDCenteredString(0,"Selections:");
    			string selections; sprintf(selections, "%i , %i , R%i", allianceColor, alliancePosition, selectedRoutine);
    			displayLCDCenteredString(1,selections);
    			wait1Msec(1000);
    		}
    	}
    }

    It's quite unusual for me to give code without really any real explanation (or comments), but I'm currently in the middle of finishing up a tutorial for holonomic x-drives. That being said, if you have any questions about the code, please ask.

    EDIT: The .c file (and the above version) contains the header and the example menu system I used. The .h version does not contain the example menu system.

  7. jpearman

    6 Oct 2013 Moderator, ROBOTC Tech Support, V5 Beta Moderator Los Angeles 8888

    @sbdrobotics I will bet you a dollar JPearman has something much cleaner and more impressive, but this will work.

    It would almost be worth writing something just to see a dollar change hands :)

    Anyway, I have posted menu type code before, here was a overly complex example which was more about demonstrating an extreme use of pointers when ROBOTC first released that capability.

    http://www.vexforum.com/showpost.php?p=315448&postcount=120

    The "open source robot" code also had some LCD menu code, although not specifically for autonomous selection but rather status display.

    http://www.vexforum.com/showpost.php?p=335899&postcount=16

    I tried both examples that were posted by Ephemeral_Being and sbdrobotics and have a few (hopefully constructive) comments.

    They both mostly work

    This is incorrect code for checking that the robot is disabled.

    while (vrDisabled == 1) { //Ensures this code will run ONLY when the robot is disabled

    vrDisabled is a constant meaning something else, the code should be

    while(bIfiRobotDisabled == 1) { //Ensures this code will run ONLY when the robot is disabled

    the concept is, however, correct. You don't want to get stuck in the pre_auton() function if the user forgets to make a selection.

    Neither program needs to define the button values, there are constants for that (from RobotCIntrinsics.c)

    #if defined(hasLCDButtons) || defined(_WINDOWS)
        typedef enum
            {
            kButtonNone     = 0x00,
            kButtonLeft     = 0x01,
            kButtonCenter   = 0x02,
            kButtonRight    = 0x04,
            kButtonExit     = 0x08,
            kButtonExit2    = 0x10,
            } TControllerButtons;
        intrinsic const TControllerButtons propertyIndex(nLCDButtons, propertySystem, kSystemLCDButtons);
    #endif

    the idea of creating two functions for checking for button press and release is good, I will point out that they hog the cpu a little, I suspect curly brackets wee slightly misplaced. This

    //Wait for Release------------------------------------------------
    void waitForRelease()
    {
        while(nLCDButtons != 0){}
        wait1Msec(5);
    }

    Should probably have been as below, the delay was outside of the while loop, not really a problem in ROBOTC as it anticipates this type of code but would be in other firmware like ConVEX. Always try and yield so the scheduler can allow other tasks at the same or lower priority level to run (higher priority tasks will always run).

    //Wait for Release------------------------------------------------
    void waitForRelease()
    {
        while(nLCDButtons != 0) {
            wait1Msec(5);
        }
    }

    I'm not going to write another complete example today, however, if I were doing this I would separate the actual display code from the button detection and action code. My version of sbdrobotics code would have been more like this (incomplete, just the menu part, no auton or operator functions here).

    // These are the different choices we have
    typedef enum {
        kLcdDispStart = 0,
    
        kLcdAuto_1    = 0,
        kLcdAuto_2,
        kLcdAuto_3,
        kLcdAuto_4,
    
        kLcdDispNumber
        } kLcdDispType;
    
    // globals for tracking choices
    short           autoMode = (-1);
    
    // Display LCD choice
    void lcdMenuDisplay(kLcdDispType current)
    {
        //Switch case that allows the user to choose from 4 different options
        switch(current){
            case kLcdAuto_1:
                //Display first choice
                displayLCDCenteredString(0, "Red Left");
                displayLCDCenteredString(1, "<     Enter    >");
                break;              
            case kLcdAuto_2:
                //Display second choice
                displayLCDCenteredString(0, "Red Right");
                displayLCDCenteredString(1, "<     Enter    >");
                break;
            case kLcdAuto_3:
                //Display third choice
                displayLCDCenteredString(0, "Blue Left");
                displayLCDCenteredString(1, "<     Enter    >");
                break;
            case kLcdAuto_4:
                //Display fourth choice
                displayLCDCenteredString(0, "Blue Right");
                displayLCDCenteredString(1, "<     Enter    >");
                break;
                
            default:
                break;
            }
    }
    
    // Pre auton code - allow auton choice until enabled or selection is made
    void pre_auton()
    {
        int     i;
        int     autoTime = 1000;
        TControllerButtons    Buttons;
        
        // current choice
        kLcdDispType    mode = kLcdAuto_1;
        
        //Clear LCD
        clearLCDLine(0);
        clearLCDLine(1);
        bLCDBacklight = true;
        
        // Initial display
        lcdMenuDisplay(mode);
        
        //Loop while disabled
        while( bIfiRobotDisabled )
            {
            // Select display Item
            Buttons = nLCDButtons;
    
            // if right or left pressed change display
            if( (Buttons == kButtonLeft) || (Buttons == kButtonRight) )
                {
                // check for button press
                if( Buttons == kButtonRight )
                    {
                    mode++;
                    if(mode >= kLcdDispNumber)
                        mode = kLcdDispStart;
                    }
                if( Buttons == kButtonLeft )
                    {
                    mode--;
                    if(mode < kLcdDispStart)
                        mode = (kLcdDispNumber-1);
                    }
             
                // update display
                lcdMenuDisplay(mode);
                 
                // wait for release or auto repeat time
                for( i=0;i<autoTime;i+=10)
                    {
                    if( nLCDButtons == kButtonNone )
                        {
                        autoTime = 1000;   
                        break;
                        }
                    wait1Msec(10);
                    }
                // shorten auto repeat for next time
                if( nLCDButtons != kButtonNone )
                    autoTime = 250;  
                }
                
            // Center button selects choice
            if( Buttons == kButtonCenter )
                {
                displayLCDCenteredString(1, "<   Selected   >");
                // set the autononomous mode (replaces choice variable from sdrobotics code)
                autoMode = (short)mode;
                wait1Msec(1000);
                return;
                }
            
            // don't hog cpu
            wait1Msec(25);
            }
    }
  8. Ephemeral_Being

    6 Oct 2013 Gilbert, Arizona N/A

    Hey, I got the commands right? Neat.

    For future reference, is there a better spot to get documentation on RobotC? I couldn't find much this morning.

  9. jpearman

    6 Oct 2013 Moderator, ROBOTC Tech Support, V5 Beta Moderator Los Angeles 8888

    @Ephemeral_Being Hey, I got the commands right? Neat.

    For future reference, is there a better spot to get documentation on RobotC? I couldn't find much this morning.

    Where were you looking? The ROBOTC wiki is not bad.
    http://www.robotc.net/wiki/Main_Page

  10. Ephemeral_Being

    6 Oct 2013 Gilbert, Arizona N/A

    @jpearman Where were you looking? The ROBOTC wiki is not bad.
    http://www.robotc.net/wiki/Main_Page

    Nice, I missed that this morning. I was piecing the program together from the F1 menu and a sample I posted at the top of the thread.

    I'll read through it later.

  11. OscarMNOVA12

    6 Oct 2013 Event Partner, V5 Beta Tester Northern VA and Pittsburgh 12

    Also, I believe in the RobotC sample files they have an autonomous chooser for the VEX LCD.

  12. JoeTPR

    6 Oct 2013 Iowa 3018

    In our team's 2013 code , we had an LCD menu with autonomous switching capabilities. To use the menu, you need a potentiometer and an LCD.

    The LCD left/right buttons are for switching which menu item is shown. (Analog sensor viewer, motor test, autonomous selector/starter, etc.)
    The potentiometer is for selecting a sub-menu item, when applicable. (Switch what analog sensor to view, which motor to test, which autonomous routine to select, etc.)
    The LCD center button is for executing an action. (Start selected autonomous routine, run motor test, calibrate line follower, etc.)

    There is probably a good way to do the same w/o a potentiometer...

  13. JesseCRN

    7 Oct 2013 Indianapolis, IN 323Z

    Thank you for all the information! I am going to have our programmers look through this!

    How do you set-up the LCD in ROBOTC?

  14. Ephemeral_Being

    7 Oct 2013 Gilbert, Arizona N/A

    There's a line at the top of the code I posted that (I think) works.

    #pragma config(UART_Usage, UART1, uartVEXLCD, baudRate19200, IOPins, None, None)

    I don't have an exact idea what that does, or what any of it means. If you use that code and plug the LCD Screen into UART1 it will respond to commands.

    This probably has something to do with the documentation Pearman posted. I really should take a look at that.

  15. jpearman

    7 Oct 2013 Moderator, ROBOTC Tech Support, V5 Beta Moderator Los Angeles 8888

    @Jesse323Z Thank you for all the information! I am going to have our programmers look through this!

    How do you set-up the LCD in ROBOTC?

    Standard behavior is for ROBOTC to configure UART2 to be the LCD, you don't need to do anything.

    @Ephemeral_Being There's a line at the top of the code I posted that (I think) works.

    #pragma config(UART_Usage, UART1, uartVEXLCD, baudRate19200, IOPins, None, None)

    I don't have an exact idea what that does, or what any of it means. If you use that code and plug the LCD Screen into UART1 it will respond to commands.

    This line of code is generated by the "Motor&Sensors Setup" menu. It is configuring UART1 for use by the LCD instead of the default which is UART2. It is setting the baud rate (the communications speed, how many bits per second are sent to the LCD) to be 19200 as well as other parameters that have little meaning on the cortex. ROBOTC is available on several platforms (NXT, arduino etc) and this #pragma has some parameters which are platform dependent.

  16. 2 weeks ago

    im looking for something similar to this, however instead of switching through autonomous modes, i want it to switch from battery voltage on the main battery to its main screen as written in this code:

    clearLCDLine(0);
    bLCDBacklight = true;
    wait1Msec(100);
    displayLCDCenteredString(0, "Darkez 8.X");
    wait1Msec(1000);
    displayLCDCenteredString(1, "ACTIVE");

    and then to the alternate sensor detections, such as a light sensor value display, a ultrasonic value display, etc.

    how would i implement the code for switching to these modes? im running a fully controlled robot, non-autonomous. the full code is as follows:

    #pragma config(Sensor, dgtl1, , sensorLEDtoVCC)
    #pragma config(Sensor, dgtl2, , sensorLEDtoVCC)
    #pragma config(Motor, port1, , tmotorVex393_HBridge, openLoop, reversed)
    #pragma config(Motor, port2, , tmotorVex393_MC29, openLoop, reversed)
    #pragma config(Motor, port3, , tmotorVex393_MC29, openLoop)
    #pragma config(Motor, port4, , tmotorVex393_MC29, openLoop, reversed)
    #pragma config(Motor, port5, , tmotorVex393_MC29, openLoop, reversed)
    #pragma config(Motor, port8, , tmotorServoStandard, openLoop)
    #pragma config(Motor, port9, , tmotorVexFlashlight, openLoop, reversed)
    #pragma config(Motor, port10, , tmotorVex393_HBridge, openLoop)
    //*!!Code automatically generated by 'ROBOTC' configuration wizard !!*//

    task flash2;
    task headlight;
    task Start_light;
    task light;

    task headlight()
    {
    while(true)
    {
    if(vexRT[Btn6U] == 1)
    {
    motor[port4] = 67;
    }
    else if(vexRT[Btn6D] == 1)
    {
    motor[port4] = -67;
    }
    else
    {
    motor[port4] = 0;
    }
    {
    if(vexRT[Btn7U] == 1)
    {
    motor[port5] = 127;
    }
    else if(vexRT[Btn7D] == 1)
    {
    motor[port5] = -127;
    }
    else
    {
    motor[port5] = 0;
    }
    }
    }
    }

    task light()
    {
    while(true)
    {
    motor[port9] = 127;
    }

    }

    task Start_light()
    {
    while(true)
    {
    SensorValue[dgtl1] = true;
    wait1Msec(500);
    SensorValue[dgtl1] = false;
    wait1Msec(500);
    }
    }

    task flash2()
    {
    while(true)
    {
    if(vexRT[Btn5U] == 1)
    {
    startTask(Start_light);
    }
    else if(vexRT[Btn5D] == 1)
    {
    stopTask(Start_light);
    SensorValue[dgtl1] = false;
    }
    if(vexRT[Btn8U] == 1)
    {
    startTask(light);
    }
    else if(vexRT[Btn8D] == 1)
    {
    stopTask(light);
    motor[port9] = 0;
    }
    }

    }

    task main()
    {
    clearLCDLine(0);
    bLCDBacklight = true;
    wait1Msec(100);
    displayLCDCenteredString(0, "Darkez 8.X");
    wait1Msec(1000);
    displayLCDCenteredString(1, "ACTIVE");
    startTask(flash2);
    startTask(headlight);
    startTask(flash2);
    while(1==1)
    {
    motor[port1] = (vexRT[Ch1] + vexRT[Ch2])/2;
    motor[port10] = (vexRT[Ch1] - vexRT[Ch2])/2;

    motor[port2] = (vexRT[Ch3]);
    motor[port3] = (vexRT[Ch3]);

    if(vexRT[Ch1] || vexRT[Ch2] == 0)
    {
    SensorValue[dgtl2] = false;
    }
    else
    SensorValue[dgtl2] = true;
    }

    }

    however, i want to add the features as described above

  17. last week

    sabarrett328

    Jul 2 Grand Blanc, MI ????? Major Trouble

    Theres some good stuff here
    https://renegaderobotics.org/tag/lcd/

 

or Sign Up to reply!