Go Down

Topic: 8 shift registers for a clock (64bit) (Read 382 times) previous topic - next topic

hugligan

Hello everyone, first post here  :)

I've been trying to get 8 shift register to work for a clock that im about to build. I need 8 registers for 60 LEDs that will spin around the clock (one each second, i was planning 2 per sec 120 total. But want to get 60 to work first.). :o

However no matter what I try it just won't work so im now desperately begging for help.
I've hooked up all of the shift-registers correctly im fairly certain. But the coding is where im stuck. Im using Autodesks 123D Circuit simulator to code.

You can see it here and i think recode and post your results if youre successful:
123D 8 Shift Registers


Appreciate any ideas! Im usually a decent googler, however ive found nothing that helps.

Here is the cuircuit, i have 64 leds now for testing purpose. They are all hooked up systematiclly to the registers.


Here is the code (Ive tried long, byte and 16/8bit int. Nothing works for me):
Code: [Select]
//Pin connected to ST_CP of 74HC595
int latchpin = 8;
//Pin connected to SH_CP of 74HC595
int clockpin = 12;
////Pin connected to DS of 74HC595
int datapin = 11;

unsigned long data1[1] = {0b00000000000000000000000000000001};
unsigned long data2[1] = {0b10000000000000000000000000000000};

void setup() {
pinMode(latchpin, OUTPUT);
pinMode(datapin, OUTPUT);
pinMode(clockpin, OUTPUT);}

void loop() {
  updateShiftRegister(data1[0], data2[0]);
  delay(5000);
}

void updateShiftRegister(unsigned long array1, unsigned long array2) {
  shiftOut(datapin, clockpin, MSBFIRST, array1);
  shiftOut(datapin, clockpin, MSBFIRST, array2);
  digitalWrite(latchpin, HIGH);
  digitalWrite(latchpin, LOW);
}



guix

#1
Dec 05, 2014, 10:37 pm Last Edit: Dec 05, 2014, 10:52 pm by guix
Hello and welcome :)

shiftOut want a byte, you give it more than that ;)

See this page

Try to change your function to this:
Code: [Select]

void updateShiftRegister(unsigned long array1, unsigned long array2) {
  shiftOut(datapin, clockpin, MSBFIRST, array1 );
  shiftOut(datapin, clockpin, MSBFIRST, array1 >> 8);
  shiftOut(datapin, clockpin, MSBFIRST, array1 >> 16);
  shiftOut(datapin, clockpin, MSBFIRST, array1 >> 24);
  shiftOut(datapin, clockpin, MSBFIRST, array2 );
  shiftOut(datapin, clockpin, MSBFIRST, array2 >> 8);
  shiftOut(datapin, clockpin, MSBFIRST, array2 >> 16);
  shiftOut(datapin, clockpin, MSBFIRST, array2 >> 24);
  digitalWrite(latchpin, HIGH);
  digitalWrite(latchpin, LOW);
}

(Far from being perfect, but it should work)

I didn't know about this 123D thing, it's very nice ;)

dlloyd

#2
Dec 05, 2014, 11:19 pm Last Edit: Dec 05, 2014, 11:26 pm by dlloyd
Some comments:

◉  need to set all outputs LOW in setup
◉  need decoupling capacitors on all ICs
◉  may need a small delay before setting latch HIGH

Try this:

Code: [Select]
//Pin connected to ST_CP of 74HC595
int latchpin = 8;
//Pin connected to SH_CP of 74HC595
int clockpin = 12;
////Pin connected to DS of 74HC595
int datapin = 11;

byte arrayData[] = {
  0b10000000, 0b01000000, 0b00100000, 0b00010000,
  0b00001000, 0b00000100, 0b00000010, 0b00000001
};
byte arraySize = sizeof(arrayData);

void setup() {
  pinMode(latchpin, OUTPUT);
  pinMode(datapin, OUTPUT);
  pinMode(clockpin, OUTPUT);
  digitalWrite(latchpin, LOW);
  digitalWrite(datapin, LOW);
  digitalWrite(clockpin, LOW);
}

void loop() {
  updateShiftRegister(arrayData);
  delay(5000);
}

void updateShiftRegister(byte *arrayData) {
  for (int i = 0; i < arraySize; i++) {
    shiftOut(datapin, clockpin, MSBFIRST, arrayData[i]);
  }
  delay(1);
  digitalWrite(latchpin, HIGH);
  delay(1);
  digitalWrite(latchpin, LOW);
}

hugligan

Hello and welcome :)

shiftOut want a byte, you give it more than that ;)

See this page

Try to change your function to this:
Code: [Select]

void updateShiftRegister(unsigned long array1, unsigned long array2) {
  shiftOut(datapin, clockpin, MSBFIRST, array1 );
  shiftOut(datapin, clockpin, MSBFIRST, array1 >> 8);
  shiftOut(datapin, clockpin, MSBFIRST, array1 >> 16);
  shiftOut(datapin, clockpin, MSBFIRST, array1 >> 24);
  shiftOut(datapin, clockpin, MSBFIRST, array2 );
  shiftOut(datapin, clockpin, MSBFIRST, array2 >> 8);
  shiftOut(datapin, clockpin, MSBFIRST, array2 >> 16);
  shiftOut(datapin, clockpin, MSBFIRST, array2 >> 24);
  digitalWrite(latchpin, HIGH);
  digitalWrite(latchpin, LOW);
}

(Far from being perfect, but it should work)

I didn't know about this 123D thing, it's very nice ;)
This worked beautifully! Thanks!

123D is very convenient but slow on my laptop.

The code is now done and can be accessible by the link in first post incase someone else need help with multiple shiftregister / 64 leds.

hugligan

Some comments:

◉  need to set all outputs LOW in setup
◉  need decoupling capacitors on all ICs
◉  may need a small delay before setting latch HIGH

Try this:

Code: [Select]
//Pin connected to ST_CP of 74HC595
int latchpin = 8;
//Pin connected to SH_CP of 74HC595
int clockpin = 12;
////Pin connected to DS of 74HC595
int datapin = 11;

byte arrayData[] = {
  0b10000000, 0b01000000, 0b00100000, 0b00010000,
  0b00001000, 0b00000100, 0b00000010, 0b00000001
};
byte arraySize = sizeof(arrayData);

void setup() {
  pinMode(latchpin, OUTPUT);
  pinMode(datapin, OUTPUT);
  pinMode(clockpin, OUTPUT);
  digitalWrite(latchpin, LOW);
  digitalWrite(datapin, LOW);
  digitalWrite(clockpin, LOW);
}

void loop() {
  updateShiftRegister(arrayData);
  delay(5000);
}

void updateShiftRegister(byte *arrayData) {
  for (int i = 0; i < arraySize; i++) {
    shiftOut(datapin, clockpin, MSBFIRST, arrayData[i]);
  }
  delay(1);
  digitalWrite(latchpin, HIGH);
  delay(1);
  digitalWrite(latchpin, LOW);
}


Ill add capacitor and the delay, thank you!
Otherwise i think i will use the code from the other person since its easier for me to keep a big array with such large elements to show every different second of the watch.

Paul__B

Much easier to use a MAX7219.  Did you know?

dlloyd

#6
Dec 06, 2014, 09:14 am Last Edit: Dec 06, 2014, 03:56 pm by dlloyd
Tried 123D ... A bit slow, timing is way off, but interesting concept.

If you only need 1 led to circle the clock perimeter, then this works for 60 leds without using any arrays or shiftOut. Would need to reverse your wiring ... Q0 to Q59 = 1sec LED to 59sec LED.

Code: [Select]
int latchpin = 8;   // connected to ST_CP of 74HC595
int clockpin = 12;  // connected to SH_CP of 74HC595
int datapin = 11;   // connected to DS of 74HC595

unsigned short sec = 0, secPrevious = 1000;
byte count = 59;

void setup() {
  pinMode(latchpin, OUTPUT);
  pinMode(datapin, OUTPUT);
  pinMode(clockpin, OUTPUT);
  digitalWrite(latchpin, LOW);
  digitalWrite(datapin, LOW);
  digitalWrite(clockpin, LOW);
}

void loop() {
  sec = millis() % 1000;
  if  (sec < 500  && secPrevious >= 500)  {
    (count >= 59) ? count = 0 : count += 1;
    (count == 0) ? digitalWrite(datapin, HIGH) : digitalWrite(datapin, LOW);
    delayMicroseconds(5);
    digitalWrite(clockpin, HIGH);
    delayMicroseconds(5);
    digitalWrite(clockpin, LOW);
    delayMicroseconds(5);
    digitalWrite(latchpin, HIGH);
    delayMicroseconds(5);
    digitalWrite(latchpin, LOW);
  }
  secPrevious = sec;
}


Could easily adapt to fill mode, then clear when count = 0:


PaulRB

#7
Dec 06, 2014, 01:23 pm Last Edit: Dec 06, 2014, 01:36 pm by PaulRB
If only one led is to be lit at once, you could use 9 Arduino outputs, 9 resistors and.... absolutely nothing else!

If you wanted to light all 60 leds at once, you could add 8 ordinary npn transistors to the above.

This technique makes the sketch more complex, but for most people this is a great trade-off to dramatically reduce the complexity of your circuit.

Paul__B's suggestion is excellent. If I wanted to control 120 leds I would use two max7219 chips. You would only need 3 Arduino pins, two resistors (instead of 120) and a few capacitors.

What about the rest of your clock: how to show the hours/minutes? 7-seg displays, 8x8 matrices? Again max7219 can make these easy.

While you are still at the design/simulation stage, you have time to explore these options.

Paul

hugligan

#8
Dec 07, 2014, 02:22 pm Last Edit: Dec 07, 2014, 02:24 pm by hugligan
If only one led is to be lit at once, you could use 9 Arduino outputs, 9 resistors and.... absolutely nothing else!

If you wanted to light all 60 leds at once, you could add 8 ordinary npn transistors to the above.

This technique makes the sketch more complex, but for most people this is a great trade-off to dramatically reduce the complexity of your circuit.

Paul__B's suggestion is excellent. If I wanted to control 120 leds I would use two max7219 chips. You would only need 3 Arduino pins, two resistors (instead of 120) and a few capacitors.

What about the rest of your clock: how to show the hours/minutes? 7-seg displays, 8x8 matrices? Again max7219 can make these easy.

While you are still at the design/simulation stage, you have time to explore these options.

Paul
How exactly would you go about to light 60 leds individually with 9 pins? :)

I have learned that maybe max7219 is more suitable, ill definitely take those into consideration. Although for resistors I could put one big resistor (same ohm) on the common ground for all leds no? That would be the same effect.

I have not yet thought about the rest of the clock. But i think ill just prevent the led at the right hour and min from lighting up. Or inverse everything depending on the light outside.

Thanks

Paul__B

Although for resistors I could put one big resistor (same ohm) on the common ground for all LEDs no? That would be the same effect.
No.

Not unless you never intend to light more than one LED at once and in case you have some "bright" idea about "strobing" them in this manner rapidly for Persistence of Vision, I (and others) have just explained in this thread just how foolish an idea that is.

If only one LED is to be lit at once, you could use 9 Arduino outputs, 9 resistors and.... absolutely nothing else!
If you wanted to light all 60 LEDs at once, you could add 8 ordinary NPN transistors to the above.
Sounds like PaulRB is describing "Charlieplexing" but got confused about "light all 60 LEDs at once" - you would have to strobe to do that.

PaulRB

#10
Dec 09, 2014, 12:32 pm Last Edit: Dec 09, 2014, 12:45 pm by PaulRB
How exactly would you go about to light 60 leds individually with 9 pins? :)
Sounds like PaulRB is describing "Charlieplexing" but got confused about "light all 60 LEDs at once" - you would have to strobe to do that.
Paul__B is correct about Charlieplexing (but I don't believe I am confused, not about this anyway).

If only 1 or a small number of LEDs needed to be lit "at once" (meaning apparently lit at once to the eye) then no transistors would be needed.

But if many/all needed to be lit at once, either the Arduino outputs would be overloaded with too much current, or the leds would be too dim.

To overcome those problems, transistors would be needed. My idea was to organise the leds into groups of 8 (the last group only having 4). An npn transistor (emitter-follower) would switch current to each group of 8 anodes. So in reality only 8 could be lit at once, but with a 1:8 multiplex ratio this would give the appearance that all 60 were lit with a good level of brightness.

I wrote this thread a while ago to try to explain how this works. I was using 7-seg displays, but the principal is the same. 8 x 7 seg displays could be driven like this which is 64 leds.

http://forum.arduino.cc/index.php?topic=188135.0

Go Up