Skip to content

Instantly share code, notes, and snippets.

@ejeklint
Last active December 12, 2015 04:28
Show Gist options
  • Save ejeklint/4714653 to your computer and use it in GitHub Desktop.
Save ejeklint/4714653 to your computer and use it in GitHub Desktop.
Squirrel code for controlling a LED strip with addressable LEDs using the almighty WS2801 driver.
//
// WS2810 RGB LED Driver Controller and Demo usage
//
//
// A selection of predefined colours. Add to taste.
//
enum Colour {
red = "\xff\x00\x00",
green = "\x00\xff\x00",
blue = "\x00\x00\xff",
yellow = "\xff\xaa\x00",
orange = "\xff\x80\x00",
purple = "\x80\x00\xff",
white = "\xff\xff\xff",
off = "\x00\x00\x00"
}
//
// Class that handles an array of WS2801 RGB LED controllers in a LED strip
// Uses spi257 so connect the strips clock to pin 5 and data to pin 7 (MOSI)
//
class WS2801 {
ledCount = null;
strip = null;
//
// Constructor. Number of LEDs in the strip must be specified.
//
constructor(noOfLEDs) {
ledCount = noOfLEDs;
strip = blob(ledCount * 3);
hardware.spi257.configure(SIMPLEX_TX, 5000); // Strip doesn't handle too fast clk. Limit to 5 MHz
imp.sleep(0.01);
}
//
// Set colour of entire strip with setColour(Colour.blue)
// Set colour of 4th LED with setColour(Colour.blue, 3)
// Set colour of several LEDs with setColour(Colour.blue, [1,2,5,8,11])
// Unless a third parameter is true, previous strip colors will be lost. To keep them
// call with for example setColour(Colour.blue, [1,2,3], true)
//
function setColour(colour, index = null, keepValues = false) {
if (!keepValues) {
// Allocate a new and clean blob (all leds off)
strip = blob(ledCount * 3);
}
if (index == null) {
// Set whole strip to same colour
for (local i = 0; i < ledCount; i++) {
strip[i*3] = colour[0];
strip[i*3+1] = colour[1];
strip[i*3+2] = colour[2];
}
} else if (typeof index == "array") {
// Set leds in array to colour
foreach(i in index) {
strip[i*3] = colour[0];
strip[i*3+1] = colour[1];
strip[i*3+2] = colour[2];
}
} else {
// Set a single led to colour
strip[index*3] = colour[0];
strip[index*3+1] = colour[1];
strip[index*3+2] = colour[2];
}
writeToStrip();
}
//
// Fills the strip in a "swipe" manner from first to last LED.
// Default wait between each step is 20 ms.
//
function colourWipe(colour, wait = 0.02) {
for (local i = 0; i < ledCount; i++) {
strip[i*3] = colour[0];
strip[i*3+1] = colour[1];
strip[i*3+2] = colour[2];
writeToStrip();
imp.sleep(wait);
}
}
//
// Loops over all colours in 256 steps. All LEDs have the same colour.
//
function rainbow(wait = 0.02) {
for (local j = 0; j < 256; j++) {
for (local i = 0; i < ledCount; i++) {
local colour = wheel((i+j) % 255);
strip[i*3] = colour[0];
strip[i*3+1] = colour[1];
strip[i*3+2] = colour[2];
}
writeToStrip();
imp.sleep(wait);
}
}
//
// Fancy effect demo that creates a rainbow distributed over the strip and the cycles the colours.
// Default values are 1 cycle and 20 ms between each colour change. Quite tedious, really...
//
function rainbowCycle(cycles = 1, wait = 0.02) {
for (local j = 0; j < 256 * cycles; j++) {
for (local i = 0; i < ledCount; i++) {
local colour = wheel(((i*256 / ledCount) + j) % 255);
strip[i*3] = colour[0];
strip[i*3+1] = colour[1];
strip[i*3+2] = colour[2];
}
writeToStrip();
imp.sleep(wait);
}
}
//
// Shift the led strip one led per call.
//
function shift() {
// Led 0 should be 1, 1 should be 2 etc
local newStrip = blob(ledCount * 3);
for (local i = 0; i < ledCount * 3; i++) {
newStrip[(i+3)%(ledCount*3)] = strip[i];
}
strip = newStrip;
writeToStrip();
}
//
// Rotate strip.
// Defaults to one complete turn and delay of 50 ms between each step.
// Note that you can rotate fractional turns too!
//
function rotate(turns = 1.0, stepDelay = 0.05) {
for (local i = 0; i < math.floor(turns * ledCount); i++) {
shift();
imp.sleep(stepDelay);
}
}
//
// Writes out data to strip and assures it latches before execution continues.
//
function writeToStrip() {
hardware.spi257.write(strip);
// Wait so strip "latches"
imp.sleep(0.001);
}
//
// Returns a colour positioned at 'position' on a colour wheel with 256 steps (I think, nicked this code).
//
function wheel(position) {
local colour = blob(3);
if (position < 85) {
colour[0] = position * 3;
colour[1] = 255 - position * 3;
colour[2] = 0;
return colour;
} else if (position < 170) {
position = position - 85;
colour[0] = 255 - position * 3;
colour[1] = 0;
colour[2] = position * 3;
return colour;
} else {
position = position - 170;
colour[0] = 0;
colour[1] = position * 3;
colour[2] = 255 - position * 3;
return colour;
}
}
}
//
// Example use below
//
server.log("Enjoy the show!");
// Instantiate
local strip = WS2801(20);
// Set all to off
strip.setColour(Colour.off);
// Set all to white
strip.setColour(Colour.white);
imp.sleep(1.0);
// Swipe in red to all LEDs
strip.colourWipe(Colour.red);
// Set first LED to red
strip.setColour(Colour.red, 0);
imp.sleep(0.5);
// Shift the strip 1 LED for each call
strip.shift();
imp.sleep(0.5);
strip.shift();
imp.sleep(0.5);
strip.shift();
imp.sleep(0.5);
// Rotate the strip 1.5 times
strip.rotate(1.5);
// Set all LEDs with even index to orange
strip.setColour(Colour.orange, [0,2,4,6,8,10,12,14,16,18]);
imp.sleep(1.0);
// Set all LEDs with odd index to green and keep the previous setting
strip.setColour(Colour.green, [1,3,5,7,9,11,13,15,17,19], true);
imp.sleep(1.0);
// Set all LEDs with even index to oranga without keeping previous setting
strip.setColour(Colour.orange, [0,2,4,6,8,10,12,14,16,18]);
imp.sleep(1.0);
// Do a fancy rainbow
strip.rainbowCycle(2, 0.005);
// And rotate it, for the world!
strip.rotate(10);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment