#include #include #include #include #include #include "WebServer.h" #include "Fader.h" #include "UDPProto.h" #include "Config.h" #include #include const uint32_t FRAME_INTERVAL_US = 16666; const uint32_t NUM_STRIPS = 8; const uint32_t NUM_LEDS = 16; const uint32_t FLIP_STRIPS_MASK = 0x000000AA; std::array STRANDS { // Avoid using any of the strapping pins on the ESP32, anything >=32, 16, 17... not much left. strand_t {.rmtChannel = 0, .gpioNum = 4, .ledType = LED_SK6812W_V1, .brightLimit = 32, .numPixels = NUM_LEDS * NUM_STRIPS}, }; bool led_on = false; size_t led_idx; size_t frame; WiFiMulti wiFiMulti; Fader ledFader(NUM_STRIPS, NUM_LEDS, 1, FLIP_STRIPS_MASK); UDPProto udpProto(&ledFader); bool initLEDs() { /**************************************************************************** If you have multiple strands connected, but not all are in use, the GPIO power-on defaults for the unused strand data lines will typically be high-impedance. Unless you are pulling the data lines high or low via a resistor, this will lead to noise on those unused but connected channels and unwanted driving of those unallocated strands. This optional gpioSetup() code helps avoid that problem programmatically. ****************************************************************************/ digitalLeds_initDriver(); for (int i = 0; i < STRANDS.size(); i++) { gpioSetup(STRANDS[i].gpioNum, OUTPUT, LOW); } strand_t *strands[STRANDS.size()]; for (int i = 0; i < STRANDS.size(); i++) { strands[i] = &STRANDS[i]; } int rc = digitalLeds_addStrands(strands, STRANDS.size()); if (rc) { Serial.print("Init rc = "); Serial.println(rc); return false; } for (int i = 0; i < STRANDS.size(); i++) { strand_t *pStrand = strands[i]; Serial.print("Strand "); Serial.print(i); Serial.print(" = "); Serial.print((uint32_t)(pStrand->pixels), HEX); Serial.println(); #if DEBUG_ESP32_DIGITAL_LED_LIB dumpDebugBuffer(-2, digitalLeds_debugBuffer); #endif } led_idx = 0; frame = 0; return true; } static void ledTask( void * parameter ) { /* loop forever */ for(;;){ uint32_t start_time = micros(); if(WiFi.status() == WL_CONNECTED) { udpProto.loop(); } led_idx++; if(led_idx >= STRANDS[0].numPixels) { led_idx = 0; } strand_t *strands[STRANDS.size()]; for (int i = 0; i < STRANDS.size(); i++) { strands[i] = &STRANDS[i]; } ledFader.update(); if(ledFader.something_changed()) { const std::vector &colors = ledFader.get_color_values(); for (size_t i = 0; i < STRANDS[0].numPixels; i++) { const Fader::Color &c = colors[i]; STRANDS[0].pixels[i] = pixelFromRGBW(c.r, c.g, c.b, c.w); } } digitalLeds_drawPixels(strands, 1); frame++; uint32_t now = micros(); uint32_t duration = now - start_time; if(frame % 50 == 0) { uint32_t load = 100 * duration / FRAME_INTERVAL_US; Serial.print("CPU Load: "); Serial.print(load); Serial.println(" %"); } if(duration < FRAME_INTERVAL_US) { delayMicroseconds(FRAME_INTERVAL_US - duration); } } /* delete a task when finish, this will never happen because this is infinity loop */ vTaskDelete( NULL ); } void wifi_setup(void) { Serial.println("Trying to connect..."); for(size_t tries = 0; tries < 10; tries++) { if(wiFiMulti.run() == WL_CONNECTED) { Serial.println(""); Serial.println("WiFi connected"); Serial.println("IP address: "); Serial.println(WiFi.localIP()); break; } led_on = !led_on; digitalWrite(2, led_on); delay(100); Serial.print("."); } if(WiFi.status() != WL_CONNECTED) { Serial.println("Connection failed, setting up access point..."); IPAddress apIP(192, 168, 42, 1); WiFi.mode(WIFI_AP); WiFi.softAPConfig(apIP, apIP, IPAddress(255, 255, 255, 0)); WiFi.softAP("๐Ÿ•ฏ๏ธ๐Ÿ’กโ˜€๏ธ", "Licht234"); WiFi.enableAP(true); } } void setup() { pinMode(2, OUTPUT); // On-Board LED Serial.begin(115200); delay(10); if(!initLEDs()) { Serial.println("LED setup failed!"); while(true) { delay(100); } } if(!SPIFFS.begin()) { Serial.println("SPIFFS setup failed!"); while(true) { delay(100); } } // load configuration (especially crypto data) Config::instance().load(); digitalWrite(2, HIGH); Serial.println(); Serial.println(); ledFader.set_color(Fader::Color{64,0,0,0}); ledFader.fade_color(Fader::Color{0,64,0,0}); xTaskCreate( ledTask, /* Task function. */ "LED Task", /* name of task. */ 10000, /* Stack size of task */ NULL, /* parameter of the task */ 2, /* priority of the task */ NULL); /* Task handle to keep track of created task */ // Connect the WiFi network (or start an AP if that doesn't work) for (auto &net : Config::instance().getWLANList()) { Serial.print("Adding network "); Serial.println(net.ssid.c_str()); wiFiMulti.addAP(net.ssid.c_str(), net.password.c_str()); } wifi_setup(); // start the UDP server udpProto.start(2703); // start the web server WebServer::instance().setFader(&ledFader); WebServer::instance().start(); } void loop() { led_on = !led_on; digitalWrite(2, led_on); delay(500); // reconnect WiFi when connection is lost if(WiFi.status() == WL_CONNECTION_LOST) { Serial.println("WLAN disconnected. Restarting setup."); wifi_setup(); } }