Skip to content

Instantly share code, notes, and snippets.

@danasf
Last active September 28, 2016 06:02
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save danasf/ae472b32b694ab74d57f to your computer and use it in GitHub Desktop.
Save danasf/ae472b32b694ab74d57f to your computer and use it in GitHub Desktop.
LED patterns with Edison
{
"name": "LEDPatternTest",
"description": "Testing WS2801 LED Strip on Intel Edison",
"version": "0.0.0",
"main": "main.js",
"engines": {
"node": ">=0.10.0"
},
"dependencies": { "mqtt": "^0.3.11" }
}
<!DOCTYPE html>
<!-- upload this to a server somewhere or serve locally -->
<html>
<head>
<title></title>
<meta charset="utf-8">
<style type="text/css">
#content { width:300px; margin:50px auto; border:2px #555; background:#eee; padding:20px; text-align: center; }
#myBtn { font-size: 1.5em; background:#0000cc; border:0; border-radius: 3px; color:#fff; padding:15px;}
#myBtn:hover { background:#000; }
</style>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
<script type="text/javascript">
$(document).ready(function() {
// on click
$("#myBtn").click(function() {
// post
$.post('message.php',{ message:"change me" },function(data) {
$("#result").html(data);
});
});
});
</script>
</head>
<body>
<div id="content">
<h1>MQTT Demonstration</h1>
<button id="myBtn">Change LED Pattern</button>
<div id="result"></div>
</div>
</body>
</html>
/* handle ws2801 led strip with edison */
var LEDStrip = function(spi,len) {
this.length = len;
this.buffer = new Buffer(this.length*3);
this.spi = spi;
this.debug = false;
}
LEDStrip.prototype.setup = function () {
this.buffer.fill(0);
this.fill(this.color(0,0,0));
};
LEDStrip.prototype.clear = function () {
this.buffer.fill(0);
this.update();
};
LEDStrip.prototype.color = function(r,g,b) {
return [r,g,b];
};
/* fill the entire strip */
LEDStrip.prototype.fill = function(color,cb) {
this.buffer.fill(0);
for(var i=0; i < this.length*3; i=i+3) {
this.buffer[i] = color[0]; // R
this.buffer[i+1] = color[1];// G
this.buffer[i+2] = color[2];// B
}
this.update();
if(cb) { cb(); }
};
/* set pixel at position x*/
LEDStrip.prototype.setPixel = function(pos,color) {
var pixelPos = pos*3;
this.buffer[pixelPos] = color[0];
this.buffer[pixelPos+1] = color[1];
this.buffer[pixelPos+2] = color[2];
};
/* write out to SPI */
LEDStrip.prototype.update = function() {
this.spi.write(this.buffer);
if(this.debug) { console.log("Strip updated!"+this.buffer.toString('hex')); }
};
module.exports = LEDStrip
/*jslint node:true, vars:true, bitwise:true, unparam:true */
/*jshint unused:true */
/*global */
/*
Proof of concept, Edison working with WS2801 LEDs
The device changes LED patterns and the LCD display when you press a button
or receive a message via MQTT.
Setup:
* Edison with Arduino breakout shield and Seeed's Grove Starter Kit
* WS2801 LEDs on SPI pins, 11, 13
* Push Button on Port D6 (Pin 6)
* RGB LCD Display on I2C bus
* Connection to iot.eclipse.org MQTT Server
*/
var m = require('mraa'), LEDStrip = require('./ledstrip.js'), LCD = require ('jsupm_i2clcd'), mqtt = require('mqtt');
var myInterval;
var count = 0; // counter, start at 0
var patterns = 6; // pattern options
// setup SPI via mraa
var spi = new m.Spi(0);
// pass SPI and number of leds
var leds = new LEDStrip(spi,35);
// setup leds
leds.setup();
// setup button on pin 6
var button = new m.Gpio(6); //setup digital read on pin 6
button.dir(m.DIR_IN); //set the gpio direction to input
// lcd
var lcd = new LCD.Jhd1313m1(6, 0x3E, 0x62);
lcdWrite("Hello!");
// mqtt
var client = mqtt.createClient(1883,"iot.eclipse.org");
//client.options.reconnectPeriod = 90;
client.subscribe("myledtest");
client.publish("myledtest","connected!");
// on receiving a new MQTT message, take action
client.on('message', function (topic, message) { console.log("incoming message!",message.toString()); takeAction(); });
// check for button press
checkforBtnPress();
function checkforBtnPress() {
// if the button is down
if(button.read()) {
client.publish("myledtest","button pushed!");
console.log("switched to action"+count);
takeAction();
}
setTimeout(checkforBtnPress,300);
};
function takeAction() {
clearInterval(myInterval);
/* show the following pattern */
switch (count) {
case 0:
// fill red
lcdWrite("fill red",[255,0,0]);
leds.fill([255,0,0]);
break;
case 1:
// fill green
lcdWrite("fill green",[0,255,0]);
leds.fill([0,255,0]);
break;
case 2:
// blue sequential fill
lcdWrite("seqment fill",[0,0,255]);
seqFill([0,0,255],function() { console.log("Done!"); });
break;
case 3:
// rainbow cycle
lcdWrite("rainbow cycle",[128,255,0]);
myInterval = rainbowCycle(10);
break;
case 4:
// circus cycle
lcdWrite("circus cycle",[128,0,128]);
var colors = [[255,0,0],[0,255,0],[0,0,255]];
myInterval = circusCycle(colors,200);
break;
case 5:
// solid rainbow cycle
lcdWrite("rainbow solid",[255,38,0]);
rainbow(10);
break;
case 6:
// solid rainbow cycle
lcdWrite("sinewave",[255,0,255]);
myInterval = sinewave(10);
break;
}
// update counter
count = (count === patterns) ? 0 : count+1;
};
/************************************
HELPERS
*************************************/
function lcdWrite(message,color) {
color = color || [0,128,0];
lcd.setColor(color[0],color[1],color[2]);
lcd.setCursor(0,1);
lcd.write(message);
};
/* color wheel function via https://github.com/adafruit/Adafruit_NeoPixel/blob/master/examples/strandtest/strandtest.ino */
function wheel(pos) {
pos = 255 - pos;
if (pos < 85) { return [255 - pos * 3, 0, pos * 3]; }
else if (pos < 170) { pos -= 85; return [0, Math.floor(pos * 3), Math.floor(255 - pos * 3)]; }
else { pos -= 170; return [Math.floor(pos * 3), Math.floor(255 - pos * 3), 0]; }
}
function rainbowValGen(len) {
var rainbow = [];
// sine period / number of leds
var seg = (2*Math.PI)/len;
for(var i=0; i < len; i++) {
// 3 offset sine waves makes a rainbow
var r = Math.floor(Math.sin(i*seg) * 127 + 128);
var g = Math.floor(Math.sin(i*seg+2) * 127 + 128);
var b = Math.floor(Math.sin(i*seg+4) * 127 + 128);
// gamma correct
rainbow.push([r,g,b].map(gamma));
}
return rainbow;
};
/* gamma correction */
function gamma(val) {
gammaVal = 2.8; // via adafruit for these led strips
return Math.floor(Math.pow(val/255,gammaVal)* 255 + 0.5);
};
/* like setInterval but limited in number of times */
function step(myFunc,cb,delay,numTimes) {
var repeat = numTimes;
(function runFn() {
if (repeat > 0) {
var times = numTimes-repeat;
myFunc(times);
repeat--;
setTimeout(runFn, delay);
} else { cb(); }
})();
};
/************************************
PATTERNS
*************************************/
/* sequential fill */
function seqFill(color,cb,delay) {
delay = delay || 50;
step(
// do a progressive fill of the LEDS
function(q) { leds.setPixel(q,color); leds.update(); },
// call back when finished
function() { if(cb) { cb(); } },
// delay between steps
delay,
// number of steps
leds.length
);
};
/* rainbow cycle */
function rainbowCycle(delay) {
/* sine wave based rainbow fill values */
var rainbows = rainbowValGen(leds.length);
return setInterval(function() {
for(var i=0; i < leds.length; i++) {
leds.setPixel(i,rainbows[i]);
}
leds.update();
rainbows.push(rainbows.shift());
},delay);
};
/* circus cycle */
function circusCycle(colors,delay) {
return setInterval(function() {
for(var i=0; i < leds.length; i++) {
var mod = i % colors.length;
leds.setPixel(i,colors[mod]);
}
leds.update();
colors.push(colors.shift());
},delay);
};
/* rainbow */
function rainbow(delay) {
var colors = [];
for (var i = 0; i < 256; i++) {
colors[i] = wheel(i).map(gamma);
}
step(
// do a progressive fill of the LEDS
function(q) { leds.fill(colors[q % 255]); },
// call back when finished
function() { console.log("Done!"); },
// 50ms delay between steps
delay,
// number of steps
colors.length
);
};
/* sine wave */
function sinewave(delay) {
var colors = [];
// sine period / number of leds
var seg = (2*Math.PI)/leds.length;
for(var i=0; i < leds.length; i++) {
//sine waves makes a rainbow
colors[i] = gamma(Math.floor(Math.sin(i*seg) * 127 + 128));
}
return setInterval(function() {
for(var i=0; i < leds.length; i++) {
var mod = i % colors.length;
leds.setPixel(i,[colors[mod],0,0]);
}
leds.update();
colors.push(colors.shift());
},delay);
};
<?php
/*
upload to a server somewhere with index.html, or serve locally
requires phpMQTT, grab the class here https://github.com/bluerhinos/phpMQTT
*/
require("./phpMQTT.php");
if($_POST['message']) {
$message = "LED Message sent at ".time();
$mqtt = new phpMQTT("iot.eclipse.org", 1883, "led test example");
if ($mqtt->connect()) {
$mqtt->publish("myledtest",$message,0);
$mqtt->close();
echo $message;
}
} else { echo "You didn't send anything!"; }
?>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment