Problem when expanding on the ShifOut tutorial for LEDs

If I unplug the 5V jumper from the arduino, they all light up. Also, if I go back to your original code, they all blink randomly except the LEDs on the first two chips.

If I use the a modified version of your code (pasted below), then each one lights up and stays on, one by one until it gets to the end. Then they just randomly blink in no discernible order. I need to be able to send COM commands (0-87) which would light up any of the LEDs depending on the number entered. Similar to the first example code in the ShiftOut tutorial.

void loop ()
{
  digitalWrite (LATCH, LOW);
  SPI.transfer (0xAB);  // chip 1
  digitalWrite (LATCH, HIGH);
  delay (300);
}  // end of loop

I'm just making up an example to prove my general method works. This code toggles them so you can see something happening:

#include <SPI.h>

const byte LATCH = 10;

void setup ()
{
  SPI.begin ();
}  // end of setup

void loop ()
{
static byte c = 0;

  digitalWrite (LATCH, LOW);
  SPI.transfer (0xAB ^ c);  // chip 1
  SPI.transfer (0xCD ^ c);  // chip 2
  SPI.transfer (0xEF ^ c);  // chip 3
  SPI.transfer (0x42 ^ c);  // chip 4
  SPI.transfer (0x55 ^ c);  // chip 5
  SPI.transfer (0x66 ^ c);  // chip 6
  SPI.transfer (0x77 ^ c);  // chip 7
  SPI.transfer (0x88 ^ c);  // chip 8
  SPI.transfer (0x44 ^ c);  // chip 9
  SPI.transfer (0x22 ^ c);  // chip 10
  SPI.transfer (0xFF ^ c);  // chip 11
  digitalWrite (LATCH, HIGH);
  delay (200);
  c ^= 0xFF;  // toggle
}  // end of loop

So far I'm up to the second chip and it works fine. Now for the 3rd.

Looks like Christmas lights alternating on and off except even more randomly. What was it supposed to look like? If I pick one, at random, and watch it, it blinks at one rate, turs off briefly, then on for a bit, then back to blinking. Seems to be no pattern to them all. Is there a way I can tell each specific one to turn on or off?

With my code they should blink very evenly. Here is how I wired it:

  • Blue wire: SS (D10)
  • Orange wire: SCK (D13)
  • Green wire: MOSI (D11)

Note that the green wire only goes to pin 14 of the first chip. Then pin 9 of the first chip goes to pin 14 of the second chip (from the right). Then pin 9 of the second chip goes to pin 14 of the third chip, and so on.

With that code the LEDs should alternate exactly every 200 mS. No randomness.

Sketch:

#include <SPI.h>

const byte LATCH = 10;

void setup ()
{
  SPI.begin ();
}  // end of setup

void loop ()
{
static byte c = 0;

  digitalWrite (LATCH, LOW);
  SPI.transfer (0xAB ^ c);  // chip 1
  SPI.transfer (0xCD ^ c);  // chip 2
  SPI.transfer (0xEF ^ c);  // chip 3
  SPI.transfer (0x42 ^ c);  // chip 4
  SPI.transfer (0x55 ^ c);  // chip 5
  SPI.transfer (0x66 ^ c);  // chip 6
  SPI.transfer (0x77 ^ c);  // chip 7
  SPI.transfer (0x83 ^ c);  // chip 8
  SPI.transfer (0x44 ^ c);  // chip 9
  SPI.transfer (0x22 ^ c);  // chip 10
  SPI.transfer (0xFF ^ c);  // chip 11
  digitalWrite (LATCH, HIGH);
  delay (200);
  c ^= 0xFF;  // toggle
}  // end of loop

Remember mine wouldn't work at all until I unplugged the 5V jumper going from the arduino to the breadboard. Once I did that, I finally got life out of it. Maybe that is a clue to some other issue. Other than that, Mine is wired just like yours. How about sending COM commands to turn each one on or off individually? Would that be a simple bit of code?

What 5V jumper? You've lost me there. There should be 5 wires going from the Arduino to the breadboard, as pictured above.

This is what it should look like:

If it doesn't, you have a wiring issue.

How about sending COM commands to turn each one on or off individually? Would that be a simple bit of code?

I'm not sure what you mean by COM commands. From where? The 11 x SPI.transfer() instructions will shift out the 11 x 8 bits (88 bits) in about 22 microseconds, much too fast to see. So all you have to do is set up the pattern you want to see in those 11 bytes before shifting it out.

It's hard to demo because I don't have 32 LEDs plugged in.

Say you want every second LED on. Then each byte would be 0xAA. It might be easier to visualize in binary ...

  digitalWrite (LATCH, LOW);
  SPI.transfer (0b00110011);  // chip 1
  SPI.transfer (0b11110011);  // chip 2
  SPI.transfer (0b00111111);  // chip 3
  SPI.transfer (0b00000011);  // chip 4
  SPI.transfer (0b00110000);  // chip 5
  SPI.transfer (0b11111111);  // chip 6
  SPI.transfer (0b01111011);  // chip 7
  SPI.transfer (0b00010011);  // chip 8
  SPI.transfer (0b00110011);  // chip 9
  SPI.transfer (0b00110011);  // chip 10
  SPI.transfer (0b00110011);  // chip 11
  digitalWrite (LATCH, HIGH);

Where there is a 1, the LED will be on. It's your job to make nice patterns, one way or another.

David82:
Remember mine wouldn't work at all until I unplugged the 5V jumper going from the arduino to the breadboard. Once I did that, I finally got life out of it. Maybe that is a clue to some other issue. Other than that, Mine is wired just like yours. How about sending COM commands to turn each one on or off individually? Would that be a simple bit of code?

You cant just chose what you feel like wiring and what not... Things have a reason to be on the schematic, including decoupling caps... Otherwise, its quite normal it wont work properly !!

If I unplug the 5v jumper on the arduino, the LEDs light up and flash/blink. If it's plugged in, nothing works. See green arrow in image below. By COM commands I'm saying I want to be able to use the Serial Monitor to tell each and any individual LED to turn on or off. Once i'ts finally at that level, I can begin to write the software for it.

Have u tried do what you was advised and connect the MOSI to the forward chips, individually to see if they work? That would definitely help you to first and foremost identify which section is causing the issues in the wiring, it seems.
You need to follow some kind of logic when re-checking all the wiring to troubleshoot.

Yep. They all blink randomly (as designed?). If I move MOSI to the forward chips, just the chips from there down work as they should. Can we move on now to turning specific LEDs on and off by command using the Serial Monitor? The whole key to this is I have to be able to send commands to it to have specific LEDs light up when I tell them to.

Mine blink on and off at exactly 200 mS intervals. There is nothing random about it. The first four should look like the video I posted, if you have the LEDs on pin 15 like I did.

Can we move on now to turning specific LEDs on and off by command using the Serial Monitor? The whole key to this is I have to be able to send commands to it to have specific LEDs light up when I tell them to.

Yes you can do that. You would need to take serial data (and only you know what your plan is) and end up converting it into those 11 bytes that get sent to the shift registers.

You may get some ideas for achieving the serial part here:

I understand how to send serial data to the arduino and the code involved but I have no idea what command, in code, turns each specific LED on. It would be something like, SPI.transfer (); There would be a loop listening for serial commands. The command data would contain the specific LED address and whether it needs to be on or off. The LED would stay on unless told to turn off. IF, for example, the first LED was told to turn on, and then told to turn on several more times without being told to turn off, it should just stay on. Something tells me that this bizarre configuration will have the lit LED sliding down the chain of LEDs instead of staying on in one place. The idea seems simple in theory, but for whatever reason, not so simple with this configuration. DO you have any idea what the code would look like because I haven't a clue for this setup?

There is no way of turning on or off one LED with a shift register, per se. That's the whole design. The shift register(s) work by sending out one bit after another. So the only way of changing a single one of those LEDs is to send all 88 bits again. As I said before, that is so fast you won't notice it, plus I think the registers don't "commit" the change until you bring the latch high again.

So you need to have in memory the data for all 11 chips. An array might be useful, eg.

const byte numberOfChips = 11;

byte LEDdata [numberOfChips] = { 0b00110011, 0b11110011, 0b11110011 };  // initial pattern

void refreshLEDs ()
  {
  digitalWrite (LATCH, LOW);
  for (byte i = 0; i < numberOfChips; i++)
    SPI.transfer (LEDdata [i]); 
  digitalWrite (LATCH, HIGH);
  } // end of refreshLEDs

OK so now refreshLEDs will set all 88 LEDs to whatever bit pattern you have set up in LEDdata [numberOfChips].

Now inside that array you can tweak bits to your heart's desire. Then when you are done, just do:

refreshLEDs ();

The idea seems simple in theory, but for whatever reason, not so simple with this configuration.

It is simple. Say you have a command from the serial port to turn all LEDs off. Here is how you would do it:

if (command == 'X')  // all LEDs off
  {
  for (byte i = 0; i < numberOfChips; i++)
    LEDdata [i] = 0;
  refreshLEDs ();
  }

And to turn them all on?

if (command == 'Y')  // all LEDs on
  {
  for (byte i = 0; i < numberOfChips; i++)
    LEDdata [i] = 0xFF;
  refreshLEDs ();
  }

Using the code below I was getting weird results so I disconnected the last 5 chips and changed the numberOfChips variable to 6. Now the last 3 LEDs light up. Is that what is supposed to happen?

#include <SPI.h>

const byte LATCH = 10;

void setup ()
{
  SPI.begin ();
}  // end of setup

const byte numberOfChips = 6;

byte LEDdata [numberOfChips] = { 0b00110011, 0b11110011, 0b11110011 };  // initial pattern

void refreshLEDs ()
  {
  digitalWrite (LATCH, LOW);
  for (byte i = 0; i < numberOfChips; i++)
    SPI.transfer (LEDdata [i]); 
  digitalWrite (LATCH, HIGH);
  } // end of refreshLEDs

void loop ()
{
  refreshLEDs ();
  delay(200);
}  // end of loop

I was able to get this code to produce the results it was designed for. As for the other code not always working as expected, I was told I needed to put a capacitor of some value somewhere to limit noise. Do you think noise is an issue?

#include <SPI.h>

const byte LATCH = 10;

void setup ()
{
  SPI.begin ();
  Serial.begin(9600);
}  // end of setup

const byte numberOfChips = 11;

byte LEDdata [numberOfChips] = { 0b00110011, 0b11110011, 0b11110011 };  // initial pattern

void refreshLEDs ()
  {
  digitalWrite (LATCH, LOW);
  for (byte i = 0; i < numberOfChips; i++)
    SPI.transfer (LEDdata [i]); 
  digitalWrite (LATCH, HIGH);
  } // end of refreshLEDs

void loop ()
{
  char command = Serial.read ();
  
  if (command == 'X')  // all LEDs off
  {
  for (byte i = 0; i < numberOfChips; i++)
    LEDdata [i] = 0;
  refreshLEDs ();
  }
  if (command == 'Y')  // all LEDs on
  {
  for (byte i = 0; i < numberOfChips; i++)
    LEDdata [i] = 0xFF;
  refreshLEDs ();
  }
}  // end of loop

The more you add, the more noise will become an issue, no doubt about that !

If the LEDdata array only contains 11 elements, how in the world does that allow for the control of 88 LEDs? If, for example, I send the command of '3' through the serial monitor I could have the for loop go through the LEDdata array and whenever the for loop counter matches the command variable, it turns that LED on. But not if there is only 11 elements. Bottom line: I need to be able to send serial commands of 0-87 (or 1-88) with some sort of prefix or suffix to indicate on or off. An example of that would be the command: '3y' which would turn only the 3rd LED (out of 88 LEDs) on.

I figured out part of it

SPI.transfer (0b00110011);
Where there is a 1, the LED will be on. It's your job to make nice patterns, one way or another.

Didn't see that tidbit of info posted earlier. Now I have to write the rest of the code.

David82:
If the LEDdata array only contains 11 elements, how in the world does that allow for the control of 88 LEDs?

8 bits per byte, 11 bytes, 8 x 11 = 88.