Tag Archives: LCD

Tutorial – PCF8574 backpacks for LCD modules and Arduino

Learn how to use inexpensive serial backpacks with character LCD modules with your Arduino.

Introduction

Using LCD modules with your Arduino is popular, however the amount of wiring requires time and patience to wire it up correctly – and also uses a lot of digital output pins. That’s why we love these serial backpack modules – they’re fitted to the back of your LCD module and allows connection to your Arduino (or other development board) with only four wires – power, GND, data and clock.

You can use this with LCD modules that have a HD44780-compatible interface with various screen sizes. For example a 16 x 2 module:

16 x 2 character LCD (white text blue background) with parallel interface from PMD Way

The backpack can also be used with 20 x 4 LCDs. The key is that your LCD must have the interface pads in a single row of sixteen, so it matches the pins on the backpack – for example:

16 x 2 character LCD (white text blue background) with parallel interface from PMD Way

Hardware Setup

Now let’s get started. First you need to solder the backpack to your LCD module. While your soldering iron is warming up, check that the backpack pins are straight and fit in the LCD module, for example:

16 x 2 character LCD (white text blue background) with parallel interface from PMD Way

Then solder in the first pin, while keeping the backpack flush with the LCD:

16 x 2 character LCD (white text blue background) with parallel interface from PMD Way

If it’s a bit crooked, you can reheat the solder and straighten it up again. Once you’re satisfied with the alignment, solder in the rest of the pins:

16 x 2 character LCD (white text blue background) with parallel interface from PMD Way

Now to keep things neat, trim off the excess header pins:

16 x 2 character LCD (white text blue background) with parallel interface from PMD Way

Once you’ve finished trimming the header pins, get four male to female jumper wires and connect the LCD module to your Arduino as shown in the following image and table. Then connect your Arduino to the computer via USB:

16 x 2 character LCD (white text blue background) with parallel interface from PMD Way
16 x 2 character LCD (white text blue background) with parallel interface from PMD Way

Software Setup

The next step is to download and install the Arduino I2C LCD library for use with the backpack. First of all, rename the “LiquidCrystal” library folder in your Arduino libraries folder. We do this just to keep it as a backup.

If you’re not sure where your library folder can be found – it’s usually in your sketchbook folder, whose location can usually be found in the Arduino IDE preferences menu:

16 x 2 character LCD (white text blue background) with parallel interface from PMD Way

Next, visit https://bitbucket.org/fmalpartida/new-liquidcrysta… and download the latest file, currently we’re using v1.2.1. Expanding the downloaded .zip file will reveal a new “LiquidCrystal” folder – copy this into your Arduino libraries folder.

Now restart the Arduino IDE if it was already running – or open it now. To test the module we have a demonstration sketch prepared, simply copy and upload the following sketch:

/* Demonstration sketch for PCF8574T I2C LCD Backpack 
Uses library from https://bitbucket.org/fmalpartida/new-liquidcrystal/downloads GNU General Public License, version 3 (GPL-3.0) */
#include <Wire.h>
#include <LCD.h>
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C	lcd(0x27,2,1,0,4,5,6,7); // 0x27 is the I2C bus address for an unmodified backpack

void setup()
{
  // activate LCD module
  lcd.begin (16,2); // for 16 x 2 LCD module
  lcd.setBacklightPin(3,POSITIVE);
  lcd.setBacklight(HIGH);
}

void loop()
{
  lcd.home (); // set cursor to 0,0
  lcd.print(" tronixlabs.com"); 
  lcd.setCursor (0,1);        // go to start of 2nd line
  lcd.print(millis());
  delay(1000);
  lcd.setBacklight(LOW);      // Backlight off
  delay(250);
  lcd.setBacklight(HIGH);     // Backlight on
  delay(1000);
}

After a few moments the LCD will be initialised and start to display our URL and the value for millis, then blink the backlight off and on.

If the text isn’t clear, or you just see white blocks – try adjusting the contrast using the potentiometer on the back of the module.

How to control the backpack in your sketch

As opposed to using the LCD module without the backpack, there’s a few extra lines of code to include in your sketches. To review these, open the example sketch mentioned earlier.

You will need the libraries as shown in lines 3, 4 and 5 – and initialise the module as shown in line 7. Note that the default I2C bus address is 0x27 – and the first parameter in the LiquidCrystal_I2C function.

Finally the three lines used in void setup() are also required to initialise the LCD. If you’re using a 20×4 LCD module, change the parameters in the lcd.begin() function.

From this point you can use all the standard LiquidCrystal functions such as lcd.setCursor() to move the cursor and lcd.write() to display text or variables as normal. The backlight can also be turned on and off with lcd.setBacklight(HIGH) or lcd.setBacklight(LOW).

You can permanently turn off the backlight by removing the physical jumper on the back of the module.

Changing the I2C bus address

If you want to use more than one module, or have another device on the I2C bus with address 0x27 then you’ll need to change the address used on the module. There are eight options to choose from, and these are selected by soldering over one or more of the following spots:

16 x 2 character LCD (white text blue background) with parallel interface from PMD Way

There are eight possible combinations, and these are described in Table 4 of the PCF8574 data sheet which can be downloaded from the NXP website. If you’re unsure about the bus address used by the module, simply connect it to your Arduino as described earlier and run the I2C scanner sketch from the Arduino playground.

This post brought to you by pmdway.com everything for makers and electronics enthusiasts, with free delivery worldwide.

To keep up to date with new posts at tronixstuff.com, please subscribe to the mailing list in the box on the right, or follow us on twitter @tronixstuff.

Arduino and KTM-S1201 LCD modules

After looking for some displays to use with another (!) clock, we came across some 12-digit numeric LCD displays. They aren’t anything flash, and don’t have a back light –  however they were very cheap. The purpose of this tutorial is to show you how they are used with an Arduino in the simplest manner possible.

Update 2019 – These displays are most likely off the market. However we’ll keep this post up for reference.

Moving forward – the modules look like OEM modules for desktop office phones from the 1990s:

topss

With a quick search on the Internet you will find a few sellers offering them for a dollar each. The modules (data sheet) use the NEC PD7225 controller IC (data sheet):

bottomss

They aren’t difficult to use, so we’ll run through set up and operation with a few examples.

Hardware setup

First you’ll need to solder some sort of connection to the module – such as 2×5 header pins. This makes it easy to wire it up to a breadboard or a ribbon cable:

headerpins

The rest of the circuitry is straight-forward. There are ten pins in two rows of five, and with the display horizontal and the pins on the right, they are numbered as such:

pins

Now make the following connections:

  • LCD pin 1 to 5V
  • LCD pin 2 to GND
  • LCD pin 3 to Arduino D4
  • LCD pin 4 to Arduino D5
  • LCD pin 5 to Arduino D6
  • LCD pin 6 to Arduino D7
  • LCD pin 7 – not connected
  • LCD pin 8 – Arduino D8
  • LCD pin 9 to the centre pin of a 10k trimpot – whose other legs connect to 5V and GND. This is used to adjust the contrast of the LCD.

The Arduino digital pins that are used can be changed – they are defined in the header file (see further on). If you were curious as to how low-current these modules are:

currentss

That’s 0.689 mA- not bad at all. Great for battery-powered operations. Now that you’ve got the module wired up, let’s get going with some demonstration sketches.

Software setup

The sketches used in this tutorial are based on work by Jeff Albertson and Robert Mech, so kudos to them – however we’ve simplified them a little to make use easier. We’ll just cover the functions required to display data on the LCD. However feel free to review the sketches and files along with the controller chip datasheet as you’ll get an idea of how the controller is driven by the Arduino.

When using the LCD module you’ll need the following header file in the same folder as your sketch.

/* Header file for Arduino and KTM-S1201 LCD module
Originally Written by Jeff Albertson Ver 1.0
Modifications and code normalisation by Robert W. Mech rob@mechsoftware.com
Modified by John Boxall 11/March/2013

These are the pins that are output on the KTM-S1201

LCD pin number
Pin 1 LcdVcc +5V dc power
pin 2 LcdVss GND
pin 3 LcdnSck Not Serial clock
pin 4 LcdSi Serial data
pin 5 LcdCnD Select Command or Data mode 
pin 6 LcdnRes Reset LCD 
pin 7 LcdnBus LCD not busy
pin 8 LcdnCs LCD not Chip select
pin 9 Pot wiper Vlc LCD Contrast Connect POT between pin 9 and GND
pin 10 NC
*/

// Here we set which LCD pins will connect to which Arduino pin
#define LcdSck 4 //Not Serial clock
#define LcdSi 5 //Serial data in
#define LcdCnD 6 //Command or Not data in
#define LcdnRes 7 //Not reset low = reset
#define LcdnBus 9// Not Busy output from LCD not used if delay(1) after LcdnCs changes
#define LcdnCs 8 //Not Chip select Low = LCD selected


// Put a delay(1) after every LcdnCs change or check LcdnBus
#define t 100
#define t1 10

// The Not Chip select pin is the only unique
// Pin on the LCD all other pins can be paralleled
// for more ktm-s1201 displays
#define _Mode 0x40
#define _USync 0x31
#define _FBlink 0x1b
#define _SBlink 0x1a
#define _NoBlink 0x18
#define _DispOn 0x11
#define _Decode 0x15
#define _NoDecode 0x14
#define _LoadPtr 0xE0
#define _SetDp 0xb8 // Set decimal point (Dp)
#define _ClearDp 0x9f // Clear decimal point (Dp)
#define _ClearDsp 0x20 // Clear display memory

// To set Dp you must be in NoDecode mode and point to character (LoadPtr)
// --- 0x01
//0x10 | | 0x02
//0x20 --- 
//0x40 | | 0x04
//0x80 --- o 0x08

#define _cet 0x31 // Celsius 
#define _ 0x0 // Space
#define _A 0x77 //
#define _B 0xF4 //
#define _C 0xE0 //
#define _D 0xE6 //
#define _E 0xF1 //
#define _F 0x71 //
#define _G 0xD5 //
#define _H 0x74 //
#define _I 0x04 //
#define _J 0x86 //
#define _K 0x70 //
#define _L 0xD0 //
#define _M 0x76 //
#define _N 0x64 //
#define _O 0xE4 //
#define _P 0x73 //
#define _Q 0xDF //
#define _R 0x60 //
#define _S 0xB5 //
#define _T 0xF0 //
#define _U 0xC4 //
#define _V 0xD6 //
#define _W 0xF6 //
#define _X 0x56 //
#define _Y 0x72 //
#define _Z 0xEB //
#define _1 0x06 //
#define _2 0xE3 //
#define _3 0xA7 //
#define _4 0x36 //
#define _5 0xB5 //
#define _6 0xF4 //
#define _7 0x07 //
#define _8 0xF7 //
#define _9 0x37 //
#define _0 0xD7 //
#define _DASH 0x20 //
#define _DEGREE 0x33 //

Then every time you open a sketch that uses the header file, it should appear in a tab next to the main sketch, for example:

headerinuse

There’s also a group of functions and lines required in your sketch. We’ll run through those now – so download the first example sketch, add the header file and upload it. Your results should be the same as the video below:

So how did that work? Take a look at the sketch you uploaded.  You need all the functions between the two lines of “////////////////////////” and also the five lines in void setup(). Then you can display a string of text or numbers using

ktmWriteString();

which was used in void loop(). You can use the digits 0~9, the alphabet (well, what you can do with 7-segments), the degrees symbol (use an asterix – “*”) and a dash (use  – “-“). So if your sketch can put together the data to display in a string, then that’s taken care of.

If you want to clear the screen, use:

ktmCommand(_ClearDsp);

Next – to individually place digits on the screen, use the function:

tmPrnNumb(n,p,d,l);

Where n is the number to be displayed (zero or a positive integer), p is the position on the LCD for the number’s  (the positions from left to right are 11 to 0…), d is the number of digits to the right of the decimal point (leave as zero if you don’t want a decimal point), and l is the number of digits being displayed for n.

When you display digits using this function you can use more than one function to compose the number to be displayed – as this function doesn’t clear the screen.

To help get your head around it, the following example sketch (download) has a variety of examples in void loop(). You can watch this example in the following video:

Conclusion

So there you have it – an incredibly inexpensive and possibly useful LCD module. Thank you to Jeff Albertson and Robert Mech for their help and original code.

This post brought to you by pmdway.com – offering everything for makers and electronics enthusiasts, with free delivery worldwide.

To keep up to date with new posts at tronixstuff.com, please subscribe to the mailing list in the box on the right, or follow us on twitter @tronixstuff.

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:

bcdtable

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:

example7p1

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:

example7p1

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).

nxpi2cbussmall

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:

ds1307small

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:

  ds1307exampleuse
 

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 0x68 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:

example7p3

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
 John Boxall - tronixstuff.com
 */

#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.

LEDborder

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.

Getting Started with Arduino! – Chapter Four

This is part of a series titled “Getting Started with Arduino!” – A tutorial on the Arduino microcontrollers. The first chapter is here, and the complete index is here.

In this chapter will be looking at getting more outputs from less pins, listening to some tunes, saying hooray to arrays, and even build a self-contained data logger.

More pins from less – sounds too good to be true, doesn’t it? No, it is true and we can learn how to do this in conjunction with a special little IC, the 74HC595 Serial In/Parallel Out 8-bit Shift Register. Let’s say hello:

74hc595

Before we get too carried away, we need to understand a little about bits, bytes and binary numbers.

A binary number can only uses zeros and ones to represent a value. Thus binary is also known as “base-2”, as it can only use two digits. Our most commonly used number types are base-10 (as it uses zero through to nine; hexadecimal is base-16 as it uses 0 to 9 and A to F). How can a binary number with only the use of two digits represent a larger number? It uses a lot of ones and zeros. Let’s examine a binary number, say 10101010. As this is a base-2 number, each digit represents 2 to the power of x, from x=0 onwards.

binary12

See how each digit of the binary number can represent a base-10 number. So the binary number above represents 85 in base-10 – the value 85 is the sum of the base-10 values. Another example – 11111111 in binary equals 255 in base 10.

binary2

Now each digit in that binary number uses one ‘bit’ of memory, and eight bits make a byte. A byte is a special amount of data, as it matches perfectly with the number of output pins that the 74HC595 chip controls. (See, this wasn’t going to be a maths lesson after all). If we use our Arduino to send a number in base-10 out through a digital pin to the ‘595, it will convert it to binary and set the matching output pins high or low.

So if you send the number 255 to the ‘595, all of the output pins will go high. If you send it 01100110, only pins 1,2,5, and 6 will go high. Now can you imagine how this gives you extra digital output pins? The numbers between 0 and 255 can represent every possible combination of outputs on the ‘595. Furthermore, each byte has a “least significant bit” and “most significant bit” – these are the left-most and right-most bits respectively.

Now to the doing part of things. Let’s look at the pinout of the 74HC595: (from NXP 74HC595 datasheet)

74hc595pinouts

Pins Q0~Q7 are the output pins that we want to control. The Q7′ pin is unused, for now. ‘595 pin 14 is the data pin, 12 is the latch pin and 11 is the clock pin. The data pin connects to a digital output pin on the Arduino. The latch pin is like a switch, when it is low the ‘595 will accept data, when it is high, the ‘595 goes deaf. The clock pin is toggled once the data has been received. So the procedure to get the data into a ‘595 is this:

1) set the latch pin low (pin 12)

2) send the byte of data to the ‘595 (pin 14)

3) toggle the clock pin (pin 11)

4) set the latch pin high (pin 12)

Pin 10 (reset) is always connected to the +5V, pin 13 (output enable) is always connected to ground.

Thankfully there is a command that has parts 2 and 3 in one; you can use digitalWrite(); to take care of the latch duties. The command shiftOut(); is the key. The syntax is:

shiftout(a,b,c,d);

where:

a = the digital output pin that connects to the ‘595 data pin (14);

b = the digital output pin that connects to the ‘595 clock pin (11);

c can be either LSBFIRST or MSBFIRST. MSBFIRST means the ‘595 will interpret the binary number from left to right; LSBFIRST will make it go right to left;

d = the actual number (0~255) that you want represented by the ‘595 in binary output pins.

So if you wanted to switch on pins 1,2,5 and 6, with the rest low, you would execute the following:

digitalWrite(latchpin, LOW);
shiftOut(datapin, clockpin, MSBFIRST,102);
digitalWrite(latchpin, HIGH);

Now, what can you do with those ‘595 output pins? More than you could imagine! Just remember the most current you can sink or source through each output pin is 35 milliamps.

For example:

  • an LED and a current-limiting resisor to earth… you could control many LEDs than normally possible with your Arduino;
  • an NPN transistor and something that draws more current like a motor or a larger lamp
  • an NPN transistor controlling a relay (remember?)

With two or more ‘595s you can control a matrix of LEDs, 7-segment displays, and more – but that will be in the coming weeks.

For now, you have a good exercise to build familiarity with the shift-register process.

Exercise 4.1

Construct a simple circuit, that counts from 0~255 and displays the number in binary using LEDs. You will require the following:

  • Your standard Arduino setup (computer, cable, Uno or compatible)
  • 8 LEDs of your choosing
  • One 74HC595 shift register
  • 8 x 560 ohm 0.25 W resistors. For use as current limiters between the LEDs and ground.
  • a breadboard and some connecting wire

The hardware is quite easy. Just remember that the anodes of the LEDs connect with the ‘595, and the cathodes connect to the resistors which connect to ground. You can use the Arduino 5V and GND.

Here is what my layout looked like:

ex4p1layoutsmall

and of course a video – I have increased the speed of mine for the sake of the demonstration.

How did you go? Here is the sketch if you need some ideas.

Next on the agenda today is another form of output – audio.

Of course you already knew that, but until now we have not looked at (or should I say, listened to) the audio features of the Arduino system. The easiest way to get some noise is to use a piezo buzzer. An example of this is on the left hand side of the image below:

soundmachine_small

These are very simple to use and can be very loud and annoying. To get buzzing, just connect their positive lead to a digital output pin, and their negative lead to ground. Then you only have to change the digital pin to HIGH when you need a buzz. For example:

// Example 4.1

void setup()
{
  pinMode(12, OUTPUT);
}

void loop()
{
  digitalWrite(12, HIGH);
  delay(500);
  digitalWrite(12, LOW);
  delay(2000);
}

You won’t be subjected to a recording of it, as thankfully (!) my camera does not record audio…

However, you will want more than a buzz. Arduino has a tone(); command, which can generate a tone with a particular frequency for a duration. The syntax is:

tone(pin, frequency, duration);

where pin is the digital output pin the speaker is connected to, frequency in Hertz, duration in milliseconds. Easy! If you omit the duration variable, the tone will be continuous, and can be stopped with notone();. Furthermore, the use of tone(); will interfere with PWM on pins 3 and 11, unless you are using an Arduino Mega.

Now, good choice for a speaker is one of those small 0.25w 8 ohm ones. My example is on the right in the photo above, taken from a musical plush toy. It has a 100 ohm resistor between the digital output pin and the speaker. Anyhow, let’s make some more annoying noise – hmm – a siren! (download)

// Example 4.2

void setup()
{
  pinMode(8, OUTPUT); // speker on pin 8
}

int del = 250; // for tone length
int lowrange = 2000; // the lowest frequency value to use
int highrange = 4000; //  the highest...

void loop()
{
  // increasing tone
  for (int a = lowrange; a<=highrange; a++)
  {
    tone (8, a, del);
  }
  // decreasing tone
  for (int a = highrange; a>=lowrange; a--)
  {
    tone (8, a, del);
  }
}

Phew! You can only take so much of that.

Array! Hooray? No… Arrays.

What is an array?

Let’s use an analogy from my old comp sci textbook. Firstly, you know what a variable is (you should by now). Think of this as an index card, with a piece of data written on it. For example, the number 8. Let’s get a few more index cards, and write one number on each one. 6, 7, 5, 3, 0, 9. So now you have seven pieces of data, or seven variables. They relate to each other in some way or another, and they could change, so we need a way to keep them together as a group for easier reference. So we put those cards in a small filing box, and we give that box a name, e.g. “Jenny”.

An array is that small filing box. It holds a series of variables of any type possible with arduino. To create an array, you need to define it like any other variable. For example, an array of 10 integers called jenny would be defined as:

int jenny[10];

And like any other variable, you can predefine the values. For example:

int jenny[10] = {0,7,3,8,6,7,5,3,0,9};

Before we get too excited, there is a limit to how much data we can store. With the Arduino Duemilanove, we have 2 kilobytes for variables. See the hardware specifications for more information on memory and so on. To use more we would need to interface with an external RAM IC… that’s for another chapter down the track.

Now to change the contents of an array is also easy, for example

jenny[3] = 12;

will change our array to

int jenny[10] = {0,7,3,12,6,7,5,3,0,9};

Oh, but that was the fourth element! Yes, true. Arrays are zero-indexed, so the first element is element zero, not one. So in the above example, jenny[4] = 6. Easy.

You can also use variables when dealing with arrays. For example:

for (int i = 0; i<10;  i++)
{
	jenny[i] = 8;
}

Will change alter our array to become

jenny[] = {8,8,8,8,8,8,8,8,8,8}

A quick way set set a lot of digital pins to output could be:

int pinnumbers [] = {2,3,4,5,6,7,8,9,10,11,12,13}

for (int i= 0; i<12; i++)
{
   pinMode(pinnumbers[i],OUTPUT);
}

Interesting… very interesting. Imagine if you had a large array, an analogue input sensor, a for loop, and a delay. You could make a data logger. In fact, let’s do that now.

Exercise 4.2

Build a temperature logger. It shall read the temperature once every period of time, for 24 hours. Once it has completed the measurements, it will display the values measured, the minimum, maximum, and average of the temperature data. You can set the time period to be of your own choosing. So let’s have a think about our algorithm. We will need 24 spaces to place our readings (hmm… an array?)

  • Loop around 24 times, feeding the temperature into the array, then waiting a period of time
  • Once the 24 loops have completed, calculate and display the results on an LCD and (if connected) a personal computer using the Arduino IDE serial monitor.

I know you can do it, this project is just the sum of previously-learned knowledge. If you need help, feel free to email me or post a comment at the end of this instalment.

To complete this exercise, you will need the following:

  • Your standard Arduino setup (computer, cable, Uno or compatible)
  • Water (you need to stay hydrated)
  • Analog Devices TMP36 temperature sensor (element-14 part number 143-8760)
  • 1 little push button
  • 1 x 10k 0.25 W resistor. For use with the button to the arduino
  • a breadboard and some connecting wire
  • one LCD display module

And off you go!

Today I decided to construct it using the Electronic Bricks for a change, and it worked out nicely. Here is a photo of my setup:

ex4p2layoutsmall

a shot of my serial output on the personal computer:

and of course the ubiquitous video. For the purposes of the demonstration there is a much smaller delay between samples…

(The video clip below may refer to itself as exercise 4.1, this is an error. It is definitely exercise 4.2)

And here is the sketch if you would like to take a peek. High resolution photos are available in flickr. Another chapter over! I’m already excited about writing the next instalment… Chapter Five.

LEDborder

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.