HELP! We were trying to program our LCD Module for RobotC but we don’t know how! Please help us this is the only thing that is stopping us.
What have you tried? I suggest this tutorial, found on the ROBOTC website: http://www.robotc.net/blog/?p=775
Hope this helps!
//Andrew
Something that I figured out in the documentation (read: not the help menus), is the buttons return their value as a bitmap to the variable “nLCDButtons”.
So if the left button is pressed, that variable takes a value of 1. the center, 2. and the right , 4. If multiple buttons are pressed, it returns the sum of the buttons’ values.
Thank you guys but my problem is i am very very new to programming and i have no idea what any of the things on the website is talking about.
I have tried nothing because i dont know how. I need to place multiple programs for autonomus.
When facing a problem like this, it is best to break it down into smaller steps that you can tackle in turn.
1) Multiple Programs
The Cortex can only have one program loaded at a time, so what you must do is write one program that can act like several different programs. The details of how you do this depend on what you are trying to accomplish.
If the programs are all very similar to each other, and vary in a few details like initial travel distance/time, then you can have one real program and just control the details of the behavior by setting a few variables. You’ll have your main() function determine which “program” you want and set the variables accordingly.
If the programs are all very different to each other, then you will probably write a function for each “program”. Then your main() function must determine which “program” you want and call the correct function.
You may have a combination of both (two very different programs with a few variations on each). In this case, your main function will set the necessary variables, as well as select the function to call to run the desired “program”.
2) Selecting Between Programs
As indicated above, the main() function is responsible for determining which program is wanted, and setting up the variables and calling the correct function.
There are many ways to accomplish this. In the past, Jumpers were commonly used; more recently many teams started using a potentiometer with multiple “zones” to select between programs. These techniques have an advantage over the LCD: Persistence & simplicity. Jumpers and potentiometers stay as-is even when the power is turned off. Also, these don’t require multiple steps to read. Your main() function simply reads the appropriate input(s) and them kicks off the right program.
For the simplest LCD interaction, you could wait for the user to press one of the three buttons, and then call one of three functions in response. That isn’t much harder code than jumpers or a potentiometer, but it also isn’t really any better. Also, it requires the user to press one of the three buttons before the robot will do anything (no persistent selection)
A more advanced LCD user interface would use one of the buttons to rotate through the available programs, and a 2nd button to run the currently selected program. This is not trivial code, but it isn’t too bad either.
3) Persistent Program Selection
I’m not aware of a way to make your selected program auto-run on the next robot power-up. The PIC microcontroller had EEPROM that could have been used to save settings like this, but the Cortex does not have EEPROM. I don’t see any way to programmatically modify flash memory in RobotC, so there may simply be no place to save such settings on the Cortex.
Sorry for the longwinded reply, but hopefully there is something in here that will help guide you to a solution.
Cheers,
- Dean
I have never tried it but it seems like if you really want to use the screen what you could do is use a pot but have the screen display a different message for each program based on the value of the pot. I have always worried about having more than 2 zones on a pot just because I am a worry-wort, however with this sort of code where the screen displays which program you are running I would feel comfortable using quite a few different zones… (which is an advantage)
Again, I have not tried this yet, it is just something I have been thinking about. If you think/know it wont work please call it out.
The other idea I had was using the screen to get you through the code selecting process by having you answer all of the obvious questions, similar to an ATM.
It would just be like a tree style diagram (that’s how I imagine it in my head)
Red or Blue (press one button for red the other for blue)
Isolation or Interaction (press one button for isolation the other for interaction)
Then from there it could ask you which of you X number of programs you want to run by reading the program name and asking you yes or no.
I figure you could use the third button which isn’t used yet as a “back button” or an “I messed up can we start this over” button.
What do you think?
~DK
That is how I do it, and it works really well, but the point about persistence its interesting, it is definitely worth considering. Though for the time being i don’t think it is necessary.
So what you are saying is there would be a motor with a potenteiometer and the LCD Module would display the program and i leave on that angle that program would run that specific “program” or function right?
P.S. That really helped guys thanks to all!
Persistence is definitely a good point to bring up.
I am always surprised at how much tougher it is to put the robot on the field than I had expected. It is definitely nice to be able to set your autonomous code before you are under the time constraints of the field, leaving you more time to, place the robot, pre-load, get plugged into the field, get vexnet linked, and allow sensors to initialize. Maybe the screen questioning mode I described earlier isn’t so great after all…
EDIT: you don’t have a motor attached to the pot, you simple put a shaft into the pot and hand turn it to one of the “zones” you have programmed. You then have your autonomous code recognize each of the “zones” and perform the autonomous program that you have linked to each position. For example you may have 2 modes, when you turn the pot to one side it will perform your red autonomous mode code and if you turn it to the other it will perform your blue autonomous mode code. You could use the screen as a way for the robot to read out which zone you are in just as a double check. I have used the pot method before and just kept a little cheat sheet with me that says which way to turn the shaft for each autonomous mode.
~DK
I’m sorry i meant
So what you are saying is that there would be a motor with a potententeiometer and there would be a specific “program” for each angle. I would then program the LCD to display the program name for each angle. If i wanted that program to run i would just leave that angle there and not mess with it. or press one of the buttons on the LCD to put that program on.
That’s basically what 1103 did this past year. For a LCD-only menu flowchart, see this post from this thread.
//Andrew
You are correct except for the motor part, you hand-turn the shaft that goes through the potentiometer to get it to the angle you want, you don’t use up a motor do do it.
Also you are going to want to program it to look at a range of angles, the potentiometer return a number between 0 and 1000 (ish, i don’t remember the exact number off hand) it is incredibly tricky to get it to stay at just one of those numbers so you are going to want to set ranges (ie. 0-250, 251-500, 501-750, 751-1000) or something like that.
~DK
So as far as stability ie. making it stay; would gears be a better option for it to stay?
The potentiometer stays put when you let go of it, it has a decent amount of friction built in so you don’t have to worry about locking it into position.
~DK
On the PIC Microcontroller, you get a 10-bit value (0 to 1023).
On the Cortex, you get a 12-bit value (0 to 4095).
In practice, you may not be able to get the full range of possible values, so you need to assume the lowest and highest few percent of values are not reachable.
I successfully used a Vex potentiometer to input characters (ASCII 32-127), so ~100 zones is possible though it was twitchy. (I got bored one afternoon and made a simple serial terminal using a Cortex, a Vex LCD, and a potentiometer :D)
I think you could reliably do 32 zones for program selection, though you’d probably want some feedback to help you find the center of your desired zone. That way you don’t have to worry about landing near the boundary between two adjacent zones.
Cheers,
- Dean
If I were to get enough zones, i would consider using a button on the LCD to “lock in” my choice so that even if it gets bumped, it will still complete the intended program
Well, generally the selection is made once at startup and selecting a different program requires power cycling the microcontroller. You can write code to watch for selection changes and react accordingly, but it doesn’t happen automatically.
Cheers,
- Dean
I think we are understanding my thoughts a little differently. Don’t worry about it, but I understand. sometimes I just ramble incomplete variants of my thoughts.
Hopefully by now you have your LCD module working so the need for example code has become unnecessary, however, I though I would post some for future searches on this thread. I had some reservations about posting this as part of the learning process is to struggle with the problem sometimes. Having said that it’s also useful to see alternative example code and learn new techniques you may have not seen before. As this code is relatively trivial and ultimately has no impact on competition outcome it seems ok to post.
Simple user selection using the LCD buttons, use left and right for selection and the center button to select. Many improvements could be made, the original had display strings initialized in a structure setup before hand so the code could be called multiple times to simulate a menu hierarchy.
#pragma config(UART_Usage, UART1, VEX_2x16_LCD)
//*!!Code automatically generated by 'ROBOTC' configuration wizard !!*//
/*-----------------------------------------------------------------------------*/
/* */
/* Module: LcdDemo.c */
/* Author: jpearman */
/* Created: 16 July 2011 */
/* */
/* Revisions: V0.1 */
/* */
/*-----------------------------------------------------------------------------*/
/* */
/* Description: */
/* */
/* Example for the use of LCD buttons and display */
/* */
/*-----------------------------------------------------------------------------*/
/* */
int UserSelect( int InitialSelection );
/*-----------------------------------------------------------------------------*/
/* */
/* Main task */
/* */
/*-----------------------------------------------------------------------------*/
task main()
{
int Selection;
while( true )
{
// call the user select routine, this will block until a selection is made
Selection = UserSelect( 0 );
// we could now do someting with the selection such as select
// our alliance color
// loop because we need to do something
while( true )
{
wait1Msec(20);
}
}
}
/*-----------------------------------------------------------------------------*/
/* */
/* Use the LCD buttons to select something we can use later */
/* */
/*-----------------------------------------------------------------------------*/
// States for UserSelection
typedef enum {
initDisplay = 0,
noButton,
waitForRelease,
leftButtonDown,
rightButtonDown,
centerButtonDown
} userControl;
#define NUMBER_OF_SELECTIONS 5
int UserSelect( int InitialSelection )
{
bool done = false;
int LcdButtons;
userControl buttonState = initDisplay;
int select = 0;
string str;
// Clear LCD
clearLCDLine(0);
clearLCDLine(1);
// What will we show when first called
if( ( InitialSelection < NUMBER_OF_SELECTIONS ) && ( InitialSelection >= 0 ) )
select = InitialSelection;
else
select = 0;
// loop until center button is pressed
while( !done )
{
// Read LCD buttons
LcdButtons = nLCDButtons;
// determine what to do
switch( buttonState )
{
case initDisplay:
case leftButtonDown:
case rightButtonDown:
// Display selected program
displayLCDPos(1, 0);
sprintf(str, "Program %d", select);
displayNextLCDString( str );
buttonState = waitForRelease;
break;
case waitForRelease:
// Wait here until nothing is pressed
if( LcdButtons == 0 )
buttonState = noButton;
break;
case noButton:
// Check left button
if( LcdButtons & kLeftButton )
{
buttonState = leftButtonDown;
if( select > 0 )
select--;
else
select = (NUMBER_OF_SELECTIONS-1);
}
// Check right button
if( LcdButtons & kRightButton )
{
buttonState = rightButtonDown;
if( select < (NUMBER_OF_SELECTIONS-1) )
select++;
else
select = 0;
}
// Check center button
if( LcdButtons & kCenterButton )
{
done = true;
}
break;
default:
// why are we here ??
buttonState = noButton;
break;
}
// 25mS Delay
wait1Msec(25);
}
displayLCDPos(1, 0);
sprintf( str, "Execute %d", select);
displayNextLCDString(str);
return( select );
}