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.
Welcome back fellow arduidans!
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!
So let’s go!
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:
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.
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.
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)
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:
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:
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
Annoying buzzer!
CC by-sa v3.0
http://tronixstuff.wordpress.com */
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
Annoying siren
CC by-sa v3.0
http://tronixstuff.wordpress.com */
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++; i<10)
{
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++; i<12)
{
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:
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.
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.











