Programming an LCD Display

I am trying to program a LCD Display for our competition robot. I just want it to show the battery voltage for now. I have tried using the sample programming but then nothing but the LCD works. please help.

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

Details about how you are programming would help. I am assuming you’re using RobotC as you mentioned a sample code. Also which battery, I am again assuming you mean the main battery, not a back up or battery on a power expander. In addition, did you make any changes to the sample? If so, can we see them?

Imperious, I am using RobotC and I want it to display the main battery and the battery for the power expander. I did not make any changes to the sample program.

You need to combine the code from the sample code with the code that you use to control your robot so that both can work together.

Can you be more specific? Here is my code. It was just a basic one to test it, when i use it the LCD works but the motors do not.

#pragma config(Motor,  port2,           M1,            tmotorVex393_MC29, openLoop)
#pragma config(Motor,  port3,           M2,            tmotorVex393_MC29, openLoop)
#pragma config(UART_Usage, UART2, uartVEXLCD, baudRate19200, IOPins, None, None)
//*!!Code automatically generated by 'ROBOTC' configuration wizard               !!*//

task main()

{
while(1 == 1)

	//Driving Motor Control
	motor[M1] = vexRT[Ch3] / 2;
	motor[M2] = vexRT[Ch3] / 2;

	{
		bLCDBacklight = true;                                    // Turn on LCD Backlight
		string mainBattery, backupBattery;

		while(true)                                                        // An infinite loop to keep the program running until you terminate it
		{
			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);
		}
	}
}

Ahh. I see what you mean. The issue is that you have nested one while true loop inside another while true loop. This means that only the internal loop will run and only your LCD will be controlled.

There are two ways you could go about fixing this. You could just put both the motor and LCD control in the same loop, or you could use tasks in order to control both of them at the same time.

Have a read up on tasks before I provide the code below, heres a link to some posts by JPearman regarding multitasking: http://www.robotc.net/wikiarchive/Multitasking_tips.

Heres an example making use of tasks:

#pragma config(Motor,  port2,           M1,            tmotorVex393_MC29, openLoop)
#pragma config(Motor,  port3,           M2,            tmotorVex393_MC29, openLoop)
#pragma config(UART_Usage, UART2, uartVEXLCD, baudRate19200, IOPins, None, None)
//*!!Code automatically generated by 'ROBOTC' configuration wizard               !!*//

// This is our first task 
// This provides the code to control the LCD
task LCDController {
	
	// Enable the backlight and setup appropriate vars.
	bLCDBacklight = true;                                    // Turn on LCD Backlight
	string mainBattery, backupBattery;
	
	while(true)                                                   // An infinite loop to keep the program running until you terminate it
	{
		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);
	}
}

task driveController {
	while(true)
	{
		//Driving Motor Control
		motor[M1] = vexRT[Ch3] / 2;
		motor[M2] = vexRT[Ch3] / 2;
		
		wait1Msec(20); // Different delay because we can update the motors more frequently
	}
}

task main()
{
	// Start the other two tasks
	startTask(LCDController);
	startTask(driveController);

	while(true) { // We will just keep the main task running once we have started the others.
		wait1Msec(1000);
	}
}

And heres an example with both instruction sets in the same, non-nested loop:

task main()
{
	// Enable the backlight and setup appropriate vars.
	bLCDBacklight = true;                                    // Turn on LCD Backlight
	string mainBattery, backupBattery;
	
	while(true)                                                   // An infinite loop to keep the program running until you terminate it
	{
		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);

		//Driving Motor Control
		motor[M1] = vexRT[Ch3] / 2;
		motor[M2] = vexRT[Ch3] / 2;
		
		//Short delay for the LCD refresh rate
		wait1Msec(100);
	}
}

Thanks I’ll have to wait till Monday to test this, I hope it works.

I was in a hurry when I wrote the above, so I will quickly explain what the first code does.

In the above code, Multitasking allows us to set separate ‘delays’ in each of the loops. This means that we can update the motors every 20ms, while updating the LCD at its refresh rate (100ms).

Confusion can arise when multitasking is mentioned - however it pays to note that the cortex cannot actually do more than one operation at a time, tasks are essentially just queuing code to run one after another, except when a task of higher priority wants to run. In theory, the same could be accomplished using a state machine, however RobotC’s ‘multitasking’ infrastructure makes it very easy to implement different sections of code (which is IMO one of RobotCs biggest strengths) and also contains the ability to terminate a task prematurely if it is taking too many processor cycles to run (which can be avoided by setting the priority high).

100ms is probably a little high for motor control, as people tend to notice delay in user interfaces at around 100-150ms. So this is a prime example of when using tasks is very helpful.

I think he is talking about the expander, not the backup battery. What you need to do is connect a 3-Pin wire to the “Status” port on the expander, and then connect it to the CORTEX as “Analog” on the Analog tab in the motors and sensors setup. Next, replace “BackupBatteryLevel/1000.0” with “SensorValue[NameOfPortWithExpander]/280.0” It should work.

Hopefully this helps! :slight_smile:

  • [TVA] Delta III

@Delta_III I added "SensorValue[NameOfPortWithExpander]/280.0 in place of the backup battery. I got most of the errors work out except for three.

Here is the code the errors are in the last to lines of code.

//Display the power expander battery voltage
						displayLCDString(1, 0, "Expander: ");
						sprintf(Expander, "%1.2f%c",); SensorValue; Expander; 
						displayNextLCDString(Expander);

Here are the errors, the first is a red x, the second was a yellow x and the third was also a red x.

Error:Procedure call Parameters don’t match declaration for ‘sprintf(char * pzCharsString, char * pzFormatString, …)’
Warning:Meaningless statement – no code generated
Error:Procedure call Parameters don’t match declaration for ‘displayNextLCDString(char * pzString)’

Any help is appreciated as is the help that has already given.

Was this just an abridged copy of the code, or is this the actual code you have used? If it is, then its not a valid way of using sprintf:


sprintf(Expander, "%1.2f%c",); SensorValue; Expander; 

Try the below:

//Display the Backup battery voltage
displayLCDString(1, 0, "Expander: ");
sprintf(expanderBattery, "%1.2f%c", SensorValue[NameOfPortWithExpander]/280.0, 'V');    //Build the value to be displayed
displayNextLCDString(expanderBattery);

In combination with the task code above and a definition of the “NameOfPortWithExpander”, this compiles with no errors:

@Delta_III @EvolvingJon thanks or all the help I got all the errors worked out. Turns out I was using the code you gave me but I was changing to many things.

@Delta_III @EvolvingJon I tried that in our program and none of the functions on the robot worked except for our LCD.

#pragma config(Sensor, in1, Expander, sensorAnalog)
#pragma config(Sensor, dgtl1, rightEncoder, sensorQuadEncoder)
#pragma config(Sensor, dgtl3, leftEncoder, sensorQuadEncoder)
#pragma config(Motor, port1, Claw, tmotorVex393_HBridge, openLoop)
#pragma config(Motor, port2, DRF, tmotorVex393_MC29, openLoop, reversed, driveRight, encoderPort, dgtl1)
#pragma config(Motor, port3, DRB, tmotorVex393_MC29, openLoop, reversed, driveRight)
#pragma config(Motor, port4, Arm1R, tmotorVex393_MC29, openLoop, reversed)
#pragma config(Motor, port5, Arm1L, tmotorVex393_MC29, openLoop, reversed)
#pragma config(Motor, port6, Arm2R, tmotorVex393_MC29, openLoop)
#pragma config(Motor, port7, Arm2L, tmotorVex393_MC29, openLoop)
#pragma config(Motor, port8, DLB, tmotorVex393_MC29, openLoop, driveLeft)
#pragma config(Motor, port9, DLF, tmotorVex393_MC29, openLoop, driveLeft, encoderPort, dgtl3)
#pragma config(Motor, port10, MG, tmotorVex393_HBridge, openLoop)
//!!Code automatically generated by ‘ROBOTC’ configuration wizard !!//

task main()

{
while(1 == 1)
{
//Driving Motor Control
motor[DLF] = vexRT[Ch3] / 2;
motor[DLB] = vexRT[Ch3] / 2;
motor[DRF] = vexRT[Ch2] / 2;
motor[DRB] = vexRT[Ch2] / 2;

	//Arm Control
	if(vexRT[Btn6U] == 1)
	{
		motor[Arm1L] = 80;
		motor[Arm1R] = 80;
		motor[Arm2L] = 80;
		motor[Arm2R] = 80;
	}
	else if(vexRT[Btn6D] == 1)
	{
		motor[Arm1L] = -70;
		motor[Arm1R] = -70;
		motor[Arm2L] = -70;
		motor[Arm2R] = -70;
	}
	else
	{
		motor[Arm1L] = 15;
		motor[Arm1R] = 15;
		motor[Arm2L] = 15;
		motor[Arm2R] = 15;
	}
	//Claw Control
	if(vexRT[Btn5U] == 1)
	{
		motor[Claw] = 100;

	}
	else if(vexRT[Btn5D] == 1)
	{
		motor[Claw] = -100;

	}
	else
	{
		motor[Claw] = 15;
	}

	// Enable the backlight and setup appropriate vars.
	bLCDBacklight = true;                                    // Turn on LCD Backlight
	string mainBattery, expanderBattery;

	while(true)                                                   // An infinite loop to keep the program running until you terminate it
	{
		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);

		displayLCDString(1, 0, "Expander: ");
		sprintf(expanderBattery, "%1.2f%c", SensorValue[Expander]/280.0, 'V');    //Build the value to be displayed
		displayNextLCDString(expanderBattery);
	}
}

}

Firstly, please make use of the

[CODE]
tags given to us by the VEX forum gods. It makes it significantly easier to read your code. Otherwise all the formatting is striped by the text renderer and your code loses all its indentation and has no syntax highlighting.

Now to your code, the issue is that you have (again) nested two while(true) loops. So inside one loop, you have put another loop that will only run the code inside that loop!

This is essentially the demise of copy-pasting code without really understanding what it does.

Take a look at the code I provided below (and in my previous post) and notice how it only has a single while(true) {} loop compared to the two in your code. What effect will this have on the code? What is the function of a while true loop (or even a while loop)? When will it end?

task main()
{
	// Enable the backlight and setup appropriate vars.
	bLCDBacklight = true;                                    // Turn on LCD Backlight
	string mainBattery, backupBattery;
	
	while(true)                                                   // An infinite loop to keep the program running until you terminate it
	{
		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);

		//Driving Motor Control
		motor[M1] = vexRT[Ch3] / 2;
		motor[M2] = vexRT[Ch3] / 2;
		
		//Short delay for the LCD refresh rate
		wait1Msec(100);
	}
}

Unless you are using tasks, having multiple infinite loops is probably a bad idea (or at least, not what you want to achieve in this case).

Now apply that knowledge to your code. Using the examples provided above as a guide (as well as the VEX wiki and the plethora of content on the forums (like this very thread)) fix the issue in your code. If you have any issues along the way that you can’t solve, after googling it, debugging your code and checking the forums, then make a post on the forums.

Tip: using the google search

where you replace with what you want to find out about is a great way to find resources on the forums.