Tutorial: Arduino and monochrome LCDs

Please note that the tutorials are not currently compatible with Arduino IDE v1.0. Please continue to use v22 or v23 until further notice. 

This is chapter twenty-four of a series originally titled “Getting Started/Moving Forward with Arduino!” by John Boxall – A tutorial on the Arduino universe.

The first chapter is here, the complete series is detailed here.

Welcome back fellow arduidans!

The purpose of this article is to summarise a range of affordable monochrome liquid-crystal display units that are available to work with our Arduino; and to replace the section about LCDs in chapter two of this series. We will first examine some fixed-character and then graphical LCD units in this article. So let’s go!

Fixed-character LCD modules

When shopping around for LCD modules, these will usually be the the most common found in retail outlets. Their size is normally measured by the number of columns and rows of characters in the display. For example, the three LCDs below are 8×2, 16×2 and 20×4 characters in size:


Currently, most LCDs should have a backlight of some sort, however you may come across some heavily-discounted models on (for example) eBay that are not. Character, background and backlight colours can vary, for example:


Interfacing these screens with our Arduino boards is very easy, and there are several ways to do so. These interface types can include four- and eight-bit parallel, three-wire,  serial, I2C and SPI interfaces; and the LCD price is usually inversely proportional to the ease of interface (that is, parallel are usually the cheapest).

Four-bit parallel interface

This is the cheapest method of interface, and our first example for this article. Your LCD will need a certain type of controller IC called a Hitachi HD44780 or compatible such as the KS0066. From a hardware perspective, there are sixteen pins on the LCD. These are usually in one row:


… or two rows of eight:


The pin labels for our example are the following:

  1. GND
  2. 5V (careful! Some LCDs use 3.3 volts – adjust according to LCD data sheet from supplier)
  3. Contrast
  4. RS
  5. RW
  6. Enable
  7. DB0 (pins DB0~DB7 are the data lines)
  8. DB1
  9. DB2
  10. DB3
  11. DB4
  12. DB5
  13. DB6
  14. DB7
  15. backlight + (unused on non-backlit LCDs) – again, check your LCD data sheet as backlight voltages can vary.
  16. backlight GND (unused on non-backlit LCDs)

As always, check your LCD’s data sheet before wiring it up.

Some LCDs may also have the pinout details on their PCB if you are lucky, however it can be hard to decipher:

Now let’s connect our example 16×2 screen to our Arduino using the following diagram.

Our LCD runs from 5V and also has a 5V backlight – yours may differ, so check the datasheet:


(Circuit layout created using Fritzing)

Notice how we have used six digital output pins on the Arduino, plus ground and 5V. The 10k ohm potentiometer connected between LCD pins 2, 3 and 5 is used to adjust the display contrast. You can use any digital out pins on your Arduino, just remember to take note of which ones are connected to the LCD as you will need to alter a function in your sketch. If your backlight is 3.3V, you can use the 3.3V pin on the Arduino.

From a software perspective, we need to use the LiquidCrystal() library. This library should be pre-installed with the Arduino IDE. So in the start of your sketch, add the following line:

Next, you need to create a variable for our LCD module, and tell the sketch which pins are connected to which digital output pins. This is done with the following function:

The parameters in the brackets define which digital output pins connect to (in order) LCD pins: RS, enable, D4, D5, D6, and D7.

Finally, in your void setup(), add the line:

This tells the sketch the dimensions in characters (columns, rows) of our LCD module defined as the variable lcd. In the following example we will get started with out LCD by using the basic setup and functions. To save space the explanation of each function will be in the sketch itself. Please note that you do not have to use an Arduino Mega – it is used in this article as my usual Arduino boards are occupied elsewhere.

And here is a quick video of the example 24.1 sketch in action:

There are also a some special effects that we can take advantage of with out display units – in that we can actually define our own characters (up to eight per sketch). That is, control the individual dots (or pixels) that make up each character. With the our character displays, each character is made up of five columns of eight rows of pixels, as illustrated in the close-up below:


In order to create our characters, we need to define which pixels are on and which are off. This is easily done with the use of an array (array? see chapter four). For example, to create a solid block character as shown in the image above, our array would look like:

Notice how we have eight elements, each representing a row (from top to bottom), and each element has five bits – representing the pixel column for each row. The next step is to reference the custom character’s array to a reference number (0~7) using the following function within void setup():

Now when you want to display the custom character, use the following function:

where 0 is the memory position of the character to display.

To help make things easier, there is a small website that does the array element creation for you. Now let’s display a couple of custom characters to get a feel for how they work. In the following sketch there are three defined characters:

And here is a quick video of the example 24.2 sketch in action:

So there you have it – a summary of the standard parallel method of connecting an LCD to your Arduino. Now let’s look at the next type:

Three-wire LCD interface

If you cannot spare many digital output pins on your Arduino, only need basic text display and don’t want to pay for a serial or I2C LCD, this could be an option for you. A 4094 shift register IC allows use of the example HD44780 LCD with only three digital output pins from your Arduino. The hardware is connected as such:


And in real life:


From a software perspective, we need to use the LCD3Wire library, which you can download from here. To install the library, copy the folder within the .zip file to your system’s \Arduino-2x\hardware\libraries folder and restart the Arduino IDE. Then, in the start of your sketch, add the following line:

Next, you need to create a variable for our LCD module, and tell the sketch which of the 4094’s pins are connected to which digital output pins as well as define how many physical lines are in the LCD module. This is done with the following function:

Finally, in your void setup(), add the line:

The number of available LCD functions in the LCD3wire library are few – that is the current trade-off with using this method of LCD connection … you lose LCD functions but gain Arduino output pins. In the following example, we will demonstrate all of the available functions within the LCD3Wire library:

And as always, let’s see it in action. The LCD update speed is somewhat slower than using the parallel interface, this is due to the extra handling of the data by the 4094 IC:

Now for some real fun with:

Graphic LCD modules

(Un)fortunately there are many graphic LCD modules on the market. To keep things relatively simple, we will examine two – one with a parallel data interface and one with a serial data interface.

Parallel interface

Our example in this case is a 128 by 64 pixel unit with a KS0108B parallel interface:


For the more technically-minded here is the data sheet. From a hardware perspective there are twenty interface pins, and we’re going to use all of them. For breadboard use, solder in a row of header pins to save your sanity!

This particular unit runs from 5V and also has a 5V backlight. Yours may vary, so check and reduce backlight voltage if different.

You will again need a 10k ohm potentiometer to adjust the display contrast. Looking at the image above, the pin numbering runs from left to right. For our examples, please connect the LCD pins to the following Arduino Uno/Duemilanove sockets:

  1. 5V
  2. GND
  3. centre pin of 10k ohm potentiometer
  4. D8
  5. D9
  6. D10
  7. D11
  8. D4
  9. D5
  10. D6
  11. D7
  12. A0
  13. A1
  14. RST
  15. A2
  16. A3
  17. A4
  18. outer leg of potentiometer; connect other leg to GND
  19. 5V
  20. GND

A quick measurement of current shows my TwentyTen board and LCD uses 20mA with the backlight off and 160mA with it on. The display is certainly readable with the backlight off, but it looks a lot better with it on.

From a software perspective we have another library to install. By now you should be able to install a library, so download this KS0108 library and install it as usual. Once again, there are several functions that need to be called in order to activate our LCD. The first of these being:

which is placed within void setup(); The parameter sets the default pixel status. That is, with NON_INVERTED, the default display is as you would expect, pixels off unless activated; whereas INVERTED causes all pixels to be on by default, and turned off when activated. Unlike the character LCDs we don’t have to create an instance of the LCD in software, nor tell the sketch which pins to use – this is already done automatically. Also please remember that whenever coordinates are involved with the display, the X-axis is 0~127 and the Y-axis is 0~63.

There are many functions available to use with the KS0108 library, so let’s try a few of them out in this first example. Once again, we will leave the explanation in the sketch, or refer to the library’s page in the Arduino website. My creative levels are not that high, so the goal is to show you how to use the functions, then you can be creative on your own time. This example demonstrate a simpler variety of graphic display functions:

Now let’s see all of that in action:

You can also send normal characters to your KS0108 LCD. Doing so allows you to display much more information in a smaller physical size than using a character  LCD. Furthermore you can mix graphical functions with character text functions – with some careful display planning you can create quite professional installations. With a standard 5×7 pixel font, you can have eight rows of twenty-one characters each. Doing so is quite easy, we need to use another two #include statements which are detailed in the following example. You don’t need to install any more library files to use this example. Once again, function descriptions are in the sketch:

Again,  let’s see all of that in action:

If you’re looking for a very simple way of using character LCD modules, check this out.


Have fun and keep checking into tronixstuff.com. Why not follow things on twitterGoogle+, subscribe  for email updates or RSS using the links on the right-hand column, or join our Google Group – dedicated to the projects and related items on this website. Sign up – it’s free, helpful to each other –  and we can all learn something.

The following two tabs change content below.

John Boxall

Founder, owner and managing editor of tronixstuff.com.

55 Responses to “Tutorial: Arduino and monochrome LCDs”

  1. Russ says:

    John – ths s excellent stuff, as usual.

    I wan’t aware t was possble to use a shft regster to reduce the number of pns used – I have been workng on a project to create a clock and have been strugglng to fnd a couple of free pns so ths may work for me, but I have a queston: I have created custom characters for alarm status and snooze – wll I loose these functons usng the shft regster?

    Many thanks


  2. eren says:

    Good tutoral. Thanks for sharng

  3. pasha34 says:

    Thnks. Very Good Ste.

  4. Justin W says:

    John, great tutorals! I just wanted to note that I was havng dffcultes wth 24.1 untl I hooked pn 5: RW up to ground, lke shown here http://arduno.cc/en/uploads/Tutoral/LCD_bb.png. Once I dd that, my text dsplayed correctly.

  5. Ed says:

    Hey! Got ths workng!

    Thanks a lot for the tutoral, t’s great!


  6. wowmir says:

    H, have you posted a lst of all the components that are requred to complete all your tutorals. If not maybe you can make your own kt to go wth ths seres. I am followng t from Inda and would not mnd buyng all of the stuff requred( two of each f possble,so that I can blow stuff out ) at one go.

    1) Ths would save a lot of tme
    2) It wll actually be cheaper
    3) Most mportantly t wll help people stay n the flow of learnng for long hours at a stretch.

    As you can see your ste s now very popular so t mght be a venture worth tryng.

  7. JRMN says:

    Is t possble to scroll a sngle contnuously lne, but not effect the prevously output text? I tred leftToRght() and rghtToLeft(), but they don’t seem to do what I’m lookng for.

    • John Boxall says:

      Yes, t could be done. However some work would be nvolved. Suggeston would be to put your text n an array of characters, then a loop would dsplay array elements 0~15, then 1~16 etc and also track when the array ended to fll the rest of the lne wth characters startng agan from array element zero.

  8. JRMN says:

    Thanks for the suggeston John, I’ll gve that a try.

  9. Mitchell says:

    H Tronxstuff.

    Ive been followng ths tutoral, ts fantastc. Thankyou.

    One Queston….
    My LCD doesnt exactly match the pnout you have gven. I can match all the pns ok except one. On the LCD data sheet I have

    Pn1= VSS, Ground, 0v
    Pn2= V0, Input voltage for LCD, “–”
    Pn3 = VDD, Supply votage for logc, 5v

    Pn2 s confusng me as t says ‘nput voltage’ but then says ‘–‘ n the column where the other two have 0v and 5v.

    What should I do wth t?

    Data sheet-


    • John Boxall says:

      What an odd LCD unt. Accordng to max ratngs on page 4, you can feed t between 0 and supply voltage. So try 5V, as you would already have 5V for pn 3.

  10. Rich Carthew says:

    H John,

    Once agan, thanks for a well thought through tutoral!

    Quck queston wth the LqudCrystal lcd constructor – Is t possble to pass n analog A1 & A2 pns [set as pnMode(A1, OUTPUT) etc n vod setup] n place of dgtal 5 and 6?
    E.g. LqudCrystal lcd(12, 8, 7, A2, A1, 4); I’d lke to free up dgtal 5 and 6 for PWM use, don’t wsh to use the 4094 & have all the other dgtal pns n use. (ATmega 328)

    Any hnts/code apprecated-
    Cheers and thanks!

    • John Boxall says:

      Theoretcally yes, but I haven’t tred t so cannot be sure. However a lot easer method would be to use an I2C-nterface LCD, then you are only usng A4/5 and 5V/GND. Adafrut sell an 2c LCD backpack (http://www.adafrut.com/products/292) whch solves the problem neatly.

      • Rich Carthew says:

        Thanks John,
        I hadn’t seen those backpack unts before – nterestng soluton and not too bad a $10 a pop. I dd try to code the analog pns to do the dgtal connecton pror to postng, however wthout much success. If I do fnd out anythng nterestng, I’ll reply agan here for others beneft.


  11. Rich Carthew says:

    H John.
    OK got t workng va a hnt from ludr on Arduno Forum- thought to post t here n case anyone else fnds t useful.

    For anyone else wantng to use an analog pn or two nstead of dgtal pns here’s a summary:
    Begnnng wth a tested and workng LCD module set up n the standard way:
    1. Change (and pass n as arguments) the analog pn numbers you want as ther respectve dgtal pn numbers n the lcd functon at the top of the sketch e.g. LqudCrystal lcd(12, 8, 7, 16, 15, 4) where 16 = analog A2 & 15 = analog A1 respectvely.
    2. Ensure you rewre correctly once you make the change! (I had the two from the LCD crossed over n error on A1 & A2 nstead of the other way as determned by the numbers n 1 (long day),
    3. Set ther pnMode’s as OUTPUT e.g. pnMode(15, OUTPUT); would be for Analog 1 == can use pnMode(A1, OUTPUT); as equvalent.

    []sde note: There s no need to dgtalWrte HIGH any analog pns used for ths partcular example (just n case t occurs for you to do so, as there s menton of dong that n some sectons on usng analog pns as dgtal outputs when readng about Arduno. dgtalWrte(pn#, HIGH) would be to turn an LED or somethng on (va a resstor n seres) etc.


  12. Nuno says:

    have a glcd k0108 and a arduno mega, conect all the wres and make upload of ks0180 and the lcd don´t do anythng on seral montor showm me ths Seral ntalzed
    GLCD Lb Confguraton: glcd ver: 3 glcd_Devce ver: 1 gText ver: 1
    Panel Confguraton:ks0108
    Pn Confguraton:ks0108-Mega
    GLCD:ks0108 DsplayWdth:128 DsplayHeght:64
    Chps:2 ChpWdth:64 ChpHeght:64
    CSEL1:33(PIN_C4) CSEL2:34(PIN_C3)
    RW:35(PIN_C2) DI:36(PIN_C1) EN:37(PIN_C0)
    D0:22(PIN_A0) D1:23(PIN_A1) D2:24(PIN_A2) D3:25(PIN_A3)
    D4:26(PIN_A4) D5:27(PIN_A5) D6:28(PIN_A6) D7:29(PIN_A7)
    Delays: tDDR:320 tAS:140 tDSW:200 tWH:450 tWL:450
    ChpSelects: CHIP0:(33,0×1, 34,0×0) CHIP1:(33,0×0, 34,0×1)
    Data mode: byte
    Dag Loop: 1
    Intalzng GLCD

    please help

  13. Rich Carthew says:

    I had the same ssue Nuno, wth exactly the same readout.

    As John ndcates, perhaps double check your wrng s correct- and also that the connectons are actually good- that was my problem- I had t hooked up on a breadboard correctly, but one of my hookup wres was faulty when I tested them all for contnuty.

  14. Mr. Sharkey says:

    Thanks so much for these excellent tutorals, I’ve learned so much more here than anywhere else.

    Regardng parallel LCD’s, I am nterested n expermentng wth 8-bt mode, but am unable to fnd any code examples that wll allow me to ntalse the dsplay n ths manner. Can you pont me at some tps and trcks for usng 8-bt mode? Everyone seems to be phobc about usng up the addtonal four pns, but I have a few to spare and would lke to see f there are any advantages to t over 4-bt.

    Thanks, and please keep makng us smarter, one tutoral at a tme!

  15. Mr. Sharkey says:

    A follow-up report on 8-bt mode:

    Although the dsplay doesn’t refresh any faster that I can see, t s more stable. Under 4-bt mode, I was seeng the ndvdual pxels blnk on and off n a scrollng pattern when the contrast was set very low (Vo controlled by a PWM pn on the Arduno) or when vewng the dsplay from an odd angle above. Now that blnkyness s gone. I’m well satsfed, and the use of the addtonal pns doesn’t affect my project n the least.

  16. sudip says:

    controllng each pxel was great, t make good graphcs
    thanks, learnng sth new.

  17. Runes says:

    I’m havng an ssue wth a KS0108B panel, n that adjustments to the pot make no dfference to the screen, t’s always blank. I’m usng a 10k pot, wth the slder (mddle pn) on pn 3 of the LCD, left pn of the pot to gnd, and the rght pn to pn 18 of the LCD. Any dea what I may be dong wrong?

  18. David says:


    After seeng John’s comment on Sparkfun’s LCD-00255 dsplay, I hooked one up as shown n the frst crcut dagram above. Ths put 5V to the backlght, whch apparently fred t. Only then dd I read that the max backlght voltage s 4.7 V for that dsplay. A current-lmtng resstor probably would have saved t.

    Oh well, t was worth t to learn how to use the dsplay. They’re cheap.

  19. David says:

    Update on above comment….

    The backlght on my Sparkfun LCD-00255 dsplay was NOT fred. There must be some sort of overvoltage protecton.

    A dfferent dsplay (a Mcrotvty IM161) came wth a 1N4004 dode wth nstructons to use t to drop the voltage for the backlght. The 1N4004 has a forward voltage drop of 0.8V, brngng the backlght voltage down to 4.2V. I tred the dode wth the Sparkfun dsplay, and the backlght works. Nce.

  20. Jack says:

    Thanks for your turtoral,t helps me a lot.

  21. Rain says:

    Hello John!
    I fnd your tutoral very nformatve, lke seeng lght at the end of a tunnel. :)
    However, have a few clarfcatons, whch s really helpful for a school project.
    1. want the text generaton to be actvated by a button. lke, once press the button, the text wll be shown.
    2. want a random number to be ncluded as well, for example, “you are (random number from 0 to 70) years old”.
    what knd of modfcatons n the code should do?

    • John Boxall says:

      It s not a modfcaton, you need to wrte your own sketch. Revew the frst few chapters as well as the LCD chapter and you wll learn the knowledge to do what you want.

  22. Adrian Lopez says:

    Concernng the KS0108B parallel nterface:

    You have one leg of the potentometer connected to pn 18 (VEE), another leg connected to ground, and the center pn connected to pn 3 (A0) of the KS0108B. The KS0108B’s datasheet, on the other hand, shows one leg of the potentometer connected to +5V, another connected to pn 18 (VEE), and the potentometer’s center pn agan connected to pn 3 (A0). Why dd you set t up the way you dd?

    Also, why do you have 5V for the LCD’s backlght when the datasheet says 4.2V?

    I’m new to electroncs, so forgve me f my questons appear nave.

    • John Boxall says:

      If usng the Sparkfun model as demonstrated t works as descrbed. Furthermore ths model has a 5V backlght. If usng LCDs from other sources you may need to modfy thngs.

      • Adrian Lopez says:

        I’m lookng at the SparkFun model of the LCD (sku LCD-00710). It’s the same datasheet as the one you lnked to above, wth 4.2V for the backlght (see page 3) and the contrast potentometer connected to +5V nstead of ground (see page 9). I’m tryng to understand the dscrepancy: Does the wrng work ether way or am I not readng the datasheet correctly?

      • John Boxall says:

        OK I bult t up agan usng my nstructons and t worked. Ether the screens are 5V tolerant or Sparkfun have changed the specfcaton snce I wrote the artcle (January 2011). If you are unsure use a resstor to drop the voltage to 4.2V.

      • Adrian Lopez says:

        Thank you. I’ll try followng the datasheet as best I can, as I suspect t may ndeed be a dfferent revson. Ths mght explan not only the backlght voltage dfferences, but also the dfferences n the wrng of the contrast potentometer (per SparkFun’s clam that the latest module “ncludes the negatve voltage crcutry on board.”).

  23. johnmach says:

    H John,

    Thanks a lot for your great and clearly tutoral about LCD Crystal. I’m tryng to make a module usng HEF 4094 n the mddle of Arduno and LCD. I see that n your tutoral, there’s a problem about the tmng when usng 4094 IC.

    I googled by myself and fnd an nterestng forum post on how to fx ths problem.
    Here’s the forum post: http://arduno.cc/forum/ndex.php?topc=115987.0
    And here’s the lbrary: https://btbucket.org/fmalpartda/new-lqudcrystal/downloads

    The problem caused by the lbrary n Arduno SDK. Ths lbrary has optmzed some code to boost the dsplay performance up.

    Hope people wll read ths comment and don’t worry about usng shft regster IC to drve LCD crystal (lke me).

    (from http://machtudong.vn)

  24. Rick says:

    I Really love these tutorals, s challengng and I learn. I thnk my queston has been answered above but want to verfy as these 2×16 LCD dsplays are expensve. I have a Topway LMB162ABC. It appears that the Backlght s 4.9 v f I read the spec correctly. Want to very that a 1n4001 wll work as f I understand t wll drop the 5v nput to 4.2 v for the backlght. I appolgze n advance f my post s trval.

    • John Boxall says:

      H Rck, thanks for your feedback. The dode wll gve you a 0.7V voltage drop.

      • Rick says:

        I was able to get the tutoral done and am qute pleased and wll try some other parts of the examples. Found out that the backlght on my Topway LMB162abc wll work just fne wth the 3.3v pn from the Arduno Uno. Dd have ssue wth black boxes on the second lne of the dsplay at frst, found that my solder job for the male 16 pn header was not good on three pns. Hope you have more tutorals planned, I would love to see a do t yourself WF from scratch.

      • John Boxall says:

        Nce to hear you’re enjoyng t. DIY WF? No hope :)

  25. Emmanuel says:

    sr how about wth a password wth keypad?

  26. Valmond says:

    H John,

    Just wanted to let you know that your tutorals are very well wrtten and very helpful. Ths tutoral got me up and runnng wth an LCD(24×2, no back lght)I scavenged from a dead Northern Telecom/Merdan offce telephone. Made n Australa no less! None of the other lbrares I tred seem to work, but I got yours to work frst tme out. For some reason, the program hangs up once uploaded, leavng a dsplay of strange dentcal characters. But once press the reset button, everythng works smoothly. I thnk t’s tmes to run through all your Arduno tutorals from the begnnng.

    (From New Brunswck, Canada)


Leave a Reply

Subscribe via email

Receive notifications of new posts by email.

The Arduino Book

Arduino Workshop

Für unsere deutschen Freunde

Dla naszych polskich przyjaciół ...

Australian Electronics!

Buy and support Silicon Chip - Australia's only Electronics Magazine.

Use of our content…

%d bloggers like this: