Arduino 17x18 Controlled Single White LED Ceiling using 74hc595

Hello everyone,

My situation:
Me and some of my roommates are currently working on a lighting project in my college house. It regards a party ceiling that is already operational but is currently using AC powered christmas lighting. We wanted to make it DC with micro controlled LED's for a while already and this christmas holiday we will have the time to work on it. If necessary I can provide a picture of what the ceiling looks like, but for now basically imagine a 4 m2 white wooden square with a 17x18 LED's matrix with led's coming through holes drilled in the wood.
I'm planning to control the LED's from the Arduino using 5 x 74hc595 8bit shift registers, giving me effectively the ability to control 40 outputs using 4 outputs from the Arduino. The LED's themselves will be set up in a matrix using transistors at all the rows and all the columns of the matrix. The collector side of the transistors on the rows will have 12V (external 12V-12A power supply, converted PSU from a computer) and the emitter side of the transistors on the columns will be connected to ground. The gate connectors of all the transistors will be connected to the shift registers (with some resistor in-between there) and thus be controllable.

My problem:
The question I've been asking myself is what would be the best way to get these 12V over the LED's (and if 12V is actually a good voltage). I first thought of connecting the LED's in series per 3 in a row, and then hooking them up in 6 parallel circuit's along the row. But this would only work if I make only that parallel section switchable I guess. I mean, let's say I would want 1 LED to light up; in that case there would be 12V over the LED, cause the other LED's are not connected that time to give me a sufficient voltage drop. Another option I guess is to put an appropriate resistor across every LED, but this seems kind of crazy for going from 12V to 3.5V...

Does anyone have an idea about how to fix the holes in this plan? :slight_smile:

The transistors on the rows they need to be PNP, on the columns NPN.

Assuming you're going to multiplex by rows (ie. power up a row, use column transistors to control the individual LEDs on that row) you need a resistor on every column between the led and the transistor for that column. This resistor needs to drop 8.5V at whatever current you want the LEDs to work at.

PS:

A ratio of 16:1 in your multiplexing won't be very bright.

12V isn't ideal, your resistors will be working hard and will get hot. Use 1W or 2W resistors.

If it's a computer PSU then doesn't it have a 5V output?

Ah thanks for the feedback!
I think the 5V out on the PSU would be a good option yeah! It would definitely make everything more balanced than when using the 12V.
About the brightness, would it really be not bright enough when using 0.02A LED's? Are there ways to improve the performance?
Thanks for the help!

Magic_V:
About the brightness, would it really be not bright enough when using 0.02A LED's? Are there ways to improve the performance?
Thanks for the help!

That depends on lots of things - ambient light, what your requirements are...

If it's not bright enough you could:
a) Split it into two halves.
b) Overdrive the LEDs a bit - many LEDs can take more current if they're being multiplexed. If you have a datasheet it will tell you the limits.

If you get 8,000 to 12,000 mcd LEDs, those are pretty darn bright at just 20mA!
You could run them all discretely - I have this board with 96 outputs, 3 of them daisychained will give 288 outputs - no multiplexing needed, can also control brightness with PWM on shift register output enable. Was intended to drive 12V powered LED strips which have built in current limit resistors, so 12V and higher current is not a problem.
Run 5V to each anode, and cathode to current limit resistor back to the boards.

If you want to stay with multiplexed array, then use TPIC6B595 to sink current from cathodes and cd74AC164 to source current to the anodes. 3 of each would do it.
Or PNP transistor/P-channel MOSFET to source current.
Use SPI.transfer() to send data to each, can do really fast multiplexing.
74HC595 is a poor chip for this application, can only handle 8-9mA per IO to stay within the 70mA IO limit on the power/gnd pins.

Thanks a lot for the info and quick response! That circuit looks awesome, were kind of on a budget though although I will definitely keep it in mind for future projects... :frowning:

With regard to the multiplexing method:
Why is the maximum output current of the 74HC595 a problem though? After all were only using the I/O pins to supply a small current to the gate of the transistors. Would this 8-9mA per transistor not be enough to make the maximal current flow of 18*0.02=0.36 A (alright a bit more with resistors) through the transistor flow from the collector to the emitter?

And how about putting a resistor in front of every LED btw? I understand this will make the current drawn higher, but it will also allow us to light up every led in the circuit simultaneously. We have a 5V - 30A (max) supply after all, it's not like were on our max by a long stretch.

I forgot you had transistors in there.

So you wiil have PNP (or P-channel MOSFETs) to control current from 5V into the anodes and NPN (or N-channel MOSFETs) to control cathodes and sink current to Gnd?

That should be fine. I would go with smaller PNPs to source current to anodes set up in rows,

and larger NPN to sink current from 1 cathode column at a time - NPNs are generally cheaper. Need to sink 17 or 18 x 0.02 = 360mA, so not that much - 1A capable part would do.
Like this one:
N-channel mosfet
logic level gate
Low Rds
Low Gate capacitance
low cost!
http://www.digikey.com/product-detail/en/AOI518/785-1569-5-ND/3152481

If you have your hearts set on PNP/NPN, they will run warmer; you are not running that much current while multiplexing, so should be okay anyway.

CrossRoads:
If you have your hearts set on PNP/NPN, they will run warmer; you are not running that much current while multiplexing, so should be okay anyway.

Even at full whack 18 LEDs is well within the capabilities of a cheap BJT.

Current status:
Alright we finished the first sketch of the circuit (I have attached the image to this post).
The main goal now is to get familiar with the components and the coding for Arduino. Me and my roommate both have experience programming in C, but the plan is to first start with a simplified circuit, like 2x2 / 4x4 matrix on a breadboard and control that, to get familiar with the programming for the 74HC595.

With regard to the design of the ceiling, I have added an image of our current situation. The idea is that the disco ball stays were it is, but the holes on the inner ring of lights will be redone to enable making a 18x17 matrix.
The plan is to strive for basic functionality as soon as possible (everything on/off) and create a serial connection from the circuit to the computer in our living room, this way we can program the ceiling as we go, trying new things every now and then. The ceiling is actually quite a hassle to remove so we wish to get as much of the hardware right straight away.

Current questions:
My current question is threefold:

  1. Does the current circuit plan seem like something that could work?
  2. If we would like to make the LED's in the ceiling dimmable is it possible to use PWM in some way?
  3. How complicated is it to make the LED's display patterns in interaction with music played? Although I never programmed something like that I would guess we would need a small sensor, use PWM on the voltage it returns and that we would have to design a pattern we would to display with different predetermined steps that would be enabled in sequence from for example 0-25, 25-50, 50-75 etc. up to 255 for the return on the sensor.

74HC595s - need 0.1uF cap from Vcc to Gnd.
OE - connect low, or to PWM output from Arduino.
MR/, connect to +5.

PNP - only need 1 resistor from PNP to anode Row. Resistor at each LED is not needed.
Multiplexing will be:
Drive all PNPs, drive a cathode NPN/column.
Drive PNPs, drive next cathode NPN/column.
Repeat for remaining columns.

Few problems still.

Way too many rows - or columns - one or the other.

For multiplexing, you simply cannot multiply the peak current by any number to achieve a given average current - eight or nine times is a more practical limit. In your layout diagram, you identify six "rings" of LEDs, it will probably be more practical to wire the matrix along the rings. The outermost ring would be 64 LEDs if it were complete (the corners are missing) so if you considered that as sixteen columns in four rows, the nextmost ring could also be 16 by 4 and you would have 16 by 8 with a one in 8 multiplex. You do the same with the next two inner rings. Total so far, 6 shift registers. For the "low side" drivers, you use two TPIC6B595 (for each pair of rings) which effectively contain your driver transistors and you need one current limit transistor per column only.

Your innermost two rings can be driven by a further two shift registers, again as a 1 in 8 multiplex. It will probably be just as simple to chain all the shift registers, using only three control lines and update them all each time you advance the multiplex. An extra control line if you fancy using the enable function to implement PWM on the whole array as one - noting of course, that you have to synchronise such PWM to the multiplexing - that is, you have to PWM each step of the multiplex (which you can also do in the multiplexing code) or have the PWM many times faster than the multiplex step.

Arguably you could do the whole job with just five MAX7219s as virtually the only components (five resistors and ten capacitors), if you could accept an average drive current of 8 mA.

Magic_V:

  1. Does the current circuit plan seem like something that could work?

There's no current limiting resistors. You need a resistor somewhere along each path (eg. before the column transistor where you've written C0 C1 C2...)

But... given the new revelation that this is a 'disco' ceiling and you want dynamic displays, with dimming... it simply isn't going to work out. It'll light up but it won't really do what you want it to do.

I'd say you have two choices:
a) Use WS2811 LED strips. You can cut them up into individual LEDs (use scissors...) and rejoin them in any shape you want, plus you get RGB color on every LED.
b) If you want white LEDs (Are those LEDs already in the ceiling), get some little WS2811 PCBs. You can attach three LEDs to each PCB and chain them together in a string. You get PWM on every LED. You don't need anything other than the PCBs, LEDs and a 5V power supply.

First of all some more details:

  • I have included a current limiting 75 Ohm resistor on every LED in this design (maybe it is indicated a little small). This way the whole ceiling can light up without using multiplexing (and thus loose brightness).
  • The picture of the ceiling with the was just to show how the ceiling looks right now with it's AC lights.

fungus:
But... given the new revelation that this is a 'disco' ceiling and you want dynamic displays, with dimming... it simply isn't going to work out. It'll light up but it won't really do what you want it to do.

Why is it exactly that creating some patterns using shift registers won't work? Are they not fast enough? Is the micro controller not fast enough? I would love to trust you on your word, but I just don't understand why it shouldn't work :smiley: We use external power supply, so the shift registers won't have to supply much current.

Thanks for the tips btw, I added the 0.1microFarad capacitors between 5v and GND to the design as well as connected 5V to MR.

Magic_V:
I have included a current limiting 75 Ohm resistor on every LED in this design (maybe it is indicated a little small). This way the whole ceiling can light up without using multiplexing (and thus loose brightness).

Oh, I see. I didn't know they were resistors...

Magic_V:
Why is it exactly that creating some patterns using shift registers won't work?

You can create patterns but PWM simply isn't going to work across that many rows with shift registers.

Magic_V:
Are they not fast enough? Is the micro controller not fast enough?

Both.

Magic_V:
I would love to trust you on your word, but I just don't understand why it shouldn't work

I'm not saying it won't work but you don't have enough CPU cycles to do a decent PWM on a matrix that big. I'm already worried about what the overall brightness will be like with 17:1 multiplexing.

I suppose you could limit yourself to having only a few different PWM brightness levels but is that really what you want?

Those WS2811 boards cost less than 30 cents each and would really make a difference to overall brightness and PWM effects. You could devote the CPU power to pattern generation and music analysis instead of just multiplexing.

Hi there everyone!
I started today testing a smaller version of the circuit (actually just 1 row and 4 columns) to make sure that it works every step of the way. Well basically the transistor setup works like a charm with the Vcc of 5V driving the led's with the Arduino outputs works as well. It's when I try to connect one 74HC595 shift register that I run into trouble :frowning:

As speed is of the essence in this design I wanted to use the SPI library to drive the led's instead of shiftOut (shiftOut did work for me though). I connect the row and four columns to the shift register as follows:

Q0,Q1,Q2,Q3 -> base on the NPN's for the columns
Q7 -> base on the PNP for the row

I thought that I could just use the following code to send 8 bits -> 11111111 to the shift register and latch it:

#include <SPI.h>
 int latchPin = 4;

void setup() 
{
  pinMode(latchPin, OUTPUT);

  SPI.setClockDivider(SPI_CLOCK_DIV4);
  SPI.begin();
  digitalWrite(latchPin,LOW);
  insertData();
  delayMicroseconds(2500);
}

void loop()
{
}

int insertData(byte a1)
{
  SPI.transfer(a1);
  Toggle();
}

void Toggle()
{
  digitalWrite(latchPin,LOW);
  delayMicroseconds(1);
  digitalWrite(latchPin,HIGH);
  delay(2000);
}

My idea was that at least all of them would have to go on then. Sadly enough nothing happens...
This whole SPI library got me considerably confused... When I just try to do what makes sense it never works...
Ah and I have the datapin connected to arduino pin 13 and the clock pin to arduino pin 11!

Swap these
SPI.setClockDivider(SPI_CLOCK_DIV4);
SPI.begin();

The rest is too convoluted.
Keep it simple:

digitalWrite(latchPin,LOW);
SPI.transfer(0b11111111);
digitalWrite(latchPin,HIGH);

Make sure OE/ is low and SRCLR is high. Have 0.1uF cap from Vcc pin to Gnd.
I have 27 shift registers daisy chained with 27 SPI.transfer between the latch LOW & HIGH.

Alright I cut the whole code down to the bare minimum:

#include <SPI.h>

int latchPin = 4;
 
void setup() 
{
  pinMode(latchPin, OUTPUT);
  
  SPI.begin();
  SPI.setClockDivider(SPI_CLOCK_DIV4);
  digitalWrite(latchPin,LOW);
  SPI.transfer(0b00000000);
  digitalWrite(latchPin,HIGH);
}

void loop()
{
}

I did the same to the circuit, leaving just the Arduino and the shift register, 2 LED's and their resistances and the 0.1 uF cap between Vcc and ground. Again no response from the circuit... So I swapped the shift register with another one, this time the lights went on, but when I changed the bit sequence in the program to 0b00000000 the lights are still on...

I made sure OE is low and SRCLR is high. The only thing I can think of is that I might have the pin order wrong on the shift register or something. Just to be sure here's one more check:

LatchPin -> pin 12 on the 74HC595 (storage register clock input) -> to pin 4 on the Arduino
clockPin -> pin 11 on the 74HC595 (shift register clock input) -> to pin 11 on the Arduino
dataPin -> pin 14 on the 74HC595 (serial data input) -> to pin 13 on the Arduino

Am I missing something here? The whole idea is that I can shift 8 bits of data at a time into the shift register right? and sending 0b00000000 or 0b01100000 or 0b11111111 should do that right?
Thanks a lot for any response guys!