Skip to content

Instantly share code, notes, and snippets.

@tomoinn
Created July 10, 2013 18:49
Show Gist options
  • Save tomoinn/5969009 to your computer and use it in GitHub Desktop.
Save tomoinn/5969009 to your computer and use it in GitHub Desktop.
A bit of code to demonstrate the light strip from insomnialighting.com here - http://www.insomnialighting.com/catalog/index.php?main_page=product_info&cPath=6_4&products_id=8 using an arduino nano. Data and clock lines on the strip are connected to pins 11 and 13 of the nano respectively to make use of hardware SPI.
#include "LPD8806.h"
#include "SPI.h"
// Simple test for 260 (5 meters) of LPD8806-based RGB LED strip, this is a
// modified version of the original demo - it creates a rainbow, animates it
// and fades from black->colours->white->colours->black in a cycle, holding
// somewhat longer on the full colour, all while cycling the rainbow colours.
// This has been tested with a high density (260 LEDs / 5m) strip and a nano
// board, running from a 5V 10A PSU.
/*****************************************************************************/
// Number of RGB LEDs in strand:
const int nLEDs = 260;
// Chose 2 pins for output; can be any valid output pins. These aren't used
// in the code as it stands as I'm using the hardware SPI support on the nano
// int dataPin = 2;
// int clockPin = 3;
// The offset is used to cycle colours along the strip
int offset = 0;
// Multiple is used to space out the spectrum, a value of 4 will be four
// times as many cycles as a value of 1 on any given length
const int multiple = 4;
// Number of steps the colour pattern advances each tick
const int offsetDelta = 2;
// First parameter is the number of LEDs in the strand. The LED strips
// are 32 LEDs per meter but you can extend or cut the strip. Next two
// parameters are SPI data and clock pins:
//LPD8806 strip = LPD8806(nLEDs, dataPin, clockPin);
// You can optionally use hardware SPI for faster writes, just leave out
// the data and clock pin parameters. But this does limit use to very
// specific pins on the Arduino. For "classic" Arduinos (Uno, Duemilanove,
// etc.), data = pin 11, clock = pin 13. For Arduino Mega, data = pin 51,
// clock = pin 52. For 32u4 Breakout Board+ and Teensy, data = pin B2,
// clock = pin B1. For Leonardo, this can ONLY be done on the ICSP pins.
// Hardware SPI on the nano uses clock = 13, data = 11
LPD8806 strip = LPD8806(nLEDs);
void setup() {
// Start up the LED strip
strip.begin();
// Update the strip, to start they are all 'off'
strip.show();
}
void loop() {
unsigned int n, mode;
for (mode = 0; mode < 8; mode++) {
for (n = 0; n < 256; n+=5) {
switch (mode) {
case 0: // Fade from black to full saturated colour
cycle(offset, 255, n);
break;
case 5: // Fade from full colour to white
cycle(offset, 255-n, 255);
break;
case 6: // Fade from white to full colour
cycle(offset, n, 255);
break;
case 7: // Fade from full colour to black
cycle(offset, 255, 255-n);
break;
default: // Cycle with full saturation and value
cycle(offset, 255, 255);
}
// Increment the offset to animate the colour pattern
offset = (offset + offsetDelta) % strip.numPixels();
}
}
}
// Set LED colours into a rainbow with specified saturation and value
void cycle(unsigned int offset, unsigned int s, unsigned int v) {
unsigned int n;
for (n = 0; n < strip.numPixels(); n++)
strip.setPixelColor(n, hsvToColour(n * multiple + offset,s,v));
strip.show();
}
// Build a colour to pass to the strip API from a hue, saturation, value triple.
// Note that with the strip I'm using the rgb values are in fact rbg, you will
// need to modify the various return statements if this isn't the case for your
// hardware. Saturation, value and hue values are all in the range 0-255. If the
// supplied values are not in this range value and saturation are clamped to 255
// if higher, hue is taken with the supplied value mod 255 (hue being a
// quantity which wraps around the edge of the colour space)
uint32_t hsvToColour(unsigned int h, unsigned int s, unsigned int v) {
unsigned char region, remainder, p, q, t;
// Sanity check ranges and check for no saturation
h = h % 256;
if (s > 255) s = 255;
if (v > 255) v = 255;
else v = (v * v) >> 8;
if (s == 0) return strip.Color(v >> 1, v >> 1, v >> 1);
// Map HSV to RGB, use to build a colour value for the strip library
region = h / 43;
remainder = (h - (region * 43)) * 6;
p = (v * (255 - s)) >> 9;
q = (v * (255 - ((s * remainder) >> 8))) >> 9;
t = (v * (255 - ((s * (255 - remainder)) >> 8))) >> 9;
v = v >> 1;
switch (region) {
case 0:
return strip.Color(v, p, t);
case 1:
return strip.Color(q, p, v);
case 2:
return strip.Color(p, t, v);
case 3:
return strip.Color(p, v, q);
case 4:
return strip.Color(t, v, p);
}
return strip.Color(v, q, p);
}
@theanswerisnt42
Copy link

When I first downloaded this I changed nLEDs to 48 because that is the length of the strip that I was using. The colors didn't really "run" down the strip, they mostly flickered.

In line 76 the % strip.numPixels() operation was resulting in the offset getting reset pretty often. I retried with the original 260 pixels (even with a strip of only 48) as well as 96 (when I connected two of my strips together) and the jumping was less pronounced but still evident.

The offset goes through a couple of other options, and is finally passed as the hue value to the hsvToColour void, when it is then returned to a value between 0 and 255 in line 101.

So, I eliminated the % strip.numPixels() portion of line 76, and the color "runs" very smoothly now down the strip. This may cause a problem eventually depending on the size of the offset integer, but works for a few cycles at least. It could be reset to zero 77 or 78 and would still look as smooth, as the reset happens when it's dark anyway.

I realize this code is quite old, however I came upon it via the adafruit/LPD8806 library looking for a starting addressable LED project and spent an hour or two figuring out what was going on. Just trying to help anyone else stumbling upon this in the future.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment