Loading
Hey! This thing is still a Work in Progress. Files, instructions, and other stuff might change!

Scalable-RGB-LED-Matrix

by Dorty, published

Scalable-RGB-LED-Matrix by Dorty Dec 8, 2012

Description

Watch a 4x6 - Matrix on YouTube:
youtube.com/watch?v=DeNzGhN-fe8

This thing is a LED-Matrix ... the Cubes are 8cm x 8cm x 3cm .. the Chip for controlling the LED's is a WS2803 (get them at ebay) .. a WS2803 is a constant-current-led-driver with 18 channels .. meaning with 1 chip you can control 18 leds or 6 rgb leds.
Please note a RGB-LED is having different voltages per color ... but the same current ;-) .. so a constant current driver will ensure the voltages are automatically set by the chip .. you dont have to care about that.

Okay .. this tiny Chips are SPI-Controller ... so they have a Input-CLOCK-Pin and Input-DATA -Pin ... AND best of all ;-) Clock-Out-Pin and Data-Out-Pin .. so you can chain this chip with 2 wires :-)

e.g. for the 15 x 6 RGB-LED-Matrix i'am building .. a build 6 Cube-Columns ... every column is powered by one WS2803 Chip which is connected to the next column .. its quite easy to build a giant LED-Matrix with this driver .. please notice .. a LED is max. requiring 20ma so in my scenario i'am using 15*6 Leds => 90 LEDs each LED will require current ;-) so you need a pretty strong power-source (5v @ 6a)

For controlling the WS2803 i'am using a simple Arduino UNO (you can use any other microcontroller you like .. Picunio .. stm32...)

At the Bottom of every column i am mounting a "electronics cube" for the ws2803 circuit .. the cubes are having wiring holes ... one led-mount (you need cooling to get the correct diameter) and a option to use cable ties .... i used a glue gun.

*** For the WS2803 you ned RGB-LEDs with same ANODE (+) ***

*** The WS2803 is a PWM-Driver so you can dim every led with 8 bit (0..255) ***

*** The photos are showing the back-side of the cubes ;-)

*** Power-Source Notes:

LED[r?] 2,2v * 20ma => 0,044 Watt per Channel
LED[g?] 3,3v * 20ma => 0,066 Watt per Channel
LED[b?] 3,4v * 20ma => 0,068 Watt per Channel
LED => 0,79 Watt per LED

e.g. 6x6 Matrix => 36 RGB-LEDs (108 Channels)

36 RGB-LEDs * 0,79W => 28,44 Watt + ICs + Microcontroller + Doubled-Security ..
Lets say a 60 Watt Power-Source should be fine in this case .. however .. do our own calculations ;-) ..

Recent Comments

view all
thanks for the info. The WS2803 chips seem very unreliable in blinking the wrong LEDs while blinking the correct ones elsewhere. Also the preliminary datasheet provided by World Semi is wrong. Or maybe, I have a bad bunch of chips. I avoided soldering by using a solderless breadboard per chip.
i didn't used the library ... just plain code ... well ... i never finished my code ... no time ... wife .. child .. you know ... i thought about a current-calculation-function for limiting the matrix when using low-current-power-supplyies .. f.e. 5v/1a usb-plug.

the code is quite simple and looks ...

const int pinCLK = 13; // 8 CLK
const int pinDATA = 11; // 9 CLK Data

void setup() {
Serial.begin(57600);
pinMode(pinCLK, OUTPUT);
pinMode(pinDATA, OUTPUT);
digitalWrite(pinCLK, HIGH);
digitalWrite(pinDATA, LOW);
}
const int cnt = 2;
byte val[18*cnt] = {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};

// Bar #1
// b r g b r g b r g b r g b r g b r g
// byte ledmap[18] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 17, 10, 9, 14, 13, 12, 11, 16, 15};

//byte ledmap[18*cnt] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 17, 10, 9, 14,13,12, 11, 16, 15 };
byte ledmap[18*cnt] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,13,14, 15, 16, 17,
18,19,20, 21,22,23, 24,25,26, 27,28,29, 30,31,32, 33,34,35 };
int ix = 0;
int j = 0;
int cx = 0;
int k = 0;
int ieff = 0;
int cv = 0;

void loop () {
byte c;
int digit;
/*
delayMicroseconds(600);
val[ledmap[ix]] = 0;
j++;
if (j > 50) {
ix++;
if (ix >= 18*cnt) ix = 0;
j = 0;
cx++;
}
val[ledmap[ix]] = 0xff;
if (cx > (18*cnt)*3) {
ieff = 1;
cx = 0;
k = 0;
}

*/
if (ieff == 2) {
delayMicroseconds(100);
} else {
delayMicroseconds(600);
}

if (ieff == 0) { // effect #1
val[ledmap[ix]] = 0;

j++;
if (j > 50) {
ix++;
if (ix >= 18) ix = 0;
j = 0;
cx++;
}

val[ledmap[ix]] = 0xff;
if (cx > (18*cnt)*3) {
ieff = 1;
cx = 0;
k = 0;
}
}

if (ieff == 1) {
j++;
if (j > 0xff) {
ix++;
if (ix >= 0xff) ix = 0;
j = 0;
cx++;
}
for(c=0;c<=(18*cnt)-1;c++) {
if ((c % 3) == cx) { val[ledmap[c]] = j; } else { val[ledmap[c]] = 0; }
}
if (cx == 3) {
cx = 0;
k++;
if (k == 2) {
k = 0;
cx = 0;
j = 0;
ieff = 2;
}
}
}

if (ieff == 2) {
j++;
for(c=0;c<=(18*cnt)-1;c++) {
cv = abs((sin( ((c*10) + j)/50 )*0xff));
cv = min(cv,0xff);
cv = max(cv,0);
val[ledmap[c]] = cv;
}
cx++;
if (cx > 1000) {
ieff = 3;
cx = 0;
}
}

if (ieff == 3) {
j++;
for(c=0;c<=(18*cnt)-1;c++) {
cv = 127+(sin( ((c*c) + j)/100 )*127);
cv = min(cv,0xff);
cv = max(cv,0);
val[ledmap[c]] = cv;
}
cx++;
if (cx > 1000) {
ieff = 4;
cx = 0;
j = 0;
}
}

if (ieff == 4) {
j++;
if (j > 50) {
ix++;
if (ix >= 0xff) ix = 0;
j = 0;
cx++;
}
for(c=0;c<=(18*cnt)-1;c++) {
if ((c % 3) == cx) { val[ledmap[c]] = 0xff; } else { val[ledmap[c]] = 0; }
}
if (cx == 3) {
cx = 0;
k++;
if (k == 6) {
k = 0;
cx = 0;
j = 0;
ieff = 5;
}
}
}

if (ieff == 5) { // effect #5
val[ledmap[ix]] = 0;
val[ledmap[(18*cnt)-1-ix]] = 0;

j++;
if (j > 50) {
ix++;
if (ix >= 18*cnt) ix = 0;
j = 0;
cx++;
}

val[ledmap[ix]] = 0xff;
val[ledmap[17-ix]] = 0xff;

if (cx > (18*cnt)*3) {
ieff = 6;
cx = 0;
k = 0;
}
}

if (ieff == 6) { // effect #6
k++;
if (k > 10) {
k = 0;
for(c=0;c<=(18*cnt)-1;c++) val[ledmap[c]] = 0;

j++;
if (j > 6) {
j = 0;
cx++;
}
ix = j;
val[ledmap[j*3+0]] = ((float)((float)ix/(float)5)*0xff);
val[ledmap[j*3+1]] = ((float)((float)ix/(float)5)*0xff);
val[ledmap[j*3+2]] = ((float)((float)ix/(float)5)*0xff);
if (cx > 10) {
ieff = 0;
cx = 0;
k = 0;
}
}

}

for(c=0;c<=(18*cnt)-1;c++) {
for(digit=7;digit>=0;digit--)
{
if(val[c] & (1 << digit)) {
digitalWrite(pinDATA, HIGH);
} else {
digitalWrite(pinDATA,LOW);
}
digitalWrite(pinCLK, HIGH);
digitalWrite(pinCLK, LOW);
}
}

}

well it stinks *g*

ps: oh .. i was always soldering the wrong wires .. *damn* .. so i used a mapping-array to fix my mistakes ;-)
I know my schematics are bad ... thats the reason i wrote it also in the description "You need to connect the WS2803 to the power-source (5v) .. and you need the connect the anode of the leds there to." *g* .. dont worry ... the first time i ordered the wrong leds too ... the dealer send my a mail and fixed my order ..

More from Electronics

view more

Makes

Liked By

view all

Give a Shout Out

If you print this Thing and display it in public proudly give attribution by printing and displaying this tag. Print Thing Tag

Instructions

Print 6 LEDCubes and clue them together ..
Print 1 LEDElectricCube and clue it at the bottom ..
Glue a RGB-LED into each LED-Cube ..
The contacts can be bent away cruciform.
Solder the ANode's of all RGB'Leds together ..
Solder all left contacts (18) to the WS2803 .. you should use some kind of order ;-) if make a mistake you should be able to fix it with a simple software based mapping.

You need to connect the WS2803 to the power-source (5v) .. and you need the connect the anode of the leds there to.

You can find some sample code at the end of this thread: mikrocontroller.net/topic/269588

Doh .. one thing left .. the WS2803 needs to know how much current it should output ;-)
so you have to connect resistor from IREF to GND .. most likly a 1400 Ohm resistor for 20ma (read the documentation of the ws2803)

!!! For powering our LED's you will need a seperate 5v power supply !!!
I am a believer :) I made & configured 12 columns of LEDs. Testing is in progress. Does the WS2801 library work for you? Would you mind sharing your test code?
i didn't used the library ... just plain code ... well ... i never finished my code ... no time ... wife .. child .. you know ... i thought about a current-calculation-function for limiting the matrix when using low-current-power-supplyies .. f.e. 5v/1a usb-plug.

the code is quite simple and looks ...

const int pinCLK = 13; // 8 CLK
const int pinDATA = 11; // 9 CLK Data

void setup() {
Serial.begin(57600);
pinMode(pinCLK, OUTPUT);
pinMode(pinDATA, OUTPUT);
digitalWrite(pinCLK, HIGH);
digitalWrite(pinDATA, LOW);
}
const int cnt = 2;
byte val[18*cnt] = {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};

// Bar #1
// b r g b r g b r g b r g b r g b r g
// byte ledmap[18] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 17, 10, 9, 14, 13, 12, 11, 16, 15};

//byte ledmap[18*cnt] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 17, 10, 9, 14,13,12, 11, 16, 15 };
byte ledmap[18*cnt] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,13,14, 15, 16, 17,
18,19,20, 21,22,23, 24,25,26, 27,28,29, 30,31,32, 33,34,35 };
int ix = 0;
int j = 0;
int cx = 0;
int k = 0;
int ieff = 0;
int cv = 0;

void loop () {
byte c;
int digit;
/*
delayMicroseconds(600);
val[ledmap[ix]] = 0;
j++;
if (j > 50) {
ix++;
if (ix >= 18*cnt) ix = 0;
j = 0;
cx++;
}
val[ledmap[ix]] = 0xff;
if (cx > (18*cnt)*3) {
ieff = 1;
cx = 0;
k = 0;
}

*/
if (ieff == 2) {
delayMicroseconds(100);
} else {
delayMicroseconds(600);
}

if (ieff == 0) { // effect #1
val[ledmap[ix]] = 0;

j++;
if (j > 50) {
ix++;
if (ix >= 18) ix = 0;
j = 0;
cx++;
}

val[ledmap[ix]] = 0xff;
if (cx > (18*cnt)*3) {
ieff = 1;
cx = 0;
k = 0;
}
}

if (ieff == 1) {
j++;
if (j > 0xff) {
ix++;
if (ix >= 0xff) ix = 0;
j = 0;
cx++;
}
for(c=0;c<=(18*cnt)-1;c++) {
if ((c % 3) == cx) { val[ledmap[c]] = j; } else { val[ledmap[c]] = 0; }
}
if (cx == 3) {
cx = 0;
k++;
if (k == 2) {
k = 0;
cx = 0;
j = 0;
ieff = 2;
}
}
}

if (ieff == 2) {
j++;
for(c=0;c<=(18*cnt)-1;c++) {
cv = abs((sin( ((c*10) + j)/50 )*0xff));
cv = min(cv,0xff);
cv = max(cv,0);
val[ledmap[c]] = cv;
}
cx++;
if (cx > 1000) {
ieff = 3;
cx = 0;
}
}

if (ieff == 3) {
j++;
for(c=0;c<=(18*cnt)-1;c++) {
cv = 127+(sin( ((c*c) + j)/100 )*127);
cv = min(cv,0xff);
cv = max(cv,0);
val[ledmap[c]] = cv;
}
cx++;
if (cx > 1000) {
ieff = 4;
cx = 0;
j = 0;
}
}

if (ieff == 4) {
j++;
if (j > 50) {
ix++;
if (ix >= 0xff) ix = 0;
j = 0;
cx++;
}
for(c=0;c<=(18*cnt)-1;c++) {
if ((c % 3) == cx) { val[ledmap[c]] = 0xff; } else { val[ledmap[c]] = 0; }
}
if (cx == 3) {
cx = 0;
k++;
if (k == 6) {
k = 0;
cx = 0;
j = 0;
ieff = 5;
}
}
}

if (ieff == 5) { // effect #5
val[ledmap[ix]] = 0;
val[ledmap[(18*cnt)-1-ix]] = 0;

j++;
if (j > 50) {
ix++;
if (ix >= 18*cnt) ix = 0;
j = 0;
cx++;
}

val[ledmap[ix]] = 0xff;
val[ledmap[17-ix]] = 0xff;

if (cx > (18*cnt)*3) {
ieff = 6;
cx = 0;
k = 0;
}
}

if (ieff == 6) { // effect #6
k++;
if (k > 10) {
k = 0;
for(c=0;c<=(18*cnt)-1;c++) val[ledmap[c]] = 0;

j++;
if (j > 6) {
j = 0;
cx++;
}
ix = j;
val[ledmap[j*3+0]] = ((float)((float)ix/(float)5)*0xff);
val[ledmap[j*3+1]] = ((float)((float)ix/(float)5)*0xff);
val[ledmap[j*3+2]] = ((float)((float)ix/(float)5)*0xff);
if (cx > 10) {
ieff = 0;
cx = 0;
k = 0;
}
}

}

for(c=0;c<=(18*cnt)-1;c++) {
for(digit=7;digit>=0;digit--)
{
if(val[c] & (1 << digit)) {
digitalWrite(pinDATA, HIGH);
} else {
digitalWrite(pinDATA,LOW);
}
digitalWrite(pinCLK, HIGH);
digitalWrite(pinCLK, LOW);
}
}

}

well it stinks *g*

ps: oh .. i was always soldering the wrong wires .. *damn* .. so i used a mapping-array to fix my mistakes ;-)
thanks for the info. The WS2803 chips seem very unreliable in blinking the wrong LEDs while blinking the correct ones elsewhere. Also the preliminary datasheet provided by World Semi is wrong. Or maybe, I have a bad bunch of chips. I avoided soldering by using a solderless breadboard per chip.
Just realized ws2801 drives common cathode LEDs. I am trying the common anode RGB LEDs.
I know my schematics are bad ... thats the reason i wrote it also in the description "You need to connect the WS2803 to the power-source (5v) .. and you need the connect the anode of the leds there to." *g* .. dont worry ... the first time i ordered the wrong leds too ... the dealer send my a mail and fixed my order ..
pretty cool.   i don't think you can power more than one (or possibly 2) 2803's  from the Arduino 5V port, plugged into the USB port...  You can fry your USB port (or the 2803 - but that's $2.00 not a laptop)

Use a separate 5V 1Amp power supply, and power the LED's, 2803's, and the Arduino (on Vin port)
Sure :-) ... i use the arduino 5v just for testing the columns ... two columns looks like the limit .. the voltage is heavly breaking down if you light up all led's ... but i should add this to the description ...
I make clocks with those same chips (and LPD6803's too), totalling 60-80 LEDs.  I use a Desktop PC power supply, and with a 400 watt P/S, I can light up all 80, @ full power white...  There are many tutorials on using a P/S for such an application.
Top