individually addressable ledstrip WS2812B

In this article I will explain how to build a individually addressable ledstrip with a WS2812 60 LED strip. This LED-strip is controlled via a webinterface. I'm using a Arduino ESP8266 Node MCU to control the strip.

 

What do you need:

 

  • Powersupply 5Volt 3A
  • ESP8266 or Arduino
  • WS2812B LED-strip
  • Soldering Iron
  • Some electrical wire

 

 

 

Connect de ledstrip to the ESP8266 as shown above. Use at least a powersupply off 3A and 5volts. If all the leds are switched on and they show the color white (white is a combination of all the other colors) and at maximum brightness the ledstrip uses a lot of current. I used an 1 meter, 60 LED strip for this project . If you are going to use more LED's, you need a bigger powersupply (more Amps still 5volt).

 

Now you need to download the Arduino IDE (it's for free) https://www.arduino.cc/en/main/software . You need to download the WS2812FX library https://github.com/kitesurfer1404/WS2812FX . and the  Adafruit NeoPixel library https://github.com/adafruit/Adafruit_NeoPixel (actually you don't need this library) . See this page, how to install libraries in Arduino IDE https://www.arduino.cc/en/guide/libraries

 

You can find the code I used in: " file" ,"examples" ,"WS2812FX", ESP8266_webinterface"

 

*
  WS2812FX Webinterface.
  
  Harm Aldick - 2016
  www.aldick.org

  
  FEATURES
    * Webinterface with mode, color, speed and brightness selectors


  LICENSE

  The MIT License (MIT)

  Copyright (c) 2016  Harm Aldick 

  Permission is hereby granted, free of charge, to any person obtaining a copy
  of this software and associated documentation files (the "Software"), to deal
  in the Software without restriction, including without limitation the rights
  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  copies of the Software, and to permit persons to whom the Software is
  furnished to do so, subject to the following conditions:

  The above copyright notice and this permission notice shall be included in
  all copies or substantial portions of the Software.

  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  THE SOFTWARE.

  
  CHANGELOG
  2016-11-26 initial version
  2018-01-06 added custom effects list option and auto-cycle feature
  
*/
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <WS2812FX.h>

extern const char index_html[];
extern const char main_js[];

#define WIFI_SSID "xxxxxx"
#define WIFI_PASSWORD "xxxxxxxxx"

//#define STATIC_IP                       // uncomment for static IP, set IP below
#ifdef STATIC_IP
  IPAddress ip(192,168,0,123);
  IPAddress gateway(192,168,0,1);
  IPAddress subnet(255,255,255,0);
#endif

// QUICKFIX...See https://github.com/esp8266/Arduino/issues/263
#define min(a,b) ((a)<(b)?(a):(b))
#define max(a,b) ((a)>(b)?(a):(b))

#define LED_PIN 3                       // 0 = GPIO0, 2=GPIO2
#define LED_COUNT 60

#define WIFI_TIMEOUT 30000              // checks WiFi every ...ms. Reset after this time, if WiFi cannot reconnect.
#define HTTP_PORT 80

#define DEFAULT_COLOR 0xFF5900
#define DEFAULT_BRIGHTNESS 30
#define DEFAULT_SPEED 2160
#define DEFAULT_MODE FX_MODE_RAINBOW_CYCLE
unsigned long auto_last_change = 0;
unsigned long last_wifi_check_time = 0;
String modes = "";
uint8_t myModes[] = {}; // *** optionally create a custom list of effect/mode numbers
boolean auto_cycle = false;

WS2812FX ws2812fx = WS2812FX(LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800);
ESP8266WebServer server(HTTP_PORT);

void setup(){
  Serial.begin(115200);
  Serial.println();
  Serial.println();
  Serial.println("Starting...");

  modes.reserve(5000);
  modes_setup();

  Serial.println("WS2812FX setup");
  ws2812fx.init();
  ws2812fx.setMode(DEFAULT_MODE);
  ws2812fx.setColor(DEFAULT_COLOR);
  ws2812fx.setSpeed(DEFAULT_SPEED);
  ws2812fx.setBrightness(DEFAULT_BRIGHTNESS);
  ws2812fx.start();

  Serial.println("Wifi setup");
  wifi_setup();
 
  Serial.println("HTTP server setup");
  server.on("/", srv_handle_index_html);
  server.on("/main.js", srv_handle_main_js);
  server.on("/modes", srv_handle_modes);
  server.on("/set", srv_handle_set);
  server.onNotFound(srv_handle_not_found);
  server.begin();
  Serial.println("HTTP server started.");

  Serial.println("ready!");
}


void loop() {
  unsigned long now = millis();

  server.handleClient();
  ws2812fx.service();

  if(now - last_wifi_check_time > WIFI_TIMEOUT) {
    Serial.print("Checking WiFi... ");
    if(WiFi.status() != WL_CONNECTED) {
      Serial.println("WiFi connection lost. Reconnecting...");
      wifi_setup();
    } else {
      Serial.println("OK");
    }
    last_wifi_check_time = now;
  }

  if(auto_cycle && (now - auto_last_change > 10000)) { // cycle effect mode every 10 seconds
    uint8_t next_mode = (ws2812fx.getMode() + 1) % ws2812fx.getModeCount();
    if(sizeof(myModes) > 0) { // if custom list of modes exists
      for(uint8_t i=0; i < sizeof(myModes); i++) {
        if(myModes[i] == ws2812fx.getMode()) {
          next_mode = ((i + 1) < sizeof(myModes)) ? myModes[i + 1] : myModes[0];
          break;
        }
      }
    }
    ws2812fx.setMode(next_mode);
    Serial.print("mode is "); Serial.println(ws2812fx.getModeName(ws2812fx.getMode()));
    auto_last_change = now;
  }
}



/*
 * Connect to WiFi. If no connection is made within WIFI_TIMEOUT, ESP gets resettet.
 */
void wifi_setup() {
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(WIFI_SSID);

  WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
  WiFi.mode(WIFI_STA);
  #ifdef STATIC_IP  
    WiFi.config(ip, gateway, subnet);
  #endif

  unsigned long connect_start = millis();
  while(WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");

    if(millis() - connect_start > WIFI_TIMEOUT) {
      Serial.println();
      Serial.print("Tried ");
      Serial.print(WIFI_TIMEOUT);
      Serial.print("ms. Resetting ESP now.");
      ESP.reset();
    }
  }

  Serial.println("");
  Serial.println("WiFi connected");  
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());
  Serial.println();
}


/*
 * Build <li> string for all modes.
 */
void modes_setup() {
  modes = "";
  uint8_t num_modes = sizeof(myModes) > 0 ? sizeof(myModes) : ws2812fx.getModeCount();
  for(uint8_t i=0; i < num_modes; i++) {
    uint8_t m = sizeof(myModes) > 0 ? myModes[i] : i;
    modes += "<li><a href='#' class='m' id='";
    modes += m;
    modes += "'>";
    modes += ws2812fx.getModeName(m);
    modes += "</a></li>";
  }
}

/* #####################################################
#  Webserver Functions
##################################################### */

void srv_handle_not_found() {
  server.send(404, "text/plain", "File Not Found");
}

void srv_handle_index_html() {
  server.send_P(200,"text/html", index_html);
}

void srv_handle_main_js() {
  server.send_P(200,"application/javascript", main_js);
}

void srv_handle_modes() {
  server.send(200,"text/plain", modes);
}

void srv_handle_set() {
  for (uint8_t i=0; i < server.args(); i++){
    if(server.argName(i) == "c") {
      uint32_t tmp = (uint32_t) strtol(server.arg(i).c_str(), NULL, 16);
      if(tmp >= 0x000000 && tmp <= 0xFFFFFF) {
        ws2812fx.setColor(tmp);
      }
    }

    if(server.argName(i) == "m") {
      uint8_t tmp = (uint8_t) strtol(server.arg(i).c_str(), NULL, 10);
      ws2812fx.setMode(tmp % ws2812fx.getModeCount());
      Serial.print("mode is "); Serial.println(ws2812fx.getModeName(ws2812fx.getMode()));
    }

    if(server.argName(i) == "b") {
      if(server.arg(i)[0] == '-') {
        ws2812fx.setBrightness(ws2812fx.getBrightness() * 0.8);
      } else if(server.arg(i)[0] == ' ') {
        ws2812fx.setBrightness(min(max(ws2812fx.getBrightness(), 5) * 1.2, 255));
      } else { // set brightness directly
        uint8_t tmp = (uint8_t) strtol(server.arg(i).c_str(), NULL, 10);
        ws2812fx.setBrightness(tmp);
      }
      Serial.print("brightness is "); Serial.println(ws2812fx.getBrightness());
    }

    if(server.argName(i) == "s") {
      if(server.arg(i)[0] == '-') {
        ws2812fx.setSpeed(max(ws2812fx.getSpeed(), 5) * 1.2);
      } else if(server.arg(i)[0] == ' ') {
        ws2812fx.setSpeed(ws2812fx.getSpeed() * 0.8);
      } else {
        uint16_t tmp = (uint16_t) strtol(server.arg(i).c_str(), NULL, 10);
        ws2812fx.setSpeed(tmp);
      }
      Serial.print("speed is "); Serial.println(ws2812fx.getSpeed());
    }

    if(server.argName(i) == "a") {
      if(server.arg(i)[0] == '-') {
        auto_cycle = false;
      } else {
        auto_cycle = true;
        auto_last_change = 0;
      }
    }
  }
  server.send(200, "text/plain", "OK");
}

 

All you have to do is to define your WiFi SSID and Password. Now you can upload your code to your ESP8266.

 

This line: define DEFAULT_MODE FX_MODE_RAINBOW_CYCLE, changes your default startup mode. You can also define the default brightness and speed.

 

determine the IP-adres of your ESP8266, and past this adres in a browser. Now you can control your ledstrip via you browser.

 

 

 

 

Effects

 

  1. Static - No blinking. Just plain old static light.
  2. Blink - Normal blinking. 50% on/off time.
  3. Breath - Does the "standby-breathing" of well known i-Devices. Fixed Speed.
  4. Color Wipe - Lights all LEDs after each other up. Then turns them in that order off. Repeat.
  5. Color Wipe Inverse - Same as Color Wipe, except swaps on/off colors.
  6. Color Wipe Reverse - Lights all LEDs after each other up. Then turns them in reverse order off. Repeat.
  7. Color Wipe Reverse Inverse - Same as Color Wipe Reverse, except swaps on/off colors.
  8. Color Wipe Random - Turns all LEDs after each other to a random color. Then starts over with another color.
  9. Random Color - Lights all LEDs in one random color up. Then switches them to the next random color.
  10. Single Dynamic - Lights every LED in a random color. Changes one random LED after the other to a random color.
  11. Multi Dynamic - Lights every LED in a random color. Changes all LED at the same time to new random colors.
  12. Rainbow - Cycles all LEDs at once through a rainbow.
  13. Rainbow Cycle - Cycles a rainbow over the entire string of LEDs.
  14. Scan - Runs a single pixel back and forth.
  15. Dual Scan - Runs two pixel back and forth in opposite directions.
  16. Fade - Fades the LEDs on and (almost) off again.
  17. Theater Chase - Theatre-style crawling lights. Inspired by the Adafruit examples.
  18. Theater Chase Rainbow - Theatre-style crawling lights with rainbow effect. Inspired by the Adafruit examples.
  19. Running Lights - Running lights effect with smooth sine transition.
  20. Twinkle - Blink several LEDs on, reset, repeat.
  21. Twinkle Random - Blink several LEDs in random colors on, reset, repeat.
  22. Twinkle Fade - Blink several LEDs on, fading out.
  23. Twinkle Fade Random - Blink several LEDs in random colors on, fading out.
  24. Sparkle - Blinks one LED at a time.
  25. Flash Sparkle - Lights all LEDs in the selected color. Flashes single white pixels randomly.
  26. Hyper Sparkle - Like flash sparkle. With more flash.
  27. Strobe - Classic Strobe effect.
  28. Strobe Rainbow - Classic Strobe effect. Cycling through the rainbow.
  29. Multi Strobe - Strobe effect with different strobe count and pause, controlled by speed setting.
  30. Blink Rainbow - Classic Blink effect. Cycling through the rainbow.
  31. Chase White - Color running on white.
  32. Chase Color - White running on color.
  33. Chase Random - White running followed by random color.
  34. Chase Rainbow - White running on rainbow.
  35. Chase Flash - White flashes running on color.
  36. Chase Flash Random - White flashes running, followed by random color.
  37. Chase Rainbow White - Rainbow running on white.
  38. Chase Blackout - Black running on color.
  39. Chase Blackout Rainbow - Black running on rainbow.
  40. Color Sweep Random - Random color introduced alternating from start and end of strip.
  41. Running Color - Alternating color/white pixels running.
  42. Running Red Blue - Alternating red/blue pixels running.
  43. Running Random - Random colored pixels running.
  44. Larson Scanner - K.I.T.T.
  45. Comet - Firing comets from one end.
  46. Fireworks - Firework sparks.
  47. Fireworks Random - Random colored firework sparks.
  48. Merry Christmas - Alternating green/red pixels running.
  49. Fire Flicker - Fire flickering effect. Like in harsh wind.
  50. Fire Flicker (soft) - Fire flickering effect. Runs slower/softer.
  51. Fire Flicker (intense) - Fire flickering effect. More range of color.
  52. Circus Combustus - Alternating white/red/black pixels running.
  53. Halloween - Alternating orange/purple pixels running.
  54. Bicolor Chase - Two LEDs running on a background color (set three colors).
  55. Tricolor Chase - Alternating three color pixels running (set three colors).
  56. ICU - Two eyes looking around.
  57. Custom - Up to four user created custom effects.
  58. Custom
  59. Custom
  60. Custom

In a browser you can change the lights by using: http://ipadresofESP/set?m=[effect number}, so http://192.168.1.130/set?m=41. To set the color of the strip: http://192.168.1.130/set?c=e5ff00. this is an yellow color.

If you control your lights in the Google Chrome browser you can pres F12, goto network. if you choose a color via the webinterface the URL code appears there.

 

Now we got a working ledstrip with webinterface. I did not like the look of the very bright leds so I made a housing for the ledstip with a difuser in front of the ledstrip, so you can only see the glow of the led and not the individual leds. I made a simple drawing of my housing so you have an idea of what I made.