4x4x4 RGB Cube+Pics TLC5940, Fixed Multiplexing...

First, the pics! Description: - Top left, top right, bottom right are TLC5940s - Bottom left is an Ardweeny http://solarbotics.com/products/kardw/ - Bottom row in the middle (large capacitor): 5V -> 10V charge pump - The other 4 component clusters in the bottom row are driving assemblies for n-channel mosfets (I know p-ch might have been better but I had these on hand)

I had to greatly reduce the brightness and adjust the shutter speed to 1/80 to get this shot. Multiplexing and the brightness of the leds wreak havoc with my cheap camera.

This project was much larger than I originally anticipated (400+ solder points) and filled with challenges. The biggest was getting multiplexing going. As acleone, author of the TlcMux library notes in his examples:

Currently I'm trying to fix timing issues by putting some D-type positive edge triggered latches between PORTC and the 3:8 line decoder, clocked on the rising edge of XLAT, but this doesn't seem to help. I'm bringing the circuit in to the logic analyzer this weekend to see exactly when the ISR runs and how long it takes to shift in the GS data.

I personally experienced ghosting (dim illumination of desired pattern in adjacent rows), flickering, and some patterns that wouldn't illuminate correctly.

Also found these unresolved forum posts: http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1285107015/8 http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1241054901 http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1265127525 ...

After lots of debugging and a nice pile of dead TLC5940s I think the issue is with undesired XLAT / BLANK latching even when disable_XLAT_pulses() is called.

The Workaround I have described these changes to acleone in a separate email. There is probably a more elegant solution but this works. Reference this diagram: http://students.washington.edu/acleone/codes/tlc5940arduino/img/breadboard-arduino-tlc5940.png - Attach XLAT and BLANK to Analog 0 (pin 14 in code) and 1 (pin 15 in code) instead of the pins listed to avoid any timer / PWM interaction. Set pinMode(14, OUTPUT); pinMode(15, OUTPUT); in setup.

  • Change the ISR:
  if (!isShifting) {
    isShifting = 1;
    // This activates pins to facilitate multiplexed power 
    PORTC = shiftPower[shiftRow];

    // -- THE IMPORTANT BIT -- //
    digitalWrite(BLANK, HIGH);
    // 3 x 62.5ns = 187.5ns  (Blank needs to exceed 300ns to avoid shortening the GS cycle)
    digitalWrite(XLAT, HIGH);
    // XLAT for 62.5 ns
    digitalWrite(XLAT, LOW);
    // Another 187.5 ns safely exceeding the minimum 300ns BLANK requirement
    digitalWrite(BLANK, LOW);
    // -- End THE IMPORTANT BIT -- //

    if (++shiftRow == NUM_ROWS){
      shiftRow = 0;
    isShifting = 0;

What does this do? Well, we've taken full control of BLANK and XLAT so data is latched immediately and only after the TLCs are fully loaded. This also matches the datasheet timings as closely as was feasible. I don't think the last set of noops are entirely necessary (the instructions before likely took all the required time) but they're there for clarity against the datasheet.

Hope that helps someone.

One more thing: Why the MOSFETs? I built small scale prototypes using a variety of transistors (2N2222, TIP142, S9013, 2SA2064, 2907A, etc.) and found that the MOSFET (an irlu8721) delivered 30% - 40% more current at full 5V. The downside is the drive circuitry (homebrew charge pump and transistors to ground the gate) but they're cheap and it was an interesting part of the project.

The MOSFETs deliver so much power (only 8 milliohms of resistance) that its trivial to cook the TLC5940s so you can be guaranteed maximum brightness within the thermal limits of the TLC5940s.

It took quite a while to design and assemble but the end result is everything I was hoping for. If there's a lot of interest, I'll do up a full design / construction article.

I plan to move on to an 8x8x8 by extending the same basic design.

Thanks to the Arduino team for a great platform!

Looks awesome. :)

Ive been having the same problems with my multiplexed 8*8 RGB, Im using a 595 to twiddle the rows, I tried your changes and it seemed to work, but as soon as I tried to set the brightness below 512 the leds went very dark, most odd, no Ive idea what`s going on.

Do you see similar issues ?

hmm looks like the brightness falls off using some kind power function, i.e. it`s not linear, in fact as you get past 512 it accelerates

Nice build! Nice pictures too!

I'm guessing; you multiplex each layer somehow? I never used TLC5940s, but three of them can do one layer simultaneously. However I can foresee some trouble if these TLC5940s also PWM their output? Like some interference between TLC5940s PWM frequency and the multiplexing. I'd like to take a peek at a more complete schematics and code.

This project was much larger than I originally anticipated

This seems to be a general rule ;)

al3ph: Brightness is relatively linear throughout the PWM range with the MOSFET drivers blocks that manage the cube's multiplexed power.

Do you still have the 512 PWM boundary if you disable multiplexing (ie. hold power constant on just one row / plane)? What is your multiplexing frequency?

raron: I use the MOSFET driver blocks to multiplex power. The driver blocks are directly controlled by non-PWM'd arduino ports, in a 1 port to 1 power plane (4x4 LEDs) configuration. The multiplexing frequency is approximately 1Khz while the PWM frequency is much higher (have to check the TLC5940 lib docs for the exact number). This gives each plane of LEDs 1 ms of uninterrupted power which seems sufficient to see PWM across the range.

I sketched most of my schematics on paper or figured things out on breadboards. Was there something specific you wanted to see (eg. charge pump, power drivers, etc.)? I'll beef up the comments in my code and post it here.