3x 74HC595N daisy chain problem

Hello,

I need to connect 3 74HC595N shift registers one to each other (so that I could control 24 LEDS using only 3 pins on the Arduino Uno). I checked my wiring hundreds of times so main problem has to be the code. I tried many different codes, I settled on the configuration which lights up the LEDS one by one from first one to the last one, and then does it backwards. Everything works perfectly when only 2 registers are connected, as soon as I add the third register, two LEDSS start to blink simultaneously with a noticeable pattern, however, that is not the desired result… Tried to google it, but I only find results of 2 registers connected to each other. I am grateful in advance for any help provided. (My code is down bellow)

int tDelay = 500;
int latchPin= 11;
int clockPin = 9;
int dataPin= 12;
bool Dir=1;
byte leds = 1;

void update1(unsigned int leds, bool isMSBFIRST=true){
byte lowLED = lowByte(leds);
byte highLED = highByte(leds);
digitalWrite(latchPin, LOW);
if (isMSBFIRST ==false)
{
 shiftOut(dataPin, clockPin, LSBFIRST, lowLED);
 shiftOut(dataPin, clockPin, LSBFIRST, highLED);
}
else {
 shiftOut(dataPin, clockPin, MSBFIRST, highLED);
 shiftOut(dataPin, clockPin, MSBFIRST, lowLED);
 }
digitalWrite(latchPin, HIGH);
}

void setup() {
 pinMode(latchPin, OUTPUT);
  pinMode(dataPin, OUTPUT);
   pinMode(clockPin, OUTPUT);
 }

void loop() {
 unsigned int leds;
 update1(leds);
delay(tDelay);
 for(int i=0; i<24; i++)
 {
 leds=0;
 bitSet(leds, i);
 update1(leds,Dir);
 delay(tDelay);
 }
 Dir=!Dir;
}

Right, you need to go back on that first post and select "modify" (bottom right options) and put the code in between the "code" tags.

While at it, put space lines between each separate function.

Since you only define two LED bytes, it is hardly surprising that the third register follows the first!

Thank you for your observations, I edited the post, as you can can guess, I am a total beginner with shift registers as well as the Arduino...

Could you edit my code in your way and post it back again? So that I could try it with my LED`S. Thank you in advance.

OK, let’s try!

int tDelay = 500;
int latchPin= 11;
int clockPin = 9;
int dataPin= 12;
bool Dir=1;

void update1(long leds, bool isMSBFIRST=true){
byte lowLED = lowByte(leds);
byte midLED = highByte(leds);
byte highLED = leds >> 16;
digitalWrite(latchPin, LOW);
if (isMSBFIRST ==false)
{
 shiftOut(dataPin, clockPin, LSBFIRST, lowLED);
 shiftOut(dataPin, clockPin, LSBFIRST, midLED);
 shiftOut(dataPin, clockPin, LSBFIRST, highLED);
}
else {
 shiftOut(dataPin, clockPin, MSBFIRST, highLED);
 shiftOut(dataPin, clockPin, MSBFIRST, midLED);
 shiftOut(dataPin, clockPin, MSBFIRST, lowLED);
 }
digitalWrite(latchPin, HIGH);
}

void setup() {
 pinMode(latchPin, OUTPUT);
 pinMode(dataPin, OUTPUT);
 pinMode(clockPin, OUTPUT);
 }

void loop() {
 long leds;
 update1(leds);
delay(tDelay);
 for(int i=0; i<24; i++)
 {
 leds=0;
 bitSet(leds, i);
 update1(leds,Dir);
 delay(tDelay);
 }
 Dir=!Dir;
}

But do use Auto-format (Ctrl-T) on the code in the IDE!.

And you are using resistors with your LEDs, are you not? :grinning:

as soon as I add the third register, two LEDS`S start to blink simultaneously with a noticeable pattern, however,

Have you any decoupling capacitors on the power pins of those shift registers? You need a 0.1 uF ceramic capacitor on each chip as close to the chip,as you can get and with as short a lead as possible.
You won’t be the first to miss them out, even the official Arduino tutorial has the capacitor in the wrong place, on the clock pin and not the power pins.

checked my wiring hundreds of times

So could you provide a schematic of how you wired them up,so we can check if it is right, as well as a photograph so we can check you implemented the schematic correctly?

To Paul__B:

thank you so much one more time, your code works flawlessly and results in desired way for LED`S to glow. I have two more question for you:

  1. Could you provide a brief explanation about your code lines:
byte lowLED = lowByte(leds);
byte midLED = highByte(leds);
byte highLED = leds >> 16;

so that I could connect even more registers back to back in the future

  1. Could you give me a hint or a fraction of code which would allow me to to turn on and distinguish multiple leds at the time (not 1 by 1) For example: I want to turn on LED`S 1-5 and 7-9 at one moment and turn them off as well.

I highly respect all your help

PS: I am using 180 Ohm resistors to each LED

To Grumpy_Mike:

here are the pictures, I hope wiring is more than understandable: https://drive.google.com/drive/folders/1kG1dHJVNNvXRRbT8o_LXfHvSX2mNG3_w?usp=sharing

If I understand you correctly, I should replace all these yellow wires with mentioned capacitors with as short terminals as possible, is that right?

PS: please ignore other registers, I am trying to understand adding them 1 by 1, for now I am only using first 3 (wired) registers

Thank you in advance for your observations and future answer

vilius00:

  1. Could you provide a brief explanation about your code lines:
byte lowLED = lowByte(leds);

byte midLED = highByte(leds);
byte highLED = leds >> 16;

Well at this point, you needed 24 bits. A byte is 8 bits, a "word" in C is (in this case) 16 bits and a "long" is 32 bits. I had to make "leds" a long to fit all the 24 bits. lowByte() is a function that picks out the least significant eight bits (and only 8 bits) of its argument. Similarly highByte() picks out the next higher eight bits - which is the highest eight bits for a "word" but if given a "long" is the high 8 bits of the lowest 16 bits!

So we have obtained the right hand most 8 bits, and the next left-most 8 bits to those. We now want the next left-most 8 bits. To do that I used the right-shift operator to simply shift 16 bits. Now "highLED" was defined as a "byte" so it only ever fits 8 bits! So however many bits were in that "long" after it was shifted, we only get the last (right-hand) 8 bits, which is as we wanted.

On this basis, this code would work just as well:

byte lowLED = leds;
byte midLED = leds >> 8;
byte highLED = leds >> 16;

and I think you can guess what the next - fourth line would look like. :grinning:

But beyond four bytes, you would need to use something longer than a "long" and you would be better using a different structure - an array.

Also, using 74HC595s is terribly messy beyond 8 LEDs and you are better off using a LED driver - a MAX7219 and there are (or used to be pre-Covid-19) inexpensive modules on eBay or Aliexpress which make it easy to wire up. The MAX7219 drives a matrix of anything up to 64 LEDs and requires only one resistor and that bypass capacitor!

vilius00:
2) Could you give me a hint or a fraction of code which would allow me to to turn on and distinguish multiple LEDs at the time (not 1 by 1) For example: I want to turn on LED`S 1-5 and 7-9 at one moment and turn them off as well.

Well the simplest way of doing that is to write the pattern as a single word (or "long") but it really depends on exactly what you want to do. :roll_eyes:

vilius00:
PS: I am using 180 Ohm resistors to each LED

Good.

vilius00:
I hope wiring is more than understandable: https://drive.google.com/drive/folders/1kG1dHJVNNvXRRbT8o_LXfHvSX2mNG3_w?usp=sharing

It is understandable, except that I cannot see a wire connecting the ground of the registers - pin 8, bridged by the blue wires - to the actual ground. You would appear to be relying on the connection of pin 13 - Output Enable - to ground for the chip to function. Not a good idea!

vilius00:
If I understand you correctly, I should replace all these yellow wires with mentioned capacitors with as short terminals as possible, is that right?

No, not replace - a capacitor does not pass DC. To "bypass" the chip with a capacitor, you would need to connect it - as well as all the present connections (and of course, the proper ground) across each chip from pin 8 (ground) to pin 16 (Vcc).

vilius00:
PS: please ignore other registers, I am trying to understand adding them 1 by 1, for now I am only using first 3 (wired) registers

If you wire them in, they will simply "echo" the pattern of earlier registers - which is what your original experience was. :grinning:


Google drive is inconvenient for posting photos to the forum. Within limits, you can attach them here and they can be embedded into the discussion thread. :sunglasses: