Pages

3.02.2013

Using the VEX LCD with the Arduino

Have you ever needed an easy way to display output from your Arduino?  Sure, it is possible to use the serial monitor when the robot is connected, or to use a blinking LED, but those options don't always work well.  (For example, displaying the error values for PID on a mobile robot.)  An LCD is a great way to display information on a mobile robot.  I'm sure there are many VEX users who have both an Arduino and a VEX LCD, so using the VEX LCD is appealing (as opposed to purchasing a different display unit).

Getting the VEX LCD to talk to the Arduino isn't exactly easy (at least, it wasn't me, as I had no experience with serial data transmission).  My goal in this blog post is to enable you to get your VEX LCD and your Arduino communicating (and display "Hello World").  In a future blog post, I will guide you through writing functions to make displaying text easier.

The Hardware Side: Wiring the LCD

To wire up the LCD, we need to look at its specifications, found on this wiki page; however, some "digging"  is required to find what input voltage.  It turns out to be 5V, which can be supplied from the Arduino's (you guessed it) 5V port.  The TX port on the LCD should be wired to the TX port on the Arduino.  (We're not using the buttons this time, thus we don't need the RX port.)  For the picture below, I've matched the colors on the wires coming from my Arduino to those on the VEX UART cable.  (I apologize for the quality, but they're what I can take.  If something's not clear, just leave a comment on the post, and I'll do what I can to make it clearer.)

The yellow cable on the Arduino is plugged into the TX port (Digital 1), the red is in the 5V port, and the black is in ground.  These are connected to the corresponding colors on the UART port.

Packets

The VEX LCD accepts commands in the form of "packets."  These packets are transmitted over the TX (serial) port on the Arduino.  Each packet has a special form that needs to be followed, which is documented in detail here.  Upon receiving a packet, the LCD updates the screen, and displays this new command until it receives another packet.

The LCD packet has 3 main parts: the header, the update information, and the checksum.  A packet is always 22 bytes long.  What goes in each part?

Header:

This data is the same for whatever text or update command you will send to the LCD display.  It consists of 4 bytes:
0xAA
0x55
0x1e
0x12

Update Information:

This is where your text goes, what line you want to update, and the backlight setting.  This consists of 17 bytes:
B000000(L)(R)
0x??
0x??
... (14 more bytes)
The first byte is the backlight and line number.  If the L bit is 1, then the backlight is on, otherwise, it is off.  If R is 0, you are updating the top row, R=1 updates the bottom row.

The following 16 bytes are your message, transcribed using characters from the VEX LCD Character sheet.  It follows ASCII for the most part, but has some deviation.

Checksum

This is the hardest part of of the packet, and is best left to the program! :-)  This value is used to determine if everything was transmitted correctly.  The idea is that the controller inside the LCD can sum all the bytes after the header and have a result of 0.  This means that the checksum is:
0x100 - (sum of bytes in Update Info)
When summing the bytes, allow "overflow" to wrap around.  Again, this is fairly easy to do in code, so we're going to do it there.

Program

So, you have your Arduino wired to the LCD, you know what a packet is, and now we need to put it all together into a program!  Below is a basic "Hello World" program that uses the Serial library for Arduino.  I'm planning on writing another blog post sometime soon that explains how to make this code modular, and more user-friendly.

void setup()
{
  // start serial port at 19200 bps (VEX speed):
  Serial.begin(19200);
}

void loop()
{
    byte toSend[22];
          //Header info
          toSend[0] = 0xAA;
    toSend[1] = 0x55;
    toSend[2] = 0x1e;
    toSend[3] = 0x12;

    //Update data
    toSend[4] = 0x02; //Light on, top row
    toSend[5] = 0x48; //H

    toSend[6] = 0x45; //E

    toSend[7] = 0x4C; //L

    toSend[8] = 0x4C; //L

    toSend[9] = 0x4F; //O

    toSend[10] = 0x20; //' ' (space)

    toSend[11] = 0x57; //W

    toSend[12] = 0x4F; //O
   
    toSend[13] = 0x52; //R

    toSend[14] = 0x4C; //L

    toSend[15] = 0x44; //D
    toSend[16] = 0x20; //
' '
    toSend[17] = 0x20; //' '
    toSend[18] = 0x20; //' '

    toSend[19] = 0x20; //' '
    toSend[20] = 0x20; //' '
    toSend[21] = 0x20; //' '
   
    //Calculate Checksum
    byte cs = 0;
    for(int i = 4; i < 22; i++) {
      cs += toSend[i]; //Sum all the update vals 
    }
    cs = 0x100 - cs; //Update to sum to 0.

    toSend[22] = cs;

    //Send to LCD

    Serial.write(toSend, 22);
   
    delay(1000);
}

No comments:

Post a Comment

Please keep comments clean! Thanks.

Note: due to comment moderation, it may take a while for a comment to display.