How do you know when you’ve had a really good idea?
It’s when you go online and realize that a bunch of other people have all done the same thing.
I use often use LCD panels in my projects – they’re cool to look at, and can really help with tracking down bugs. Trouble is, they often take waaaay too many pins to control. Even using the 4-bit transfer mode you still use 6 pins.
The “Rolls-Royce” solution is to get an LCD to serial adapter, then hookup a software serial library and control the LCD from just one pin. You can get these boards here.
I own two from Modern Devices, but I own a lot more LCDs and it soon became apparent that buying a serial controller for each one was probably not the way to go. So I had a rummage around to see what I could use at instead.
I found a big bag o’ 74HC595 shift registers that I got for next-to-nothing on eBay. The 595 shift register can control an almost unlimited number of output pins from just 3 control lines. This seemed a good place to start – so I designed a small add-on board, much like the serial adapters – with a small pot for contrast control, and the option of controlling the backlight or two additional LEDs from one 595 chip.
The data sheet for the 595 is here.
I made the board as “single-sided” as I could – but it still requires 3 jumpers. The very top one can be the resistor used to run the backlight on the LCD (if one is required – check with the data sheet for your LCD). I left space for a small MOSFET to control the backlight – but I just jumpered this out so the backlight remains on all the time.
I updated the Arduino (22 release) LiquidCrystal library to use the 595 board. Download is here.
It was only after I’d finished it, that I realised a couple of other people had done a similar thing – although I think it’s fair to say this is the most compact solution.
UPDATE (via the adaftruit forum) – this is a neat idea – using a non-latching shift register, a diode and a resistor you can reduce the number of pins down to 2. It does require more work on the uController, as you have to shift out zeros to clear the register first, but it’s a clever solution.






Steve Hobley works for a software company, but in his spare time likes to deconstruct all the lovely consumer goods with a goal to make unique and interesting things.











{ 16 comments… read them below or add one }
OR…..you could buy a display with SPI bus interface built into it.
http://www.lcd-module.com/products/dog.html
How much are they?
Last time I looked anything like that was expensive.
I can get a four line LCD for around $11 and the rest of the parts were under $2.
3×16 LCD module from Mouser is less than $12. Works with SPI / 4-bit / 8-bit plus works with both 3.3V and 5V.
http://www.mouser.com/Search/Refine.aspx?Keyword=dog+character+lcd+module
I just checked them out – looks good, but it says “4-wire SPI” I didn’t think you needed four wires for SPI – does that include power and ground?
4 wire spi = clk,enable,dout,din
3 wire spi = clk,enable,dout/din
with three wire spi the master needs to tristate the data pin when reading from the slave
if you don’t need to read from a four wire spi just ignore the extra pin
Thanks so much for your work. You do have, sir, the only bloody library that has managed to do the right thing, and I’ve tried a few
One quick note on LED pins… the LCD doesn’t respond immediately to setLEDxPin(), _register needs to be sent (e.g. calling lcd.shift595() in the setLEDx call) maybe that’d be something to add to the code?
many thanks for making this library available! I have a question though: I’d like to make my own 595 circuit on a veroboard and I prefer to use different connections of pins between the LCD and the 595. Is it possible to use your library by changing some pin definitions inside your code? eg suppose I want the LCD RS pin connected to pin 1 (not 7) of the 595 etc
thank you!
It seems to me you’ve made a small mistake in the LiquidCrystal595.cpp file :
—–Shift Reg to LCD——–
* SR Pin 15 – ENABLE 10000000
* SR Pin 1 – D4 00000010
* SR Pin 2 – D5 00000100
* SR Pin 3 – D6 00001000
* SR Pin 4 – D7 00010000
* SR Pin 5 – MOSFET / LED1 00100000
* SR Pin 6 – LED 2 01000000
* SR Pin 7 – RS 00000001
*
* ———————————————————————————–
*/
// 595 mappings – LED1 is also the backlight controller
#define ENABLE_PIN B00000001
#define RS_PIN B10000000
#define LED1_PIN B00100000
#define LED2_PIN B01000000
#define DATABITS B00011110
#define PIN_D4 B00000010
#define PIN_D5 B00000100
#define PIN_D6 B00001000
#define PIN_D7 B00010000
Did you mistake RS and EN in the comment or in the code?
Trying to use your library together with an ETT ET-CONV board (which is nothing more than a prebuilt 75HC595 board, see http://img.auctiva.com/imgdata/0/1/9/6/2/1/webimg/259999884_o.jpg for the diagram) but am getting no results so far, possibly due to a wrong pinout definition in the .cpp file
Possibly – although I have a couple of boards running OK right now.
I might have posted an earlier file by mistake.
I got it to work in the end; pinout for the ET-CONV is
* SR Pin 15 – BACKLIGHT 00000001
* SR Pin 1 – RS 00000010
* SR Pin 2 – RW/LED2 00000100
* SR Pin 3 – EN 00001000
* SR Pin 4 – D4 00010000
* SR Pin 5 – D5 00100000
* SR Pin 6 – D6 01000000
* SR Pin 7 – D7 10000000
Also managed to port the library to Arduino 1.0 quite easily; just a few things changed. Here are the diffs
LiquidCrystal595.h
95c98
virtual void write(uint8_t);
LiquidCrystal595.cpp
40c43
#include “WProgram.h”
190c193
= _numlines ) {
—
> if ( row > _numlines ) {
275c278
inline void LiquidCrystal595::write(uint8_t value) {
277d279
< return 1; // assume sucess
I could not quite follow Jan-Albert’s advice to make this library Arduino 1.0 compatible, so I had a look in to it myself, here is what worked for me:
Open LiquidCrystal.h and look around line 98 for:
virtual void write(uint8_t);
change to:
virtual size_t write(uint8_t);
Save and close.
Open LiquidCrystal.cpp. There are two changes for this file.
Change 1: Look around line 44 for:
#include “WProgram.h”
change to: (this will make it Arduino 1 and = 100
#include
#else
#include
#endif
Change 2: Look around line 279 for:
inline void LiquidCrystal595::write(uint8_t value) {
send(value, HIGH);
}
change this to:
inline size_t LiquidCrystal595::write(uint8_t value) {
send(value, HIGH);
}
Save and close.
Quit Arduino and open it up again – everything should now compile just fine.
Good luck and thanks to Stephen for writing this library.
Thanks for posting this update.
Steve
Very good indeed, built a custom PCB for my lcd .
Thx a lot , going to use a lot !
Alex
Hi Steve
I just put up a page with my HW implementation of your circuit , it works like a charm !
sites.google.com/site/elettronicaarduinoesperimenti/Home/lcd-serial-interface-with-74595
Hello,
Nice project.
However, how do i control the leds with code.
Thanks
I was wondering if you have an actual schematic for this design? Looking at your board layout there seems to be something wrong with the way the backlight is wired up. It could just be the way I am looking at it. I am more comfortable looking at a regular schematic. I have tried several different designs like this though and I have never been able to get one to work. I have a feeling though that it is either in the libraries or the software I am using. I will probably buy the AdaFruit one though and see if I can get that to work.
{ 1 trackback }