Skip to content


Arduino LCD Interfacing Part 1

LCD 8-Bit GraphicI have scrounged up several LCD displays and wanted to use one with the Arduino. At the very least I wanted to test the displays. For future projects with the Arduino having a LCD display could be very handy so for this reason it is a good first project as well.

Unfortunately interfacing an LCD uses up much of the available I/O pins. All the digital I/O pins end up used (except for serial) for an 8-Bit LCD interface. I want to have more then just an LCD to display information. I also want to have buttons for interacting with the Arduino software. The ultimate goal here is to have both an LCD to display data and at least four buttons for interaction. Also, there has to be some I/O left over for interfacing to the application as well.

The answer is to interface the LCD using 4-bit mode and to use the same I/O lines to read four pushbutton switches. When the I/O lines are not used to transfer data to the LCD they can be read to get the state of the pushbuttons. Assuming this multiplexing can be done, there would be some I/O left for projects. Lucky for me there is already a 4-bit LCD interfacing library. After getting the probably easier 8-Bit interfacing working, I plan to change to 4-Bit interfacing as the next step toward the ultimate goal.

I would like to create a standard LCD and Keypad interface with a matching Library for the Arduino. Let me know in the comments if someone has already solved this problem. I know there are serial LCD modules and even some that have integrated buttons but I want to keep the serial port free.

There is a lot of information on the web for interfacing the Arduino to LCD displays. I chose to use the basic 8-Bit library and to follow the LCD interfacing tutorial for my first try at getting an LCD to work. I have several LCD modules that have been scrounged here and there. This easy tutorial should give me a setup to test all my scrounged modules.

References:
You can learn all bout interfacing an LCD to the Arduino with the links below.

From the Arduino playground site. Lots of information and links. Probably the best starting place for information related to Arduino LCD interfacing.
http://www.arduino.cc/playground/Code/LCD

Arduino Liquid Crystal Library Tutorial. This is the best starting point for your first Arduino project.
http://www.arduino.cc/en/Tutorial/LCDLibrary

Datasheet for the Hitachi controller used in almost every text LCD module
http://www.electronic-engineering.ch/microchip/datasheets/lcd/hd44780.pdf

Great description of how-to interface LCD displays. Written for PIC microcontrollers as part of an free online book. Excellent source for information.
http://www.mikroe.com/en/books/picbook/7_09chapter.htm

Initialization is tricky with the Hitachi controller luckily you don’t have to worry about it as the free Arduino library takes care of this. But if you want to know more about this process check this out.
http://www.doc.ic.ac.uk/~ih/doc/lcd/initiali.html

This is the top level LCD page for the link mentioned above. Looks like a valuable resource for interfacing these LCD modules to a PC.
http://www.doc.ic.ac.uk/~ih/doc/lcd/

This site looks like a comprehensive source for working with the industry standard Hitachi controller
http://home.iae.nl/users/pouweha/lcd/lcd.shtml

This short article shows how to interface the Arduino to an LCD without using the existing libraries.
http://www.arduino.cc/en/Tutorial/LCD8Bits

We are talking about the small text LCD displays you see on some devices. These display’s are very common and usually have a standard 14 or 16 pin connection. They use the Hitachi HD44780 or compatible controller and are easy and cheap to get. All Electronics has 16×2 LCD modules for $10/each with LED backlighting and $6/each without.

My first attempt 8-bit interfacing:
The standard 14 pin connector is shown below. Some of the units I have had 16 pin connectors with the extra two used for backlight. The pin-out diagram below shows what I found to be the wiring. I successfully tested several modules with both 14 and 16 pin connectors, all worked with the following pin outs.

LCD Module Front BackPin-Description
1—Ground
2—+V
3—Contrast
4—Register Select (RS)
5—Read/Write (R/W)
6—Enable (E)
7—Data Bit 0 LSB (D0)
8—Data Bit 1 LSB (D1)
9—Data Bit 2 LSB (D2)
10–Data Bit 3 LSB (D3)
11–Data Bit 4 LSB (D4)
12–Data Bit 5 LSB (D5)
13–Data Bit 6 LSB (D6)
14–Data Bit 7 LSB (D7)
15–Backlight -
16–Backlight +

I had to edit the source for the Arduino 8 bit LCD library. The pinMode, digitalWrite and digitalRead prototypes had to be commented out in the LiquidCrystal.cpp file as they are apparently defined elsewhere with slightly different parameter types.

Other then finding the pin out and the initial problem with the library the only other issue I had was that my LCD modules were very sensitive to the contrast voltage. I used a 100K potentiometer (pot) hooked across 5V to supply the contrast voltage. The voltage needed to be very near 0V to see anything at all.

Once I got the initial setup going I tested every text LCD module I could find. Surprisingly all the modules I have worked. Even a 4 line module seemed to work well.

Plans for Part 2
For part 2 of this article I plan to get the 4-bit mode working and figure out the button interface.

Posted in Arduino, Development Tools, Discovering, Microcontroller, Parts, Projects, Scrounging, Scrounging Parts.


19 Responses

Stay in touch with the conversation, subscribe to the RSS feed for comments on this post.

  1. brandonu says

    Lots of good information and a great list of references! I have a couple of projects in mind that will benefit from this article. Looking forward to Part 2!

  2. Mr. Meval says

    http://www.eetkorea.com/ARTICLES/2001SEP/2001SEP03_AMD_MSD_AN.PDF?SOURCES=DOWNLOAD

    It has several kinds of contrast circuits.

  3. micsaund says

    Beware that if you have extended-temperature LCDs, the contrast voltage is different. I got a box of 44780 2×20 large format displays for free one time, and spent ages wondering why I could not see anything on them unless I tilted them to an extreme angle. It turns-out that the freebies I got were extended-temp, which is great for use in a car or something like that, but a PITA if you don’t know you’ve got them ;)

    Mike

  4. xSmurf says

    If I can make a suggestion, it’s very easy to communication with I2C bidirectional shift registers. You can link up to 16 (well TI and NXP both make that IC, each have 8 different addresses). And they have input interrupt pins. Very neat chip. Super easy to interface using the arduino/wiring api. I don’t recall the exact part numbers (TPI8***, iirc), but they should be easy to find. Look at TI.. they were quiet generous with samples too! (10 to be exact!)

  5. xSmurf says

    I forgot to mention the punch line :”]

    All that on two wires! (and only one for unidirectional)

  6. arrarra says

    >Unfortunately interfacing an LCD uses up much of the
    >available I/O pins. All the digital I/O pins end up used
    >(except for serial) for an 8-Bit LCD interface.

    You can use the LCD 4 bit transfer mode, with a shift register to feed the Hitachi interface.
    Only two I/O needed (but You have to use software delays because the LCD busy flag can’t be read.

    http://www.rentron.com/Myke1.htm

  7. dfowler says

    Great comments, with lots of usefull information!

    Arrarra, I am trying to get the 4 bit mode to work with my LCD modules and am having trouble. I made required changes (R/W to ground) and it just does not work.

    After I get this working (if) I plan to add four buttons so I would be using 5 I/O bits to get teh LCD and four user input buttons.

    I realy like xSmurfs sugestion to use I2C chips. The only negative I can see is that you must have these chips, but as he points out, samples are avaialble. Maybe xSmurf will do an article showing how easy this is to do. If anyone knows the part number please share with a comment.

  8. xSmurf says

    Ok I looked into my receipt (I moved recently all the electronics are still in boxes) and found the exact part number for IT. PCF8574(NE4) is what you’re looking for. I’m not sure it’s worth writing a whole article on usage… using the Wire.h library with the Arduino API it’s as simple as something like this

    #include

    void setup(void) {
    Serial.begin(9600);
    Wire.begin(); // join i2c bus (address optional for master)
    Wire.beginTransmission(33); // transmit to device #4 as per the datasheet and the IC's jumper
    Wire.send(0); // sends one byte
    Wire.endTransmission(); // stop transmitting
    }

    void loop () {
    Wire.requestFrom(32, 1); // request 1 bytes from slave device #32

    while(Wire.available()) // slave may send less than requested
    {
    c = Wire.receive(); // receive a byte as character
    if (c%2 == 1) {
    Serial.print((c >> 1), HEX); // print the character
    }

    Serial.println();
    }

    Wire.beginTransmission(33); // transmit to device #33
    Wire.send(c >> 1); // sends one byte
    Wire.endTransmission(); // stop transmitting

    delay(500);
    }

    This solution has for advantage of being able to use the interrupt for the busy flag, all using only 2 IO (unidirectional + busy or 3 for bidi). Let me know if you’re still interested in knowing more :)
    I’ve mostly used the chip for input (along with the pricey 74C922 16 key encoder) and it worked like a charm. I’ll look back tonight when I get back from work to see if you have anymore questions ^.^ On a side note, I also got an I2C real time clock/calendar (PCF8563P) from NXP, I sadly never got it to work… definitely something worth investigating though, the chip looks very neat…

  9. xSmurf says

    (For some reason that didn’t show up nicely, but the included file is Wire.h)

  10. Axeman says

    @dfowler: The 4 bit mode requires a special initialization, ’cause LCD starts up in 8 bit mode, so you must send a “fake” set of 8 bit commands using only the 4 bits connected. The first time I used 4 bit mode, I had to find the tricky sequence (and the right timing!!!) by trials and errors.

    I have the resulting function and timings that SURELY works on my server, but it’s still boxed in the basement after I’ve moved in the new house.

  11. dfowler says

    Axeman,

    I assumed that the Arduino 4-Bit LCD library would do the initalization.

    http://www.arduino.cc/playground/Code/LCD4BitLibrary

    The instructions indicate that I should only need to tie the R/W to ground to make it work. So far my LCD just sits there when I try to use this Library.

    I have tried leaving the extra data bits open, grounded and tied to VCC. Any help would be aperceiated. I guess I will have to dig into the library code to figure this out.

  12. dfowler says

    xSmurf,

    This is the kind of article that I would like to have at uC Hobby. Pack your text, some links and some pictures into a short How-To for uCHobby and receive an Ardunio kit.

  13. Axeman says

    @dfowler

    Yes, the library contains some form of 4 bit initialization, and if I remember correctly, that init sequence is the one shown on the old Hitachi 44780 datasheet. Unfortunately, it doesn’t work on every version of 44780 (or equivalent LCD controller). Also, timing is critical in the early init phase is if the busy flag can’t be read (and you can’t read busy flag with R/W tied to ground). I’ve used delays in MILLIseconds range in the init…

    On the “new” datasheet http://web.mit.edu/6.115/www/datasheets/44780.pdf there is an updated init sequence for 4 bit operations (page 42) that “should” work nearly anywhere.

    Anyway I’ll be able to recover my original PIC source code and post it here in a few days…

  14. xSmurf says

    @dfowler #12: Fair enough! Work is keeping me a little busy, but I guess there’s this time when you’ve gotta give back ^-^ As I said most of my stuff is still packed away, but it’s a good enough reason to unpack them. I’ll look into it :) It’s too bad I messed around the breadboard (3 wide), I pretty much had everything set. Ok enough talking…
    *reaches for them boxes*

  15. JohnS says

    Hi Dave, great article, and you probably saved me hours by talking about commenting out the lines in the LCD library! Once I got that fixed, it took me quite a while to write to the second line of my display. I eventually figured out that the library does not default to a two line display so moving to the second line or writing there was impossible.

    There must be some magic to editing the library (probably some compile step I don’t know yet) so I couldn’t get changes to take there. I finally pulled the whole init routine out of the library and put it into my main program and all worked well.

    Now that the LCD is working well (in full 8-bit mode), I’m putting together a panel with 3 LEDs, 5 push buttons, and a beeper.

    Thanks again for pointing me toward this mini Arduino board. It’s awsome.

    John

  16. John Main says

    You can interface a standard 12 button keypad and an LCD in 4 bit mode on a single 8 bit port without any extra interfacing circuits or components.

    Check out the ezine page at http://www.best-microcontroller-projects.com

  17. dfowler says

    John,

    Can you provide a link to the article that describes LCD interfacing? I tried the link you provided. The site is so full of ads and popups that I cant find anything.

  18. John says

    Yes your right those ads don’t do much anyway! and I removed that anoying external popup it’s now DHTML so can be ignored on home page!

    Here’s a link to the ezine page to get access to the lcd-keypad project:
    http://www.best-microcontroller-projects.com/ezine

    The LCD keypad should be applicable to any microcontroller.

  19. Tweeks says

    I’m using the Arduino LCD4bit library with a HD44780 4×20 unit. I found that some of the init timing was not to spec (100uS instead of 160uS, etc). But the stock connections of 2(E),7(d4),8(d5),9(d6),10(d7),11(_R/W),12(_I/D) didn’t work. I had to tie _R/W to ground instead of 11, even though I hadn’t disabled it. But everything worked after that.

    Tweeks