For one of my project, I want to create a 32*32 RGB LED matrix with 5050 SMD LED. I have been doing research and it seems like the way to do it is to build the matrix and use multiplexing to power them. However, with multiplexing, it will require 32 out pins to power them. I am wondering if there's anyway to power such matrix with less pins? Also is there a general tutorial on how to build such matrix?
Sorry if I am asking noob question. Any help is appreciated!!
Well, 32x32RGB is really more like 32 x 96.
One way is banks of shift registers to source current into rows, and them more shift registers to sink current from columns. Every 400uS, use SPI.transfer to send out 4 bytes of anode data, and 12 bytes of cathode data. Only need 4 pins - SCK, MOSI, and slave select for each bank. Maybe a 5th pin for output enable of the cathode drives ,
disable the cathode drive while anode data is being set up to prevent ghosting.
Sending the data will take around 20uS if done properly (direct port manipulation, no loops, data pulled from arrays,
SPDR = anode[(arrayPointer * 4)+0]; nop; (15 nop's total)
SPDR = anode[(arrayPointer * 4)+1]; nops...
SPDR = anode[(arrayPointer * 4)+2]; nops...
SPDR = anode[(arrayPointer * 4)+3]; nops...
anode array will hold the info to be displayed, every 4 bytes is a vertical column
byte anode[] = {
c0a, c0b, c0c, c0d, // Red: c0a represents data for column 0 byte a, then byte b, byte c, byte d
c1a, c1b, c1c, c1d, // Green: RGB column 0
c2a, c2b, c2c, c2d, // Blue: RG column 0
:
c93a, c93b, c93c, c93d, // Red RGB column 31
c94a, c94b, c94c, c94d, // Green RGB colomn 31
c95a, c95b, c95c, c95d, // Blue RGB column 32
}
and
SPDR =cathode[cathodePointer[0]]; nops...
SPDR =cathode[cathodePointer[1]]; nops...
SPDR =cathode[cathodePointer[2]]; nops...
SPDR =cathode[cathodePointer[3]]; nops...
SPDR =cathode[cathodePointer[4]]; nops...
SPDR =cathode[cathodePointer[5]]; nops...
SPDR =cathode[cathodePointer[6]]; nops...
SPDR =cathode[cathodePointer[7]]; nops...
SPDR =cathode[cathodePointer[8]]; nops...
SPDR =cathode[cathodePointer[9]]; nops...
SPDR =cathode[cathodePointer[10]]; nops...
SPDR =cathode[cathodePointer[11]]; nops...
cathode array will hold the info for the column to be turned on
byte cathode[] = {
0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,
}
after each column, manipulate the data to walk the 1 across the array.
So column 0 looks like above, then:
0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,
0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,
0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,
and ending
0x20, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x40, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x80, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
Could also put all that into a big array.
Already using 4 x 96 = 384 bytes for the anodes,
cathode would need another 12 x 96 = 1152 bytes. Put it PROGMEM I suppose.
So, the display can be left on for ~380uS per column.
400uS will yield a 26 Hz refresh rate, so it should not seem flickery to the eye.
With 5050 LEDS and ~500mcd luminous intenstity, I think it will still plenty bright too.
Might want to get a few and try first.
If not bright enough then can pulse them at higher currents, up to 100mA:
Peak Forward Current (1/10th duty cycle, 0.1ms pulse width) IFP 3x100 mA
(this approach is 1/96th duty cycle, 0.38mS pulse width.
Can one argue that
(20mA x0.1mS)/10 = (.02 * .0001)/10 = .000,000,2AS
is comparable to
(100mA x .4mS)/96 =(.1 * .0004)/96 = 0.000,000,42AS ??
Or would that higher on-time at the larger current burn the LEDs out? I don't know.
Will need P-channel MOSFETs to source 20+ to 100mA current to the rows, and N-channel MOSFETs to sink current from the columns, 32 x 100mA = 3.2A, so be sure to get like a 4A capable supply.
If stick with 20mA, then CD74AC164 would be a good anode driver
With 20mA, need to sink 640mA/column, so a Logic Level, Lew Rds, Low Gate Capacitance N-channel MOSFET per column, driven by 74HC595, would be good
Use a pull down resistor on the gate to turn them off when HC595 output is disabled to save time & prevent ghosting:
// psuedo code, should give the idea of what will be done
void loop(){
if (time to update display){ // blink without delay stlye of time capture/compare
// point to next column of data
anodePointer = anodePointer +1;
// reset it at end
if (anodePointer == 32){anodePointer = 0;}
// turn off cathode drive
HC595 OE off using direct port manipulation of HC595 OE pin (or send out 12 bytes of 0)
// send out anode data
SPDR transfers from above
// send out cathode info
SPDR transfers from above
// and turn outputs back on if turned off
HC595 OE on using direct port manipulation of HC595 OE pin
// LEDs are now on - update cathode info for next pass
// large array: SPDR transfers as above
// or: code to walk a 1 across the 12 bytes
} // end time check
// make array updates if needed based on whatever - finish it in 400uS
} // end loop
Alternately, break the display into 2 halves, 32 x 16 each (32x48 with RGB) and set up one, then setup the other, can leave refresh at 800uS then. Only takes another set of row drives.
yansuck:
I want to create a 32*32 RGB LED matrix with 5050 SMD LED. I have been doing research and it seems like the way to do it is to build the matrix and use multiplexing to power them. However, with multiplexing, it will require 32 out pins to power them. I am wondering if there's anyway to power such matrix with less pins?...
One option would be to use WS2812 / WS2812B LEDs, they're in the 5050 form factor but come with their own LED driver chip so they only need 1 Arduino pin. You can control them with Arduino libraries like FastSPI_LED2 or Adafruit's NeoPixel.
You will have trouble driving a matrix that size with a standard Arduino. A 32x32 RGB matrix will need 3K of RAM and the Uno, Leonardo, etc. only have 2K.
You may want to look at the Teensy 3.0 / 3.1; they have at least 16K of RAM and you can use the OctoWS2811 library to efficiently control thousands of LEDs.
I'd like to see the math behind that please, as I demonstarted that only 384 bytes are needed to hold the on/off state of 32x96 LEDs above.
You're correct you can do it with 384 bytes but as you say that only gives 1 bit per RGB LED element, which gives a gamut of 8 colors:
RGB
000 - black
001 - blue
010 - green
011 - cyan
100 - red
101 - purple
110 - yellow
111 - white
This may be acceptable for yansuck's project but in my experience most people want RGB matrixes for fancy color effects or shading etc., which requires more color depth, which requires more bits per pixel. The standard is 8 bits per element, which is how I came up with 3K needed (32 x 32 x 3). Sorry for the confusion.