First try on WS2812FX library integration

This commit is contained in:
Tobias Blum 2017-02-05 01:48:28 +01:00
parent ff878f8ef6
commit c83a560d30
5 changed files with 169 additions and 253 deletions

View file

@ -26,12 +26,11 @@ WebSocketsServer webSocket = WebSocketsServer(81);
// ***************************************************************************
// Load libraries / Instanciate Neopixel
// Load libraries / Instanciate WS2812FX library
// ***************************************************************************
#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
#include <avr/power.h>
#endif
// https://github.com/kitesurfer1404/WS2812FX
#include <WS2812FX.h>
WS2812FX strip = WS2812FX(NUMLEDS, PIN, NEO_GRB + NEO_KHZ800);
// Parameter 1 = number of pixels in strip
// Parameter 2 = Arduino pin number (most are valid)
@ -40,7 +39,6 @@ WebSocketsServer webSocket = WebSocketsServer(81);
// NEO_KHZ400 400 KHz (classic 'v1' (not v2) FLORA pixels, WS2811 drivers)
// NEO_GRB Pixels are wired for GRB bitstream (most NeoPixel products)
// NEO_RGB Pixels are wired for RGB bitstream (v1 FLORA pixels, not v2)
Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUMLEDS, PIN, NEO_GRB + NEO_KHZ800);
// IMPORTANT: To reduce NeoPixel burnout risk, add 1000 uF capacitor across
// pixel power leads, add 300 - 500 Ohm resistor on first pixel's data input
@ -76,7 +74,7 @@ void configModeCallback (WiFiManager *myWiFiManager) {
uint16_t i;
for (i = 0; i < strip.numPixels(); i++) {
strip.setPixelColor(i, 0, 255, 0);
strip.setPixelColor(i, 0, 0, 255);
}
strip.show();
}
@ -114,9 +112,11 @@ void setup() {
// ***************************************************************************
// Setup: Neopixel
// ***************************************************************************
strip.begin();
strip.init();
strip.setBrightness(brightness);
strip.show(); // Initialize all pixels to 'off'
strip.setSpeed(200);
strip.setMode(FX_MODE_RAINBOW_CYCLE);
strip.start();
// ***************************************************************************
// Setup: WiFiManager
@ -334,6 +334,15 @@ void setup() {
getStatusJSON();
});
server.on("/get_modes", []() {
getModesJSON();
});
server.on("/set_mode", []() {
getArgs();
mode = SET_MODE;
});
server.begin();
}
@ -342,37 +351,42 @@ void loop() {
webSocket.loop();
// Simple statemachine that handles the different modes
if (mode == OFF) {
//colorWipe(strip.Color(0, 0, 0), 50);
uint16_t i;
for (i = 0; i < strip.numPixels(); i++) {
strip.setPixelColor(i, 0, 0, 0);
if (mode == SET_MODE) {
DBG_OUTPUT_PORT.printf("SET_MODE: %d %d\n", ws2812fx_mode, mode);
strip.setMode(ws2812fx_mode);
mode = HOLD;
}
strip.show();
//mode = HOLD;
if (mode == OFF) {
strip.setColor(0,0,0);
strip.setMode(FX_MODE_STATIC);
mode = HOLD;
}
if (mode == ALL) {
uint16_t i;
for (i = 0; i < strip.numPixels(); i++) {
strip.setPixelColor(i, main_color.red, main_color.green, main_color.blue);
}
strip.show();
//mode = HOLD;
strip.setColor(main_color.red, main_color.green, main_color.blue);
strip.setMode(FX_MODE_STATIC);
mode = HOLD;
}
if (mode == WIPE) {
colorWipe(strip.Color(main_color.red, main_color.green, main_color.blue), delay_ms);
strip.setColor(main_color.red, main_color.green, main_color.blue);
strip.setMode(FX_MODE_COLOR_WIPE);
mode = HOLD;
}
if (mode == RAINBOW) {
rainbow(delay_ms);
strip.setMode(FX_MODE_RAINBOW);
mode = HOLD;
}
if (mode == RAINBOWCYCLE) {
rainbowCycle(delay_ms);
strip.setMode(FX_MODE_RAINBOW_CYCLE);
mode = HOLD;
}
if (mode == THEATERCHASE) {
theaterChase(strip.Color(main_color.red, main_color.green, main_color.blue), delay_ms);
strip.setColor(main_color.red, main_color.green, main_color.blue);
strip.setMode(FX_MODE_THEATER_CHASE);
mode = HOLD;
}
if (mode == THEATERCHASERAINBOW) {
theaterChaseRainbow(delay_ms);
strip.setMode(FX_MODE_THEATER_CHASE_RAINBOW);
mode = HOLD;
}
if (mode == HOLD) {
if (exit_func) {
@ -382,4 +396,8 @@ void loop() {
if (mode == TV) {
tv();
}
if (mode != TV) {
strip.service();
}
}

View file

@ -40,22 +40,6 @@ void updateLed (int led, int brightness) {
}
// Input a value 0 to 255 to get a color value.
// The colours are a transition r - g - b - back to r.
uint32_t Wheel(byte WheelPos) {
WheelPos = 255 - WheelPos;
if (WheelPos < 85) {
return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3);
}
if (WheelPos < 170) {
WheelPos -= 85;
return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3);
}
WheelPos -= 170;
return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
}
// See: http://forum.mysensors.org/topic/85/phoneytv-for-vera-is-here/13
void tv() {
checkForRequests();
@ -114,111 +98,5 @@ void tv() {
}
// Fill the dots one after the other with a color
void colorWipe(uint32_t c, uint8_t wait) {
uint16_t i;
for (i = 0; i < strip.numPixels(); i++) {
strip.setPixelColor(i, 0, 0, 0);
}
strip.show();
for (uint16_t i = 0; i < strip.numPixels(); i++) {
strip.setPixelColor(i, c);
strip.show();
checkForRequests();
if (exit_func) {
exit_func = false;
return;
}
delay(wait);
}
mode = HOLD;
}
void rainbow(uint8_t wait) {
uint16_t i, j;
for (j = 0; j < 256; j++) {
for (i = 0; i < strip.numPixels(); i++) {
strip.setPixelColor(i, Wheel((i + j) & 255));
}
strip.show();
checkForRequests();
if (exit_func) {
exit_func = false;
return;
}
delay(wait);
}
}
// Slightly different, this makes the rainbow equally distributed throughout
void rainbowCycle(uint8_t wait) {
uint16_t i, j;
for (j = 0; j < 256; j++) { // 1 cycle of all colors on wheel
for (i = 0; i < strip.numPixels(); i++) {
strip.setPixelColor(i, Wheel(((i * 256 / strip.numPixels()) + j) & 255));
}
strip.show();
checkForRequests();
if (exit_func) {
exit_func = false;
return;
}
delay(wait);
}
}
// Theatre-style crawling lights.
void theaterChase(uint32_t c, uint8_t wait) {
for (int q = 0; q < 3; q++) {
for (int i = 0; i < strip.numPixels(); i = i + 3) {
strip.setPixelColor(i + q, c); //turn every third pixel on
}
strip.show();
checkForRequests();
if (exit_func) {
exit_func = false;
return;
}
delay(wait);
for (int i = 0; i < strip.numPixels(); i = i + 3) {
strip.setPixelColor(i + q, 0); //turn every third pixel off
}
}
}
// Theatre-style crawling lights with rainbow effect
void theaterChaseRainbow(uint8_t wait) {
for (int j = 0; j < 256; j++) { // cycle all 256 colors in the wheel
for (int q = 0; q < 3; q++) {
for (int i = 0; i < strip.numPixels(); i = i + 3) {
strip.setPixelColor(i + q, Wheel( (i + j) % 255)); //turn every third pixel on
}
strip.show();
checkForRequests();
if (exit_func) {
exit_func = false;
return;
}
delay(wait);
for (int i = 0; i < strip.numPixels(); i = i + 3) {
strip.setPixelColor(i + q, 0); //turn every third pixel off
}
}
}
}

View file

@ -1,9 +1,9 @@
// Neopixel
#define PIN 5 // PIN where neopixel / WS2811 strip is attached
#define NUMLEDS 12 // Number of leds in the strip
#define NUMLEDS 24 // Number of leds in the strip
#define HOSTNAME "ESP8266_01" // Friedly hostname
#define HOSTNAME "ESP8266_02" // Friedly hostname
// ***************************************************************************
@ -12,12 +12,14 @@
#define DBG_OUTPUT_PORT Serial // Set debug output port
// List of all color modes
enum MODE { HOLD, OFF, ALL, WIPE, RAINBOW, RAINBOWCYCLE, THEATERCHASE, THEATERCHASERAINBOW, TV };
enum MODE { SET_MODE, HOLD, OFF, ALL, WIPE, RAINBOW, RAINBOWCYCLE, THEATERCHASE, THEATERCHASERAINBOW, TV };
MODE mode = RAINBOWCYCLE; // Standard mode that is active when software starts
MODE mode = RAINBOW; // Standard mode that is active when software starts
int delay_ms = 50; // Global variable for storing the delay between color changes --> smaller == faster
int brightness = 128; // Global variable for storing the brightness (255 == 100%)
int ws2812fx_speed = 128; // Global variable for storing the delay between color changes --> smaller == faster
int brightness = 192; // Global variable for storing the brightness (255 == 100%)
int ws2812fx_mode = 0; // Helper variable to set WS2812FX modes
bool exit_func = false; // Global helper variable to get out of the color modes when mode changes

View file

@ -12,31 +12,16 @@ void getArgs() {
main_color.green = server.arg("g").toInt();
main_color.blue = server.arg("b").toInt();
}
delay_ms = server.arg("d").toInt();
if (main_color.red > 255) {
main_color.red = 255;
}
if (main_color.green > 255) {
main_color.green = 255;
}
if (main_color.blue > 255) {
main_color.blue = 255;
ws2812fx_speed = constrain(server.arg("s").toInt(), 0, 255);
if (server.arg("s") == "") {
ws2812fx_speed = 128;
}
if (main_color.red < 0) {
main_color.red = 0;
}
if (main_color.green < 0) {
main_color.green = 0;
}
if (main_color.blue < 0) {
main_color.blue = 0;
}
ws2812fx_mode = constrain(server.arg("m").toInt(), 0, strip.getModeCount()-1);
if (server.arg("d") == "") {
delay_ms = 20;
}
main_color.red = constrain(main_color.red, 0, 255);
main_color.green = constrain(main_color.green, 0, 255);
main_color.blue = constrain(main_color.blue, 0, 255);
DBG_OUTPUT_PORT.print("Mode: ");
DBG_OUTPUT_PORT.print(mode);
@ -46,8 +31,8 @@ void getArgs() {
DBG_OUTPUT_PORT.print(main_color.green);
DBG_OUTPUT_PORT.print(", ");
DBG_OUTPUT_PORT.print(main_color.blue);
DBG_OUTPUT_PORT.print(", Delay:");
DBG_OUTPUT_PORT.print(delay_ms);
DBG_OUTPUT_PORT.print(", Speed:");
DBG_OUTPUT_PORT.print(ws2812fx_speed);
DBG_OUTPUT_PORT.print(", Brightness:");
DBG_OUTPUT_PORT.println(brightness);
}
@ -97,15 +82,31 @@ void handleNotFound() {
char* listStatusJSON() {
char json[255];
snprintf(json, sizeof(json), "{\"mode\":%d, \"delay_ms\":%d, \"brightness\":%d, \"color\":[%d, %d, %d]}", mode, delay_ms, brightness, main_color.red, main_color.green, main_color.blue);
snprintf(json, sizeof(json), "{\"mode\":%d, \"ws2812fx_mode\":%d, \"ws2812fx_mode_name\":\"%s\", \"speed\":%d, \"brightness\":%d, \"color\":[%d, %d, %d]}", mode, strip.getMode(), strip.getModeName(strip.getMode()), ws2812fx_speed, brightness, main_color.red, main_color.green, main_color.blue);
return json;
}
void getStatusJSON() {
server.send ( 200, "application/json", listStatusJSON() );
}
String listModesJSON() {
String modes = "[";
for(uint8_t i=0; i < strip.getModeCount(); i++) {
modes += "{\"mode\":";
modes += i;
modes += ", \"name\":\"";
modes += strip.getModeName(i);
modes += "\"},";
}
modes += "{}]";
return modes;
}
void getModesJSON() {
server.send ( 200, "application/json", listModesJSON() );
}
void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t lenght) {
switch (type) {
case WStype_DISCONNECTED:
@ -131,16 +132,17 @@ void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t lenght
main_color.red = ((rgb >> 16) & 0xFF);
main_color.green = ((rgb >> 8) & 0xFF);
main_color.blue = ((rgb >> 0) & 0xFF);
strip.setColor(main_color.red, main_color.green, main_color.blue);
DBG_OUTPUT_PORT.printf("Set main color to: [%u] [%u] [%u]\n", main_color.red, main_color.green, main_color.blue);
webSocket.sendTXT(num, "OK");
}
// # ==> Set delay
// # ==> Set speed
if (payload[0] == '?') {
// decode delay data
uint8_t d = (uint8_t) strtol((const char *) &payload[1], NULL, 10);
delay_ms = ((d >> 0) & 0xFF);
DBG_OUTPUT_PORT.printf("WS: Set delay to: [%u]\n", delay_ms);
ws2812fx_speed = constrain(d, 0, 255);
strip.setSpeed(ws2812fx_speed);
DBG_OUTPUT_PORT.printf("WS: Set speed to: [%u]\n", ws2812fx_speed);
webSocket.sendTXT(num, "OK");
}
@ -239,6 +241,28 @@ void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t lenght
DBG_OUTPUT_PORT.println(json);
webSocket.sendTXT(num, json);
}
// $ ==> Get WS2812 modes.
if (payload[0] == '~') {
DBG_OUTPUT_PORT.printf("Get WS2812 modes.");
String json = listModesJSON();
DBG_OUTPUT_PORT.println(json);
webSocket.sendTXT(num, json);
}
// $ ==> Set WS2812 mode.
if (payload[0] == '/') {
mode = HOLD;
uint8_t ws2812fx_mode = (uint8_t) strtol((const char *) &payload[1], NULL, 10);
ws2812fx_mode = constrain(ws2812fx_mode, 0, 255);
strip.setColor(main_color.red, main_color.green, main_color.blue);
strip.setMode(ws2812fx_mode);
//String json = listStatusJSON();
//DBG_OUTPUT_PORT.println(json);
webSocket.sendTXT(num, "OK");
}
break;
}
}

View file

@ -11,8 +11,8 @@
<meta charset="utf-8"/>
</head>
<body>
<nav class="light-blueXXX lighten-1XXX" role="navigation" id="mc-nav">
<body class="">
<nav class="blue light-blueXXX lighten-1XXX" role="navigation" id="mc-nav">
<div class="nav-wrapper container"><a id="logo-container" href="#" class="brand-logo">Mc Lighting</a>
<ul class="right hide-on-med-and-down">
<li><a href="#" class="mc-navlink" data-pane="pane1">Wheel</a></li>
@ -33,7 +33,7 @@
<div class="row" id="mc-wsloader">
<div class="col">
<div class="preloader-wrapper active">
<div class="spinner-layer spinner-red-only">
<div class="spinner-layer spinner-blue-only">
<div class="circle-clipper left">
<div class="circle"></div>
</div><div class="gap-patch">
@ -73,56 +73,6 @@
<div class="container mc_pane hide" id="pane2">
<div class="section">
<div class="row">
<div class="col s12 m6 l3 btn_grid">
<button class="btn waves-effect waves-light btn_mode" name="action" data-mode="off">Off
<i class="material-icons right">send</i>
</button>
</div>
<div class="col s12 m6 l3 btn_grid">
<a class="btn waves-effect waves-light btn_mode" name="action" data-mode="all">All
<i class="material-icons right">send</i>
</a>
</div>
<div class="col s12 m6 l3 btn_grid">
<a class="btn waves-effect waves-light btn_mode" name="action" data-mode="wipe">Wipe
<i class="material-icons right">send</i>
</a>
</div>
<div class="col s12 m6 l3 btn_grid">
<a class="btn waves-effect waves-light btn_mode" name="action" data-mode="rainbow">Rainbow
<i class="material-icons right">send</i>
</a>
</div>
<div class="col s12 m6 l3 btn_grid">
<a class="btn waves-effect waves-light btn_mode" name="action" data-mode="rainbowCycle">Rainbow cycle
<i class="material-icons right">send</i>
</a>
</div>
<div class="col s12 m6 l3 btn_grid">
<a class="btn waves-effect waves-light btn_mode" name="action" data-mode="theaterchase">Theaterchase
<i class="material-icons right">send</i>
</a>
</div>
<div class="col s12 m6 l3 btn_grid">
<a class="btn waves-effect waves-light btn_mode" name="action" data-mode="theaterchaseRainbow">Theaterchase rainbow
<i class="material-icons right">send</i>
</a>
</div>
<div class="col s12 m6 l3 btn_grid">
<a class="btn waves-effect waves-light btn_mode" name="action" data-mode="tv">TV
<i class="material-icons right">send</i>
</a>
</div>
</div>
<div class="row">
<form class="col s12">
<div class="row">
@ -142,7 +92,7 @@
<div class="row">
<div class="input-field col s12">
<label for="txt_delay">Delay</label><br/>
<label for="txt_delay">Speed</label><br/>
<p class="range-field"><input type="range" id="rng_delay" min="0" max="255" value="50" class="update_delay" /></p>
</div>
</div>
@ -155,12 +105,32 @@
</div>
</form>
</div>
<div class="row">
<div class="col s12 m6 l4 btn_grid">
<a class="btn waves-effect waves-light btn_mode_static blue" name="action" data-mode="off">OFF
<i class="material-icons right">send</i>
</a>
</div>
<div class="col s12 m6 l4 btn_grid">
<a class="btn waves-effect waves-light btn_mode_static blue" name="action" data-mode="tv">TV
<i class="material-icons right">send</i>
</a>
</div>
<div id="modes">
<div class="input-field col s12">
Loading animations...
</div>
</div>
</div>
</div>
</div>
<footer class="page-footer">
<footer class="page-footer blue">
<div class="footer-copyright">
<div class="container">© 2016
<div class="container">© 2017
<a class="grey-text text-lighten-4 right" href="https://github.com/toblum/McLighting">Project home</a>
</div>
</div>
@ -174,13 +144,13 @@
<!--Import jQuery before materialize.js-->
<script type="text/javascript" src="https://code.jquery.com/jquery-2.1.1.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.97.6/js/materialize.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.98.0/js/materialize.min.js"></script>
<script type="text/javascript">(function($){
$(function(){
// Settings
var host = window.location.hostname;
//host = "192.168.0.24";
host = "esp8266_02.local";
var ws_url = 'ws://' + host + ':81';
var connection;
@ -215,6 +185,24 @@ $(function(){
console.log("Connection websockets to:", ws_url);
connection = new WebSocket(ws_url, ['arduino']);
// Load modes async
$.getJSON("http://" + host + "/get_modes", function(data) {
//console.log("modes", data);
var modes_html = "";
data.forEach(function(current_mode){
if (current_mode.mode !== undefined) {
modes_html += '<div class="col s12 m6 l4 btn_grid">';
modes_html += '<a class="btn waves-effect waves-light btn_mode blue" name="action" data-mode="' + current_mode.mode + '">' + current_mode.name + '';
modes_html += '<i class="material-icons right">send</i>';
modes_html += '</a>';
modes_html += '</div>';
}
});
$('#modes').html(modes_html);
});
// When the connection is open, send some data to the server
connection.onopen = function () {
//connection.send('Ping'); // Send the message 'Ping' to the server
@ -236,11 +224,6 @@ $(function(){
};
}
// ******************************************************************
// Helper
// ******************************************************************
// ******************************************************************
// Modes
@ -250,10 +233,18 @@ $(function(){
last_mode = mode;
var btn = $(this);
setMode(mode, function() {
$(".btn_mode").removeClass("blue");
btn.addClass("blue");
$(".btn_mode, .btn_mode_static").removeClass("red").addClass("blue");
btn.removeClass("blue").addClass("red");
});
});
$("#pane2").on("click", ".btn_mode_static", function() {
var mode = $(this).attr("data-mode");
var btn = $(this);
wsSendCommand("=" + mode);
$(".btn_mode, .btn_mode_static").removeClass("red").addClass("blue");
btn.removeClass("blue").addClass("red");
});
$("#pane2").on("change", ".update_colors", setMainColor);
@ -271,10 +262,9 @@ $(function(){
});
function setMode(mode, finish_funtion) {
var url = "http://" + host + "/" + mode;
console.log("Mode: ", mode);
wsSendCommand("=" + mode);
wsSendCommand("/" + mode);
finish_funtion();
}
@ -410,6 +400,10 @@ $(function(){
$('#status').css("backgroundColor", hexColor);
$('#status_color').text(hexColor + " - R=" + color[0] + ", G=" + color[1] + ", B=" + color[2]);
$('#status_pos').text("x: " + pos.x + " - y: " + pos.y);
$("#rng_red").val(color[0]);
$("#rng_green").val(color[1]);
$("#rng_blue").val(color[2]);
}
//handle the touch event