Array with ShiftOut

Hi There,

I’m trying to program 58 motors to turn on and off in a pattern using shift register chips 74hc595 and MOSFET board. I’ve done some research but most examples don’t really apply to this project.

Two goals here:

Easy visual adjustments of arrays
Turning all things on and off at the same time… not in sequence.

The physical layout of the motors is circular and so if possible I’d like to create a binary array that can mimic that shape. ( see code ). I’ve done a lot of tests. Sometimes it comes out in sequence, other times random motors turn on.

Is it possible to create an array that is visually justified within the sketch?
How can I get that array to turn all motors on and off and the same time?

In this test code there are only three patterns. The final project will have many more and may need to be adjusted from time to time which is why a easy visual layout would be helpful.

thanks

int latchPin = 12; //Pin connected to ST_CP of 74HC595
int clockPin = 13; //Pin connected to SH_CP of 74HC595
int dataPin = 11; //Pin connected to DS of 74HC595

int pattern1[] = {
     1,1,1,1,1, 
   1,1,1,1,1,1,1, 
  1,1,1,1,1,1,1,1, 
 1,1,1,1,1,1,1,1,1, 
 1,1,1,1,1,1,1,1,1, 
  1,1,1,1,1,1,1,1, 
   1,1,1,1,1,1,1, 
     1,1,1,1,1
};

int pattern2[] = {
     0,0,0,0,0, 
   0,0,1,1,1,0,0, 
  0,0,1,1,1,1,0,0, 
 0,0,1,1,1,1,1,0,0, 
 0,0,1,1,1,1,1,0,0, 
  0,0,1,1,1,1,0,0, 
   0,0,1,1,1,0,0, 
     0,0,0,0,0
};

int pattern3[] = {
     0,0,0,0,0, 
   0,0,0,0,0,0,0, 
  0,0,0,0,0,0,0,0, 
 0,0,0,0,0,0,0,0,0, 
 0,0,0,0,0,0,0,0,0, 
  0,0,0,0,0,0,0,0, 
   0,0,0,0,0,0,0, 
     0,0,0,0,0
};
void setup() { 
  pinMode(latchPin, OUTPUT);
  pinMode(clockPin, OUTPUT);
  pinMode(dataPin, OUTPUT);
}

void loop() {

runPattern1();
runPattern2();
runPattern3();
runPattern2();
} 

void runPattern1(){

    for (int i = 0; i < 58; i++){
    digitalWrite(latchPin, LOW); //ground latchPin and hold low for as long as you are transmitting
    shiftOut(dataPin, clockPin, MSBFIRST, pattern1[i]);
    }
    digitalWrite(latchPin, HIGH); //return the latch pin high to signal chip that it
    delay(100);
}

void runPattern2(){

    for (int i = 0; i < 58; i++){
    digitalWrite(latchPin, LOW); //ground latchPin and hold low for as long as you are transmitting
    shiftOut(dataPin, clockPin, MSBFIRST, pattern2[i]);
    }
    digitalWrite(latchPin, HIGH); //return the latch pin high to signal chip that it
    delay(100);
}

void runPattern3(){

    for (int i = 0; i < 58; i++){
    digitalWrite(latchPin, LOW); //ground latchPin and hold low for as long as you are transmitting
    shiftOut(dataPin, clockPin, MSBFIRST, pattern3[i]);
    }
    digitalWrite(latchPin, HIGH); //return the latch pin high to signal chip that it
    delay(100);
}

Lubby:
How can I get that array to turn all motors on and off and the same time?

A good place to start would be to get your feet wet by setting up a 595 to realize the code in the shift out() description in the reference section. Then it's just expanding on that.

Each shiftOut() will output a single byte and it is the state of the bits of this byte that determine which outputs of the shift register are turned on. With that in mind look at what your arrays contain and which bits of the registers will be set after each shiftOut()

Thanks all.

Seeing I want to work with individual bits rather than bytes I altered the code to drop shiftOut()… appreciate the pointer dougp.

Below is some working code. There’s likely a more elegant way of writing it (and I’d be open to suggestions) but it is working.

int latchPin = 12; //Pin connected to ST_CP of 74HC595
int clockPin = 13; //Pin connected to SH_CP of 74HC595
int dataPin = 11; //Pin connected to DS of 74HC595
int bitVal = 0;

int pattern1[] = {
     1,1,1,1,1, 
   1,1,1,1,1,1,1, 
  1,1,1,1,1,1,1,1, 
 1,1,1,1,1,1,1,1,1, 
 1,1,1,1,1,1,1,1,1, 
  1,1,1,1,1,1,1,1, 
   1,1,1,1,1,1,1, 
     1,1,1,1,1
};

int pattern2[] = {
     0,0,0,0,0, 
   0,0,1,1,1,0,0, 
  0,0,1,1,1,1,0,0, 
 0,0,1,1,1,1,1,0,0, 
 0,0,1,1,1,1,1,0,0, 
  0,0,1,1,1,1,0,0, 
   0,0,1,1,1,0,0, 
     0,0,0,0,0
};

int pattern3[] = {
     0,0,0,0,0, 
   0,0,0,0,0,0,0, 
  0,0,0,0,0,0,0,0, 
 0,0,0,0,0,0,0,0,0, 
 0,0,0,0,0,0,0,0,0, 
  0,0,0,0,0,0,0,0, 
   0,0,0,0,0,0,0, 
     0,0,0,0,0
};
void setup() { 

  Serial.begin(9600);
  pinMode(latchPin, OUTPUT);
  pinMode(clockPin, OUTPUT);
  pinMode(dataPin, OUTPUT);
}

void loop() {
runPattern2();
runPattern1();
runPattern2();
runPattern3();
} 

void runPattern1(){

    digitalWrite(latchPin, LOW); //ground latchPin and hold low for as long as you are transmitting   
    for (int i = 0; i < 58; i++){
     bitVal = pattern1[i];
     Serial.print(bitVal);
    digitalWrite(clockPin, LOW);
    digitalWrite(dataPin, bitVal);   
    digitalWrite(clockPin, HIGH);
    }
    Serial.println(" = Pattern1");
    digitalWrite(latchPin, HIGH); //return the latch pin high to signal chip that it
    delay(2500);
}

void runPattern2(){

     digitalWrite(latchPin, LOW); //ground latchPin and hold low for as long as you are transmitting
    for (int i = 0; i < 58; i++){
     bitVal = pattern2[i];
     Serial.print(bitVal);
    digitalWrite(clockPin, LOW);
    digitalWrite(dataPin, bitVal);   
    digitalWrite(clockPin, HIGH);
    }
    Serial.println(" = Pattern2");
    digitalWrite(latchPin, HIGH); //return the latch pin high to signal chip that it
    delay(2500);
}

void runPattern3(){

   digitalWrite(latchPin, LOW); //ground latchPin and hold low for as long as you are transmitting
   
    for (int i = 0; i < 58; i++){
     bitVal = pattern3[i];
    Serial.print(bitVal);
    digitalWrite(clockPin, LOW);
    digitalWrite(dataPin, bitVal);   
    digitalWrite(clockPin, HIGH);
    }
    Serial.println(" = Pattern3");
    digitalWrite(latchPin, HIGH); //return the latch pin high to signal chip that it
    delay(2500);
}

You are still wasting tons of memory by using ints in your arrays instead of bytes.

Even if you use bytes you will still be wasting 7 out of 8 of the bits in each byte but I appreciate that laying out the arrays in teh way you have helps to visualise the outputs.

Do you notice how similar each runPatterX function is ?
How about using a single function to which you pass the array name ?

UKHeliBob:
You are still wasting tons of memory by using ints in your arrays instead of bytes.

Even if you use bytes you will still be wasting 7 out of 8 of the bits in each byte but I appreciate that laying out the arrays in teh way you have helps to visualise the outputs.

you can accomplish what you want using bit fields:

template <typename T> void printBits (T& t, Stream& stream, bool usePrefix = true)
{
  if (usePrefix) stream.print("0b");
  size_t numBits = sizeof(t) << 3;  // (*8)
  for (uint8_t i = 0; i < numBits; i++)
  {
    stream.print(((t >> (numBits - i - 1)) & 0x01)? "1" : "0");
  }
  stream.println();
//  return numBits;
}

int latchPin = 12; //Pin connected to ST_CP of 74HC595
int clockPin = 13; //Pin connected to SH_CP of 74HC595
int dataPin = 11; //Pin connected to DS of 74HC595

struct Pattern {
  bool bit00 :1;  //byte:bit but the names are arbitrary
  bool bit01 :1;
  bool bit02 :1;
  bool bit03 :1;
  bool bit04 :1;
  bool bit05 :1;
  bool bit06 :1;
  bool bit07 :1;
  bool bit10 :1;
  bool bit11 :1;
  bool bit12 :1;
  bool bit13 :1;
  bool bit14 :1;
  bool bit15 :1;
  bool bit16 :1;
  bool bit17 :1;
  bool bit20 :1;
  bool bit21 :1;
  bool bit22 :1;
  bool bit23 :1;
  bool bit24 :1;
  bool bit25 :1;
  bool bit26 :1;
  bool bit27 :1;
  bool bit30 :1;
  bool bit31 :1;
  bool bit32 :1;
  bool bit33 :1;
  bool bit34 :1;
  bool bit35 :1;
  bool bit36 :1;
  bool bit37 :1;
  bool bit40 :1;
  bool bit41 :1;
  bool bit42 :1;
  bool bit43 :1;
  bool bit44 :1;
  bool bit45 :1;
  bool bit46 :1;
  bool bit47 :1;
  bool bit50 :1;
  bool bit51 :1;
  bool bit52 :1;
  bool bit53 :1;
  bool bit54 :1;
  bool bit55 :1;
  bool bit56 :1;
  bool bit57 :1;
  bool bit60 :1;
  bool bit61 :1;
  bool bit62 :1;
  bool bit63 :1;
  bool bit64 :1;
  bool bit65 :1;
  bool bit66 :1;
  bool bit67 :1;
  bool bit70 :1;
  bool bit71 :1;
  bool bit72 :1;
  bool bit73 :1;
  bool bit74 :1;
  bool bit75 :1;
  bool bit76 :1;
  bool bit77 :1;
};

void setPattern(const Pattern* pattern);

const Pattern pattern2 = {
     0,0,0,0,0, 
   0,0,1,1,1,0,0, 
  0,0,1,1,1,1,0,0, 
 0,0,1,1,1,1,1,0,0, 
 0,0,1,1,1,1,1,0,0, 
  0,0,1,1,1,1,0,0, 
   0,0,1,1,1,0,0, 
     0,0,0,0,0,

0,0,0,0,0,0  //unused
};

const Pattern pattern1 = {
     1,1,1,1,1, 
   1,1,1,1,1,1,1, 
  1,1,1,1,1,1,1,1, 
 1,1,1,1,1,1,1,1,1, 
 1,1,1,1,1,1,1,1,1, 
  1,1,1,1,1,1,1,1, 
   1,1,1,1,1,1,1, 
     1,1,1,1,1,

0,0,0,0,0,0  //unused
};

const Pattern pattern0 = {
     0,0,0,0,0, 
   0,0,0,0,0,0,0, 
  0,0,0,0,0,0,0,0, 
 0,0,0,0,0,0,0,0,0, 
 0,0,0,0,0,0,0,0,0, 
  0,0,0,0,0,0,0,0, 
   0,0,0,0,0,0,0, 
     0,0,0,0,0,

0,0,0,0,0,0  //unused
};

void setup()
{
  Serial.begin(9600);
  Serial.println(sizeof(pattern0));
  unsigned long long int patternAsBinary = 0x00;
  memcpy(&patternAsBinary, &pattern0, sizeof(Pattern));
  printBits(patternAsBinary, Serial);
  
  memcpy(&patternAsBinary, &pattern1, sizeof(Pattern));
  printBits(patternAsBinary, Serial);

  memcpy(&patternAsBinary, &pattern2, sizeof(Pattern));
  printBits(patternAsBinary, Serial);
  Serial.println();
}

void loop() {
  setPattern(&pattern0);
  delay(1000);
  setPattern(&pattern1);
  delay(1000);
  setPattern(&pattern2);
  delay(1000);
  while(1){}
}

void setPattern(const Pattern* pattern) {
  uint64_t patternAsBinary = 0;
  memcpy(&patternAsBinary, pattern, sizeof(Pattern));
  for (size_t i = 0; i < sizeof(Pattern); i++) {
    uint8_t currentByte  = 0xFF & (patternAsBinary >> i*8);
    digitalWrite(clockPin, LOW);
    shiftOut(dataPin, clockPin, LSBFIRST, currentByte);
    digitalWrite(clockPin, HIGH);
    printBits(currentByte, Serial, false);
  }
  Serial.println();
}

outputs:

8
0b0000000000000000000000000000000000000000000000000000000000000000
0b0000001111111111111111111111111111111111111111111111111111111111
0b0000000000000111000011110000111110000111110000111100001110000000

00000000
00000000
00000000
00000000
00000000
00000000
00000000
00000000

11111111
11111111
11111111
11111111
11111111
11111111
11111111
00000011

10000000
11000011
11000011
10000111
00001111
00001111
00000111
00000000

Thanks BulldogLowell,

I'm just finalizing this project now that I have all the hardware running.

I'm new to the idea of a Bit Field 'struct' and as such have a hard time deciphering what's actually going on in the suggested code. I've taken sometime to search elsewhere but I haven't been able to find much information to clarify things.

Is it possible for yourself or someone else to comment out each set in the code provided so I have a better idea as to how it works and how it can be manipulated. I'm following it a bit but am also a little lost as to the function of each piece of code and why it's there.

It would be a real help