The HD44780 (and compatible) based alphanumeric displays are usually available in 16x2 (2 lines consisting of 16 characters) and 20x4 configurations, but can be found in many more forms. The most 'complicated' display would be a 40x4 display, this sort of display is special as it has 2 HD44780 controllers, one for the upper two row and one for the bottom two rows. Some graphic LCDs have two controllers as well.
The HD44780 LCDs are great, they are very cheap, readable and quite easy to work with. But they also have some drawbacks, these displays take up a lot of I/O pins when connected to the Arduino. In simple projects this is not a concern, but when projects get big, with a lot of IO, or where certain pins are needed for things such as an Analog read or PWM, the fact these LCDs require a minimum of 6 pins can become a problem.
But we can solve this problem in a cheap and interesting way.
Step 1: Getting the components
2 - 74HC595 package DIP16
1 - Generic male header - 2 pins. This is not required, I used this as a way to permanently disable backlight.
3 - Ceramic Capacitor - capacitance 0.1µF; voltage 50V
1 - Electrolytic Capacitor - capacitance 10µF; voltage 35V
1 - Ceramic Capacitor - capacitance 220pF; voltage 50V
1 - NPN-Transistor - part # PN2222A*
1 - 1k Ω Resistor
1 - Trimmer Potentiometer - maximum resistance 5kΩ
1 - 470 Ω Resistor
* With an NPN transistor the backlight will stay off until it is turned on by software. If you want to have the backlight on by default, use a PNP type transistor. Changes in the code of the library provided will have to be made, though.
Sub total for this list is $0.744. The pin header is also not required, so you can save 15cents right there and the subtotal will be $0.6.
Step 2: Know your hardware #1
The HD44780 can work in two modes:
1. 4-bit mode, where each byte sent to the LCD consists of 2 4-bit parts.
2. 8-bit mode, on which we will focus.
The LCD has 16 pins in total, 3 control pins and 8 data pins:
RS - Controls whether we want to send a command or data to the LCD. Where 'high' means data (a character) and 'low' means a command byte.
R/W - The HD44780 controller allows you to read from its RAM. When this pin is 'high' we can read data from its data pins. When it is 'low' we can write data to the LCD. Although the option to read from LCD can be useful in some cases, we will not go over it in this tutorial, and we will simply ground this pin to ensure that it is always in Write mode.
E - E is the 'Enable' pin, this pin is toggled 'high' then 'low' to write the data to its RAM and eventually display it on the screen.
DB0-7 - These are the data pins. In 4-bit mode we only use the 4 high bits DB4-DB7, and in 8 bit mode all of them are utilized.
VSS - This is the ground pin.
VCC - This the power pin, the LCD runs off a 5V power supply, we can easily feed it power from the Arduino's +5v pin.
Vo - This is the pin which allows you to set the contrast level for the display, it requires a potentiometer, normally a 5K Ohm pot is used.
LED+ - This is the power source for the backlight. Some LCDs do not come with a backlight, and only have 14 pins. In most cases this pin also requires a +5v connection.
LED- - This is the ground for the backlight.*
* It is important to check the displays datasheet or inspect its PCB to check for a backlight resistor, most LCDs will have them built-in, in which case all you have to do is apply power to LED+ and ground to LED-. But in the case your LCD doesn't have a built-in resistor for the backlight, it is important that you add one, otherwise the backlight will consume a lot of power and it will eventually burn out.
In most cases the way this LCD is wired to the Arduino is by using it in 4-bit mode and grounding the R/W pin. This way we use pins RS, E and DB4-DB7. Running in 4-bit mode has another small disadvantage in that it takes twice as long to write data to the screen as it would take in an 8-bit configuration. The LCD has a 'settling' time of 37 microseconds, this means you have to wait 37 microseconds before sending the next command or data-byte to the LCD. Since in 4-bit mode we have to send data twice for each byte, the total time it takes to write a single byte goes up to 74microseconds. This is still fast enough, but I wanted my design to produce the best possible results.
The solution to our problem with the number of pins used lies in a Serial to Parallel converter...
Step 3: Know your hardware #2
In comes the 74HC595 chip. This is a very cheap and simple to operate shift register. In essence what it does is take in a clock and data signals which it uses to fill an internal 8 bit buffer with the 8 last bits that were 'clocked in'. Once the 'Latch' (ST_CP) pin has been brought 'high' it moves these bits into its 8 outputs. The 595 has a very nice feature, it has a serial data out pin (Q7'), this pin can be used to daisy chain 2 or more 595's together to form Serial to Parallel adapters which are 16 or more bits wide. For this project we will need 2 of these chips. The schematic can also be modified to work with a single 595 in 4-bit mode, but this won't be covered by this tutorial.
Step 4: Wiring it all up
In the schematic we see 2 595 chips daisy chained together to form a 16 bit parallel output.
The bottom chip is actually the main one, and the upper one is daisy chained to it.
What we see here is that the bottom 595 is driving the LCD's data pins in an 8-bit configuration, the top chip controls the RS signal and backlight by turning a transistor on or off. Remember the *note about the LCD backlight on Know your hardware #1 page, in the case your LCD doesn't have a backlight resistor, don't forget to add one in your circuit. In my case the LCDs I have already come with a resistor built-in, so I skipped this step.
The contrast is applied through a 5K Ohm pot, one pin goes to GND the second one goes to VCC and the wiper to the Vo pin on the LCD.
The capacitors used on the LCD's and 595's VCC lines are decoupling capacitors, they are there to get rid of interference. They are not a must if you are working on a breadboard, but should be used in case you build your own version of this circuit to be used outside of "lab conditions".
R5 and C9 in that very specific order create an RC delay, which makes sure that the data in the 595's outputs has time to stabilize before the Enable pin on the LCD is set 'high' and reads the data.
Q7' of the bottom 595 goes into the serial data input of the 595 on the top, this creates a daisy chain of 595s and thus a 16 bit interface.
Wiring up to the Arduino is easy. We use a 3-wire configuration, using Arduino's SPI pins. This allows for very fast data transfers, sending 2 bytes to the LCD usually takes about 8 microseconds. This is very fast, and it is actually much faster than the time it takes the LCD to process the data, thus a delay of 30 microseconds is needed between each write.
One very big benefit of using SPI is that pins D11 and D13 are shared with other SPI devices. This means that if you already have another component which uses SPI, such as an accelerometer, this solution will only use one extra pin for the enable signal.
On the next page we will see the result. I have built a backpack on a perfboard and it is working very well for me so far.
Step 5: The result + Library
These are images of the completed product, the Fritzing PCB view is the perfboard layout I used to build my backpack. You may find it useful if you want to build your own.
I liked it so much that I designed a PCB using DipTrace and ordered a batch of 10 PCBs. I will need 2 or 3 units for myself but will make the rest available for a symbolic price when I receive them. So if anyone is interested please let me know.
* Edit: The PCBs are here, and they work. Here's the full picture gallery for this project, including the actual PCBs.
Of course I did not forget the most important thing, a library to use this circuit with.
It is compatible with the LiquidCrystal library included with the Arduino IDE, so you can easily replace the declarations at the top of your sketch and not have to change anything else in your sketch. There is also an example sketch which demonstrates how each function in the library works, so check it out.