LeventeDaradici

How to make a webserver for the WS2812 RGB LED strip

Nov 9th, 2021 (edited)
266
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 8.11 KB | None | 0 0
  1. /*
  2.   WS2812FX Webinterface.
  3.  
  4.   Harm Aldick - 2016
  5.   www.aldick.org
  6.  
  7.  
  8.   FEATURES
  9.     * Webinterface with mode, color, speed and brightness selectors
  10.  
  11.  
  12.   LICENSE
  13.  
  14.   The MIT License (MIT)
  15.  
  16.   Copyright (c) 2016  Harm Aldick
  17.  
  18.   Permission is hereby granted, free of charge, to any person obtaining a copy
  19.   of this software and associated documentation files (the "Software"), to deal
  20.   in the Software without restriction, including without limitation the rights
  21.   to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  22.   copies of the Software, and to permit persons to whom the Software is
  23.   furnished to do so, subject to the following conditions:
  24.  
  25.   The above copyright notice and this permission notice shall be included in
  26.   all copies or substantial portions of the Software.
  27.  
  28.   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  29.   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  30.   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  31.   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  32.   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  33.   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  34.   THE SOFTWARE.
  35.  
  36.  
  37.   CHANGELOG
  38.   2016-11-26 initial version
  39.   2018-01-06 added custom effects list option and auto-cycle feature
  40.  
  41. */
  42. #ifdef ARDUINO_ARCH_ESP32
  43.   #include <WiFi.h>
  44.   #include <WebServer.h>
  45.   #define WEB_SERVER WebServer
  46.   #define ESP_RESET ESP.restart()
  47. #else
  48.   #include <ESP8266WiFi.h>
  49.   #include <ESP8266WebServer.h>
  50.   #define WEB_SERVER ESP8266WebServer
  51.   #define ESP_RESET ESP.reset()
  52. #endif
  53.  
  54. #include <WS2812FX.h>
  55.  
  56. extern const char index_html[];
  57. extern const char main_js[];
  58.  
  59. #define WIFI_SSID "YOUR WIFI SSID"
  60. #define WIFI_PASSWORD "YOUR WIFI PASSWORD"
  61.  
  62. //#define STATIC_IP                       // uncomment for static IP, set IP below
  63. #ifdef STATIC_IP
  64.   IPAddress ip(192,168,0,123);
  65.   IPAddress gateway(192,168,0,1);
  66.   IPAddress subnet(255,255,255,0);
  67. #endif
  68.  
  69. // QUICKFIX...See https://github.com/esp8266/Arduino/issues/263
  70. #define min(a,b) ((a)<(b)?(a):(b))
  71. #define max(a,b) ((a)>(b)?(a):(b))
  72.  
  73. #define LED_PIN 2                       // 0 = GPIO0, 2=GPIO2
  74. #define LED_COUNT 24
  75.  
  76. #define WIFI_TIMEOUT 30000              // checks WiFi every ...ms. Reset after this time, if WiFi cannot reconnect.
  77. #define HTTP_PORT 80
  78.  
  79. #define DEFAULT_COLOR 0xFF5900
  80. #define DEFAULT_BRIGHTNESS 128
  81. #define DEFAULT_SPEED 1000
  82. #define DEFAULT_MODE FX_MODE_STATIC
  83.  
  84. unsigned long auto_last_change = 0;
  85. unsigned long last_wifi_check_time = 0;
  86. String modes = "";
  87. uint8_t myModes[] = {}; // *** optionally create a custom list of effect/mode numbers
  88. bool auto_cycle = false;
  89.  
  90. WS2812FX ws2812fx = WS2812FX(LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800);
  91. WEB_SERVER server(HTTP_PORT);
  92.  
  93. void setup(){
  94.   Serial.begin(115200);
  95.   delay(500);
  96.   Serial.println("\n\nStarting...");
  97.  
  98.   modes.reserve(5000);
  99.   modes_setup();
  100.  
  101.   Serial.println("WS2812FX setup");
  102.   ws2812fx.init();
  103.   ws2812fx.setMode(DEFAULT_MODE);
  104.   ws2812fx.setColor(DEFAULT_COLOR);
  105.   ws2812fx.setSpeed(DEFAULT_SPEED);
  106.   ws2812fx.setBrightness(DEFAULT_BRIGHTNESS);
  107.   ws2812fx.start();
  108.  
  109.   Serial.println("Wifi setup");
  110.   wifi_setup();
  111.  
  112.   Serial.println("HTTP server setup");
  113.   server.on("/", srv_handle_index_html);
  114.   server.on("/main.js", srv_handle_main_js);
  115.   server.on("/modes", srv_handle_modes);
  116.   server.on("/set", srv_handle_set);
  117.   server.onNotFound(srv_handle_not_found);
  118.   server.begin();
  119.   Serial.println("HTTP server started.");
  120.  
  121.   Serial.println("ready!");
  122. }
  123.  
  124.  
  125. void loop() {
  126.   unsigned long now = millis();
  127.  
  128.   server.handleClient();
  129.   ws2812fx.service();
  130.  
  131.   if(now - last_wifi_check_time > WIFI_TIMEOUT) {
  132.     Serial.print("Checking WiFi... ");
  133.     if(WiFi.status() != WL_CONNECTED) {
  134.       Serial.println("WiFi connection lost. Reconnecting...");
  135.       wifi_setup();
  136.     } else {
  137.       Serial.println("OK");
  138.     }
  139.     last_wifi_check_time = now;
  140.   }
  141.  
  142.   if(auto_cycle && (now - auto_last_change > 10000)) { // cycle effect mode every 10 seconds
  143.     uint8_t next_mode = (ws2812fx.getMode() + 1) % ws2812fx.getModeCount();
  144.     if(sizeof(myModes) > 0) { // if custom list of modes exists
  145.       for(uint8_t i=0; i < sizeof(myModes); i++) {
  146.         if(myModes[i] == ws2812fx.getMode()) {
  147.           next_mode = ((i + 1) < sizeof(myModes)) ? myModes[i + 1] : myModes[0];
  148.           break;
  149.         }
  150.       }
  151.     }
  152.     ws2812fx.setMode(next_mode);
  153.     Serial.print("mode is "); Serial.println(ws2812fx.getModeName(ws2812fx.getMode()));
  154.     auto_last_change = now;
  155.   }
  156. }
  157.  
  158.  
  159.  
  160. /*
  161.  * Connect to WiFi. If no connection is made within WIFI_TIMEOUT, ESP gets resettet.
  162.  */
  163. void wifi_setup() {
  164.   Serial.println();
  165.   Serial.print("Connecting to ");
  166.   Serial.println(WIFI_SSID);
  167.  
  168.   WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
  169.   WiFi.mode(WIFI_STA);
  170.   #ifdef STATIC_IP  
  171.     WiFi.config(ip, gateway, subnet);
  172.   #endif
  173.  
  174.   unsigned long connect_start = millis();
  175.   while(WiFi.status() != WL_CONNECTED) {
  176.     delay(500);
  177.     Serial.print(".");
  178.  
  179.     if(millis() - connect_start > WIFI_TIMEOUT) {
  180.       Serial.println();
  181.       Serial.print("Tried ");
  182.       Serial.print(WIFI_TIMEOUT);
  183.       Serial.print("ms. Resetting ESP now.");
  184.       ESP_RESET;
  185.     }
  186.   }
  187.  
  188.   Serial.println("");
  189.   Serial.println("WiFi connected");  
  190.   Serial.print("IP address: ");
  191.   Serial.println(WiFi.localIP());
  192.   Serial.println();
  193. }
  194.  
  195.  
  196. /*
  197.  * Build <li> string for all modes.
  198.  */
  199. void modes_setup() {
  200.   modes = "";
  201.   uint8_t num_modes = sizeof(myModes) > 0 ? sizeof(myModes) : ws2812fx.getModeCount();
  202.   for(uint8_t i=0; i < num_modes; i++) {
  203.     uint8_t m = sizeof(myModes) > 0 ? myModes[i] : i;
  204.     modes += "<li><a href='#'>";
  205.     modes += ws2812fx.getModeName(m);
  206.     modes += "</a></li>";
  207.   }
  208. }
  209.  
  210. /* #####################################################
  211. #  Webserver Functions
  212. ##################################################### */
  213.  
  214. void srv_handle_not_found() {
  215.   server.send(404, "text/plain", "File Not Found");
  216. }
  217.  
  218. void srv_handle_index_html() {
  219.   server.send_P(200,"text/html", index_html);
  220. }
  221.  
  222. void srv_handle_main_js() {
  223.   server.send_P(200,"application/javascript", main_js);
  224. }
  225.  
  226. void srv_handle_modes() {
  227.   server.send(200,"text/plain", modes);
  228. }
  229.  
  230. void srv_handle_set() {
  231.   for (uint8_t i=0; i < server.args(); i++){
  232.     if(server.argName(i) == "c") {
  233.       uint32_t tmp = (uint32_t) strtol(server.arg(i).c_str(), NULL, 10);
  234.       if(tmp >= 0x000000 && tmp <= 0xFFFFFF) {
  235.         ws2812fx.setColor(tmp);
  236.       }
  237.     }
  238.  
  239.     if(server.argName(i) == "m") {
  240.       uint8_t tmp = (uint8_t) strtol(server.arg(i).c_str(), NULL, 10);
  241.       uint8_t new_mode = sizeof(myModes) > 0 ? myModes[tmp % sizeof(myModes)] : tmp % ws2812fx.getModeCount();
  242.       ws2812fx.setMode(new_mode);
  243.       Serial.print("mode is "); Serial.println(ws2812fx.getModeName(ws2812fx.getMode()));
  244.     }
  245.  
  246.     if(server.argName(i) == "b") {
  247.       if(server.arg(i)[0] == '-') {
  248.         ws2812fx.setBrightness(ws2812fx.getBrightness() * 0.8);
  249.       } else if(server.arg(i)[0] == ' ') {
  250.         ws2812fx.setBrightness(min(max(ws2812fx.getBrightness(), 5) * 1.2, 255));
  251.       } else { // set brightness directly
  252.         uint8_t tmp = (uint8_t) strtol(server.arg(i).c_str(), NULL, 10);
  253.         ws2812fx.setBrightness(tmp);
  254.       }
  255.       Serial.print("brightness is "); Serial.println(ws2812fx.getBrightness());
  256.     }
  257.  
  258.     if(server.argName(i) == "s") {
  259.       if(server.arg(i)[0] == '-') {
  260.         ws2812fx.setSpeed(max(ws2812fx.getSpeed(), 5) * 1.2);
  261.       } else if(server.arg(i)[0] == ' ') {
  262.         ws2812fx.setSpeed(ws2812fx.getSpeed() * 0.8);
  263.       } else {
  264.         uint16_t tmp = (uint16_t) strtol(server.arg(i).c_str(), NULL, 10);
  265.         ws2812fx.setSpeed(tmp);
  266.       }
  267.       Serial.print("speed is "); Serial.println(ws2812fx.getSpeed());
  268.     }
  269.  
  270.     if(server.argName(i) == "a") {
  271.       if(server.arg(i)[0] == '-') {
  272.         auto_cycle = false;
  273.       } else {
  274.         auto_cycle = true;
  275.         auto_last_change = 0;
  276.       }
  277.     }
  278.   }
  279.   server.send(200, "text/plain", "OK");
  280. }
  281.  
Add Comment
Please, Sign In to add comment