Arduino code to drive Octobrite LEDs

I picked up an Octobrite from www.macetech.com at Maker Faire last weekend and finally got around to trying it out. Here’s some code that works for a single Octobrite, and should work for multiple daisy-chained together as well.

/*

// Color channel constants
#define RED 0
#define GREEN 1
#define BLUE 2

// TLC5947 maintains 12 bits of grayscale per LED channel
#define CHANNEL_BITS 12
#define CHANNEL_MAX ( (1<<CHANNEL_BITS) - 1)

// TLC5947 pins
int SIN_PIN = 8;
int SCLK_PIN = 9;
int BLANK_PIN = 10;
int XLAT_PIN = 11;

// Interpolation constants
int lerpsteps = 5;
int stepdelay = 25;

int lerpindex = 0;

// Color table and current/prev color state. The interpolation looks
// best when only one channel is changing during an interpolation
// between a pair of adjacent colors.
int colorCount = 6;
int clutred[6] = { 1, 1, 0, 0, 0, 1};
int clutgreen[6] = { 0, 0, 0, 1, 1, 1};
int clutblue[6] = { 0, 1, 1, 1, 0, 0};
int currentColorIndex = 0;
int previousColor[3];
int currentColor[3];

void setup()
{
// Setup TLC5947 pins
pinMode(SIN_PIN, OUTPUT);
pinMode(SCLK_PIN, OUTPUT);
pinMode(BLANK_PIN, OUTPUT);
pinMode(XLAT_PIN, OUTPUT);

// Turn off all LEDs
digitalWrite(BLANK_PIN, HIGH);

// Default state for clock and data latch
digitalWrite(SCLK_PIN, LOW);
digitalWrite(XLAT_PIN, LOW);

// Init comms for debug info
Serial.begin(9600);

// Reset color state
currentColor = clutred[currentColorIndex];
currentColor = clutgreen[currentColorIndex];
currentColor = clutblue[currentColorIndex];
NextColor();

// And write the colors to the octobrite
WriteColors();

// Finally enable the LEDs
digitalWrite(BLANK_PIN, LOW);
}

// Called when we’ve completed an interpolation between a pair of
// colors. This sets us up to interpolate to the next color in
// the lookup table
void NextColor()
{
// We’ve finished interpolating to the current color, so it becomes the
// previoud color we’re interpolating from
previousColor = currentColor;
previousColor = currentColor;
previousColor = currentColor;

// And pick the next color in the CLUT for the current color
currentColorIndex = (currentColorIndex + 1) % colorCount;
lerpindex = 0;
currentColor = clutred[currentColorIndex];
currentColor = clutgreen[currentColorIndex];
currentColor = clutblue[currentColorIndex];
}

// Writes out a single 12-bit grayscale channel
void WriteChannel(int value)
{
int bit;

// Write value, MSB first
for (bit=11; bit>=0; --bit)
{
if (value & (1<<bit))
{
digitalWrite(SIN_PIN, HIGH);
}
else
{
digitalWrite(SIN_PIN, LOW);
}

// We need to wait 30ns after writing data before clocking it in.
// Fortunately, our AVR is slow enough that we don’t need to
// do an explicit wait here
digitalWrite(SCLK_PIN, HIGH);
digitalWrite(SCLK_PIN, LOW);
}
}

void WriteColors()
{
// First calculate the current interpolated color value
int red = (CHANNEL_MAXpreviousColor(lerpsteps-lerpindex) + CHANNEL_MAXcurrentColorlerpindex) / lerpsteps;
int green = (CHANNEL_MAXpreviousColor(lerpsteps-lerpindex) + CHANNEL_MAXcurrentColorlerpindex) / lerpsteps;
int blue = (CHANNEL_MAXpreviousColor(lerpsteps-lerpindex) + CHANNEL_MAXcurrentColorlerpindex) / lerpsteps;

// Disbaled debug output
if (false)
{
Serial.print(“RGB=(”);
Serial.print(red);
Serial.print(", “);
Serial.print(green);
Serial.print(”, “);
Serial.print(blue);
Serial.println(”)");
}

// Now write the next RGB value, which will shift the colors
// down along the other LEDs
WriteChannel(red);
WriteChannel(green);
WriteChannel(blue);

// Finally latch in the new color values
digitalWrite(XLAT_PIN, HIGH);
delay(1);
digitalWrite(XLAT_PIN, LOW);
}

void loop()
{
// Step the interpolation by one frame
++lerpindex;
if (lerpindex > lerpsteps)
{
// We finished the interpolation between the current
// color pair. Set up the next color pair.
NextColor();
}

// Update the LEDs
WriteColors();

// Throttle the animation
delay(stepdelay);
}

[/quote]

That's awesome....to be honest, you probably have more experience running the OctoBrite than I do at this point :)

It sort of demanded to be designed when I found the TLC5947, and after playing around with the silkscreen it demanded to be produced. But I'm still trying to think of a really good use for it. Maybe some kind of RGB Stribe variant...what ideas do you have?

You did a great job on that board -- it's a thing of beauty! Everything is so tiny and the silkscreen is very cool.

I'm thinking of using it as a backlight for a picture frame. Hopefully I'll get some time next week to work on it.

The form factor and how light it is might also suggest a POV application...

I ordered my Octobrite yesterday. While waiting (patiently?) for it to arrive, I have a few newbie questions that the MaceTech documentation page didn’t address:

  1. I assume the “5V” pad is for +5 volts?
  2. Is there a ground connection required for the Octobrite?

I’m new at board level interfacing, and don’t want to fry anything on my first try.

Thanks!

-Rich

Rich,

The documentation at http://docs.macetech.com/doku.php/octobrite should contain everything you need...it discusses the various power supply requirements. I did just add a comment about needing to connect the grounds to the ground pads.

Ok, thanks!

FYI, here's a video of the code. http://www.youtube.com/watch?v=f_cK9FAbxxw

Nice I love the way those color ramps look.

I altered the code slightly and used it to drive some more subtle color animations for this picture frame:

http://www.atomsandelectrons.com/blog/post/Octobrite-Picture-Frame.aspx

how can i connect actobrite to arduino ?