Saturday, 16 January 2010

Controlling an LCD Display with a Shift Register

When I first ordered my Arduino Experimentation Kit from those nice people at oomlout I also ordered a 16 character by 2 line LCD display.

It was really easy to set up and use thanks to the instructions that came with it and the LiquidCrystal library bundled with the Arduino software.
The only problem is that it takes up a lot of valuable output pins, 6 in 4bit mode and 10 in 8bit mode, this makes it difficult to use in large projects, as you can quickly run out of pins.

The solution to this was quite obvious; use a shift register. So I fired up Google and had a look to see what other people had done. I found a great article on the Arduino playground (here) except I could figure out how to get their circuit to work with my shift register, as they use 74*LS*164 but I had a few 74HC595 registers knocking about. I also tried the other article on Arduino playground, but that one doesn't work very well, as it has large delays in it and you have to make sure that data you are sending to it is in the correct format (for example, it doesn't like numbers, you have to convert them into strings first)

So, here are my goals
  • Operate the LCD screen using a shift register
  • Use no more than three data pins
  • Maintain full compatibility with the LiquidCrystal library

The first two these are quite simple. Use the circuit below for a 4bit interface:


This circuit will allow us to control the output of the display, as well as the LED backlight. The backlight is controlled by an N-Channel MOSFT connected to pin QF on the shift register. We are using a MOSFET because the input impedance of the MOSFET is very very high which makes it ideal for using in logic circuits.

To meet the third goal I decided to modify the LiquidCrystal library. The reason being that the wonderful people who wrote it in the first place already did all the hard work of programming the methods for initialising the display and outputting data so it would be a bit daft to re-write all of that when all that is really needed is to change the way that the LiquidCrystal library sends data to the display.

After a couple of hours I had successfully rewritten the 'send', 'write8bits' and 'write4bits' methods and began testing.
The image above looks very complicated, but that is because those two bread boards contain both the 8bit and 4 bit versions (the screen is plugged into the 8bit interface).

In conclusion: the shift register interface is very simple to build and not too hard to program and makes the LCD screen easier to use in your projects.


You can download my completed ShiftLCD Library here

40 comments:

  1. Hey Chris, nice work. I was just asking this question on an arduino forum (adafruit.com) and sure enough i came across your post. Great work. Given the principle it should be easy enough to scale that up to more LCD's if you daisy chain more 595 shift registers right? I was looking to implement 4 16x1's but wanted a way to conserve pin outs by utilizing a shift register. I think you've pointed me in the right direction.

    ReplyDelete
  2. Thank you very much! You really helped me improving my project. I love the internet with its kind people :-)

    ReplyDelete
  3. Hi sir,

    I am N.Nandhakumar, from India. I am a Final Year student doing project on Arduino.I was searching a lot to interface JHD162a 16*2 display with GPS [shielded] and Arduino with less than 5 pins.

    I found your post and it was really useful. I built the schematic you have told, but the LCD dint respond.I get only black blocks in the first line of the LCD.I am using a 74HC595 and built it on a BreadBoard.

    I have few doubts in the schematic like

    The list of Components used for the circuit.
    Few more details of MOSFET.

    Please help me out.

    Waiting for your valuable suggestions.

    Regards
    N.Nandhakumar

    ReplyDelete
  4. Hi,

    Very nice project! Is it possible to add 3 more shift registers? Right now im contolling 3, 7segment displays with 3 595`s. The 595lcd has to go in front of them.

    Thanks!

    Collin

    ReplyDelete
  5. chris, i took a look at your code and it looks great! did you happen to make anymore attempts at the 74ls164n? i've been tinkering with it for a bit, but its looks the two ICs are a little different... any plans for a 2 wire version? im off to dig for 595's! cheers!
    -john c.

    ReplyDelete
  6. Hi Chris

    I liked and appreciated very much your shift lcd library and the way you created the Shift LCD. Actually I'm using ths as part od a complete motor step controller based on Arduino with several enhancements. Please, contact me as soon as possible, thank you.

    Enrico aka Alicemirror
    (enrico.miglino@ovi.com)

    ReplyDelete
  7. Chris,

    Its brilliant, thanks! I've also combined it with some AND gates so I use 2 pins to select which device is being controlled by the shift register, and then 3 pins for shift registers. I now have a total of 5 digital pins used for 4 different types of display (2xlcd, 2x7seg display).

    What's best about it is that once I had rewired the board, changed the library it was importing, and used the shiftlcd initialisation, I didn't need to change anything else.

    Thanks very much

    Perry

    ReplyDelete
  8. Chris,
    I too had a number of HC595 available. So I downloaded your library to tried it our. As others have already said, Brilliant.

    I have a number of SPI controlled items in a project, and I am wondering it this library can be converted to use SCK and MOSI and a unique Strobe pin?

    Matthew

    ReplyDelete
  9. Very useful in theory, though I can't get it to work. I just get black bars on the first row and that's it. Checked all connections twice too. The lcds I'm using work just fine with the normal library, am I missing something?

    ReplyDelete
  10. Scratch that, I had a 1uf capacitor in the circuit, and removing it fixed it.

    Thank you very much for this!

    ReplyDelete
  11. Hi Chris, nice work!
    Could you help me how to change the delayMicroseconds(); to some no delay() stops because I have a 8x8 LED matrix which starts flickering when I write to the LCD.
    I need the speed because there is a non flickering animation in the background. The rows of the matrix are turned on when a variable reaches a value from 0 to 7.



    void doCountTo8(){
    // count to 8 and set global 8 value
    unsigned long currentMillis = micros();
    if(currentMillis - previousMillis > 400) {
    previousMillis = currentMillis;
    Gl_Counter_8++;
    }
    if (Gl_Counter_8 == 8) {
    Gl_Counter_8=0;
    }
    }

    Thanks:
    Dan

    ReplyDelete
  12. thank you very much for suppling this wonderful library... i try too much to connect Parallel LCD with Serial fashion with 595 shift register,, i tried around 30 times buts i was fail but using your library i was success... thanks a lot....

    ReplyDelete
  13. Thanks, your solution works almost perfectly.
    I just saw an interesting behavior, not sure if this is an issue with your library or is native arduino library doing the same thing (haven't tested yet). When you do lcd.print("1234567890a234567890b234567890c234567890d234567890") with a 16x2 screen, on the second line only the string from letter "d" appears. Any Ideas what might be wrong?

    ReplyDelete
  14. Just installed the library and tested it with an auto-range ohm meter I am busy with at the moment. And it works like a charm. Thanks a lot.
    Saves me some pins for further expansion.

    ReplyDelete
  15. I seem to have a problem writing to the LCD after using backlightOn() and backlightOff().

    In the example Backlight.pde I have just added;
    lcd.setCursor(0,0);
    lcd.Print("some text");

    in the loop.

    After the first call to backlightOn() I get garbled characters.

    Is this a known issue, or am I doing something wrong?

    ReplyDelete
  16. Hello Chris,

    Thanks for your library which works very well with arduino uno...
    But I have recently bought the new chipkit uno32 ("100% compatible" they said...) and ShiftLCD doesn't work with it!
    After many research on google and on the chipkit forum ( http://www.chipkit.org/forum/index.php )I couldn't find ANY SOLUTION...(I am a newbie )
    Do you know how to transfer the library on the uno32?

    Thank you.

    Alexandre C from France

    ReplyDelete
  17. Hi Chris,

    Congrats on what i can see to be excellent code.

    However, summet is scuppering me...

    on compilation in arduino22, i get...

    expected',' or '...' before '&' token

    right at the start of the code..

    Here
    "/**
    * Computerised RC transmitter project
    * Arduino powered PPM transmitter
    * Version 0.2
    *
    * This is the first version to manage to sucessfully output a PPM train to the
    * transmitter and have a receiver decode it into servo movements.
    *
    * The idea behind this project is to take my old 35mHz Micron FM 6D transmitter
    * and replace the PPM encoder board with an Arduino based encoder, allowing me
    * to program in mixers, as well as adjust servo centers, end points and throws.
    *
    --* The PPM pulse chain is produced using--
    timer 1, a 16bit up/down timer.
    */"

    (where the two lines are)

    been over and over the code but cannot find a logical reason for it.

    Have you encountered this before and if so...what was the cause?

    Would love to have a play with your code, bt cant get any further.

    Many thanks.

    Mike.(Norwich UK)

    ReplyDelete
  18. HI Chris,

    Sorry to bother you, any chance you could give 30secs to advise on this?

    Many thanks.

    Mike. (UK)

    ReplyDelete
  19. Hello Chris,

    Thank you for this great library! Now I can go on designing my Arduino-controlled lab power supply / function generator... :-)

    Juha

    ReplyDelete
  20. Hello,

    I was wondering if anyone knew how to make this library work in 1.0?

    Here is the error that I am getting.
    In file included from HelloWorld.cpp:55:
    /Users/dan/Documents/Arduino/libraries/ShiftLCD/ShiftLCD.h:116: error: conflicting return type specified for 'virtual void ShiftLCD::write(uint8_t)'
    /Applications/Arduino.app/Contents/Resources/Java/hardware/arduino/cores/arduino/Print.h:48: error: overriding 'virtual size_t Print::write(uint8_t)'


    Thanks!

    ReplyDelete
    Replies
    1. This comment has been removed by the author.

      Delete
    2. Sorry, 1st attempt had a badly formatted link:

      You could start by taking a look at Arduino's Release notes here:
      http://arduino.cc/en/Main/ReleaseNotes

      If that doesn't do it try this one from Make:
      http://blog.makezine.com/2011/12/01/arduino-1-0-is-out-heres-what-you-need-to-know/

      Delete
    3. Hi!
      Just replace on line 116 void with size_t
      Also replace Wprorgam.h with Arduino.h

      Delete
  21. To everyone looking for this, can I recommend the more standard LCD3Wires setup and the arduino 1.0 compatible code I wrote do give full LiquidCrystal functionality?
    http://marc.merlins.org/perso/arduino/post_2012-01-23_LiquidCrystal-driver-support-LCD3Wire-hardware-_pebble-and-others_.html

    ReplyDelete
  22. I downloaded and try to use this library, but i giving me some errors even though i replace 116 void with size_t and replace Wprogram.h with Arduino.h
    I am using arduino1.0 Pleae help me

    ReplyDelete
  23. I get an error when compiling the sketch with the Arduino IDE 1.0.
    The error happens on all my computers.

    This is the error:

    In file included from HelloWorld.cpp:55:
    D:\Programma's\Arduino-1.0\libraries\ShiftLCD/ShiftLCD.h:116: error: conflicting return type specified for 'virtual void ShiftLCD::write(uint8_t)'
    D:\Programma's\Arduino-1.0\hardware\arduino\cores\arduino/Print.h:48: error: overriding 'virtual size_t Print::write(uint8_t)'


    How can I solve this problem?

    ReplyDelete
  24. Here's how to make the code compatible with Aruduino 1.0.

    In ShiftLCD.h
    Change line 116 to virtual size_t write(uint8_t);

    In ShiftLCD.cpp
    Change line 6 to #include "Arduino.h"
    Change line 256 to inline size_t ShiftLCD::write(uint8_t value) {

    I also encountered the backlight problem, and I came up with an ugly solution. I have no idea why it solves the issue but I realized that in my code I needed to turn ON the backlight twice before I can input any more text in properly. Same for off, I needed to call the Off twice, reseting the cursor each time and then text will display properly.

    // This will turn the backlight on
    void ShiftLCD::backlightOn(void) {
    _backlight = LCD_BL_PIN;
    updateBacklight();
    setCursor(0,1);
    updateBacklight();
    }

    // This will turn the backlight off
    void ShiftLCD::backlightOff(void) {
    _backlight &= ~LCD_BL_PIN;
    updateBacklight();
    setCursor(0,1);
    updateBacklight();
    }

    Hopefully some can shed some light on this issue and come up with a more elegant fix.

    ReplyDelete
    Replies
    1. Thanks! It works, but "size_t ShiftLCD::write(uint8_t value)" is on line 252 instead of 256!

      Delete
  25. muito bom mesmo,era justamente o que vinha procurando ha algum tempo...

    parabens...,muito bom mesmo ...

    ReplyDelete
  26. Hi Chris,

    Thanks for the information and well laid out documentation. I am currently attempting to interface a 4x20 LCD to an Atmega 328P. Will I require more than one 74HC595?

    ReplyDelete
  27. Thanx for ur post nd ur article, today I just tell u about a biggest retailar in electronics, ya Sargam Electronics is the biggest Retail Chain in Electronics in Delhi. Sargam deals with big brands like Samsung, Sony, Lg, Toshiba, Sansui, Hitachi, Voltas, Godrej, Azure, Nikon, Whirlpool, Dell, HP, Acer and many more brands. Sargam Electronics offers you to buy many electronics products like laptop,mobile,camera,washing machine,refrigerator,air conditionar and multiple electronics products at huge discount.

    ReplyDelete
  28. I could not make this work, even after some adjusts pointed by @Ckwong. Probably I miss something, because the lcd was showing some chars randomly. But it makes me understand how it should work. Thank you Chris Parish.

    At the end I got this: http://playground.arduino.cc/Main/LiquidCrystal.
    It works with my arduino uno 1.0 and. This is a good alternative.

    ReplyDelete
  29. I don't know the answer to that. But maybe one of the readers here can help answer your question here is some more interesting lcd screens

    ReplyDelete
  30. Thanks! It works, but "size_t ShiftLCD::write(uint8_t value)"

    By Marcello BOSS HD

    ReplyDelete
  31. This comment has been removed by the author.

    ReplyDelete
  32. Hi Chris. I find this post really useful but I cant make it compile on arduino 1.05. Please give me some pointers on how to make it work. thanks

    ReplyDelete
  33. Hello, Does this work with Arduino2560? what are the changes to make?

    ReplyDelete