Learn LCD Arduino-V1-B PDF
Learn LCD Arduino-V1-B PDF
A Comprehensive Guide on LCD interfacing to Arduino Board with different code examples.
1 http://www.handsontec.com
Table of Contents
2 http://www.handsontec.com
6.2: LCD Connection where Pin 1 on LCD is far left .............................................................................................. 43
6.3: Wiring up the RTC Module: ............................................................................................................................. 44
6.4: Checking It Works ........................................................................................................................................... 45
6.5: Setting the Time in the RTC............................................................................................................................. 45
6.6: Uploading the Time Sketch ............................................................................................................................. 47
7. Appendix ................................................................................................................................................................ 49
7.1: LCD Application Manual .................................................................................................................................. 49
7.2: HandsOn Technology Products Quality Commitments .................................................................................. 49
3 http://www.handsontec.com
Solution1:Setting Up the LCD
1.1: Parts You’ll Need for This Chapter:
Arduino Uno
USB cable (A to B for Uno)
Speaker
Pushbuttons (n2)
Small DC fan
16x2 character LCD
4.7kΩ resistors (n2)
10kΩ resistors (n2)
150Ω resistor
10kΩ potentiometer
TC74A0-5.0VAT I2C temperature sensor
Jumper wires
Breadboard
In this chapter, you learn how to connect an LCD to your Arduino, and you learn how to use the
ArduinoLiquidCrystal library to write text and arbitrary custom characters to your LCD. After you have
the basics down, you add some components to make a simple thermostat capable of obtaining local
temperature data, reporting it to you, and controlling a fan to compensate for heat. An LCD will give you
live information, a speaker will alert you when the temperature is getting too hot, and the fan will turn on
to automatically cool you down.
To complete the examples in this chapter, we use a parallel LCD screen. These are extremely common
and come in all kinds of shapes and sizes. The most common is a 16×2 character display with a single
row of 16 pins (14 if it does not have a backlight). In this chapter, we use a 16-pin LCD display that can
show a total of 32 characters (16 columns and 2 rows).If your display didn’t come with a 16-pin header
already soldered on, you need to solder one on so that you can easily install it in your breadboard. With
the header successfully soldered on, your LCD should look like the one shown in Figure 1-1, and you can
insert it into your breadboard. Refer to Figure 1-2 board layout for complete pins assignment.
4 http://www.handsontec.com
Fig1.2: Figure 1.2 Board layout and pins of the Arduino Uno
Next, you wire up your LCD to a breadboard and to your Arduino. All of these parallel LCD modules
have the same pin-out and can be wired in one of two modes: 4-pin or 8-pin mode. You can accomplish
everything you might want to do using just 4 pins for communication; that’s how you’ll wire it up. There
are also pins for enabling the display, setting the display to command mode or character mode, and for
setting it to read/write mode. Table 1-1 describes all of these pins.
5 http://www.handsontec.com
Here’s a breakdown of the pin connections:
• The contrast adjustment pin changes how dark the display is. It connects to the center pin of a
potentiometer.
• The register selection pin sets the LCD to command or character mode, so it knows how to
interpret the next set of data that is transmitted via the data lines. Based on the state of this pin,
data sent to the LCD is either interpreted as a command (for example, move the cursor) or
characters (for example, the letter a).
• The RW pin is always tied to ground in this implementation, meaning that you are only writing to
the display and never reading from it.
• The EN pin is used to tell the LCD when data is ready.
• Data pins 4~7 are used for actually transmitting data, and data pins 0~3 are left unconnected.
• You can illuminate the backlight by connecting the anode pin to 5V and the cathode pin to ground
if you are using an LCD with a built-in resistor for the backlight. If you are not, you must put a
current-limiting resistor in-line with the anode or cathode pin. The datasheet for your device will
generally tell you if you need to do this.
We can connect the communication pins of the LCD to any I/O pins on the Arduino. In this chapter, they
are connected as shown in Table 1-2.
Reference the wiring diagram shown in Figure 1-3 and hook up your LCD accordingly.
6 http://www.handsontec.com
Figure 1-3: LCD wired to breadboard and Arduino
Now your LCD is ready for action! Once you get the code loaded in the next section, you can start
displaying text on the screen. The potentiometer will adjust the contrast between the text and the
background color of the screen.
The Arduino IDE includes the LiquidCrystal library, a set of functions that makes it very easy to interface
with the parallel LCD that you are using. The LiquidCrystal library has an impressive amount of
functionality, including blinking the cursor, automatically scrolling text, creating custom characters, and
changing the direction of text printing. This chapter does not cover every function, but instead gives you
the tools you need to understand to interface with the display using the most important functions. You can
find descriptions of the library functions and examples illustrating their use on the Arduino website:
https://www.arduino.cc/en/Reference/LiquidCrystal
7 http://www.handsontec.com
1.3: Adding Text to the Display
In this first example, we add some text and an incrementing number to the display. This exercise
demonstrates how to initialize the display, how to write text, and how to move the cursor. First, include
the LiquidCrystal library:
#include <LiquidCrystal.h>
The arguments for the LCD initialization represent the Arduino pins connected to RS, EN, D4, D5, D6,
and D7, in that order. In the setup, you call the library’s begin() function to set up the LCD display with
thecharacter size.
(The one we are using is a 16×2 display, but you might be using another size, such as a 20×4). The
arguments for this command represent the number of columns and the number of rows, respectively:
lcd.begin(16, 2);
After doing that, you can call the library’s print() and setCursor()commands to print text to a given
location on the display. For example, if you want to print your name on the second line, you issue these
commands:
lcd.setCursor(0, 1);
lcd.print(“Mr.Arduino Uno”);
The positions on the screen are indexed starting with (0,0) in the top-left position. The first argument of
setCursor() specifies which column number, and the second specifies which row number. By default, the
starting location is (0,0). So, if you call print() without first changing the cursor location, the text
starts in the top-left corner.
WARNING: The library does not check for strings that are too long. So, if you try to print a string
starting at position 0 that is longer than the number of characters in the row you are addressing, you
might notice strange behavior. Make sure to check that whatever you are printing will fit on the display!
Using this knowledge, we can now write a simple program that displays some text on the first row and
that prints a counter that increments once every second on the second row. Listing 3-1 shows the
complete program to accomplish this. Load it on to your Arduino and confirm that it works as expected.
If you don’t see anything, adjust the contrast with the potentiometer.
There are more ways of connecting the LCD Module to Arduino. In above example, we implemented the
simplest of allversions. It requires the minimum amount of cables. However, there are four types intotal:
Having access to the RW pin will allow us to read from the monitor, which is notreally useful as we are
the ones who also write on it. Usually, this pin is justconnected to GND to make it stay in receive mode.
8 http://www.handsontec.com
Using all eight data lines is notnecessary but is twice as fast as only using four.There are also some I2C-
based LCD displays that only require the two I2C pins. Ifwe are tight on pins, that is the solution.
/*
void setup()
{
//Set up the LCD's number of columns and rows:
lcd.begin(16,2);
void loop()
{
//Move cursor to second line, first position
lcd.setCursor(0,1);
//Print Current Time
lcd.print(time);
//Wait 1 second
delay(1000);
//Increment the time
time++;
}
This program combines all the steps that you learned about earlier. The library is first included at the top
of the program. A time variable is initialized to 0, so that it can be incremented once per second during
theloop(). A LiquidCrysal object called lcd is created with the proper pins assigned based on the circuit
we’ve already wired up. In the setup, the LCD is configured as having 16 columns and 2 rows, by calling
lcd.begin(16,2). Because the first line never changes, it can be written in the setup. This is accomplished
with a call to lcd.print(). Note that the cursor position does not need to be set first, because we want the
text to be printed to position (0,0), which is already the default starting location. In the loop, the cursor is
always set back to position (0,1) so that the number we print every second overwrites the previous
number. The display updates once per second with the incremented timevalue.
What if we want to display information that cannot be expressed using normal text? Maybe we want to
add a Greek letter, a degree sign, or some progress bars. Thankfully, the LiquidCrystal library supports
the definition of custom characters that can be written to the display. In the next example, we use this
9 http://www.handsontec.com
capability to make an animated progress bar that scrolls across the display. After that, we take advantage
of custom characters to add a degree sign when measuring and displaying temperature.
Creating a custom character is pretty straightforward. If we take a close look at the LCD, you’ll see that
each character block is actually made up of a 5×8 grid of pixels. To create a custom character, we simply
have to define the value of each of these pixels and send that information to the display. To try this out,
we make a series of characters that will fill the second row of the display with an animated progress bar.
Because each character space is 5 pixels wide, there will be a total of five custom characters: one with
one column filled, one with two columns filled, and so on.
At the top of our sketch where we want to use the custom characters, create a byte array with 1s
representing pixels that will be turned on and with 0s representing pixels that will be turned off. The byte
array representing the character that fills the first column (or the first 20% of the character) looks like
this:
byte p20[8] = {
B10000,
B10000,
B10000,
B10000,
B10000,
B10000,
B10000,
B10000,
};
We chose to call this byte array p20, to represent that it is filling 20 percent of one character block (the p
stands for percent). In the setup() function, call the createChar() function to assign our byte array to a
custom character ID. Custom character IDs start at 0 and go up to 7, sowe can have a total of eight custom
characters. To map the 20% character byte array to custom character 0, type the following within our
setup() function:
lcd.createChar(0, p20);
When we’re ready to write a custom character to the display, place the cursor in the right location and use
the library’s write() function with the ID number:
lcd.write((byte)0);
In the preceding line, (byte) casts, or changes, the 0 to a byte value. This is necessary only when writing
character ID 0 directly (without a variable that is defined to 0), to prevent the Arduino compiler from
throwing an error caused by the variable type being ambiguous. Try removing the “byte cast” and observe
the error that the Arduino IDE displays. We can write other character IDs without it, like this:
lcd.write(1);
Putting this all together, we can add the rest of the characters and put two nested for() loops in our
program loop to handle updating the progress bar.
The completed code looks like the code shown in Listing 1-2.
10 http://www.handsontec.com
Listing 1-2: LCD Progressing Bar-graph
/*==========================================================================
11 http://www.handsontec.com
B11111,
B11111,
B11111,
B11111,
};
void setup()
{
//Set up the LCDs number of columns and rows:
lcd.begin(16,2);
void loop()
{
//Move cursor to second line
lcd.setCursor(0,1);
//Clear the line each time it reaches the end
//with 16 " " (spaces)
lcd.print(" ");
At the beginning of each pass through the loop, the 16-character-long string of spaces is written to the
display, clearing the progress bar before it starts again. The outer for() loop iterates through all 16
positions. At each character position, the inner for() loop keeps the cursor there and writes an
incrementing progress bar custom character to that location. The byte cast is not required here because the
ID 0 is defined by the j variable in the for() loop.
When successfully complied and load into Arduino board, the LCD display will look similar as shown in
Figure 1-4.
12 http://www.handsontec.com
Figure 1-4: Display running the Listing 1.2 code.
Now, let’s make this display a bit more useful. To do so, we add the temperature sensor.The display
shows the temperature and the current fan state.When it gets too hot, the speaker makes a noise to alert
you, and the fan turnson. When it gets sufficiently cool again, the fan turns off. Using two pushbuttonsand
the de-bounce code,weadd the ability to increment or decrementhe desired temperature.
A low-power DC fan hooked directly to a 5V I/O pin will suffice to show that it spins when it should. It
will be accelerating slowly enough that you don’t need to worry too much about inductive spikes. The
two buttons have one side connected to power; the other side is connectedto ground through 10kΩ pull-
down resistors and to the Arduino.The speaker is connected to an I/O pin through a 150Ω resistor and to
ground.The frequency of the sound will be set in the program.
Placing it in front of the LCD’s contrast potentiometer allows us to conservesome breadboard space and
to fit everything onto the same half-size breadboardthatwe’ve been using so far. The diagram in Figure 2-
1 shows thecomplete wiring setup with everything you need to create this project. Thesymbol for the
TC74 temperature sensor has been made partially transparentso that you can see the potentiometer behind
it.
13 http://www.handsontec.com
Figure 2-1: LCD thermostat system
Having some parameters in place before hand makes writing information to the LCD screen easier. First,
use degrees Celsius for the display, and second, assume that we’ll always be showing two digits for the
temperature. Once the software is running, the LCD display will look something like Figure 2.2.
The "Current:" and "Set:" strings are static; they can be written to thescreen once at the beginning and left
there. Similarly, because the temperaturesare assumed to be two digits, we can statically place both "°C"
strings into thecorrect locations. The current reading will be displayed in position (8,0) andwill be
updated on every run through the loop(). The desired, or set, temperaturewill be placed in position (8,1)
14 http://www.handsontec.com
and updated every time a button is usedto adjust its value. The fan indicator in the lower right of the
display will be atposition (15,1). It should update to reflect the fan’s state every time it changes.
The degree symbol, fan off indicator, and fan on indicator are not part of theLCD character set. Before
using them in our sketch, we need to create them astype arrays at the beginning of our program, as shown
in the following snippet.
Writing these characters will be done in setup(). Move the cursor to the rightlocations, and with the LCD
library’s write() and print() functions, updatethe screen, as shown in the following snippet.
15 http://www.handsontec.com
lcd.print("C");
lcd.setCursor(15,1);
lcd.write(1);
You also update the fan indicator and temperature values each time throughloop(). You need to move the
cursor to the right location each time before you update these characters.
We used a debounce() function for key press. One button will increase the set point, and theother will
decrease it. We need to define variables for holding the previous and current button states:
booleandebounce(booleanlast,int pin)
{
boolean current =digitalRead(pin);
if(last != current)
{
delay(5);
current=digitalRead(pin);
}
return current;
}
In loop(), we want to check both buttons using the debounce()function,change the set_temp variable as
needed, and update the set value that is displayedon the LCD:
16 http://www.handsontec.com
The preceding code snippet first runs the debounce() function for each button,and then adjusts the set
temperature variable if one of the buttons has beenpressed. Afterward, the temperature displayed on the
LCD is updated, as arethe button state variables.
In this section, we add code to control the fan and the speaker. Although theLCD showing us live
information is nice, we’ll often find it useful to havean additional form of feedback to tell us when
something is happening. Forexample, the speaker beeps when the fan turns on. In this example,
weusetone() paired with delay() and a notone() command. We could instead add aduration argument to
tone() to determine the duration of the sound. Wewantto make sure that the tone plays only one time so
(and does not beep foreverwhen above the set temperature).
Using a state variable, we can detect when the speaker has beeped and thuskeep it from beeping again
until after the temperature dips below the set temperatureand resets the state variable.When the fan turns
on, an indicator changes on the LCD (represented by the custom character we defined at the top of the
program). The following codesnippet checks the temperature and controls the speaker, the fan indicator
onthe LCD, and the fan:
if(c >=set_temp)
{
//So that the speaker will only beep one time...
if(!one_time)
{
tone(SPEAKER,400);
delay(500);
one_time= true;
}
//Turn off the speaker if it's done
else
{
noTone(SPEAKER);
}
//Turn the fan on and update display
digitalWrite(FAN, HIGH);
lcd.setCursor(15,1);
lcd.write(2);
}
//It't not to hot!
else
{
//Make sure the speaker is off, reset the “one beep” variable
//Update the fan state, and LCD display
noTone(SPEAKER);
one_time= false;
digitalWrite(FAN, LOW);
lcd.setCursor(15,1);
lcd.write(1);
}
}
17 http://www.handsontec.com
The one_time variable is used to make sure that the beep plays only one timeinstead of continuously.
Once the speaker has beeped for 500ms at 400Hz, thevariable is set to true and is reset to false only when
the temperature dropsback below the desired temperature.
It’s time to bring all the parts together into a cohesive whole. We need to makesure that you include the
appropriate libraries, define the pins, and initializethe state variables at the top of the sketch. Listing 2-1
shows the complete program.Load it on to Arduino and observe the result.
/*==========================================================================
// Author : Handson Technology
// Project : Arduino Uno
// Description : Building Thermostat with LCD
// LiquidCrystal Library
// Download the complete source code: LCD_Thermostat
//==========================================================================
*/
18 http://www.handsontec.com
B00100,
B00100,
B11111,
B00100,
B00100,
B00100,
B00000,
};
//Pin Connections
constint SPEAKER =8;
constint DOWN_BUTTON =9;
constint UP_BUTTON =10;
constint FAN =11;
void setup()
{
pinMode(FAN, OUTPUT);
19 http://www.handsontec.com
}
return current;
}
void loop()
{
//Get the Temperature
Wire.beginTransmission(TEMP_ADDR);//Start talking
Wire.write(0);//Ask for register zero
Wire.endTransmission();//Complete transmission
Wire.requestFrom(TEMP_ADDR,1);//Request 1 byte
while(Wire.available()==0);//Wait for response
int c =Wire.read();//Get the temp in C
lcd.setCursor(8,0);//Move the cursor
lcd.print(c);//Print this new value
20 http://www.handsontec.com
digitalWrite(FAN, LOW);
lcd.setCursor(15,1);
lcd.write(1);
}
}
We no longer need to have the Arduino and components tethered to thecomputer to see what the
temperature is. If you like, you can plug in a batteryor wall power supply and place it anywhere in your
room.
Pairing an Arduino with an LCD is a great way to display text feedback and add menu-browsing
capabilities to our project. So how exactly does one send text toan LCD?In the Arduino and other
computer programming languages, text is thought of asa sequence of characters. For example, if we were
to put together the four characters “T, e, x, t“we would make the word Text. In this way, all text is
represented in code asan array of characters.
There are two main ways to create our text in code (or, more generally, to createany sequence of
characters). One way is to use the String data type, and the other isto use a null-terminated array of type
char. If that makes complete sense to us, great!If not, don’t worry; it’s much simpler than it sounds. Let’s
take a look and see what thefuss is all about.
As previously mentioned, all text in our code will actually be an array of characters.For more control, a
container class called the String class was created, which enables us to manipulate this array of characters
in many complex ways. Wecancompare two Strings against each other to see if they’re the same, search a
String of text for a substring, and append characters to the end of a String or even concatenate multiple
Strings. Table 3.1 provides an overview of the various functions that can beperformed on a String
variable. As you can see, the String class is extremely powerfuland can be useful for preparing text on our
character display.
Function Description
charAt() Accesses a particular character of a String
compareTo(String two) Tests if two Strings are equal, or if one comes beforeor after the other
concat(String two) Combines two Strings into one new String
endsWith(String two) Tests whether a String ends with the charsof another
equals(String two) Performs case-sensitive comparison of twoStrings’ equality
equalsIgnoreCase(String two) Performs non-case-sensitive comparison of twoStrings’ equality
getBytes(char [ ], int length) Copies a String’s characters to the supplied buffer
indexOf(val) Locates a character or String within another String
indexOf(val, int index) starting from the front (val can be a char or String)
length() Returns the length of the String in characters
replace(String one, String two) Replaces all instances of a character or substring with another
21 http://www.handsontec.com
setCharAt(int index, char c) Sets or changes a particular character of a String
startsWith(String s) Returns a Boolean (true/false) indicating whether aString starts
withthe characters of another String
substring(int start) Returns a substring of a String
toCharArray(char [ ], intlength) Copies a String’s characters to the supplied array
Both of these lines will create a String called s, the first from a constant string ofcharacters, and the
second from an integer number (defaults to base 10).The String functions outlined in table 7.1 provide
many utilities. For example, tocombine these two lines,
String third would now be “Hello World”. But as is often the case, this added functionalityof the String
class comes at the price of memory, and because memory canbe precious on the Arduino, we may want to
bypass the String type and use the morelightweight array of type char directly.
NOTE: You may have noticed that up until now we’ve been referring to Strings with a capital S; for char
strings, we’ll use a lowercase s.
There are many ways to represent a string as a char array, as you can see in table 3.2.Character strings
normally end with a null character (ASCII code 0), which ensuresthat Arduino functions such as
Serial.print() know exactly where the end of thestring is. This is why the arrays two[5] and three[5] in
table 3.2 are five characterslong, even though text is technically only four characters long; the Arduino
compiler automatically inserts the extra null character at the end. One last important reminder:constant
strings are always declared inside double-quotes, whereas single chars aredeclared in single-quotes. See
table 3.2 for examples.
22 http://www.handsontec.com
char six[10] = "text"; Initializes the array with extra space for a larger string
At this point, we’ve hopefully demystified the differences between the String typeand the array of char
type strings that we’ll encounter when working with the Arduinoand LCDs. Next we’ll look at wiring up
our first LCD, so without further ado,please welcome the Hitachi HD44780.
The Hitachi HD44780 is one of the most common LCD controller chips designed forembedded systems
and microcontrollers. The chip supports many shapes and sizesof displays, and in this example, we’ll use
one to drive a 16 x 2 LCD (2 rows, 16 characterslong).The pervasiveness of the Hitachi HD44780
controller (and other similar LCD chips)is great news for us, because they can usually be purchased
cheaply or salvaged fromyour old machines. Some are even pretty fancy, offering single and multicolor
(RGB)backlighting.Backlit LCDs have lights (LEDs) embedded in the screen, which can be turned onto
make the screen glow. This isn’t only great for low-lit situations, but also for visualfeedback. For
example, an LCD such as the Hitachi HD44780 that has an RGB backlightcan light the screen with
different colors, reporting the status of your Arduino. Youmight turn the screen red to let the user know
something is wrong, or green to signalthat things are OK.
Hitachi HD44780-based LCDs come in many different configurations, but there are two ways in which
we can interface with the Hitachi HD44780 LCD: 4-bit and 8-bit. Themain trade-off between the 4-bit
and 8-bit configurations is the number of pins neededon the Arduino versus speed of execution.Because
it’s a parallel LCD, the simplest means of communication would be tosend the full byte (8-bits) of data all
at once (in a 1-byte message). To do this wouldrequire at least 10 I/O pins on the Arduino. In contrast, the
4-bit mode requires just 6I/O pins and splits the byte into two 4-bit nibbles. This saves pins but takes a
littlemore time (two messages versus one message). The 4-bit mode is still “parallel” in the sense that we
receive 4 bits at a time, but it’s split into two messages that are sent oneafter another.
Luckily for us, working with LCDs based on the Hitachi HD44780 chipset (or other similarchipsets) is a
breeze. One of the standard librariespreinstalled in the Arduino IDE is the LiquidCrystal LCD library. It’s
compatible withboth 4-bit and 8-bit configurations and provides us with many useful functions for
controlling our LCD.Table 3.3 details the functions available in theLiquidCrystal library.
23 http://www.handsontec.com
display() Turns the display on and restores text if turned off bynoDisplay()
noDisplay() Turns off the display, saving current text
scrollDisplayLeft() Scrolls text one space to the left
scrollDisplayRight() Scrolls text one space to the right
autoscroll() Automatically scrolls text, pushing previous character oneposition to the
left or right
noAutoscroll() Disables autoscrolling
leftToRight() Sets the direction of text being displayed
rightToLeft() Sets the direction of text being displayed
createChar(intnum, byte[] Defines a custom 5 x 8 character
charData)
Now that we have a good understanding of how the Hitachi HD44780 communicateson both the hardware
and software level, we’re ready to start connecting everything. For this, we’re going to need the following
components:
NOTE:In figure 3.1, the backlight LED+ (if present) is connected to 5V on theArduino via a 68-ohm
current-limiting resistor. This value may differ andshould be calculated based on the specification of your
screen backlight.There are many tutorials and online calculators to help you determine theoptimal value
for your screen.
To save our precious I/O pins for other sensors and devices, we can connecteverything in 4-bit
mode.TheLiquidCrystal library automatically takes care of the logic required to communicate in 4-bit
mode, so there’s no difference in terms of coding. Our completed wiring will look similar to figure 3-1.If
possible, the first thing we should do is look up the data sheet for our particularLCD module. This is
useful foridentifying the pin layout of our LCD if the layout isn’talready silk-screened onto the LCD
circuit board itself. If there isn’t a printed label onyour board, or a sticker with the model number, and
you purchased the LCD from anonline hobby store, check the retailer’s website because they often
provide links to thedata sheets. If you salvaged your LCD from an old printer or other machine, and
youcan’t find any information about the pin layout, be careful. Most 16-pin Hitachi77480-compatible
LCDs will follow a similar pin layout, but incorrectly wiring up theLCD can damage both the LCD and
your Arduino.
24 http://www.handsontec.com
Figure 3.1: The connections between a Hitachi HD44780-based LCD display and the Arduino
As per the circuit diagram in figure 3.1, first connect the Vss pin to GND. The nextpin, Vcc, supplies
power to the LCD and should be connected to +5V on the Arduino (or 3.3V depending on your LCD).
Next, we’ll want to connect the V0 pin on the LCDto the wiper (middle leg) of a 10k linear
potentiometer. Connect the left leg to +5Vand the right to GND. This is used to set the contrast of your
LCD, and you may preferto use a trimpot if the contrast is something you want to set and forget.
NOTE Ground and power rails have been created using the vertical columnslabelled “+” and “-”.Now
that power and contrast are all set, we can move on to your communicationlines. Connect the Register
Select (RS) pin on the LCD to Arduino digital pin 12.This RS pin is used to control where in the LCD’s
internal memory the Arduino will write the current character. Next, wire the Enable (E) pin to Arduino
digital pin 11.Enable is what actually allows writing to those registers. Read/Write (RW) can beconnected
directly to GND or to Arduino digital pin 10 (optional). Tying RW to digitalpin 10 instead of ground
gives you the added functionality of being able to sendinformation back from the LCD if you so choose.
If you don’t wish to read from theLCD (which you won’t in most cases), save yourself the digital pin and
connect RWdirectly to ground.
25 http://www.handsontec.com
Figure 3.2 Power and contrast wiring for the Hitachi HD44780 parallel LCD
Since we’re running in 4-bit mode, the next four pins on the LCD (DB0–DB3)don’t need to be connected.
That brings us to LCD bits DB4–DB7: DB4 should be connectedtoArduino digital pin 5, DB5 to digital
pin 4, DB6 to digital pin 3, and DB7 todigital pin 2. If your LCD has a backlight, now would be the time
to connect the backlightLED+ to +5V on the Arduino through a series resistor (see the earlier note), and
the LED- to GND on your Arduino.
Voilà! We’re now ready to test our first sketch and communicate with your LCD. If you want to triple
check your connections, please refer to table 3.4.
Table 3.4 The required circuit connections between the Hitachi HD44780 LCD and the Arduino
26 http://www.handsontec.com
Now that everything is wired up, let’s print something to the screen. Open up theArduino IDE and
carefully copy the code from the following listing into your emptysketch (or simply run the provided
sketch).
#include <LiquidCrystal.h>
LiquidCrystallcd(12,11,5,4,3,2);
void setup(){
lcd.begin(16,2);
lcd.print("Arduino in");
lcd.setCursor(0,1);
lcd.print("Action Rocks!");
}
First, we must include the LiquidCrystal library header file to tell Arduino that we wish to use the
LiquidCrystal library. Next, we create an instance of the Liquid-Crystal class, lcd, and pass in the
Arduino pins to which our LCD is connected. The number of arguments we pass in to the constructor
automatically configures thelcd object to run in 4-bit or 8-bit mode.
In our setup routine, configure the size of our screen, and then print sometext to the LCD. Because the
text we want to print is longer than one row, we print the first half, then go to the second line using the
setCursormethodandthen print the second half of the text.
Connect the USB cable to your Arduino and verify that the sketch compiles. Make sureyour board and
serial port are selected in the Tools menu, and click the Upload icon.Shortly after the sketch completes,
your LCD should display the words “ArduinoinAction Rocks!” (It should look similar to the image in
figure 7.3.).Exciting! If you don’t see anything displayed on the screen, or if the text is too dim, turn the
potentiometerwired to V0 to adjust the contrast of the screen.Seeing text on your LCD for the first time is
always very exciting, especially whenthe display is giving you useful information.
Now that you’ve tackled displaying statictext in your first LCD project.
27 http://www.handsontec.com
Figure 3.3: Completing the wiring for the Hitachi HD44780 parallel LCD
The LCD-Keypad Shield attaches to your Arduino board to provide a 16-character by 2-line display,
white character, blue back light LCD with a keypad consisting of 5 keys > “select”, “up”, “right”, “down”
and “left”. With this shield you will be able to move through menus and make selections straight from
one board attached to your Arduino without requiring a massive tower of shields or wiring tangling
around. The LCD-Keypad Shield works perfectly in 4-bit mode with the “LiquidCrystal” library found in
the Arduino IDE, using this library will allow you to control the LCD with only 6 digital I/O lines. This
shield provides you with the capability of pushing multiple buttons at once and combining the results. No
longer will you be restrained to only 5 inputs, now you have the ability to make use of 32 different button
combinations!
This LCD Keypad Shield use total of 6-pins to control the LCD display which is pin-4, 5, 6, 7, 8, 9. For
LCD Data, it use pin-4, 5, 6, 7, while for the RS and Enable pin, it use pin-8 and 9. The Arduino-LCD
Keypad Shield is only required to plug into the Arduino main board and there was no soldering are
required such as shown in figure below.
28 http://www.handsontec.com
4.2: Pins Assignment
Arduino Pin Function
4 LCD DB4
5 LCD DB5
6 LCD DB6
7 LCD DB7
9 LCD Enable, En
The below code listing demonstrate the use of this LCD+Keypad shield.
//==========================================================================
// Author : Handson Technology
// Project : Arduino Uno
// Description : Display "Hello World" and 6-keys press
// Source-Code :Key_press.ino
29 http://www.handsontec.com
//==========================================================================
//Include the LiquidCrystal header file which is inside the Arduino IDE
#include <LiquidCrystal.h>
// Set the I/O pin for LCD 4-bit mode following the library assignment:
// LiquidCrystal(rs, en, d4, d5, d6, d7).
LiquidCrystal lcd(8,9,4,5,6,7);
/*******************************************************************************
* PRIVATE FUNCTION: setup()
* PARAMETERS:void
* RETURN:void
* DESCRIPTIONS:
* Define of I/O pin as Input or Output
*
*******************************************************************************/
void setup ()
{
lcd.begin(16,2);// set the lcd type: 16-character by 2-lines
lcd.clear();// LCD screen clear
lcd.print(" HandsOn Tech ");// Send the ASCII code to the LCD for
// displaying the message
30 http://www.handsontec.com
lcd.setCursor(0,1);
lcd.print("Pls press any");
adc_key_old = analogRead(analogPin);// store the unpress key value
}
/*******************************************************************************
* PRIVATE FUNCTION: loop()
* PARAMETERS: void
* RETURN: void
* DESCRIPTIONS:
* Non-Stop looping
*******************************************************************************/
void loop()
{
adc_key_in = analogRead(analogPin);// Read the value at analogPin A0 and store
// the value in the adc_key_in register
adc_key_in = get_key(adc_key_in);// Send the adc_key_in value to
// get_key() subroutine.
lcd.setCursor(0,1);
lcd.print(msgs[adc_key_in]);// Display message with msgs[]
// according to adc_key_in value
}
/*******************************************************************************
* PRIVATE FUNCTION: get_key
* PARAMETERS: integer
* RETURN:unsigned int input
* DESCRIPTIONS:
* convert the ADC value to number between 0 to 4
*******************************************************************************/
int get_key(unsignedint input)
{
int k;
return k;
}
31 http://www.handsontec.com
Fig 4.1: Display with code Listing4.1: LCD+Keypad Sketch running.
Once the code is successfully compiled and upload into Arduino board, you should see the display as
above shown. The code is self explanatory with the detail comments. Compile and upload the code into
Arduino board and watch the result.
You want to control the position of text displayed on the LCD screen; for example, todisplay values in
specific positions.
This sketch displays a countdown from 9 to 0. It then displays a sequence of digits inthree columns of
four characters. Change numRows and numCols to match the rows andcolumns in your LCD:
32 http://www.handsontec.com
constintnumRows=2;
constintnumCols=16;
int count;
void setup()
{
lcd.begin(numCols,numRows);
void loop()
{
intcolumnWidth=4;//spacing for the columns
intdisplayColumns=3;//how many columns of numbers
lcd.clear();
Discussion:
The lcd.print( ) functions are similar to Serial.print( ). In addition, the LCD library hascommands that
control the cursor location (the row and column where text will beprinted).
The lcd.print( )statement displays each new character after the previous one. Text printedbeyond the end
of a line may not be displayed or may be displayed on another line.Thelcd.setCursor() command enables
you to specify where the next lcd.print( )willstart. You specify the column and row position (the top-left
corner is 0,0). Once thecursor is positioned, the next lcd.print( )will start from that point, and it will
overwriteexisting text. The sketch in this recipe’s Solution uses this to print numbers in fixedlocations.
lcd.setCursor(12,0) ensures that each number is printed in the same position, thethirteenth column, first
row, producing the digit shown at a fixed position, rather thaneach number being displayed after the
previous number.
33 http://www.handsontec.com
Note: Rows and columns start from zero, so setCursor(4,0) would set thecursor to the fifth column on the
first row. This is because there are fivecharacters located in positions 0 through 4. If that is not clear, it
mayhelp you if you count this out on your fingers starting from zero.
The following lines use setCursor( ) to space out the start of each column to
providecolumnwidthspacesfrom the start of the previous column:
lcd.clear( ) clears the screen and moves the cursor back to the top-left corner.
To adjust how many numbers are displayed in a row to fit the LCD, calculate thedisplayColumns value
rather than setting it.
Change:
intdisplayColumns = 3;
to:
Fig 5.1: Display with code Listing 5.1: Formatting Text running
34 http://www.handsontec.com
5.2: Displaying Special Symbols
You want to display special symbols: ° (degrees), ¢, ÷, π (pi), or any other symbol storedin the LCD
character memory.
Identify the character code you want to display by locating the symbol in the characterpattern table in the
LCD data sheet. This sketch prints some common symbols insetup( ). It then shows all displayable
symbols in loop( ):
/*==========================================================================
// Author : Handson Technology
// Project : Arduino Uno
// Description : Displaying Special Symbols
// LiquidCrystal Library
// Source Code : special_symbols.ino
//==========================================================================
*/
#include <LiquidCrystal.h>
//set constants for number of rows and columns to match your LCD
constintnumRows=2;
constintnumCols=16;
int col;
int row;
void setup()
{
lcd.begin(numRows,numCols);
showSymbol(degreeSymbol,"degrees");
showSymbol(piSymbol,"pi");
showSymbol(centsSymbol,"cents");
showSymbol(sqrtSymbol,"sqrt");
showSymbol(omegaSymbol,"ohms");
lcd.clear();
}
void loop()
{
lcd.print(charCode);
calculatePosition();
35 http://www.handsontec.com
if(charCode==255)
{
// finished all characters so wait another few seconds and start over
delay(2000);
lcd.clear();
row= col =0;
charCode=32;
}
charCode=charCode+1;
voidcalculatePosition()
{
col= col +1;
Discussion:
A table showing the available character patterns is in the data sheet for the LCD controller chip (you can
find it on page-9 of the data sheet at http://www.handsontec.com/pdf_files/GDM2002G.pdf).To use the
table, locate the symbol you want to display. The code for that character isdetermined by combining the
binary values for the column and row for the desiredsymbol (see Figure 5-2).
36 http://www.handsontec.com
Fig 5-2: Using data sheet to derive character codes
For example, the degree symbol (°) is the third-from-last entry at the bottom row of thetable shown in
Figure 5-2. Its column indicates the upper four bits are 1101 and itsrow indicates the lower four bits are
1111. Combining these gives the code for thissymbol: B11011111. You can use this binary value or
convert this to its hex value(0xDF) or decimal value (223). Note that Figure 5-2shows only 4 of the 16
actualrows in the data sheet.The LCD screen can also show any of the displayable ASCII characters by
using theASCII value in lcd.print( ).The sketch uses a function named showSymbol to print the symbol
and its description:
37 http://www.handsontec.com
5.3: Creating Custom Characters
You want to define and display characters or symbols (glyphs) that you have created.The symbols you
want are not predefined in the LCD character memory. Uploading the following code will create an
animation of a face, switching between smiling and frowning:
#include <LiquidCrystal.h>
LiquidCrystallcd(8,9,4,5,6,7);
byte happy[8]=
{
B00000,
B10001,
B00000,
B00000,
B10001,
B01110,
B00000,
B00000
};
bytesaddy[8]=
{
B00000,
B10001,
B00000,
B00000,
B01110,
B10001,
B00000,
B00000
};
void setup(){
lcd.createChar(0, happy);
lcd.createChar(1,saddy);
lcd.begin(16,2);
// Turn on LCD backlight
pinMode(10, OUTPUT);// sets backlight pin-10 as PWM output
analogWrite(10,125);// Set backlight to 50% brightness
}
void loop(){
for(inti=0;i<2;i++)
{
lcd.setCursor(0,0);
lcd.write(i);
delay(1000);
}
}
38 http://www.handsontec.com
Discussion
The LiquidCrystal library enables you to create up to eight custom characters, whichcan be printed as
character codes 0 through 8. Each character on the screen is drawnon a grid of 5×8 pixels. To define a
character, you need to create an array of eight bytes.Each byte defines one of the rows in the character.
When written as a binary number,the“1” indicates a pixel is “On”, “0” is “Off” (any values after the fifth
bit are ignored). The sketchexample creates two characters, named happy and saddy (see Figure 5-4).
The following line in setup creates the character using data defined in the happy arraythat is assigned to
character 0:
lcd.createChar(0, happy);
To print the custom character to the screen you would use this line:
lcd.write(0);
Note the difference between writing a character with or without anapostrophe. The following will print a
zero, not the happy symbol:
Code in the for loop switches between character 0 and character 1 to produce ananimation.
You want to combine two or more custom characters to print symbols larger than asingle character; for
example, double-height numbers on the screen.The following sketch writes double-height numbers using
custom characters:
39 http://www.handsontec.com
// Source Code : double_height.ino
//==========================================================================
*/
#include <LiquidCrystal.h>
LiquidCrystallcd(8,9,4,5,6,7);
byte glyphs[5][8]={
{ B11111,B11111,B00000,B00000,B00000,B00000,B00000,B00000},
{ B00000,B00000,B00000,B00000,B00000,B00000,B11111,B11111},
{ B11111,B11111,B00000,B00000,B00000,B00000,B11111,B11111},
{ B11111,B11111,B11111,B11111,B11111,B11111,B11111,B11111},
{ B00000,B00000,B00000,B00000,B00000,B01110,B01110,B01110}};
//arrays to index into custom characters that will comprise the big numbers
// digits 0 - 4 0 1 2 3 4 5 6 7 8 9
constcharbigDigitsTop[10][digitWidth]={3,0,3,0,3,32,2,2,3,0,2,3,3,1,3,3,2,2,3,2,2,0,0
,3,3,2,3,3,2,3};
constcharbigDigitsBot[10][digitWidth]={3,1,3,1,3,1,3,1,1,1,1,3,32,32,3,1,1,3,3,1,3,32
,32,3,3,1,3,1,1,3};
char buffer[12];// used to convert a number into a string
void setup ()
{
lcd.begin(20,4);
void loop ()
{
// now show the number of seconds since the sketch started
int number =millis()/1000;
showNumber( number,0);
delay(1000);
}
voidshowDigit(intdigit,int position)
{
lcd.setCursor(position *(digitWidth+1),0);
for(inti=0;i<digitWidth;i++){
lcd.write(bigDigitsTop[digit][i]);
}
40 http://www.handsontec.com
lcd.setCursor(position *(digitWidth+1),1);
for(inti=0;i<digitWidth;i++){
lcd.write(bigDigitsBot[digit][i]);
}
}
VoidshowNumber(intvalue,int position)
{
int index;// index to the digit being printed, 0 is the leftmost digit
itoa(value, buffer,10);// see Recipe 2.8 for more on using itoa
Discussion:
The LCD display has fixed-size characters, but you can create larger symbols by combining characters.
This solution creates five custom characters using the technique describedin5.3. These symbols (see
Figure 5-5) can be combined to createdouble-sized digits (see Figure 5-6).
The sketch displays a countdown from 9 to 0 onthe LCD using the big digits. It then displays the number
of seconds since the sketchstarted.Theglyphs array defines pixels for the five custom characters. The
array has two dimensionsgiven in the square brackets:
byte glyphs[5][8] = {
[5] is the number of glyphs and [8] is the number of rows in each glyph. Each element contains 1s and 0s
to indicate whether a pixel is on or off in that row. If you comparethe values in glyph[0] (the first glyph)
with Figure 5-2, you can see that the 1s correspond to dark pixels:
{ B11111,B11111,B00000,B00000,B00000,B00000,B00000,B00000 } ,
Each big number is built from six of these glyphs, three forming the upper half of thebig digit and three
forming the lower half. bigDigitsTop and bigDigitsBot are arraysdefining which custom glyph is used for
the top and bottom rows on the LCD screen.
41 http://www.handsontec.com
Figure 5-5: Custom characters used to form big digits
In this tutorial we’ll show you how to turn an Arduino into a clock using a 1602 LCD module, an
Arduino, a hand full of jumpers and a Real Time Clock chip/module. Great as an accessory for your desk
at home or work.
42 http://www.handsontec.com
6.1: The Components
• Arduino Uno
• 16x02 LCD Module or any HD44780 based screen works
• 1307 RTC Chip module
• Jumper
This project will use a number of jumper cables within a very small space so take your time to check and
recheck your placements so as not to produce any magic blue smoke.
Connect the LCD to the Arduino, just to check everything works as it should. Start with the red and black
power cables from the Arduino to the breadboard, and then power to the LCD screen. If your display
doesn't have a backlight, ignore pins 15 and 16 on the LCD screen (the far right connectors).
• 1 - Ground Rail
• 2 - 5v Rail
• 3 - To potentiometer
• 4 - Digital 12
• 5 - Ground Rail
• 6 - Digital 11
• 11 - Digital 5
• 12 - Digital 4
• 13 - Digital 3
• 14 - Digital 2
• 15 (Backlight) - 5V Rail
• 16 (Backlight) - Ground Rail
43 http://www.handsontec.com
The screen is based on the HD44780 chip, a very versatile chip that is used in a number of different
screen sizes, ranging from 16x1 up to 40x2. All of these will work fine, the only minor adjustment
required is to ensure everything lines up correctly within the code, but this is annotated to make it easy to
suit to your needs.
Once the screen is wired up, you can connect the RTC module. Different modules may have a different
order of pins, so check closely with your module before moving on to the next step.
• SDA - A4
• SCL - A5
• 5V/VCC - 5V Rail
• GND - Ground Rai
44 http://www.handsontec.com
6.4: Checking It Works
Before adding some power, it's best to double check the wiring, ensuring the power and ground cables are
in the right places.
Once you’re happy, connect the Arduino. You'll see a line of black boxes on the screen. If you don't, try
adjusting the potentiometer until something appears.
You should have the Arduino IDE (latest at time of writing is v1.0.5) installed on your computer. If not,
visit the Arduino website to download and install.
Within the Arduino IDE, click File > Examples >LiquidCrystal>HelloWorld. A new window full of
code will open. Click File and then Upload. In less than a minute the LCD will spring to life, showing
Hello World and counting up every second.
You'll need to tell the RTC chip the correct time. As the chip uses a battery to keep count, it can only do
this once it has a time to start counting from.
45 http://www.handsontec.com
Starting with a fresh Arduino screen, copy and paste the following code, scrolling down a little to change
the time to the current time.Listing 6-1 only run once to set the correct time or when you wish to change
the time.
/*==========================================================================
// Author : Handson Technology
// Project : Arduino Uno
// Description : DS1307 Real Time Clock RTC with LCD
// : Routine for time setting
// LiquidCrystal Library
// Source-Code :ds1307_RTC.ino
//==========================================================================
*/
#include "Wire.h"
#define DS1307_I2C_ADDRESS 0x68
bytedecToBcd(byte val)
{
return((val/10*16)+(val%10));
}
void setDateDs1307(
byte second,// 0-59
byte minute,// 0-59
byte hour,// 1-23
bytedayOfWeek,// 1-7 1=Mon, 7=Sun
bytedayOfMonth,// 1-28/29/30/31
byte month,// 1-12
byte year // 0-99
)
{
Wire.beginTransmission(DS1307_I2C_ADDRESS);
Wire.write(0);
Wire.write(decToBcd(second));
Wire.write(decToBcd(minute));
Wire.write(decToBcd(hour));
Wire.write(decToBcd(dayOfWeek));
Wire.write(decToBcd(dayOfMonth));
Wire.write(decToBcd(month));
Wire.write(decToBcd(year));
Wire.endTransmission();
}
void setup()
{
byte second, minute, hour,dayOfWeek,dayOfMonth, month, year;
Wire.begin();
pinMode(13, OUTPUT);
// Change these values to what you want to set your clock to.
// It is best to add 30 seconds to a minute to allow time for your
// computer to compile and upload the current time.
// Only run this script once, as running it again will
// overwrite the time set in the RTC chip!
// Hours are in 24 hour format
// Day of week starts with Monday = 1 up to Sunday = 7
// Year is in YY format, so only use the last 2 digits of the year
//
// Once you have run the program, the LED on pin 13 will flash
// to say it has finished, DO NOT UNPLUG OR RESET.
46 http://www.handsontec.com
// Simply follow the tutorial and upload the LCD code
// to avoid overwriting the correct time with this time again.
//
second=0;
minute=36;
hour=20;
dayOfWeek=6;
dayOfMonth=12;
month=12;
year=14;
setDateDs1307(second, minute, hour,dayOfWeek,dayOfMonth, month, year);
}
void loop()
{
digitalWrite(13, HIGH);// turn the LED on (HIGH is the voltage level)
delay(1000);// wait for a second
digitalWrite(13, LOW);// turn the LED off by making the voltage LOW
delay(1000);
}
The last step is the actual sketch that will run the clock. The only changes you will need to make is to set
the date to how you would normally read it. The current script shows the date as DD/MM/20YY, to
change this scroll down to the very end of the code, I have marked the 2 lines that can be changed as well
as the screen
/*==========================================================================
// Author : Handson Technology
// Project : Arduino Uno
// Description : DS1307 Real Time Clock RTC with LCD
// : Routine to display the time
// LiquidCrystal Library
// Source Code :ds1307_RTC_Display.ino
//==========================================================================
*/
#include "Wire.h"
#include <LiquidCrystal.h>
LiquidCrystallcd(8,9,4,5,6,7);
bytebcdToDec(byte val)
{
return((val/16*10)+(val%16));
}
47 http://www.handsontec.com
Wire.beginTransmission(DS1307_I2C_ADDRESS);
Wire.write(0);
Wire.endTransmission();
Wire.requestFrom(DS1307_I2C_ADDRESS,7);
*second=bcdToDec(Wire.read()&0x7f);
*minute =bcdToDec(Wire.read());
*hour =bcdToDec(Wire.read()&0x3f);
*dayOfWeek=bcdToDec(Wire.read());
*dayOfMonth=bcdToDec(Wire.read());
*month =bcdToDec(Wire.read());
*year =bcdToDec(Wire.read());
}
void setup()
{
byte second, minute, hour;
bytedayOfWeek,dayOfMonth, month, year;
Wire.begin();
void loop()
{
byte second, minute, hour;
bytedayOfWeek,dayOfMonth, month, year;
String s, m, d,mth, h;
getDateDs1307(&second,&minute,&hour,&dayOfWeek,&dayOfMonth,&month,&year);
char* days[]={"NA","Mon","Tue","Wed","Thu","Fri","Sat","Sun"};
lcd.clear();
// PREFIX THE 20 AS THE RTC CHIP ONLY USES 2 DIGITS FOR THE YEAR //
lcd.print(String(days[dayOfWeek])+" "+ d +"/"+mth+"/20"+ year);
delay(1000);// Wait 1 second
}
When you are happy with your changes, click Upload. Your screen will now display the current date and
time, even after being unplugged.
48 http://www.handsontec.com
You will have a brilliant homemade clock for your desk or bedside table that won't require setting again.
As it is made using an Arduino, and having 7 extra pins available you can add a buzzer, LEDs or buttons
to add an alarm easily.
7. Appendix
HandsOn Technology wish to be perceived as simple and affordable by our customers. However the joy
over a low price is never greater than the disappointment over poor quality products. All our parts are
original genuine parts with proper data specifications from manufacturers. This is to ensure you always
get the high quality genuine original part as stated in our products information.
49 http://www.handsontec.com
www.handsontec.com
20x4 LCD Display Module Stepper Motor Driver PWM Motor Speed Controller
Breakout Board & Integrated Circuits Discrete Parts Assembled Kits Connectors
Modules
50 http://www.handsontec.com
This page is intentional left blank.
51 http://www.handsontec.com