Shift registers and LED's

Thanks for that. I'll play around with those type of arrays if I can work out how to put them into your code. Yes it did perplex me when I saw that
" byte dataArray[]= {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 " in your original code you gave me because straight after it you had some in the B00000001 format but it was "commented out"

#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

I think that it's time for me to really knuckle down and get a grasp on how all this coding is put together. Thanks again Crossroads and I'll let you know how I go, Pedro.

The commented out part was to show you what the initial data would look like.
dataArray [ x ] represents one column of data, the columns are 0 to 7. Or perhaps 7 to 0. You can make all the data 0 except for 1 and see how your display actually relates to the array data.

Yes I am starting to see how it works. I had a play around with it last night and managed to make a diagonal cross and the letter H. Now there’s progress XD
I have a lot of written material about all things Arduino, but can you recommend anything in particular that I read as there is so much information on Arduino in general that it’s hard to know where to start. Thinking in three dimensions with the cubes and two dimensions with data moving in, down and across with the matrix is certainly taxing my intellect I can tell you. Sometimes I’m flat out thinking in one dimension.

I struggle with the same. So much of what can be found for examples is like uncommented cryptic C commands, hard to follow or to tell what it does.
And then they go into classes and functions and libraries and .cpp files and .h files, and its late at night & my eyes just glaze over.
Get some basic stuff working, ask questions in the forum.
I downloaded a book
"Thinking in C++ Vol 1 - 2nd Edition_bumatek.pdf"
"Thinking in C++ Vol 2 - 2nd Edition_bumatek.pdf"
but didn't get very far reading it yet.

I must admit that I am a tad inpatient and want to learn how to do what I want to do asap… a bad trait on my behalf XD After having a good look at how the arrays for anodes and cathodes generated "pixels" I am confidently turning on any combination of LED's in a static situation so now I will try and tackle some dynamic movement and eventually some scrolling text. I had a look at the Arduino Cookbook and it looks well written so I think that I'll just refer to it when I stop moving forward with all this. Thanks again for the help and inspiration and have a good week, Pedro

The movement is just updating the display array.
One thing you can do is create a larger array, say 8 x 80, 640 bytes used. So that will hold 10 'frames' stuff to be displayed.
Then every so often (250ms? 4 updates a second?) copy the 8 frames into the display array.
Conceptually:

if (250mS elapsed){
masterArrayPointer = masterArrayPointer+1
  for (x = 0 to 7){
  displayArray[x] = master Array[masterArrayPointer + x]
  }
}

Have to do some checking at the end for a smooth wrap around, or just let the end of the masterArray 'slide off' to the left and start over.

So basically in an 8 x 80 array it's like 10 frames of film where each object changes its position from one frame to the next creating the movement. The "if" and "for" command changes the data being displayed by moving sequentially through the frames every 250 ms. This can be used to say scroll through a word , phrase or any simple graphic image. I'll definitely have to bite the bullet and start using these two commands (if and for) and make more use of arrays etc rather than relying on the simple methods I have been using. Oh well the world is my oyster better go and hit the books over the weekend and thanks for the explanation. 8)

Yes.
The 80 columns can be scrolled thru 8 at a time, so a whole new frame comes in, or 1 column at a time so 1 frame gets pushed a column at a time as a new one comes in.
The next frame to be scrolled in can also be pulled from PROGMEM so you really just need 2 frames in SRAM. As the final column gets shifted into the display frame, the next one frame gets pulled from PROGMEM (the flash memory) and put into the array in place of the one that was just shifted out.
Thus you can have scrolling messages as long as you want and not be limited by the meager SRAM size of an Uno.

I would just like to verify that I am thinking about this the right way. I assume that I am because it works, but stranger things have happened. To generate this display for the number 2; please refer to the attached Diagram 1.

Using this code;

byte dataArray

B00000000, B00011000, B00100100, B00001000, B00010000, B00100000, B00111100, B00000000

byte cathodePins

B00000000, B01000000, B00100000, B00010000, B00001000, B00000100, B00000010, B00000000

Am I reasoning correctly in thinking that B00011000 in byte dataArray is indicating C4 and C5 and that B01000000 in byte cathodePins is indicating R2 thus lighting LED's in C4 / R2 and
C5 / R2 and similairly all the "pairs" of byte dataArray and byte cathodePins data sets?

As I said it works but something tells me that I should be inputting it in a "two dimensional array" like the one you indicated;

dataArray[0] = B00000001
dataArray[1] = B00000010
dataArray[2] = B00000100
dataArray[3] = B00001000
dataArray[4] = B00010000
dataArray[5] = B00100000
dataArray[6] = B01000000
dataArray[7] = B10000000

but I cannot quite work out how to use this array because if for example I worked out how to put it in the byte dataArray section of code, what do I put into the byte catodePins section, the same array? And although I have tried various things I haven't been successful.

I hope that my explanation makes sense, thanks Pedro.

Diagram 1.doc (31 KB)

There is no reason for you to change this and this:

byte cathodePins[] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80};  // used to turn on 1 cathode at a time
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

All you should be changing is the data in here:
dataArray[]= {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80};

Do whatever you're going to do that array, the code at the beginning of void loop() will then display it.
DO NOT turn on two cathodes at once.

If you want multiple anodes in a Row to be on, then you have to set the same bit in the anode array:

cccccccc
76543210

10000000
01000000
00111000
00010000
00001000
00000111
00000010
00000001

and rotate it 90 degrees so the code can recognize it:
dataArray[7] = B10000000 column 7
dataArray[6] = B01000000 column 6
dataArray[5] = B00111000 column 5
dataArray[4] = B00010000 column 4
dataArray[3] = B00001000 column 3
dataArray[2] = B00000111 column 2
dataArray[1] = B00000010 column 1
dataArray[0] = B00000001 column 0

I am a bit slow on the uptake sometimes 8) but I think that maybe now I am getting it.
I should leave the code in byte cathodePins as;

{0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80}; or

B10000000, B01000000, B00100000, B00010000, B00001000, B00000100, B00000010, B00000001

Seeing as I will be coding the dataArray in Binary.

This is because the basic principle of multiplexing is POV where only one LED is on at any given time and this code "sweeps" through the cathodes sequentially one at a time and then repeats, the individual switching of the LED's being controlled by the anodes.

So the way I was coding the anodes via the dataArray was right but I was mistakenly switching on more than one cathode at a time which will damage the IC in the Arduino.

Does it sound like I now have a better understanding or am I still kidding myself. Thanks Pedro

Almost -
"This is because the basic principle of multiplexing is POV where only one LED is on at any given time "
The POV we have going turns one whole column at a time, up to 8 LEDs. That's why we use the ULN2803, or TPIC6B595, for the cathodes.

If you want a whole row to appear on, then you leave the same anode on, and the action of quickly turning the cathodes on one by one fools and POV makes it look like the whole row is on.

I will just have to think about that for a short while. Just when I think I understand…
I shoot myself down in flames :smiley:

I realise that I may be labouring over this point, but I dislike thinking that I understand a process when I do not. So….
What is happening is that the ULN2803 is supplying ground to each column one after the other. It is being controlled by the cathode shift register as it shifts out a byte of data with one bit a digital one and the other seven bits zero’s. The bit that is digital one changes sequentially from the first position in the byte to the last position in the byte. The anode shift register shifts out it’s byte of data determining which row or rows is supplied power. Therefore we could have a situation where more than one LED is illuminated at the same time (from one to eight LED’s)
This differs from multiplexing because in that situation power and ground is only supplied to one LED at a time.
Am I any closer to enlightenment, Pedro?

Soooo close! Who says we're limited to multiplexing just 1 bit? Lets multiplex 8 bits!

When an anode is driven, all the anodes in that row are driven. As only 1 cathode is turned on, only LED in that 1 column is turned on.
To make things efficient, all 8 anodes are driven together - but still just 1 cathode, so only 1 column is turned on.

This makes the multiplexing faster. Up to 8 LEDs are switched at a time, versus just 1 LED. So 8 cathode cycles, 64 LEDs.

It is also quicker - read a byte from memory, write the byte to the anodes, turn on a column. Repeat 8 times. Hardware SPI used to shift out the bytes, very fast.
Compare to read a byte from memory, mask off the 7 non-driven anode bits, write the byte to the anodes, turn on a cathode. Bigger software effort to pick off the one bit to be made high from the byte each time. Repeat 64 times.

So just the Repeat 8 times vs Repeat 64 times is a huge speed advantage.

Downside to 8 bits: a part like ULN2803 is needed.
Upside: Brighter display. Faster updates. Easier software. Win-Win-Win.

How does that saying go? So close yet so far... I'll just ruminate on that information for a while.
I'm determined to get my head around this. 8)

I have a quick question as a noob to the 74HC595 Shift registers I am working on shifting out pins for an LED matrix and was just getting started when I noticed that my Pin Q0 (parallel data output 0) pin 15 is putting out a lot more voltage than the other 7 pins.

Here is the information to reconstruct what I have done on a bread board:

I have it hooked up to my Arduino Uno and Shift Register (NXP 74HC595N) like the image in step 2 of Example 1 of the Serial to Parallel Shift Out description found at this page http://www.arduino.cc/en/Tutorial/ShiftOut

Except my power is connected to Arduino 3.3V and I am using DS 595 pin 14 to Arduino data pin 9, SHCP 595 pin 11 to Arduino clock pin 10, and 595 STCP pin 12 to Arduino latch pin 11

The code running is designed to turn all pins on and is as follows:

int latchPin = 11;             //595 pin 12
int clockPin = 10;          //595 pin 11
int dataPin = 9;           //595 pin 14
//595 pin 16 has 5VDC
//595 pin 8 has GND

void setup() {
 pinMode(latchPin, OUTPUT);
 pinMode(clockPin, OUTPUT);
 pinMode(dataPin, OUTPUT);
}
void loop() {
   digitalWrite(latchPin, LOW);
   shiftOut(dataPin, clockPin, MSBFIRST, B11111111);
   digitalWrite(latchPin, HIGH);
   delay(5000);
}

Now that I have that out of the way... I plug in the Arduino to a 12 volt source and metered each of the parallel pins of the register 1-7, 15. I get about 0.045 from each pin until I get to number 15 which shows 0.991. I first noticed the issue when trying to light a small string of leds like in the example and one of the leds was much brighter than the others. I have tried two different shift registers with the same results and can not find any documentation so far that points to a difference between 595 pin 15 versus the other 595 1-7 pins.

Like I said I am new to this and could be missing something obvious.

http://www.nxp.com/documents/data_sheet/74HC_HCT595.pdf

First thing: If you have a cap on pin 12, remove it. That is incorrect. We have asked to have that corrected numerous times. It can only damage the Arduino output pin it is connected to.

You have Arduino uC powered at 5V?
So it has 0 to 5V outputs?

You have 74HC595 powered at 3.3V?
Its inputs should be in the range of -0.5V to +3.8V:
VIn < -0.5V or VIn > VCC + 0.5V
So you have a problem there potentially.

The Arduino also has limited current capability at 3.3V. You could be seeing that with all current going into the first LED and the rest being underpowered.

What do you have for current limit resistors between its output pins, LEDs, and Gnd?
Do you have HC595 pin 13, Output Enable, connected to Gnd?
Do you have HC595 pin 10, Master Clear, connected to pin 16?
Do you have a 0.1uF cap from pin 16 to Gnd?

OK, like I said I am new, and I made a noob mistake. Thanks CrossRoads. You didn't mention it but in checking my board against your various thoughts I found that my GRD pin 8 was not in fact grounded. I have corrected the board and now recieve 0.12 V on 1-7,and 15. Thanks!

I am sure I will have a few more questions as I work through my new project of building an 16x16 RGB LED matrix using PWM. Thanks for the quick response.

Ok. Please post your questions as a new thread.
You can start it by looking at TLC5940 and WS2803 for PWM controllers for LEDs.