Let’s make an Arduino LCD shield
In this short tutorial we make an Arduino LCD shield.
Updated 18/03/2013
Today we are going to make an Arduino shield with an LCD module. More often than not I have needed to use an LCD shield in one of my projects, or with the Arduino tutorials. Naturally you can buy a pre-made one, however doing your own is always fun and nice way to pass an afternoon. Before we start, let me say this: “to fail to plan is to plan to fail”. That saying is very appropriate when it comes to making your own shields.
The first step is to gather all of the parts you will need. In this case:
- an LCD module (backlit if possible, but I’m being cheap and using a non-backlit module) that is HD44780-compatible
- a 10k linear trimpot, used to adjust the LCD contrast
- a blank protoshield that matches your Arduino board
- various header pins required to solder into the shield (they should be included with your protoshield)
- plenty of paper to draw on
For example:
Next, test your parts to ensure everything works. So, draw a schematic so you have something to follow:
And then build the circuit on a solderless breadboard, so you can iron out all the hardware bugs before permanently soldering into the shield. If you have a backlit LCD, pins 15 and 16 are also used, 15 for backlight supply voltage (check your data sheet!) and 16 for backlight ground:
Once connected, test the shield with a simple sketch – for example the “HelloWorld” example in the Arduino IDE. Make sure you have the library initialization line:
LiquidCrystal lcd();
filled with the appropriate parameters. If you’re not sure about this, visit the LCD display tutorial in my Arduino tutorials.
Now to make the transition from temporary to permanent. Place your components onto the protoshield, and get a feel for how they can sit together. Whilst doing this, take into account that you will have to solder some jumper wires between the various pads and the digital pin contacts and the 5V strip at the top row, as well as the GND strip on the bottom row. You may find that you have to solder jumper wires on the bottom of the shield – that’s fine, but you need to ensure that they won’t interfere with the surface of your Arduino board as well.
Furthermore, some protoshields have extra functions already added to the board. For example, the shield I am using has two LEDs and a switch, so I will need to consider wiring them up as well – if something is there, you shouldn’t waste the opportunity to not use them.
If your shield has a solder mask on the rear, a great way to plan your wiring is to just draw them out with a whiteboard marker:
Remember to solder these wires in *before* the LCD … otherwise you will be in a whole world of pain. The LCD should be soldered in second-last, as it is the most difficult thing to desolder if you have made any mistakes. The last items to solder will be the header pins. So let’s get soldering…
After every solder joint, I pushed in the LCD module – in order to check my placement. You can never check too many times, even doing so I made a small mistake. Having a magnifying glass handy is also a great idea:
Now just to soldier on, soldering one pad at a time, then checking the joint and its relationship with where it should be on the board. Be very careful when applying solder to the pads, they can act as a “drain” and let lots of solder flow into the other side. If this happens you will spend some time trying to remove that excess solder – a solder sucker and some solder wick is useful for this.
Finally all the wires and pads were connected, and I checked the map once more. Soldering in the LCD was the easiest part – but it is always the most difficult to remove – so triple check your work before installing the display. Now it was time to sit in the header sockets, and test fit the shield into my arduino board. This is done to make sure there is sufficient space between the wires on the bottom of our shield and the top of the arduino:
Even though you wouldn’t normally put a shield on top of this shield, I used the header sockets to allow access to all of the arduino pins just in case. Soldering the sockets was easy, I used blu-tack to hold them into place. Crude but effective.
And we’re finished. Soldering is not the best of my skills, so I checked continuity between the pins on the LCD and where they were supposed to go, and also electrically checked for bridges between all the soldered pins to check for shorts. A multimeter with a continuity buzzer makes this easy. Naturally I had a short between LCD pin 14 and 13, but some solder wick helped me fix that.
So electrically it was correct… time to see if it actually worked! At this point it is a good idea to clear up the workspace, switch off the soldering iron, put it somewhere safe to cool down, then wash your hands thoroughly.
Here are some photos of the finished product on my arduino board:
As we’re using a Freetronics protoshield with onboard LEDs, the only thing to do was alter the demonstration sketch to take account for the pin placements, and insert some code to blink the LEDs. I never need an excuse to make a video clip, so here is the result:
So there you have it. With a little planning and care, you too can make your own Arduino shield. An LCD shield would be useful for everyone, as they are great for displaying data and requesting input, yet quite fiddly to use with a solderless breadboard. High resolution photos are available on flickr.
In the meanwhile have fun and keep checking into tronixstuff.com. Why not follow things on twitter, Google+, subscribe for email updates or RSS using the links on the right-hand column? And join our friendly 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.
Getting Started with Arduino! – Chapter Seven
This is part of a series titled “Getting Started with Arduino!” – A tutorial on the Arduino microcontrollers. The first chapter is here, the complete index is here.
Welcome back fellow arduidans!
This week is going to focus around the concept of real time, and how we can work with time to our advantage. (Perhaps working with time to our disadvantage is an oxymoron…) Once we have the ability to use time in our sketches, a whole new world of ideas and projects become possible. From a simple alarm clock, to complex timing automation systems, it can all be done with our Arduino and some brainpower. There is no time to waste, so let’s go!
First of all, there are a few mathematical and variable-type concepts to grasp in order to be able to understand the sketch requirements. It is a bit dry, but I will try and minimise it.
The first of these is binary-coded decimal.
Can you recall from chapter four how binary numbers worked? If not, have a look then come back. Binary coded decimal (or BCD) numbers are similar, but different… each digit is stored in a nibble of data. Remember when working with the 74HC595 shift registers, we sent bytes of data – a nibble is half of a byte. For example:
Below is a short clip of BCD in action – counting from 0 to 9 using LEDs:
However, remember each digit is one nibble, so to express larger numbers, you need more bits. For example, 12 would be 0001 0010; 256 is 0010 0101 0110, etc. Note that two BCD digits make up a byte. For example, the number 56 in BCD is 0101 0110, which is 2 x 4 bits = 1 byte.
Next, we will need to work with variables that are bytes. Like any other variable, they can be declared easily, for example:
byte seconds = B11111;
B11111 is 31 in base 10, (that is, 2^4+2^3+2^2+2^1+2^0 or 16+8+4+2+1)
However, you can equate an integer into a byte variable. Here is a small sketch demonstrating this.
And the result:
If you printed off the results of the sketch in example 7.1, it would make a good cheat sheet for the Binary Quiz program in Chapter Five.
Anyhow, moving forward we now take a look at hexadecimal numbers. ‘Hex’ numbers are base-16, in that 16 digits/characters are used to represent numbers. Can you detect a pattern with the base-x numbers? Binary numbers are base-2, as they use 0 and 1; decimal numbers are base-10, as they use 0 to 9 – and hexadecimal numbers use 0 to 9 then A to F. Run the following sketch to see how they compare with binary and decimal.
Below is a screenshot of the result: the left column is binary, the centre decimal, and the right hexadecimal.
Unfortunately the IC we use for timing uses BCD, so we need to be able to convert to and from BCD to make sense of the timing data.
So now we have an understanding of BCD, binary, base-10 decimal, bytes, hexadecimal and nibbles. What a mouthful that was!
Coffee break.
Before we head back to timing, let’s look at a new function: switch… case. Say you needed to examine a variable, and make a decision based on the value of that variable, but there were more than two possible options. You could always use multiple if…then…else if functions, but that can be hard on the eyes. That is where switch… case comes in. It is quite self-explanatory, look at this example:
switch (zz) {
case 10:
//do something when variable zz equals 10
break;
case 20:
//do something when variable zz equals 20
break;
case 30:
// do something when variable equals 30
break;
default:
// if nothing else matches, do the default
// default is optional
}
OK, we’re back. It would seem that this chapter is all numbers and what not, but we are scaffolding our learning to be able to work with an integrated circuit that deals with the time for us. There is one last thing to look at then we can get on with timing things. And that thing is…
The I2C bus.
(There are two ways one could explain this, the simple way, and the detailed way. As this is “Getting Started with Arduino”, I will use the simple method. If you would like more detailed technical information, please read this document: NXP I2C Bus.pdf, or read the detailed website by NXP here)
The I2C bus (also known as “two wire interface”) is the name of a type of interface between devices (integrated circuits) that allows them to communicate, control and share data with each other. (It was invented by Philips in the late 1970s. [Philips spun off their semiconductor division into NXP]). This interchange of data occurs serially, using only two wires (ergo two wire interface), one called SDA (serial data) and the other SCL (serial clock).
I2C bus – image from NXP documentation
A device can be a master, or a slave. In our situation, the Arduino is the master, and our time chip is the slave. Each chip on the bus has their own unique “address”, just like your home address, but in binary or in hexadecimal. You use the address in your sketch before communicating with the desired device on the I2C bus. There are many different types of devices that work with the I2C bus, from lighting controllers, analogue<> digital converters, LED drivers, the list is quite large. But the chip of interest to us, is the:
Maxim DS1307 Serial I2C real-time clock. Let’s have a look:
This amazing little chip, with only a few external components, can keep track of the time in 12-and 24-hour formats, day of week, calendar day, month and year, leap years, and the number of days in a month. Interestingly, it can also generate a square wave at 1Hz, 4kHz, 8kHz, or 32 kHz. For further technical information, here is the DS1307 data sheet.pdf. Note – the DS1307 does not work below 0 degrees Celsius/32 degrees Fahrenheit, if you need to go below freezing, use a DS1307N.
Using the DS1307 with our Arduino board is quite simple, either you can purchase a board with the chip and external circuitry ready to use, or make the circuit yourself. If you are going to do it yourself, here is the circuit diagram for you to follow: (click on image to enlarge)
The 3V battery is for backup purposes, a good example to use would be a CR2032 coin cell – however any 3V, long-life source should be fine. If you purchase a DS1307 board, check the battery voltage before using it…. my board kept forgetting the time, until I realised it shipped with a flat battery. The backup battery will not allow the chip to communicate when Vcc has dropped, it only allows the chip to keep time so it is accurate when the supply voltage is restored. Fair enough. The crystal is 32.768 kHz, and easily available. The capacitor is just a standard 0.1uF ceramic.
Now to the software, or working with the DS1307 in our sketches. To enable the I2C bus on Arduino there is the wire library which contains the functions required to communicate with devices connected to our I2C bus. The Arduino pins to use are analogue 4 (data) and analogue 5 (clock). If you are using a Mega, they are 20 (data) and 21 (clock). There are only three things that we need to accomplish: initially setting the time data to the chip; reading the time data back from the chip; and enabling that 1Hz square-wave function (very useful – if you were making an LED clock, you could have a nice blinking LED).
First of all, we need to know the I2C address for our DS1307. It is 0×68 in hexadecimal. Addresses are unique to the device type, not each individual device of the same type.
Next, the DS1307 accepts or returns the timing data in a specific order…
- seconds (always set seconds to zero, otherwise the oscillator in the DS1307 will stay off)
- minutes
- hours
- day of week (You can set this number to any value between 1 and 7, e.g. 1 is Sunday, then 2 is Monday…)
- day of month
- month
- year
- control register (optional – used to control the square-wave function frequency and logic level)
… but it only accepts and returns this data in BCD. So – we’re going to need some functions to convert decimal numbers to BCD and vice-versa (unless you want to make a BCD clock …)
However, once again in the interests of trying to keep this simple, I will present you with a boilerplate sketch, with which you can copy and paste the code into your own creations. Please examine this file. Note that this sketch also activates the 1Hz square wave, available on pin 7. Below is a quick video of this square wave on my little oscilloscope:
This week we will look at only using 24-hour time; in the near future we will examine how to use 12-hour (AM/PM) time with the DS1307.
Here is a screen capture of the serial output box:
Now that you have the ability to send this time data to the serial output box, you can send it to other devices. For example, let’s make a simple LCD clock. It is very easy to modify our example 7.3 sketch, the only thing to take into account is the available space on the LCD module. To save time I am using the Electronic Brick kit to assemble this example. Below is a short clip of our LCD clock operating:
and here is the sketch. After seeing that clock fire up and work correctly, I felt really great – I hope you did too.
Update – for more information on the DS1307 real-time clock IC, visit this page.
Now let’s head back in time, to when digital clocks were all the rage…
Exercise 7.1
Using our Arduino, DS1307 clock chip, and the exact hardware from exercise 6.2 (except for the variable resistor, no need for that) – make a nice simple digital clock. It will only need to show the hours and minutes, unless you wish to add more display hardware. Have fun!
Here is my result, in video form:
and the sketch. Just an interesting note – after you upload your sketch to set the time; comment out the line to set the time, then upload the sketch a second time. Otherwise every time your clock loses power and reboots, it will start from the time defined in the sketch!
As mentioned earlier, the DS1307 has a square-wave output that we can use for various applications. This can be used from pin 7. To control the SQW is very easy – we just set the pointer to the SQW register then a value for the frequency. This is explained in the following sketch:
/*
DS1307 Square-wave machine
Used to demonstrate the four different
square-wave outputs from Maxim DS1307
See page nine of data sheet for more information
http://tronixstuff.wordpress.com
CC by-nc-sa v3.0
*/
#include "Wire.h"
#define DS1307_I2C_ADDRESS 0x68 // each I2C object has a unique bus address, the DS1307 is 0x68
void setup()
{
Wire.begin();
}
void sqw1() // set to 1Hz
{
Wire.beginTransmission(DS1307_I2C_ADDRESS);
Wire.write(0x07); // move pointer to SQW address
Wire.write(0x10); // sends 0x10 (hex) 00010000 (binary)
Wire.endTransmission();
}
void sqw2() // set to 4.096 kHz
{
Wire.beginTransmission(DS1307_I2C_ADDRESS);
Wire.write(0x07); // move pointer to SQW address
Wire.write(0x11); // sends 0x11 (hex) 00010001 (binary)
Wire.endTransmission();
}
void sqw3() // set to 8.192 kHz
{
Wire.beginTransmission(DS1307_I2C_ADDRESS);
Wire.write(0x07); // move pointer to SQW address
Wire.write(0x12); // sends 0x12 (hex) 00010010 (binary)
Wire.endTransmission();
}
void sqw4() // set to 32.768 kHz (the crystal frequency)
{
Wire.beginTransmission(DS1307_I2C_ADDRESS);
Wire.write(0x07); // move pointer to SQW address
Wire.write(0x13); // sends 0x13 (hex) 00010011 (binary)
Wire.endTransmission();
}
void sqwOff()
// turns the SQW off
{
Wire.beginTransmission(DS1307_I2C_ADDRESS);
Wire.write(0x07); // move pointer to SQW address
Wire.write(0x00); // turns the SQW pin off
Wire.endTransmission();
}
void loop()
{
sqw1();
delay(5000);
sqw2();
delay(5000);
sqw3();
delay(5000);
sqw4();
delay(5000);
sqwOff();
delay(5000);
}
And here it is in action – we have connected a very old frequency counter to pin 7 of the DS1307:
And there we have it – another useful chapter. Now to move on to Chapter Eight.
Have fun and keep checking into tronixstuff.com. Why not follow things on twitter, Google+, 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.

















