Thursday 30 October 2014

ATTiny85 Tutorial 8 – Drive More Outputs With A Shift Register

So, I thought that I’d skip ahead a bit and get straight into the control of LED via a shift register. As the ATTiny85 has few pin outs, the main thing to be able to go beyond the simple binary pin to pin scheme is to get a shift register working for you.

For this tutorial, I have tried to fit all of the components onto a half+ board. Of course, I’m using my 5V regulator, so I am cheating slightly. However, the ATTiny85 and the 74HC595 both fit on the board along with the required 8 LED.

The original Arduino sketch includes the instantiation of Serial communication, that hasn’t been enabled on my ATTiny85, so I’m just commenting it out in the sketch. I am also omitting the smoothing capacitor between data and GND, if you want to include it, by all means, knock yourself out.

The shift register tutorial uses only digital pins in the original, so I am substituting like for like in the ATTiny85 platform.

The wiring is a little confusing (probably because I crammed it all into a half+ board), but there really isn’t much to it.

Lesson 08 - Drive More With A Shift Register_bb

So long as you get the connections between the ATTiny85 and the 74HC595, then it’s really just a matter of poke and play (of course, you’ll need to be careful with the Vcc and GND connections!).

ATTiny85 - Connections to Shift Register

I’ve taken the liberty of changing the sketch to something closer to what I’ll actually be using, so beware that there are some functional changes (although very few).

Onto the sketch:

/*
  Shift Register Example
  Turning on the outputs of a 74HC595 using an array.
  Modified for ATTiny85

Hardware:
* 74HC595 shift register
* ATTiny85
* LEDs attached to each of the outputs of the shift register

*/
//Pin connected to ST_CP (12) of 74HC595
int latchPin = 2;
//Pin connected to SH_CP (11) of 74HC595
int clockPin = 3;
////Pin connected to DS (14) of 74HC595
int dataPin = 0;

//holders for information you're going to pass to shifting function
byte data;
byte chaseArray[8];

void setup() {
  //set pins to output because they are addressed in the main loop
  pinMode(latchPin, OUTPUT);
//  Serial.begin(9600);

  chaseArray[0] = 1;   //00000001
  chaseArray[1] = 2;   //00000010
  chaseArray[2] = 4;   //00000100
  chaseArray[3] = 8;   //00001000
  chaseArray[4] = 16;  //00010000
  chaseArray[5] = 32;  //00100000
  chaseArray[6] = 64;  //01000000
  chaseArray[7] = 128; //10000000
 
  //function that blinks all the LEDs
  //gets passed the number of blinks and the pause time
  blinkAll_2Bytes(2, 500);
}

void loop() {

  for (int j = 0; j < 8; j++) {
    //load the light sequence you want from array
    data = chaseArray[j];
    //ground latchPin and hold low for as long as you are transmitting
    digitalWrite(latchPin, 0);
    //move 'em out
    shiftOut(dataPin, clockPin, data);
    //return the latch pin high to signal chip that it
    //no longer needs to listen for information
    digitalWrite(latchPin, 1);
    delay(60);
  }
}

 

// the heart of the program
void shiftOut(int myDataPin, int myClockPin, byte myDataOut) {
  // This shifts 8 bits out MSB first,
  //on the rising edge of the clock,
  //clock idles low

  //internal function setup
  int i=0;
  int pinState;
  pinMode(myClockPin, OUTPUT);
  pinMode(myDataPin, OUTPUT);

  //clear everything out just in case to
  //prepare shift register for bit shifting
  digitalWrite(myDataPin, 0);
  digitalWrite(myClockPin, 0);

  //for each bit in the byte myDataOut
  //NOTICE THAT WE ARE COUNTING DOWN in our for loop
  //This means that 000001 or "1" will go through such
  //that it will be pin Q0 that lights.
  for (i=7; i>=0; i--)  {
    digitalWrite(myClockPin, 0);

    //if the value passed to myDataOut and a bitmask result
    // true then... so if we are at i=6 and our value is
    // %11010100 it would the code compares it to %01000000
    // and proceeds to set pinState to 1.
    if ( myDataOut & (1<<i) ) {
      pinState= 1;
    }
    else { 
      pinState= 0;
    }

    //Sets the pin to HIGH or LOW depending on pinState
    digitalWrite(myDataPin, pinState);
    //register shifts bits on upstroke of clock pin 
    digitalWrite(myClockPin, 1);
    //zero the data pin after shift to prevent bleed through
    digitalWrite(myDataPin, 0);
  }

  //stop shifting
  digitalWrite(myClockPin, 0);
}


//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_2Bytes(int n, int d) {
  digitalWrite(latchPin, 0);
  shiftOut(dataPin, clockPin, 0);
  shiftOut(dataPin, clockPin, 0);
  digitalWrite(latchPin, 1);
  delay(200);
  for (int x = 0; x < n; x++) {
    digitalWrite(latchPin, 0);
    shiftOut(dataPin, clockPin, 255);
    shiftOut(dataPin, clockPin, 255);
    digitalWrite(latchPin, 1);
    delay(d);
    digitalWrite(latchPin, 0);
    shiftOut(dataPin, clockPin, 0);
    shiftOut(dataPin, clockPin, 0);
    digitalWrite(latchPin, 1);
    delay(d);
  }
}

Running

I thoroughly recommend that you do this tutorial on the Arduino first before attempting the ATTiny85 version, so that you know what to expect and how the connections work. Other than that, this makes a nice and tiny board project, now I need to play with laying this out on a board so that I can etch it … that should be fun.

5V Reg - Powered

Testing the ATTiny85 Shift Register Sub Board

The above video is the ATTiny85 and 75HC595 sub board connected to breadboarded LED. This is the next step on from the breadboard version in this article, but uses the same sketch and is functionally identical.

Check out the rest of the tutorials here.

No comments:

Post a Comment

Paypal Donations

Donations to help me to keep up the lunacy are greatly appreciated, but NOT mandatory.