Friday, July 26, 2013

Shift Registers

video
I bought a "Nano 3.0 for Arduino" for eight quid - a neat little thing that reminds me of the Hexbug Nanos I bought my niece and nephew for Christmas a couple of years ago, but is rather more interesting for grownups.  It fits directly into a breadboard, and is powered and programmed through a USB lead (standard "mini A" connector).


The pins are:

Top row: digital pins D12 to D2 (D2 is just above the TX LED), ground, reset, RX and TX (RX and TX are D0 and D1 on an Arduino Uno).

Bottom row: digital 13, 3.3 V, REF (analogue reference, labelled AREF on bigger boards), analogue inputs A0 to A7 (two more than on the Uno, A7 is just below the LED), 5 V, reset, ground, and input voltage (VIN).

This is almost, but not quite, the same layout as the official Arduino Nano, and considerably cheaper.  I stuck it on a breadboard with a couple of shift register chips (74HC595), and used it to control some RGB LED units.

The RGB units have three LEDs with a common anode, so controlling four of them requires twelve bits.  I've used two shift registers, so that gives sixteen bits to play with.

A diagram is below.

Things to note: the board shown in the diagram doesn't have the same pin order as mine, and my breadboard (see below) has a very different layout but the circuit is the same.  The connections from the board are: 5V pin to the top power rail (which is then linked to the lower power rail in the middle, and the bottom power rail), ground pin to the top ground rail (similarly linked to the middle and bottom), and the SPI connection to the first shift register: blue wire links D2 to the data pin on the 74HC595, green wire links D4 to the latch pin, and yellow wire links D3 to the clock pin.

The two 74HC595 chips have the clock and latch pins linked (horizontal green and yellow wires), and the serial output from the first goes to the data pin on the second (horizontal blue wire below the yellow one).  This means that when two bytes are sent into the first chip, the first byte is displaced into the second chip (you can chain these things even further - so if you had four linked chips and sent four bytes into the first one, the fourth chip would contain the first byte sent, the third chip the second byte, the second chip the third byte and the first chip the fourth byte).

I have only shown the connections for one of the LED units - the horizontal red, blue and green wires connect from pins Q3, Q2 and Q1 of the first 74HC595 to the cathodes of one of the LED units.  Pins Q7-Q5 of the first 74HC595 go to the RGB cathodes of the second unit, and the third and fourth units are connected to the same pins on the second 74HC595.  On my breadboard (see below) there are no wires making these connections - I just bridged the pins of the 74HC595 chips to the LED units with resistors (270 Ω).

I'm not using pins Q0 or Q4 on either 74HC595 - they aren't needed (and Q0 is in a slightly inconvenient position, on the other side of the chip to the other seven output pins, next to the data pin).


Code:

const int latchPin = 4;
const int clockPin = 3;
const int dataPin  = 2;

const byte red     = 0x08;
const byte green   = 0x02;
const byte blue    = 0x04;
const byte yellow  = red   | green;
const byte magenta = red   | blue;
const byte cyan    = green | blue;
const byte white   = red   | green | blue;
const byte black   = 0x00;

const byte sequence[8] = {black, red, yellow, green, 
  cyan, blue, magenta, white};

void put_four_leds(byte leds[4])
{
    byte a = leds[0] | (leds[1] << 4);
    byte b = leds[2] | (leds[3] << 4);
    
    digitalWrite(latchPin, LOW);
    // Flip bits because low is on, high is off
    // Second pair goes first because that byte is shifted
    // through to the second shift register. 
    shiftOut(dataPin, clockPin, MSBFIRST, ~b);
    shiftOut(dataPin, clockPin, MSBFIRST, ~a);
    digitalWrite(latchPin, HIGH);
}

void setup() 
{
  //set pins to output so you can control the shift register
  pinMode(latchPin, OUTPUT);
  pinMode(clockPin, OUTPUT);
  pinMode(dataPin, OUTPUT);
}

void loop() 
{
  byte led_array[4];
  int  i, j;
  
  for (i=0; i<8; i++)
  {
    for (j=0; j<4; j++)
    {
      led_array[j] = sequence[(i + j) % 8];
    }
    put_four_leds(led_array);
    delay(500);
  }
}
 
 

No comments:

Post a Comment