Pages: [1] 2 3 ... 5   Go Down
Author Topic: Shift registers and LED's  (Read 7669 times)
0 Members and 1 Guest are viewing this topic.
Canberra Australia
Offline Offline
God Member
*****
Karma: 8
Posts: 504
Hardcore Arduino
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

I have been using Arduino Uno and two 74HC595 shift registers daisy chained to control 16 LED's and now I would like to have independent control of 64 LED's in an 8 x 8 matrix wired as per attached diagram 1. As I see it, from my limited knowledge, the shift register connected to the anodes via resistors and transistors would set the appropriate anode row HIGH and the second shift register connected to the cathodes would set the appropriate cathode column LOW.  I understand the basic concept of coding for a single shift register to control eight LED's in whatever order I want them to light or not, but this matrix is baffling me. I only really want to do this to further my understanding the procedure with a view to ultimately building an 8 x 8 x 8 LED cube controlled by Arduino Uno and 8 bit shift registers. If someone could give me a few clues in lay terms I would appreciate some help. Thanks for your time Pedro.

* 8 x 8 Matrix (part).doc (21.5 KB - downloaded 93 times.)
Logged


Manchester (England England)
Offline Offline
Brattain Member
*****
Karma: 509
Posts: 31472
Solder is electric glue
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Have a read of this
http://www.thebox.myzen.co.uk/Workshop/LED_Matrix.html
Logged

Canberra Australia
Offline Offline
God Member
*****
Karma: 8
Posts: 504
Hardcore Arduino
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks for that Mike. I have seen your excellent electronic tutorials etc on your site and elsewhere online but to be honest this one is above my skill level. I "somewhat" understand current syncing and sourcing to reduce the current that is actually drawn from the Arduino but was just hoping for some "simple code" to drive the shift registers I mentioned so I might start to understand how they might be used to control a matrix. However I will persist in trying to understand more of what you explain in this tutorial and thanks again for your response, Pedro.
Logged


Global Moderator
Boston area, metrowest
Offline Offline
Brattain Member
*****
Karma: 439
Posts: 23769
Author of "Arduino for Teens". Available for Design & Build services. Now with Unlimited Eagle board sizes!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Try this Pedro. Not debugged, should be pretty close.
Some might suggest burying stuff in functions, I say skip that and just let it run fast!

Code:
// code to read data from an 8 byte array and display on 8x8 LED matrix with shift registers and current limit resistors driving anodes,
// and shift register with high current drivers sinking common cathodes.
// SPI commands will be used to send the data out

// sequence: every xx milliseconds, turn off all cathodes
// set up anodes from data stored in an array
// turn on next cathode
//
// while time is passing for the next set of anodes, do other stuff
// repeat

#include <SPI.h> // bring in SPI library

byte SSanodes = 9; // output latch for anodes shift register.  Can be any pin except 10,11,12,13.
byte SScathodes = 10; // output latch for cathodes shift register.  Pin D10 needs to be an output for SPI.
byte dataArray[]= {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80};  // load up some initial data
// dataArray[0] = B00000001
// dataArray[1] = B00000010
// dataArray[2] = B00000100
// dataArray[3] = B00001000
// dataArray[4] = B00010000
// dataArray[5] = B00100000
// dataArray[6] = B01000000
// dataArray[7] = B10000000

byte cathodePins[] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80};  // used to turn on 1 cathode at a time

unsigned long timeNow = 0;  // capture time
unsigned long previousTime = 0; // store previous time
unsigned long elapsedTime = 5; // time that each column will be on

byte anodeColumn = 0;  // keep track of column being driven

void setup(){
pinMode (SSanodes, OUTPUT);
pinMode (SScathodes, OUTPUT);

SPI.begin();  // commits 11,12,13 for hardware SPI transfer. Make sure shift registers have 0.1uF/100nF on their VCC pins to ground.
}

void loop(){

timeNow = millis(); // capture the current 'time'
if ((timeNow - previousTime)>= elapsedTime){  // display refresh time?
previousTime = previousTime + elapsedTime; //setup for next pass

// keep track of which column is being written
anodeColumn = anodeColumn+1;
if (anodeColumn == 8){anodeColumn = 0;}  // reset after going 0,1,2,3,4,5,6,7 >> 0

// turn off current cathode
digitalWrite (SScathodes, LOW);
SPI.transfer(0); // 0 = all cathode off >> assumes HC595 driving base of NPN transistor or ULN2803
digitalWrite (SScathodes, HIGH);

// shift out next set of anodes
digitalWrite (SSanodes, LOW);
SPI.transfer(dataArray[anodeColumn]); // read data from the array and send it out
digitalWrite (SSanodes, HIGH);

// turn the next cathode on
digitalWrite (SScathodes, LOW);
SPI.transfer(cathodePins[anodeColumn]); // 0 = all cathode off >> assumes HC595 driving base of NPN transistor or ULN2803
digitalWrite (SScathodes, HIGH);

} // end of time check

// make sure that all compiles & runs okay. If too flickery, decrease elapsedTime. Maybe even go to micros() instead of millis();

// next, add your code to read buttons, receive serial data, whatever your method for making updates to dataArray[x]
// for example, this should move the On LED in each row across the screen every 1/2 second
/*  add variable definitions as above
// timeNow already captured at the top of void loop
if ( (timeNow - previousShiftTime)>= elapsedShiftTime){
previousShiftTime = previousShiftTime + elapsedShiftTime;
tempArray = arrayData[0];  // store column 0
arrayData[0] = arrayData[1]; // column 0 becomes column 1
arrayData[1] = arrayData[2]; // 1 becomes 2
arrayData[2] = arrayData[3];
arrayData[3] = arrayData[4];
arrayData[4] = arrayData[5];
arrayData[5] = arrayData[6];
arrayData[6] = arrayData[7];
arrayData[7] = tempArray;  // finally 7 becomes what 0 was.
}
*/
// display will show the new data at the next display update interval

} // end void loop
« Last Edit: July 19, 2012, 09:52:16 pm by CrossRoads » Logged

Designing & building electrical circuits for over 25 years. Check out the ATMega1284P based Bobuino and other '328P & '1284P creations & offerings at  www.crossroadsfencing.com/BobuinoRev17.
Arduino for Teens available at Amazon.com.

Canberra Australia
Offline Offline
God Member
*****
Karma: 8
Posts: 504
Hardcore Arduino
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks for that Crossroads, I will build that matrix and try your code out. I just wanted to make sure that using shift registers was a viable option before actually building the matrix. Thanks again Pedro
Logged


Global Moderator
Boston area, metrowest
Offline Offline
Brattain Member
*****
Karma: 439
Posts: 23769
Author of "Arduino for Teens". Available for Design & Build services. Now with Unlimited Eagle board sizes!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Wow, tried to compile that, only 2 errors!

Needed to add these to the top  of the sketch:

#include <SPI.h>
byte anodeColumn = 0;

Revised post above to include them.
Logged

Designing & building electrical circuits for over 25 years. Check out the ATMega1284P based Bobuino and other '328P & '1284P creations & offerings at  www.crossroadsfencing.com/BobuinoRev17.
Arduino for Teens available at Amazon.com.

Canberra Australia
Offline Offline
God Member
*****
Karma: 8
Posts: 504
Hardcore Arduino
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Hey you're working on this harder than I am... your making me look bad. If I draw up how I think the circuit should go, would you mind perusing it and pointing out the inevitable mistakes I know that I am going to make. Thanks Pedro.
Logged


Global Moderator
Boston area, metrowest
Offline Offline
Brattain Member
*****
Karma: 439
Posts: 23769
Author of "Arduino for Teens". Available for Design & Build services. Now with Unlimited Eagle board sizes!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

smiley

What, you mean this?
Picture it rotated 90 degrees counter-clockwise so the anodes are driven from the left and the cathodes from the bottom.


* 8x8_matrix.jpg (84.65 KB, 960x720 - viewed 164 times.)
« Last Edit: July 19, 2012, 11:19:43 pm by CrossRoads » Logged

Designing & building electrical circuits for over 25 years. Check out the ATMega1284P based Bobuino and other '328P & '1284P creations & offerings at  www.crossroadsfencing.com/BobuinoRev17.
Arduino for Teens available at Amazon.com.

Canberra Australia
Offline Offline
God Member
*****
Karma: 8
Posts: 504
Hardcore Arduino
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Good God man, you've done it... what do you walk around carrying 8 x 8 matrix circuit diagrams in your back pocket?  smiley-lol
Logged


Global Moderator
Boston area, metrowest
Offline Offline
Brattain Member
*****
Karma: 439
Posts: 23769
Author of "Arduino for Teens". Available for Design & Build services. Now with Unlimited Eagle board sizes!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

No, it had been drawn up already for an earlier discussion.
Is there a way to see the date on that file? Oct 2011 smiley-cool
Logged

Designing & building electrical circuits for over 25 years. Check out the ATMega1284P based Bobuino and other '328P & '1284P creations & offerings at  www.crossroadsfencing.com/BobuinoRev17.
Arduino for Teens available at Amazon.com.

Canberra Australia
Offline Offline
God Member
*****
Karma: 8
Posts: 504
Hardcore Arduino
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

As my knowledge of electronics is rudimentary, I am trying to understand the basic power flow in this matrix. As I see it the Arduino digital signal goes to the input of the anode shift register which applies current to the selected anode row of the  matrix. The cathode shift register which is daisy chained to the anode shift register sends it's output to the input of the ULN2803. The output of the ULN2803 goes to the cathode columns of the  matrix.
Therefore when the selected input of the  ULN2803 receives current from the corresponding output of the cathode shift register, ground is applied to the corresponding output of the cathode shift register, effectively grounding the relevant matrix cathode column and lighting the LED. I apologise for my verbose, and more than likely technically inept explanation and have attached a basic flow chart which hopefully makes sense. Is this anything close to how it might operate and be constructed ? Thanks for your time, again… Pedro.

* 8 X 8 Matrix flow chart.doc (21 KB - downloaded 26 times.)
Logged


Global Moderator
Boston area, metrowest
Offline Offline
Brattain Member
*****
Karma: 439
Posts: 23769
Author of "Arduino for Teens". Available for Design & Build services. Now with Unlimited Eagle board sizes!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

You are basically correct.

I did not daisy chain them in the code, I made the anodes seperately writeable from the cathodes.

8 bits are shifted into the cathode shift register, turning off any high outputs, which turns off any UN2803 outputs.
8 bits are shifted into the Anode shift register, can be high or low.
8 bits are shifted into cathode shift register, only one will be a 1. The ULN2803 output for that 1 goes Low, any LEDs with a high anode turned on.

By wiring SCK & MOSI to both shift registers in parallel, both shift register input stages are loaded with the same data every time. Only the shift register that gets the seperate Register Clock (SSanode or SScathode) has the data moved to the output stage to show up at the LED matrix.

Compare that to daisy chaining them, where 2 bytes must be shifted out every time, even tho the anode outputs only change 1 of those times:
cathodes off + no anode change
cathodes off + new anodes
cathode on + no anode change

vs just 1 byte
cathodes off
new anodes
cathode on

Having the cathode off before changing the anode prevents any ghosting as the display is updated.
The digitalWrite for the Register Clock will be slow part of this operation, that can be changed to direct port manipulation later to really speed it up.
One thing at a time tho ...


* 8_X_8_Matrix_flow_chart[1].docx (12.28 KB - downloaded 31 times.)
Logged

Designing & building electrical circuits for over 25 years. Check out the ATMega1284P based Bobuino and other '328P & '1284P creations & offerings at  www.crossroadsfencing.com/BobuinoRev17.
Arduino for Teens available at Amazon.com.

Canberra Australia
Offline Offline
God Member
*****
Karma: 8
Posts: 504
Hardcore Arduino
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

I am endeavouring to draw up the matrix circuit based on my limited use of 74HC595 shift registers and Crossroads invaluable help. There seems to be a few different pinouts for the components but the  ones I will be using  worked o.k. when I used them to drive eight LED's using them as in attached diagram 1.

Crossroads from what you indicated in your code and flow chart, I thought that;

Pin 9 Arduino might go to pin 12 of anodes shift register
Pin 10 Arduino might go to pin 12 of cathodes shift register

It seems that pin 8 of my shift registers are VCC ?  where you indicate 0.1uf – 100nf capacitors ?

I see from your flowchart that  Arduino pins 11, and 13 go, in parallel to the SCK and RCK pins of the two shift registers  but there seem to be a multitude of names for these pins and I am uncertain as to what pin is what on the shift registers that I am using.

Also in the eight LED matrix circuit attached, pin 13  (OE) went to ground – what about in this 8 x 8 matrix ?

I apologise for being so vague, but as stated I am a rank  but enthusiastic amatuer here. (It's been a long day…)

I have included the circuit diagram 2 of what I have drawn up so far and would appreciate some further guidance if possible.

Thanks Pedro.

p.s – I just realise that I wired up the outputs of the cathode shift register to the inputs of the ULN2803 in the reverse order



* Diagram 2.bmp (958.4 KB, 678x482 - viewed 171 times.)
« Last Edit: March 15, 2013, 06:51:14 pm by Pedro147 » Logged


Canberra Australia
Offline Offline
God Member
*****
Karma: 8
Posts: 504
Hardcore Arduino
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

For some reason Diagram 1 did not hurtle through cyber-space too... so here it comes  smiley-cool


* Diagram 1.bmp (1149.15 KB, 823x476 - viewed 121 times.)
Logged


Canberra Australia
Offline Offline
God Member
*****
Karma: 8
Posts: 504
Hardcore Arduino
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

I have been “goggling my heart out”  smiley-cool, and  am I right in suggesting that;
SCK is shift register clock input which is pin 11  SH CP of the shift register
RCK is storage register clock input  which is pin 12 ST CP of the shift register
Serial data is pin 14  DS of the shift register
So I connect;
Arduino pin 9 to  anode shift register pin 12
Arduino pin 10 to cathode shift register pin 12
Arduino pin 13 to pin 11 on both anode and cathode shift registers
Arduino pin 11 to pin 14 on both anode and cathode shift registers

If this is all correct I am still wondering about the necessity of the  ground to shift register pins 13 OE that I used in the single shift register driving eight LED’s circuit (are they required in this circuit?) and if those capacitors are in the right place on shift register pin 8 (if this is in fact pin VCC)
Also does the rest of the circuit appear to be o.k. apart from my homemade shift register and ULN2803 symbols.
Logged


Pages: [1] 2 3 ... 5   Go Up
Jump to: