Tag Archives: 74hc595

Remember the colours – a game

The following article is based on this entry on Newton’s blog (in Polish). All the pictures, program code and the video clip came from there.

This project’s goal was to use as many parts from the Arduino Starter Kit, as possible. So, what is this project exactly? As the title itself suggests, it’s a game, whose object is to remember a colour sequence and recreate it. At the very beginning the sequence consists of 3 colours only, hovever, the difficulty level increases – an extra colour is added each time. Every colour has a different tone assigned. This tone is emitted from a buzzer when the corresponding colour is displayed, so the game involves two senses, both sight and hearing. User interface consists of: RGB LED diode displaying the colours, 8 red LED diodes arranged in a row to display which colour in turn we are setting and two microswitch type buttons. By pushing both in the same time we are starting the game, the left button chooses the colour, the right – accepts. There are two more LED diodes, indicating whether we have recreated the sequence properly (left LED), or not (right LED).

Whole device mounted on a breadboard looks like the following:

Device mounted on a breadboard

You can see (and hear) how it works on this video clip. Hereunder is the circuit schematic made in Fritzing:

Circuit schematic

Circuit schematic

All the resistors used are 220Ω and the IC in the centre of the breadboard is 74HC595 shift register, which allows to drive eight LEDs using only three Arduino digital pins. This was described in “Shifted LEDs” article.

When everything is connected, we should take care of the code. At the beginning we must declare where we have connected what (to which input/output). The following code is responsible of it:

int latchPin = 8, clockPin = 12, dataPin = 3; //shift register
byte data = 0; //register data

int led8 = 7, led9 = 6; //additional LEDs
int ledR = 11, ledG = 10, ledB = 9; //LED RGB
int buttonLeft = 5, buttonRight = 4; //buttons
int speakerPin = 13; //buzzer

Here comes the initialization part – setting pin as input/output, turning internal pull-up resistors on and so on:

void setup()
{
  Serial.begin(57600);
  for(int i=3;i<=13;i++) // setting all the pins
    pinMode(i, OUTPUT); // from 3 to 13 as outputs
  pinMode(buttonLeft, INPUT); // setting the button pins
  pinMode(buttonRight, INPUT); // as inputs

  digitalWrite(buttonLeft, HIGH); // turning internal pull-up
  digitalWrite(buttonRight, HIGH); // resistors on
  randomSeed(analogRead(0)); // initializing the pseudorandom number generator
  // with the value read from analog input no. 0 
  // - each time it's different
  clearLeds();
}

If you are wondering what stands for such a strange notation:

 a ? b : c

here is the explanation.

The main loop of our program looks like the following:

void loop()
{
  effect();
  clearLeds();
  if(waitForButton() == 3)
    return;

  for(int j=3;j<=8;j++)
    if(!playLevel(7, j))
      return;
}

Consecutively: at the beginning, effect() function turns on visual and light effects, clearLeds turns all the LEDs off. After that, unless the user pushes both buttons at the same time, what will cause a reset, playLevel function starts successive levels of the game, increasing the second parameter (number of the lights to remember) by 1. The first parameter denotes the total number of colours (from 0 to 7). Of course, we can lower it, but then the game will become too easy. It’s better to add another colours using setColor function (changing parameters in setRGB) and upgrade it. Then, we can put the total number of colours (remember – the numeration starts from 0!) as the first parameter of playLevel function to make the game more difficult and hence – more addicting ;).

The whole program code with comments is available here. I think it’s clear enough and doesn’t require any additional explanations.

I want more digital outputs!

Arduino offers quite a few digital outputs, but sometimes you want even more… When a keypad and LCD are connected, it doesn’t remain much free outputs.

Today I found out a simple solution for that – EZ Expander shield. The shield utilises two shift registers, 74HC595 to ‘multiply’ digital outputs. Of course, the additional outputs can be used only in output mode (there is no possibility to read from them).

EZ Expander CC by http://nootropicdesign.com/ez-expander/

So, this is the shield, but if you need more outputs (LED diodes?), then you can use only EZ Expander’s library and any shift registers (74HC595 of course will fit). Just wire up the registers and send values to them with simple digitalWrite – take a look at ‘Advanced API usage’ section in the documentation. But don’t fear the ‘advanced’ :)

There is a few other interesting things at nootropic, for example Arduino-based video game system. It uses TVout – library for generating composite video on AVR chip (so, Arduino too). If you want to know, how to generate video with Arduino, check the Sprae’s blog (Arduino as a graphics card – unfortunately, only in Polish).

Shifted LEDs

The last piece of Arduino Starter Kit, which still remains undescribed is small, but powerful integrated circuit – shift register. It is 74HC595, SIPO type (Serial-In, Parallel-Out) shift register with 8 parallel outputs.

Shift register has serial input and some (usually 8) parallel outputs. What it means? With every clock impulse the output states are shifted by one position. So, logic level of the 1st output appears on the 2nd one. Content of the 1st output is changed depending on serial input content.

How can we take advantage of this?

We should consider using shift register in every place which needs many logic outputs. You can say that three pins can control many more outputs. Let’s see it on the simplest example – LED diodes.

This article is based on tutorial published on Arduino.cc, which is source of illustrations. These are depicting more than one breadboard, but I decided to use them to speed up writing this article – making a clear illustration in Fritzing is rather impossible.

Let’s begin from wiring it up:

Circuit diagram with shift register - assembled on breadboard

Circuit diagram with shift register - assembled on breadboard

Power is spreaded by rails on the breadboard. On the left board the LEDs are connected with resistors. On the right one is connected the 74HC595 itself.
Its pinout:

74HC595 pinout

74HC595 pinout

On the preceding diagram is shoved the pinout according to datasheet from manufacturer (ST Microelectronics), whose chips are in offer of Nettigo and are part of Starter Kit. On the Arduino site there is description suitable to ICs marked according to Philips nomenclature. What it means? Fortunately the only difference is signals naming (for example, outputs – in STM: QA to QH, in Philips version: Q0 to Q7), placing and functions of pins is the same. In this tutorial I will be using naming compliant with STM.

The simplest connection between Arduino and shift register looks like the following:

  • +5V power to register pin 16
  • Ground to register pin 8

If we don’t mind the fact that after turning the power on the LEDs may light in random configuration and we want to use less digital outputs, we can connect it like this:

  • G – register pin 13 to ground
  • SCLR – register pin 10 to ground

The minimal configuration to control a shift register from Arduino is (all Arduino pins are digital inputs):

  • SI – register pin 14 to Arduino pin 11
  • SCK – register pin 11 to Arduino pin 12
  • RCK – register pin 12 to Arduino pin 8

Between RCK pin and ground there should be capacitor (1 μF – not supplied with Starter Kit). A number of experiments I made prove that it isn’t necessary :)

Here is logic diagram of the connection:

Logic diagram of the connection

Logic diagram of the connection

What remains? The code:

//**************************************************************//
//  Name    : shiftOutCode, One By One                          //
//  Author  : Carlyn Maw, Tom Igoe                           //
//  Date    : 25 Oct, 2006                                      //
//  Version : 1.0                                               //
//  Notes   : Code for using a 74HC595 Shift Register           //
//          : to count from 0 to 255                            //
//****************************************************************

//Pin connected to ST_CP of 74HC595
int latchPin = 8;
//Pin connected to SH_CP of 74HC595
int clockPin = 12;
////Pin connected to DS of 74HC595
int dataPin = 11;

//holder for infromation you're going to pass to shifting function
byte data = 0; 

void setup() {
  //set pins to output because they are addressed in the main loop
  pinMode(latchPin, OUTPUT);
  pinMode(clockPin, OUTPUT);
  pinMode(dataPin, OUTPUT);

}

void loop() {

  //function that blinks all the LEDs
  //gets passed the number of blinks and the pause time
  blinkAll(1,500); 

 // light each pin one by one using a function A
  for (int j = 0; j < 8; j++) {
    lightShiftPinA(j);
    delay(1000);
  }

  blinkAll(2,500);  

 // light each pin one by one using a function A
  for (int j = 0; j < 8; j++) {
    lightShiftPinB(j);
    delay(1000);
  } 

}

//This function uses bitwise math to move the pins up
void lightShiftPinA(int p) {
  //defines a local variable
  int pin;

  //this is line uses a bitwise operator
  //shifting a bit left using << is the same
  //as multiplying the decimal number by two.
  pin = 1<< p;

  //ground latchPin and hold low for as long as you are transmitting
  digitalWrite(latchPin, LOW);
  //move 'em out
  shiftOut(dataPin, clockPin, MSBFIRST, pin);
  //return the latch pin high to signal chip that it
  //no longer needs to listen for information
  digitalWrite(latchPin, HIGH);

}

//This function uses that fact that each bit in a byte
//is 2 times greater than the one before it to
//shift the bits higher
void lightShiftPinB(int p) {
  //defines a local variable
  int pin;

  //start with the pin = 1 so that if 0 is passed to this
  //function pin 0 will light.
  pin = 1;

  for (int x = 0; x < p; x++) {
    pin = pin * 2;
  }

  //ground latchPin and hold low for as long as you are transmitting
  digitalWrite(latchPin, LOW);
  //move 'em out
  shiftOut(dataPin, clockPin, MSBFIRST, pin);
  //return the latch pin high to signal chip that it
  //no longer needs to listen for information
  digitalWrite(latchPin, HIGH);

}

//blinks the whole register based on the number of times you want to
//blink "n" and the pause between them "d"
//starts with a moment of darkness to make sure the first blink
//has its full visual effect.
void blinkAll(int n, int d) {
  digitalWrite(latchPin, LOW);
  shiftOut(dataPin, clockPin, MSBFIRST, 0);
  digitalWrite(latchPin, HIGH);
  delay(200);
  for (int x = 0; x < n; x++) {
    digitalWrite(latchPin, LOW);
    shiftOut(dataPin, clockPin, MSBFIRST, 255);
    digitalWrite(latchPin, HIGH);
    delay(d);
    digitalWrite(latchPin, LOW);
    shiftOut(dataPin, clockPin, MSBFIRST, 0);
    digitalWrite(latchPin, HIGH);
    delay(d);
  }
}

This will light all the diodes, then light every diode one by one, flash all the LEDs twice and light again using another method.

The most important informations:

  • shiftOut is a function from Arduino library, serially sending selected byte to specified output
  • we can send data to the register by setting RCK (connected to Arduino pin 8) in low state