Writing multi-byte to 8-bit register

i am learning to use shiftOut() and going through the “Knight Rider” exercises which uses arrays when one first starts learning Arduino.

i understand using the 74HC595 chip and am now trying out linking more than one.

i have successfully done the led scrolling with 16 leds, and now proceed to make the “fluid” version with 2 leds at a time.

the code i made (probably rather crude method) is as follows:

//
int latchPin = 8;
int clockPin = 12;
int dataPin = 11;

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

void loop()  {
//  int led=1;  // one led at a time
int led=3;  // two leds at a time

  for (int i=0; i<8; i++)  {
    digitalWrite(latchPin, LOW);
    
    shiftOut(led);
    shiftOut(0);
    led = led*2;  // scroll leds right to left

    digitalWrite(latchPin, HIGH);
    delay(200);
  }

// have to reset the value per byte
led=3;

  for (int i=0; i<8; i++)  {
    digitalWrite(latchPin, LOW);
    shiftOut(0);
    shiftOut(led);
    led = led*2;  // scroll leds right to left
    digitalWrite(latchPin, HIGH);
    delay(500);
  }
}

// declaring own function ALSO called "shiftOut()" !!
void shiftOut(byte dataOut) {
  // boolean var pinState is initialised.
  boolean pinState;
  // Data and Clock set LOW to reset lines ready for fresh data to be sent.
  digitalWrite(dataPin, LOW);
  digitalWrite(clockPin, LOW);

  for (int i=0; i<=7; i++) {
    // Clock set low prior to sending a Data bit.
    digitalWrite(clockPin, LOW);

// DETERMINE DATA (bit) TO SEND
    // compare with bitmask to set each bit from i=0 to i=7
    if ( dataOut & (1<<i) ) {
      pinState = HIGH;
    }
    else {
      pinState = LOW;
    }

// ACTUAL WRITE DATA TO REGISTER
    // write either a HIGH or LOW to Data Pin    then 
    digitalWrite(dataPin, pinState);
    // set Clock Pin HIGH to write that bit into register.
    digitalWrite(clockPin, HIGH);
  }
  digitalWrite(clockPin, LOW);  // stop shifting out data
}

it seems to work okay, but there is an imperfection when straddling the 2 registers, shfting from the first byte to the second byte, an led has to be lit on each of the two chips, so i can’t just use the ‘shunt’ method.

how should i approach correcting this ?

Shift out better data?

0b11100000, 0b00000000, 0b01110000, 0b00000000, 0b00111000, 0b00000000, 0b00011100, 0b00000000, 0b00001110, 0b00000000, 0b00000111, 0b00000000, 0b00000011, 0b10000000, 0b00000001, 0b11000000, 0b00000000, 0b11100000. etc.

CrossRoads: Shift out better data?

0b11100000, 0b00000000, 0b01110000, 0b00000000, 0b00111000, 0b00000000, 0b00011100, 0b00000000, 0b00001110, 0b00000000, 0b00000111, 0b00000000, 0b00000011, 0b10000000, 0b00000001, 0b11000000, 0b00000000, 0b11100000. etc.

yes, that would be obvious. currently i use 2 x for loops to 8, for a smooth transition one would likely use 1x for loop to 16 - but then the easy shifting by led = led * 2wouldn't be applicable. i'll have to mull that one over... how to formulate the 2 bytes together. any hints on what i should be "looking for" ? 'carry over' perhaps ? i'm not yet well versed in bitwise operators. (only just grasped the concept of bitmask for this tutorial)

Just make an array of what you want displayed. Loop thru the array. Ditch the shifting.

CrossRoads:
Just make an array of what you want displayed. Loop thru the array.
Ditch the shifting.

by that you mean, using the bitmask through the for loop, right ?
but we’re still writing data to the “shift register” - so in the section of the above code of :

// DETERMINE DATA (bit) TO SEND
    if ( dataOut & (1<<i) ) {
      pinState = HIGH;
    }
    else {
      pinState = LOW;
    }

we simply replace it with :

  pinState = dataOut[i];

but now the parameter for the function has to be declared as an array variable first.

byte led[];

and since it will only be composed of ‘0’ & ‘1’, can we just use;

boolean led8bitArray[];

and with 2 x 74HC595, the array can be “16 bit” - and the for loop extended to 16 iterations ?

on a side note;
are these equivalent ?

function(0b00010000);
function(16);

Why are you making it so difficult?

byte dataArray[] = {
0b11100000, 0b00000000,
0b01110000, 0b00000000,
0b00111000, 0b00000000,
0b00011100, 0b00000000,
0b00001110, 0b00000000,
0b00000111, 0b00000000,
0b00000011, 0b10000000,
0b00000001, 0b11000000,
0b00000000, 0b11100000,
0b00000000, 0b01110000,
0b00000000, 0b00111000,
0b00000000, 0b00011100,
0b00000000, 0b00001110,
0b00000000, 0b00000111,
};

void loop(){
currentMillis = millis;
elapsedMillis = currentMillis - previousMillis();
if (elapsedMillis >=onDuration){ // all time related elements are unsigned long
previousMillis = previousMills + onDuration;
dataCount = dataCount +2; // 0,2,4,6,8,10,12,14
if (dataCount == 28){ // for example say you had 16 patterns, 32 bytes
dataCount = 0;
}
digitalWrite (latchPin, LOW); // D10 SS
SPI.transfer(dataArray[dataCount]); // D13 SCK, connects to CLOCK, D11 MOSI connects to Serial in
SPI.transfer(dataArray[dataCount +1]); // Serial out connect to next Serial, D13 & D10 to both chips
digitalWrite (latchPin, HIGH); // data changes  this clock edge
} // end time check
} // end loop

And you can work it out how work dataCount backwards.

CrossRoads: Why are you making it so difficult?

sorry, but i'm very slow at learning, others might be more efficient and just get to knowing the solution immediately, but i tend to go on tangents and try to learn why (other related) things are so - i'm still learning to USE the Arduino, not finding out how i can do something specific WITH the Arduino.

CrossRoads: And you can work it out how work dataCount backwards.

i'm afraid i don't understand that sentence.

byte dataArray[] = {
0b11100000, 0b00000000,
0b01110000, 0b00000000,
0b00111000, 0b00000000,
0b00011100, 0b00000000,
0b00001110, 0b00000000,
0b00000111, 0b00000000,
0b00000011, 0b10000000,
0b00000001, 0b11000000,
0b00000000, 0b11100000,
0b00000000, 0b01110000,
0b00000000, 0b00111000,
0b00000000, 0b00011100,
0b00000000, 0b00001110,
0b00000000, 0b00000111,
};

void loop(){
currentMillis = millis;
elapsedMillis = currentMillis - previousMillis();
if (elapsedMillis >=onDuration){ // all time related elements are unsigned long
previousMillis = previousMills + onDuration;
dataCount = dataCount +2; // 0,2,4,6,8,10,12,14
if (dataCount == 28){ // for example say you had 16 patterns, 32 bytes
dataCount = 0;
}
digitalWrite (latchPin, LOW); // D10 SS
SPI.transfer(dataArray[dataCount]); // D13 SCK, connects to CLOCK, D11 MOSI connects to Serial in
SPI.transfer(dataArray[dataCount +1]); // Serial out connect to next Serial, D13 & D10 to both chips
digitalWrite (latchPin, HIGH); // data changes  this clock edge
} // end time check
} // end loop

okay, it looks like you've condensed the shiftOut function to it's bare basics - that looks like very nice simple code, i'll try to digest that slowly. i assume that one has to import the SPI library first, that deals with all the int latchPin, int clockPin, int dataPin in one fell swoop.

condensed the shiftOut function to it's bare basics

No, I replaced convoluted software control of invidual bits and clock with hardware internal to the chip that does the parallel to serial conversion at a much faster rate without needing all the software intervention. You write into the SPI register, the data gets blasted out. Done.

CrossRoads:

condensed the shiftOut function to it’s bare basics

No, I replaced convoluted software control of invidual bits and clock with hardware internal to the chip that does the parallel to serial conversion at a much faster rate without needing all the software intervention. You write into the SPI register, the data gets blasted out. Done.

whew…
years… (hopefully, months !) from now i’ll appreciate that concise response - i guess that’ll teach me to try and go “scuba diving” without learning how setting up the oxygen tank works !

what i meant was the function in the code above that performs the “writing to the shift register”, it got confusing because it was named the same as the Arduino function.

okay, by convoluted, would you be referring to digitalWrite() ?

so what you’ve done is connect the 74HC595 via the SPI bus; latchPin = SS, clockPin = CLK, dataPin = MOSI and just… ahh, shiftOut() is also part of the convoluted !

okay, thanks - i think i get it now.

oh, just to be clear;

internal to the chip that does the parallel to serial conversion

by ‘chip’, you meant the Atmega, and parallel to serial refers to the 8-bits simultaneously from Atmega and fed one bit at a time for the 74HC595 instead of the example’s software method which uses the bitmask to read the byte one bit at a time.