Using forLoop and byte arrays for cycling through 595 shift register outputs

Hello all,
I’m trying to turn on and off an LED, then go to the next LED in line and do the same, with a for loop going through all outputs. (Using solenoids for finished product but using LEDs here for simplicity) I am currently using 2 595 shift registers to control 16 LEDs.

It gets a bit confusing for me when trying to use bytes in arrays with multiple shift registers and this is what I have scrounged together, I’ve already looked through and kinda derived my code from this tutorial:

Just to clarify, MY CODE WORKS but I am wondering if there is an easier/shorter way to do this (maybe I will want to use more than 2 shift registers one day):

int clockPin = 2;
int latchPin = 3;
int dataPin = 4;

byte firstEightLEDs[] = {1, 2, 4, 8, 16, 32, 64, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0};
byte secondEightLEDs[] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 4, 8, 16, 32, 64, 128, 0};

const int NUM_LED = 16;

void setup() {

  pinMode(latchPin, OUTPUT);
  pinMode(dataPin, OUTPUT);
  pinMode(clockPin, OUTPUT);

}

void loop() {
  for (int i = 0; i < NUM_LED; i++) {

    digitalWrite(latchPin, LOW);
    shiftOut(dataPin, clockPin, MSBFIRST, firstEightLEDs[i]);
    shiftOut(dataPin, clockPin, MSBFIRST, secondEightLEDs[i]);
    digitalWrite(latchPin, HIGH);

    delay(500);
    
            //Array value 16 is 0 for both arrays... so it turns both off
    digitalWrite(latchPin, LOW);
    shiftOut(dataPin, clockPin, MSBFIRST, firstEightLEDs[16]);
    shiftOut(dataPin, clockPin, MSBFIRST, secondEightLEDs[16]);
    digitalWrite(latchPin, HIGH);

    delay(500);

  }
}

Just trying to pick your brains to see if I can understand this topic a bit better,
Much Appreciated

For the example presented I'd use a 16-bit integer and just shift a one through using the for() loop. To separately access both bytes of the integer for transmission, create a union containing the 16-bit variable and a two-byte byte array.

You may find it useful to put the shift code into a function.

marcussavery:
Hello all,
I'm trying to turn on and off an LED, then go to the next LED in line and do the same, with a for loop going through all outputs....

just to be clear, is this the pattern you want,
Capture.PNG

or this one?
Capture1.PNG

Capture1.PNG

Capture.PNG

sherzaad:
just to be clear...

Good catch!

There’s bit-bang way of doing it

void shift_out_16(uint16_t bb16)
{
	for(byte i = 0; i < 16; i++)
	{
		digitalWrite(dataPin, (bb16 & 1));
		digitalWrite(clockPin, 1);
		digitalWrite(clockPin, 0);
		bb16 >>= 1;
	}
	digitalWrite(latchPin, 1);
	digitalWrite(latchPin, 0);
}

You can put delays in wherever you want as the 595 is synchronous it won’t do anything prior to the clock/latch pins pulsing.

sherzaad:
or this one?
Capture1.PNG

It would be the second one as there will be a time interval where all leds are off

DKWatson:
There’s bit-bang way of doing it

dougp:
use a 16-bit integer and just shift a one through using the for() loop.

Used both of your advice and help and it ended up bringing down the ‘in loop’ code down to a few lines and makes more sense now, thanks

int clockPin = 2;
int latchPin = 3;
int dataPin = 4;
const int NUM_LED = 16;

int x = 1;

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

void loop() {
  for (int i = 0; i < NUM_LED; i++) {
    int result = x << i;

    shift_out_16(result);
    delay(200);
    shift_out_16(0);
    delay(200);
  }
}

void shift_out_16(uint16_t bb16)
{
  for (byte i = 0; i < 16; i++)
  {
    digitalWrite(dataPin, (bb16 & 1));
    digitalWrite(clockPin, 1);
    digitalWrite(clockPin, 0);
    bb16 >>= 1;
  }
  digitalWrite(latchPin, 1);
  digitalWrite(latchPin, 0);
}

Google “C++ bit-shiftiing operator”.

In your code, [nobbc]firstEightLEDs[i][/nobbc] is exactly the same as the expression [nobbc]1 << i[/nobbc]