Is it possible to drive an led matrix from just 2 595 shift registers? I can get one axis working, but am more than a little stumped on how to get the other going...
ps, I know I can just use a max7219, but their $10 and I can get 4 595s for a dollar.
hi
you can get the 7219 usually as a sample if you only need a few.. Can be ordered through the Maxim site.
D
i've acutally just ordered my samples ;). but the project I'm working on requires multiple 8x8 displays and i'm trying to cut costs down as far as possible. If I can do it with two chips (the 595 or other shift registers) I wouldn't mind trying. any suggestions?
i think it should be possible in general, but much slower than with a 7219.
if you have your LED matrix set up, you basically have to connect the 8 anodes to your first
595 and all the cathodes to second 595.
your can be divided into rows(anodes) and columns(cathodes).
now you have to "manually" do what the 7219 automatically does for you.
activate the FIRST COLUMN(cathodes), by setting the corresponding shift register to 01111111. which means that only the first column of your LEDs is connected to ground.
Now you can turn those first 8 LEDs on by latching the ROWS' shift register. all LEDs on would mean to latch 11111111.
the problem is, that your're only able to control one column at the same time. the 7219 does this very fast, so you won't notice.
i don't know how fast you can go doing this on arduino. but i think if you are planning to use multiple matrices it will be much more safe to go with the maxims.
still i would like to know how this setup would perform.
//best, kuk
i tried this out last night, and couldn't get anything to light up at all. with just one 595 controlling the columns and stepping the leds over one at a time 1000000 01000000 00100000 etc, I can run it with no delays at all, essentially making it appear that the screen is fully lit with no flicker... just can't seem to get the rows to step correctly.
another thought I just had was to invert the bytes sent by the 595 and step through the rows with a 4017 decade counter... you don't have to use all ten steps and can loop it through hardware for only 8 steps. this would cut down on allot as I would only need one pin to pulse the 4017 to step once per loop. I won't get to try this until tomorrow, but I definitely give it a try.
hi
I don't think this is possible without driver transistors or mosfets on the rows and columns. The basic probelm is that two 74HC595's can't source and sink enough current on their output pins.
What you need:
For a matrix of 8 leds X 8 Leds, there are 64 Leds.
For all leds "on", total current = 64 leds X @15ma each = 960ma source ability, 960ma sink ability.
What you have:
With two 74HC595 chips, or 4017's or similar logic chip, you have potentially
8 pins X 20ma = 160ma X 2 chips= 320 ma maximum of sink/source switching ability
(By contrast, the 7219 has eight digit pins with 500ma digit sink each and eight segment pins with 100ma segment source each. That's almost five amps of sink/course LED switching ability.)
If you think about it, this is not going to work without external transistors or Mosfets to handle the current requirements, since
an active row or column connected to one pin in an 8X8 array would need to souce or sink potentially 120ma or more, which is well beyond the abilitiies of the 74HC595...
I guess you could do some high-speed multiplexing on the outpus so that only one led in a row was ever on at one time... then it might be possible.
Standard disclaimer: of course I could be completey wrong.
I'm getting a bit closer... tonight I wired up a 4017 and set it to loop at 8 steps. I wired the anodes of my matrix to the 4017 and all the cathodes to ground. set up a simple test code to pulse the clock pin and bingo... with no delay added, the whole matrix lit up solid (effectively multiplexing the rows) with no visible flicker (flicker is barely visible with a 3ms delay added but any more starts to get rough on the eyes) ;). so here's what I'm trying next... the 4017 will serve as my row driver and the 595 will work the columns. this should add very little code as all I need to do is pulse the clock pin of the 4017 after writing each byte to the 595. this way I'm only writing one byte per loop to the 595 too. I will however report that the LEDs are a bit dimmer than they should be, but the lack of current also removes the need for the obligatory resistors in the circuit :).
Success! Using the 4017 to multiplex the rows and the 595 to drive the columns.... it works great! the leds are a bit dim at high speed, but I'm working on that next ;). Basically each row displays an inverted byte and it can do it so fast that there is no visible flicker at all. good stuff. I'll post some schems in a few days when I work all the bugs out... this is a great $1 alternative to the $10 7219 and may end up being easier to control too! :o
Cool. I'm looking forward to seeing how you did it.
actually... there's not much to tell now. I've switched back to using two 595s for two reasons. 1): the 4017 did not put out enough current to evenly light the display while plexing at high speed. 2): the 4017 would not reliably start on "step one". the logic can start off with garbage left over from the last time you ran it so the image might not be centered... a more controlled method was needed.
the whole process is almost identical to the 595 tutorial 2.3 "dual defined arrays". the only real difference is the bytes used and the delay was removed entirely. if you wire the first 595 to the cathodes of the matrix and the second 595 in the chain to the anodes through current limiting resisters and use the code below, you'll get a little space invader on your display. using two 595s the display is bright and even.
it works by using one 595 to bring the rows low one at a time while writing bytes to the collumns. this literally goes so fast, you can't see any flicker even if you shake the display (this usually gives away multiplexing on things like LED clocks). The best part is I didn't even use the shown capacitor (laziness, your milage may vary) so the whole thing is 2 595s and 8 resisters. all and all about 60 cents minus the display.
I'd be happy to take some pics or something if someone wants to see it running... I'd like to further develop this code though to make it more dynamic.
cheers,
byte dataPin = 2; // 74HC595 pin 14
byte latchPin = 3; // 74HC595 pin 12
byte clockPin = 4; // 74HC595 pin 11
byte data; // storage for the current data byte
byte dataArray[8]; // define the data array
byte row; // storrage for the current row byte
byte rowArray[8]; // define the row array
void setup()
{
pinMode(latchPin, OUTPUT); //pinmode setup
// column registers for image data.
dataArray[0] = 0x18; // 00011000
dataArray[1] = 0x3C; // 00111100
dataArray[2] = 0x7E; // 01111110
dataArray[3] = 0xDB; // 11011011
dataArray[4] = 0xFF; // 11111111
dataArray[5] = 0x24; // 00100100
dataArray[6] = 0x5A; // 01011010
dataArray[7] = 0xA5; // 10100101
// row registers... DO NOT CHANGE THESE!
rowArray[0] = 0xFE; // 11111110
rowArray[1] = 0xFD; // 11111101
rowArray[2] = 0xFB; // 11111011
rowArray[3] = 0xF7; // 11110111
rowArray[4] = 0xEF; // 11101111
rowArray[5] = 0xDF; // 11011111
rowArray[6] = 0xBF; // 10111111
rowArray[7] = 0x7F; // 01111111
}
void loop()
{
for(int j = 0; j < 8; j++){ // load the byte...
data = dataArray[j]; // from the data array...
row = rowArray[j]; // and the row array
digitalWrite(latchPin, LOW); // ground the latch pin
shiftOut(dataPin, clockPin, data); // shift out the data
shiftOut(dataPin, clockPin, row); // shift out the row byte
digitalWrite(latchPin, HIGH); // it's finished so bring the latch pin high
}
}
// this is all explained int the tutorial
void shiftOut(int myDataPin, int myClockPin, byte myDataOut)
{
int i = 0;
int pinState;
pinMode(myClockPin, OUTPUT);
pinMode(myDataPin, OUTPUT);
digitalWrite(myDataPin, LOW);
digitalWrite(myClockPin, LOW);
for( i = 7; i >= 0; i--){
digitalWrite(myClockPin, LOW);
if(myDataOut & (1 << i)){
pinState = HIGH;
}
else{
pinState = LOW;
}
digitalWrite(myDataPin, pinState);
digitalWrite(myClockPin, HIGH);
digitalWrite(myDataPin, LOW);
}
digitalWrite(myClockPin, LOW);
}
Cool. It seems so simple, which is nice. BTW, which version of the Arduino software are you using? Arduino 0007 has a built-in shiftOut() function; do you know if your code will work with that one?
I'm actually using Wiring at the moment :-[. however I've been planning the switch for a while now... I like my Wiring board and all, but this community seems to be progressing a bit quicker.
I'll need to pick up an Arduino board now just to test the shiftOut() function... that would cut down on the code even further! I see no reason why it shouldn't work, but can't wait to test it out
Cool. It seems so simple, which is nice. BTW, which version of the Arduino software are you using? Arduino 0007 has a built-in shiftOut() function; do you know if your code will work with that one?
Mellis, apparently I've been on the moon this month and didn't notice the shiftOut function is in wiring too now. I've tested the code and it works like a charm. I'll be posting some pictures of everything on Friday. the new code is:
byte dataPin = 0; // 74HC595 pin 14
byte latchPin = 1; // 74HC595 pin 12
byte clockPin = 2; // 74HC595 pin 11
byte data; // storage for the current data byte
byte dataArray[8]; // define the data array
byte row; // storrage for the current row byte
byte rowArray[8]; // define the row array
void setup()
{
pinMode(dataPin, OUTPUT); //pinmode setup
pinMode(latchPin, OUTPUT);
pinMode(clockPin, OUTPUT);
// column registers for image data.
dataArray[0] = 24; // 00011000
dataArray[1] = 60; // 00111100
dataArray[2] = 126; // 01111110
dataArray[3] = 219; // 11011011
dataArray[4] = 255; // 11111111
dataArray[5] = 90; // 01011010
dataArray[6] = 129; // 10000001
dataArray[7] = 66; // 01000010
// row registers... DO NOT CHANGE THESE!
rowArray[0] = 127; // 01111111
rowArray[1] = 191; // 10111111
rowArray[2] = 223; // 11011111
rowArray[3] = 239; // 11101111
rowArray[4] = 247; // 11110111
rowArray[5] = 251; // 11111011
rowArray[6] = 253; // 11111101
rowArray[7] = 254; // 11111110
}
void loop()
{
for(int j = 0; j < 8; j++){ // load the byte...
data = dataArray[j]; // from the data array...
row = rowArray[j]; // and the row array
digitalWrite(latchPin, LOW); // ground the latch pin
shiftOut(dataPin, clockPin, MSBFIRST, data); // shift out the data byte
shiftOut(dataPin, clockPin, MSBFIRST, row); // shift out the row byte
digitalWrite(latchPin, HIGH); // it's finished so bring the latch pin high
//delay(50); // left in to display the plex at low speed
}
}
sorry for the late post and overly wirey pic (I got new larger displays and was too lazy to rewire the whole thing.
edit: rewired to show simplicity... new pic