32 LED control with Arduino UNO

Hi, I need to have:
12 LED's being run in a loop for 1 hour each (12 hours on a clock)
an extra LED for each hour (12 in total) to blink during that hour

4 LED's to run in a look for 15 minutes each
an extra LED for each of those also blinking

could i do this with the 12 digital outputs on my uno and 4 shift registers? (74HC595)

and if it is were do i start to code it?

help :disappointed_relieved:

When you have more LED's than output pins (as you do) you get to decide between more output pins or a matrix. For more output pins you would probably want shift registers. Four 8-bit registers would work four your design. For each output pin you will need a resistor to limit the current going to the LED. Also make sure your shift register outputs can handle the current required by your LED (typically 20 mA).

If this is to be a clock and you want to keep fairly accurate time for mare than a few hours, be sure to get either a RealTimeClock chip or a source of accurate time information (GPS or Internet access).

thank you for the reply.

i have the RTC module (foresaw that problem), its the coding im stuck with. i just cant get my head round it, as i want 4 loops to happen simultaneously and i cant have more than one void loop(), so is there a way i can tell each output to be on for 1 hour then off for 11. then if they are connected through shift registers what do i type in to tell the arduino what the pin is called, as it wont just be 13, or 12, or 8 etc...

can you tell im a complete beginner? XD

You can use the BlinkWithoutDelay example to toggle a variable between 1 and 0 every 'n' milliseconds without using the delay() function. That can be used to do the blinking, assuming the blinking LED's all blink at the same rate.

You can wire the LED's in any order you like. Let's say the steady Hour lights are 0-11, the blinking ones are 12-23, the steady 1/4 Hour ones are 24-27 and the blinking ones are 28-32. You can figure out which of the four shift registers each bit is in by dividing by 8. The result will be 0-3. The remainder when dividing by 8 (% 8) is the index within the register.

I would keep an array of four bytes to hold the flags representing each light. Start by setting them all to 0 (== LOW).

Then get the current time (Hour and Minute). Divide the Minute by 15 to get QuarterHour. Set the bit for (Hour-1) {assuming hours are 1-12} HIGH and bit for 11+Hour (or 12+Hour-1) to the current blink value (0 or 1). Set the bit for 24+QuarterHour to HIGH and the bit for 27+QuarterHour to the current blink value.

Use shiftOut() to send the four bytes to the four shift registers.

Repeat. :slight_smile:

"could i do this with the 12 digital outputs on my uno "

You have the analog pins all tied?
A4/A5 are I2C, many RTCs use that (such as DS1307).
A0-A4 are then D14-D17 if needed (maybe you are using to read buttons for time setting).

I like John's approach, use an array to store the state of the LEDs.
I would write it as a loop that read the state of the 1Hz square wave out of the RTC, every time it went low you could read the 7 or 8 bytes, parse out the hours minutes, do a little logic to decide which LEDs you wanted on and update your accordingly, and turn on the blinking LED.
Then read the square wave again, when it went high you could turn off the blinking LED.
Then wait for a low again, and repeat the time check.
This way the blinking LEDs go on/off once a second, no need to mess with dividing time down, etc., just some simple code:

if (time == whatever){
change array value
write arrays to shift registers
}
kind of code.

i have finally been able to wire my shift registers and LED's correctly (only doing it for 16LED's (ignoring the blinking ones for now)

i have been testing it with the code supplied on. http://arduino.cc/en/Tutorial/ShiftOut and have wired my 2 shift registers the same as it is shown.

the problem i have is when it is turned on, all the LED's turn on and do nothing, occasionally it will do some sort of array but not what it should be doing.

do i need to reset the shift registers? they are 74h595's and if so how?

this is the code i want to test it with which is taken from the above link

//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;

//holders for infromation you're going to pass to shifting function
byte dataRED;
byte dataGREEN;
byte dataArrayRED[10];
byte dataArrayGREEN[10];

void setup() {
//set pins to output because they are addressed in the main loop
pinMode(latchPin, OUTPUT);
Serial.begin(9600);

//Arduino doesn't seem to have a way to write binary straight into the code
//so these values are in HEX. Decimal would have been fine, too.
dataArrayRED[0] = 0xFF; //11111111
dataArrayRED[1] = 0xFE; //11111110
dataArrayRED[2] = 0xFC; //11111100
dataArrayRED[3] = 0xF8; //11111000
dataArrayRED[4] = 0xF0; //11110000
dataArrayRED[5] = 0xE0; //11100000
dataArrayRED[6] = 0xC0; //11000000
dataArrayRED[7] = 0x80; //10000000
dataArrayRED[8] = 0x00; //00000000
dataArrayRED[9] = 0xE0; //11100000

//Arduino doesn't seem to have a way to write binary straight into the code
//so these values are in HEX. Decimal would have been fine, too.
dataArrayGREEN[0] = 0xFF; //11111111
dataArrayGREEN[1] = 0x7F; //01111111
dataArrayGREEN[2] = 0x3F; //00111111
dataArrayGREEN[3] = 0x1F; //00011111
dataArrayGREEN[4] = 0x0F; //00001111
dataArrayGREEN[5] = 0x07; //00000111
dataArrayGREEN[6] = 0x03; //00000011
dataArrayGREEN[7] = 0x01; //00000001
dataArrayGREEN[8] = 0x00; //00000000
dataArrayGREEN[9] = 0x07; //00000111

//function that blinks all the LEDs
//gets passed the number of blinks and the pause time
blinkAll_2Bytes(2,500);
}

void loop() {

for (int j = 0; j < 10; j++) {
//load the light sequence you want from array
dataRED = dataArrayRED[j];
dataGREEN = dataArrayGREEN[j];
//ground latchPin and hold low for as long as you are transmitting
digitalWrite(latchPin, 0);
//move 'em out
shiftOut(dataPin, clockPin, dataGREEN);
shiftOut(dataPin, clockPin, dataRED);
//return the latch pin high to signal chip that it
//no longer needs to listen for information
digitalWrite(latchPin, 1);
delay(300);
}
}

// the heart of the program
void shiftOut(int myDataPin, int myClockPin, byte myDataOut) {
// This shifts 8 bits out MSB first,
//on the rising edge of the clock,
//clock idles low

//internal function setup
int i=0;
int pinState;
pinMode(myClockPin, OUTPUT);
pinMode(myDataPin, OUTPUT);

//clear everything out just in case to
//prepare shift register for bit shifting
digitalWrite(myDataPin, 0);
digitalWrite(myClockPin, 0);

//for each bit in the byte myDataOut?
//NOTICE THAT WE ARE COUNTING DOWN in our for loop
//This means that %00000001 or "1" will go through such
//that it will be pin Q0 that lights.
for (i=7; i>=0; i--) {
digitalWrite(myClockPin, 0);

//if the value passed to myDataOut and a bitmask result
// true then... so if we are at i=6 and our value is
// %11010100 it would the code compares it to %01000000
// and proceeds to set pinState to 1.
if ( myDataOut & (1<<i) ) {
pinState= 1;
}
else {
pinState= 0;
}

//Sets the pin to HIGH or LOW depending on pinState
digitalWrite(myDataPin, pinState);
//register shifts bits on upstroke of clock pin
digitalWrite(myClockPin, 1);
//zero the data pin after shift to prevent bleed through
digitalWrite(myDataPin, 0);
}

//stop shifting
digitalWrite(myClockPin, 0);
}

//blinks the whole register based on the number of times you want to
//blink "n" and the pause between them "d"
//starts with a moment of darkness to make sure the first blink
//has its full visual effect.
void blinkAll_2Bytes(int n, int d) {
digitalWrite(latchPin, 0);
shiftOut(dataPin, clockPin, 0);
shiftOut(dataPin, clockPin, 0);
digitalWrite(latchPin, 1);
delay(200);
for (int x = 0; x < n; x++) {
digitalWrite(latchPin, 0);
shiftOut(dataPin, clockPin, 255);
shiftOut(dataPin, clockPin, 255);
digitalWrite(latchPin, 1);
delay(d);
digitalWrite(latchPin, 0);
shiftOut(dataPin, clockPin, 0);
shiftOut(dataPin, clockPin, 0);
digitalWrite(latchPin, 1);
delay(d);
}
}

Your shift our function is all wrong.
I can't see the latch pin being toggles at all. Look at the tutorial on shift registers to see how it should be done.

All the examples show MSBFIRST, LSBFIRST being used.
Seems to compile ok tho - maybe try adding to reflect how you are wired?

shiftOut(data, clock, MSBFIRST, data);

i have wired it the same as the tutorial and copied and pasted the code in but nothing happens...

i just changed the 2 shift registers for 2 others, 8 LED's turned on then, then off, and then stayed off... maybe the wireing is wrong...

i have wired it the same as the tutorial

Does that include the 1uF capacitor on the latch line? That is a big mistake and can damage your arduino, they refuse to correct it. Instead wire it to the 5V on the shift register chip, keep the other end at ground.

maybe the wireing is wrong.

I would put money on it.

I'm only jumping in here to ask Grumpy_Mike about

Does that include the 1uF capacitor on the latch line? That is a big mistake and can damage your arduino, they refuse to correct it. Instead wire it to the 5V on the shift register chip, keep the other end at ground.

Please see my Nick Gammon's post and my questions at: 4-digit display made from minimal parts - #14 by system - LEDs and Multiplexing - Arduino Forum

It's a clock based on Gammon's example, and I DID add that cap on the latch line as mentioned in the shiftOut tutorial, however I do NOT have that cap from shift register pin 16 Vcc to Gnd as Gammon shows. The project has been working fine for some time - should I pull that cap off the pin 12 (latch) line???

Thanks you!

should I pull that cap off the pin 12 (latch) line???

Yes most defiantly.
When a cap is discharged it presents a short circuit load. This causes current to flow in excess of the current limit for the pin. The same occurs when going from a HIGH to a LOW.
We take precautions on the gate of an FET with a series resistor for capacitance several orders of magnitude smaller, so it is a bit silly to not to do this on the whopping big capacitor.
Basically it was a classic beginners mistake by Tom who wrote it. He experienced intermittent operation that looked like jitter on the latch so he wapped on a capacitor and it fixed it.
However, in reality what he was doing was providing parasitic supply decoupling through the output pin. That is why it seemed to cure the problem. If he had applied some read decoupling ( cap across the power pins ) then there would have been no problem.
Unfortunately for what ever reason this has not been corrected. So yes remove it, it's an arduino killer.

Thank you for the explanation tho it's a little over my head :slight_smile: I removed that suspect cap and put it in series with +5 to pin 16 Vcc on the shift reg (#1) as Mr. Gammon showed. I noticed a "slight" increase in flicker which really is barely noticeable.

put it in series with +5 to pin 16 Vcc

I hope you put it in parallel with the 5V / ground.

Yes, my mistake - thanks. Pic attached. I have the blue cap to Gnd from the same common row on the breadboard where pin 16 Vcc goes to +5v power. I assume this is correct!

Yes that is better than nothing.
For best results they should be as close to the chip as possible.