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:

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:


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:

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:

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)

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:

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

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

will change our array to

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:

Will change alter our array to become

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

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.

The following two tabs change content below.

John Boxall

Founder, owner and managing editor of tronixstuff.com.

19 Responses to “Getting Started with Arduino! – Chapter Four”

  1. T. Zoltan says:

    Hi!
    I’m little confused about MSB,LSB explanation at the beginning of this page. The graphics should be reversed because the explanation “most significant bit -left” and “least significant bit right” is OK!

    As far as a know the AVR a little endian,am I right?!

    Otherwise this site is GREAT!

  2. Sonny says:

    Question about “Tone”
    First a quick explanation of what I was attempting:
    I want to make a momentary switch go HIGH/Low with normal button push ( done not a problem) but than I wanted it to recognize if the button was held down for more than 2 seconds and if so, pulse HIGH/LOW until you release the button.
    I tried using “TONE” for the pulsing since it is a 50% duty cycle, but no matter what frequency I changed it to, the LED was flashing but extremely dim. Is there a way to adjust the power output of “TONE”?

    • John Boxall says:

      Hello Sonny
      Thank you for you question.
      tone() may have a 50% duty cycle, but even with a value of, say, 50, means that it will blink 50 times per second – which is generally too fast for the eye to discern between on and off. analogWrite() on a digital PWM isn’t useful either, as the frequency is around 500 Hz from memory. You will have to alter your sketch to either manually set the LED high and low whilst reading the button that is being held down, or perhaps use two LEDs, one normal for the first button press stage, then a flashing LED to kick in when the button is held down.
      cheers
      john

  3. thomas says:

    hi,
    excellent post, love your idea about the logger…
    i have a couple of questions.
    - i want to take samples of temperature every half an hour (period=1800000). if i set my array to 24 values, i can log for 12 hours, correct? what happens after 12 hours?
    my device will run for about 10 consecutive days, is there a need to reset the array?
    - i want my device to log, but display the values at the press of a button. i may press the button, before the 12 hours, that means that the calculation of the average cant be /24, correct? i use a variable “count” to count the samples taken and divide the sum by that.
    - lastly, because i monitor humidity as well, i need 2 arrays[24], for temp and hum.
    i cant understand if the 2k memory on the ATmega328 is enough.

    thank u in advance (from Greece) and,
    great work with the tutorials…
    keep it up…

    • John Boxall says:

      Hello
      Thank you for your comments and question. You would be much better off writing your log data to an EEPROM such as the 24LC256 described in chapter 21 of the tutorials. One or two of those would be plenty of space for your data. Furthermore, I recommend using a real-time clock IC to track your duration, doing so will be much more accurate. For example, the DS1307 described in chapters seven and twenty,
      Cheers
      john

  4. dario says:

    Hi john, i’ve got my arduinno board (Uno) and another stuff some days ago, it’s really good. Between yesterday and today i’ve been doing a led cube, with a 74hc595, and it works. You say here that the ’595 can provide 35mA per pin, but i understand that the total is 70mA. So before every led (27 leds, yes, it’s a 3x3x3 cube :-P ) i conected a resistance and a transistor, so the current the ic is giving me is just about 0.04mA, so i won’t overload the ic in the case i turn on every led.

  5. Dibakar says:

    Hey an amateur here. im having a perpetual problem with the 595 and the 7 segment display. firstly does MSBFIRST make q0 msb or q7? i tried bothways but it wouldnt work.
    and umm i havent been using resistors with my LEDs coz the ones i had to use 20 mA around. i didnt use with them with the 7 segment one also while testing it and it worked so i didnt use them with in the 595 circuit. could that be a problem? does the ic overload with 20mA?
    please doreply.

  6. Dibakar says:

    have doubts about my analog values as well as i dont know which pins u connected to q0 and so on, when i tallied with ur sketch.

  7. Brandon Landesman says:

    I’m a little confused. From all that I know you read Binary right to left 2^0 being on the right and 2^7 being on the left, but you have it setup in reverse order. What am I missing here?

  8. Brandon Landesman says:

    NM…I think I figured it out…that is where LSB and MSB comes into play…right?

  9. Hoang says:

    In the Exercise 4.1, I run your sketch without connecting latchpin to pin 12 of the 595 (the code is unchanged, i just pull out the latchpin wire)
    The circuit still works. Anyone plz explains this, i will be very thankful!

  10. Ben says:

    digitalWrite(latchpin, LOW);
    shiftOut(datapin, clockpin, MSBFIRST,102);
    digitalWrite(latchpin, HIGH);
    Hi John,
    At last, with your explanation how the 74HC595 functions, The concept has penetrated my thick skull.
    that little piece of code did the trick.
    Very relieved, I can proceed from here.

  11. Brian says:

    Hi John,
    I’m puzzled by your code here
    for (int i = 0; i<10; i++; i<10)

    Normally a for loop has three parts for(_;_;_), but your code has extra semicolons and ‘i&lt’. What does that mean?

  12. BG says:

    I got this circuit working exactly like your video with some modifications in the code. I changed LiquidCrystal lcd(10,11,12,13,14,15,16) to LCDCrystal lcd(7,8,9,10,11,12) as the Arduino Uno only goes up to pin13. I changed waitforpress(8) to
    waitforpress(2).
    Some questions: Could the waitforpress function been written earlier in the sketch?
    What is the purpose of “int period=1000″? I know 1000 means 1000mS,but how or where is it used in the program?
    Thanks for these great tutorials!

Trackbacks/Pingbacks


Leave a Reply

Receive notifications of new posts by email.

The Arduino Book

Arduino Workshop

Für unsere deutschen Freunde

Dla naszych polskich przyjaciół ...

Australian Electronics!

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

Use of our content…

%d bloggers like this: