diff --git a/CHANGELOG.md b/CHANGELOG.md index cffb78ed7..d777a96c8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,8 +1,47 @@ ## WLED changelog +#### Build 2406290 +- WLED 0.15.0-b4 release +- LED settings bus management update (WARNING only allow available outputs) +- Add ETH support for LILYGO-POE-Pro (#4030 by @rorosaurus) +- Update usermod_sn_photoresistor (#4017 by @xkvmoto) +- Several internal fixes and optimisations + - move LED_BUILTIN handling to BusManager class + - reduce max panels (web server limitation) + - edit WiFi TX power (ESP32) + - keep current ledmap ID in UI + - limit outputs in UI based on length + - wifi.ap addition to JSON Info (JSON API) + - relay pin init bugfix + - file editor button in UI + - ESP8266: update was restarting device on some occasions + - a bit of throttling in UI (for ESP8266) + +#### Build 2406120 +- Update NeoPixelBus to v2.8.0 +- Increased LED outputs one ESP32 using parallel I2S (up to 17) + - use single/mono I2S + 4x RMT for 5 outputs or less + - use parallel x8 I2S + 8x RMT for >5 outputs (limit of 300 LEDs per output) +- Fixed code of Smartnest and updated documentation (#4001 by @DevilPro1) +- ESP32-S3 WiFi fix (#4010 by @cstruck) +- TetrisAI usermod fix (#3897 by @muebau) +- ESP-NOW usermod hook +- Update wled.h regarding OTA Password (#3993 by @gsieben) +- Usermod BME68X Sensor Implementation (#3994 by @gsieben) +- Add a usermod for AHT10, AHT15 and AHT20 temperature/humidity sensors (#3977 by @LordMike) +- Update Battery usermod documentation (#3968 by @adamsthws) +- Add INA226 usermod for reading current and power over i2c (#3986 by @LordMike) +- Bugfixes: #3991 +- Several internal fixes and optimisations (WARNING: some effects may be broken that rely on overflow/narrow width) + - replace uint8_t and uint16_t with unsigned + - replace in8_t and int16_t with int + - reduces code by 1kB + #### Build 2405180 +- WLED 0.14.4 release +- Fix for #3978 - Official 0.15.0-b3 release -- Merge 0.14.3 fixes +- Merge 0.14.3 fixes into 0_15 - Added Pinwheel Expand 1D->2D effect mapping mode (#3961 by @Brandon502) - Add changeable i2c address to BME280 usermod (#3966 by @LordMike) - Effect: Firenoise - add palette selection diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index f813999bb..cd50b133d 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -28,7 +28,7 @@ You are all set if you have enabled `Editor: Detect Indentation` in VS Code. #### Blocks -Whether the opening bracket of e.g. an `if` block is in the same line as the condition or in a separate line is up to your discretion. If there is only one statement, leaving out block braches is acceptable. +Whether the opening bracket of e.g. an `if` block is in the same line as the condition or in a separate line is up to your discretion. If there is only one statement, leaving out block brackets is acceptable. Good: ```cpp @@ -49,7 +49,7 @@ if (a == b) doStuff(a); ``` There should always be a space between a keyword and its condition and between the condition and brace. -Within the condition, no space should be between the paranthesis and variables. +Within the condition, no space should be between the parenthesis and variables. Spaces between variables and operators are up to the authors discretion. There should be no space between function names and their argument parenthesis. diff --git a/package-lock.json b/package-lock.json index b9dc5e0e3..38f2099d6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "wled", - "version": "0.15.0-b3", + "version": "0.15.0-b4", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "wled", - "version": "0.15.0-b3", + "version": "0.15.0-b4", "license": "ISC", "dependencies": { "clean-css": "^5.3.3", diff --git a/package.json b/package.json index b19ecc48a..e3c12629c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wled", - "version": "0.15.0-b3", + "version": "0.15.0-b4", "description": "Tools for WLED project", "main": "tools/cdata.js", "directories": { diff --git a/platformio_override.sample.ini b/platformio_override.sample.ini index 6becc5d7d..be959e46a 100644 --- a/platformio_override.sample.ini +++ b/platformio_override.sample.ini @@ -10,7 +10,7 @@ default_envs = WLED_tasmota_1M # define as many as you need #---------- # SAMPLE #---------- -[env:WLED_tasmota_1M] +[env:WLED_generic8266_1M] extends = env:esp01_1m_full # when you want to extend the existing environment (define only updated options) ; board = esp01_1m # uncomment when ou need different board ; platform = ${common.platform_wled_default} # uncomment and change when you want particular platform @@ -26,9 +26,9 @@ lib_deps = ${esp8266.lib_deps} ; adafruit/Adafruit BME280 Library@^2.2.2 ; Wire ; robtillaart/SHT85@~0.3.3 -; gmag11/QuickESPNow ;@ 0.6.2 +; ;gmag11/QuickESPNow @ ~0.7.0 # will also load QuickDebug ; https://github.com/blazoncek/QuickESPNow.git#optional-debug ;; exludes debug library -; https://github.com/kosme/arduinoFFT#develop @ 2.0.1 ;; used for USERMOD_AUDIOREACTIVE +; ${esp32.AR_lib_deps} ;; used for USERMOD_AUDIOREACTIVE build_unflags = ${common.build_unflags} build_flags = ${common.build_flags} ${esp8266.build_flags} ; @@ -51,6 +51,11 @@ build_flags = ${common.build_flags} ${esp8266.build_flags} ; -D WLED_DISABLE_ESPNOW ; -D WLED_DISABLE_BROWNOUT_DET ; +; enable optional built-in features +; -D WLED_ENABLE_PIXART +; -D WLED_ENABLE_USERMOD_PAGE # if created +; -D WLED_ENABLE_DMX +; ; PIN defines - uncomment and change, if needed: ; -D LEDPIN=2 ; or use this for multiple outputs @@ -64,6 +69,8 @@ build_flags = ${common.build_flags} ${esp8266.build_flags} ; ; Limit max buses ; -D WLED_MAX_BUSSES=2 +; -D WLED_MAX_ANALOG_CHANNELS=3 # only 3 PWM HW pins available +; -D WLED_MAX_DIGITAL_CHANNELS=2 # only 2 HW accelerated pins available ; ; Configure default WiFi ; -D CLIENT_SSID='"MyNetwork"' @@ -128,12 +135,12 @@ build_flags = ${common.build_flags} ${esp8266.build_flags} ; ; Use PIR sensor usermod and configure it to use GPIO4 and timer of 60s ; -D USERMOD_PIRSWITCH -; -D PIR_SENSOR_PIN=4 +; -D PIR_SENSOR_PIN=4 # use -1 to disable usermod ; -D PIR_SENSOR_OFF_SEC=60 +; -D PIR_SENSOR_MAX_SENSORS=2 # max allowable sensors (uses OR logic for triggering) ; ; Use Audioreactive usermod and configure I2S microphone ; -D USERMOD_AUDIOREACTIVE -; -D UM_AUDIOREACTIVE_USE_NEW_FFT ; -D AUDIOPIN=-1 ; -D DMTYPE=1 # 0-analog/disabled, 1-I2S generic, 2-ES7243, 3-SPH0645, 4-I2S+mclk, 5-I2S PDM ; -D I2S_SDPIN=36 @@ -155,18 +162,22 @@ build_flags = ${common.build_flags} ${esp8266.build_flags} ; -D DEFAULT_LED_COUNT=30 ; or this for multiple outputs ; -D PIXEL_COUNTS=30,30 -; -; set milliampere limit when using ESP pin to power leds +; +; set the default LED type +; -D DEFAULT_LED_TYPE=22 # see const.h (TYPE_xxxx) +; +; set milliampere limit when using ESP power pin (or inadequate PSU) to power LEDs ; -D ABL_MILLIAMPS_DEFAULT=850 +; -D LED_MILLIAMPS_DEFAULT=55 ; ; enable IR by setting remote type -; -D IRTYPE=0 ;0 Remote disabled | 1 24-key RGB | 2 24-key with CT | 3 40-key blue | 4 40-key RGB | 5 21-key RGB | 6 6-key black | 7 9-key red | 8 JSON remote +; -D IRTYPE=0 # 0 Remote disabled | 1 24-key RGB | 2 24-key with CT | 3 40-key blue | 4 40-key RGB | 5 21-key RGB | 6 6-key black | 7 9-key red | 8 JSON remote ; ; set default color order of your led strip ; -D DEFAULT_LED_COLOR_ORDER=COL_ORDER_GRB ; ; use PSRAM on classic ESP32 rev.1 (rev.3 or above has no issues) -; -DBOARD_HAS_PSRAM -mfix-esp32-psram-cache-issue +; -DBOARD_HAS_PSRAM -mfix-esp32-psram-cache-issue # needed only for classic ESP32 rev.1 ; ; configure I2C and SPI interface (for various hardware) ; -D I2CSDAPIN=33 # initialise interface diff --git a/requirements.txt b/requirements.txt index 35c89a5e2..c4ce9445f 100644 --- a/requirements.txt +++ b/requirements.txt @@ -42,7 +42,7 @@ pyelftools==0.29 # via platformio pyserial==3.5 # via platformio -requests==2.31.0 +requests==2.32.0 # via platformio semantic-version==2.10.0 # via platformio @@ -54,7 +54,7 @@ tabulate==0.9.0 # via platformio typing-extensions==4.11.0 # via starlette -urllib3==1.26.18 +urllib3==1.26.19 # via requests uvicorn==0.20.0 # via platformio diff --git a/usermods/LD2410_v2/readme.md b/usermods/LD2410_v2/readme.md new file mode 100644 index 000000000..40463d4b0 --- /dev/null +++ b/usermods/LD2410_v2/readme.md @@ -0,0 +1,36 @@ +# BH1750 usermod + +> This usermod requires a second UART and was only tested on the ESP32 + + +This usermod will read from a LD2410 movement/presence sensor. + +The movement and presence state are displayed in both the Info section of the web UI, as well as published to the `/movement` and `/stationary` MQTT topics respectively. + +## Dependencies +- Libraries + - `ncmreynolds/ld2410@^0.1.3` + - This must be added under `lib_deps` in your `platformio.ini` (or `platformio_override.ini`). +- Data is published over MQTT - make sure you've enabled the MQTT sync interface. + +## Compilation + +To enable, compile with `USERMOD_LD2410` defined (e.g. in `platformio_override.ini`) +```ini +[env:usermod_USERMOD_LD2410_esp32dev] +extends = env:esp32dev +build_flags = + ${common.build_flags_esp32} + -D USERMOD_LD2410 +lib_deps = + ${esp32.lib_deps} + ncmreynolds/ld2410@^0.1.3 +``` + +### Configuration Options +The Usermod screen allows you to: +- enable/disable the usermod +- Configure the RX/TX pins + +## Change log +- 2024-06 Created by @wesleygas (https://github.com/wesleygas/) diff --git a/usermods/LD2410_v2/usermod_ld2410.h b/usermods/LD2410_v2/usermod_ld2410.h new file mode 100644 index 000000000..4d96b32ff --- /dev/null +++ b/usermods/LD2410_v2/usermod_ld2410.h @@ -0,0 +1,237 @@ +#warning **** Included USERMOD_LD2410 **** + +#ifndef WLED_ENABLE_MQTT +#error "This user mod requires MQTT to be enabled." +#endif + +#pragma once + +#include "wled.h" +#include + +class LD2410Usermod : public Usermod { + + private: + + bool enabled = true; + bool initDone = false; + bool sensorFound = false; + unsigned long lastTime = 0; + unsigned long last_mqtt_sent = 0; + + int8_t default_uart_rx = 19; + int8_t default_uart_tx = 18; + + + String mqttMovementTopic = F(""); + String mqttStationaryTopic = F(""); + bool mqttInitialized = false; + bool HomeAssistantDiscovery = true; // Publish Home Assistant Discovery messages + + + ld2410 radar; + bool stationary_detected = false; + bool last_stationary_state = false; + bool movement_detected = false; + bool last_movement_state = false; + + // These config variables have defaults set inside readFromConfig() + int8_t uart_rx_pin; + int8_t uart_tx_pin; + + // string that are used multiple time (this will save some flash memory) + static const char _name[]; + static const char _enabled[]; + + void publishMqtt(const char* topic, const char* state, bool retain); // example for publishing MQTT message + + void _mqttInitialize() + { + mqttMovementTopic = String(mqttDeviceTopic) + F("/ld2410/movement"); + mqttStationaryTopic = String(mqttDeviceTopic) + F("/ld2410/stationary"); + if (HomeAssistantDiscovery){ + _createMqttSensor(F("Movement"), mqttMovementTopic, F("motion"), F("")); + _createMqttSensor(F("Stationary"), mqttStationaryTopic, F("occupancy"), F("")); + } + } + + // Create an MQTT Sensor for Home Assistant Discovery purposes, this includes a pointer to the topic that is published to in the Loop. + void _createMqttSensor(const String &name, const String &topic, const String &deviceClass, const String &unitOfMeasurement) + { + String t = String(F("homeassistant/binary_sensor/")) + mqttClientID + F("/") + name + F("/config"); + + StaticJsonDocument<600> doc; + + doc[F("name")] = String(serverDescription) + F(" Module"); + doc[F("state_topic")] = topic; + doc[F("unique_id")] = String(mqttClientID) + name; + if (unitOfMeasurement != "") + doc[F("unit_of_measurement")] = unitOfMeasurement; + if (deviceClass != "") + doc[F("device_class")] = deviceClass; + doc[F("expire_after")] = 1800; + doc[F("payload_off")] = "OFF"; + doc[F("payload_on")] = "ON"; + + JsonObject device = doc.createNestedObject(F("device")); // attach the sensor to the same device + device[F("name")] = serverDescription; + device[F("identifiers")] = "wled-sensor-" + String(mqttClientID); + device[F("manufacturer")] = F("WLED"); + device[F("model")] = F("FOSS"); + device[F("sw_version")] = versionString; + + String temp; + serializeJson(doc, temp); + DEBUG_PRINTLN(t); + DEBUG_PRINTLN(temp); + + mqtt->publish(t.c_str(), 0, true, temp.c_str()); + } + + public: + + inline bool isEnabled() { return enabled; } + + void setup() { + Serial1.begin(256000, SERIAL_8N1, uart_rx_pin, uart_tx_pin); + Serial.print(F("\nLD2410 radar sensor initialising: ")); + if(radar.begin(Serial1)){ + Serial.println(F("OK")); + } else { + Serial.println(F("not connected")); + } + initDone = true; + } + + + void loop() { + // NOTE: on very long strips strip.isUpdating() may always return true so update accordingly + if (!enabled || strip.isUpdating()) return; + radar.read(); + unsigned long curr_time = millis(); + if(curr_time - lastTime > 1000) //Try to Report every 1000ms + { + lastTime = curr_time; + sensorFound = radar.isConnected(); + if(!sensorFound) return; + stationary_detected = radar.presenceDetected(); + if(stationary_detected != last_stationary_state){ + if (WLED_MQTT_CONNECTED){ + publishMqtt("/ld2410/stationary", stationary_detected ? "ON":"OFF", false); + last_stationary_state = stationary_detected; + } + } + movement_detected = radar.movingTargetDetected(); + if(movement_detected != last_movement_state){ + if (WLED_MQTT_CONNECTED){ + publishMqtt("/ld2410/movement", movement_detected ? "ON":"OFF", false); + last_movement_state = movement_detected; + } + } + // If there hasn't been any activity, send current state to confirm sensor is alive + if(curr_time - last_mqtt_sent > 1000*60*5 && WLED_MQTT_CONNECTED){ + publishMqtt("/ld2410/stationary", stationary_detected ? "ON":"OFF", false); + publishMqtt("/ld2410/movement", movement_detected ? "ON":"OFF", false); + } + } + } + + + void addToJsonInfo(JsonObject& root) + { + // if "u" object does not exist yet wee need to create it + JsonObject user = root[F("u")]; + if (user.isNull()) user = root.createNestedObject(F("u")); + + JsonArray ld2410_sta_json = user.createNestedArray(F("LD2410 Stationary")); + JsonArray ld2410_mov_json = user.createNestedArray(F("LD2410 Movement")); + if (!enabled){ + ld2410_sta_json.add(F("disabled")); + ld2410_mov_json.add(F("disabled")); + } else if(!sensorFound){ + ld2410_sta_json.add(F("LD2410")); + ld2410_sta_json.add(" Not Found"); + } else { + ld2410_sta_json.add("Sta "); + ld2410_sta_json.add(stationary_detected ? "ON":"OFF"); + ld2410_mov_json.add("Mov "); + ld2410_mov_json.add(movement_detected ? "ON":"OFF"); + } + } + + void addToConfig(JsonObject& root) + { + JsonObject top = root.createNestedObject(FPSTR(_name)); + top[FPSTR(_enabled)] = enabled; + //save these vars persistently whenever settings are saved + top["uart_rx_pin"] = default_uart_rx; + top["uart_tx_pin"] = default_uart_tx; + } + + + bool readFromConfig(JsonObject& root) + { + // default settings values could be set here (or below using the 3-argument getJsonValue()) instead of in the class definition or constructor + // setting them inside readFromConfig() is slightly more robust, handling the rare but plausible use case of single value being missing after boot (e.g. if the cfg.json was manually edited and a value was removed) + + JsonObject top = root[FPSTR(_name)]; + + bool configComplete = !top.isNull(); + if (!configComplete) + { + DEBUG_PRINT(FPSTR(_name)); + DEBUG_PRINT(F("LD2410")); + DEBUG_PRINTLN(F(": No config found. (Using defaults.)")); + return false; + } + + configComplete &= getJsonValue(top["uart_rx_pin"], uart_rx_pin, default_uart_rx); + configComplete &= getJsonValue(top["uart_tx_pin"], uart_tx_pin, default_uart_tx); + + return configComplete; + } + + +#ifndef WLED_DISABLE_MQTT + /** + * onMqttConnect() is called when MQTT connection is established + */ + void onMqttConnect(bool sessionPresent) { + // do any MQTT related initialisation here + if(!radar.isConnected()) return; + publishMqtt("/ld2410/status", "I am alive!", false); + if (!mqttInitialized) + { + _mqttInitialize(); + mqttInitialized = true; + } + } +#endif + + uint16_t getId() + { + return USERMOD_ID_LD2410; + } +}; + + +// add more strings here to reduce flash memory usage +const char LD2410Usermod::_name[] PROGMEM = "LD2410Usermod"; +const char LD2410Usermod::_enabled[] PROGMEM = "enabled"; + + +// implementation of non-inline member methods + +void LD2410Usermod::publishMqtt(const char* topic, const char* state, bool retain) +{ +#ifndef WLED_DISABLE_MQTT + //Check if MQTT Connected, otherwise it will crash + if (WLED_MQTT_CONNECTED) { + last_mqtt_sent = millis(); + char subuf[64]; + strcpy(subuf, mqttDeviceTopic); + strcat(subuf, topic); + mqtt->publish(subuf, 0, retain, state); + } +#endif +} diff --git a/usermods/PIR_sensor_switch/usermod_PIR_sensor_switch.h b/usermods/PIR_sensor_switch/usermod_PIR_sensor_switch.h index d66b1b333..7a67dd749 100644 --- a/usermods/PIR_sensor_switch/usermod_PIR_sensor_switch.h +++ b/usermods/PIR_sensor_switch/usermod_PIR_sensor_switch.h @@ -58,7 +58,11 @@ private: bool sensorPinState[PIR_SENSOR_MAX_SENSORS] = {LOW}; // current PIR sensor pin state // configurable parameters +#if PIR_SENSOR_PIN < 0 + bool enabled = false; // PIR sensor disabled +#else bool enabled = true; // PIR sensor enabled +#endif int8_t PIRsensorPin[PIR_SENSOR_MAX_SENSORS] = {PIR_SENSOR_PIN}; // PIR sensor pin uint32_t m_switchOffDelay = PIR_SENSOR_OFF_SEC*1000; // delay before switch off after the sensor state goes LOW (10min) uint8_t m_onPreset = 0; // on preset diff --git a/usermods/SN_Photoresistor/usermod_sn_photoresistor.h b/usermods/SN_Photoresistor/usermod_sn_photoresistor.h index c09b5d907..45cdb66ad 100644 --- a/usermods/SN_Photoresistor/usermod_sn_photoresistor.h +++ b/usermods/SN_Photoresistor/usermod_sn_photoresistor.h @@ -3,7 +3,9 @@ #include "wled.h" //Pin defaults for QuinLed Dig-Uno (A0) +#ifndef PHOTORESISTOR_PIN #define PHOTORESISTOR_PIN A0 +#endif // the frequency to check photoresistor, 10 seconds #ifndef USERMOD_SN_PHOTORESISTOR_MEASUREMENT_INTERVAL @@ -207,4 +209,4 @@ const char Usermod_SN_Photoresistor::_readInterval[] PROGMEM = "read-interval-s" const char Usermod_SN_Photoresistor::_referenceVoltage[] PROGMEM = "supplied-voltage"; const char Usermod_SN_Photoresistor::_resistorValue[] PROGMEM = "resistor-value"; const char Usermod_SN_Photoresistor::_adcPrecision[] PROGMEM = "adc-precision"; -const char Usermod_SN_Photoresistor::_offset[] PROGMEM = "offset"; \ No newline at end of file +const char Usermod_SN_Photoresistor::_offset[] PROGMEM = "offset"; diff --git a/usermods/usermod_v2_auto_save/usermod_v2_auto_save.h b/usermods/usermod_v2_auto_save/usermod_v2_auto_save.h index 2a63dd4d8..52ff3cc1d 100644 --- a/usermods/usermod_v2_auto_save/usermod_v2_auto_save.h +++ b/usermods/usermod_v2_auto_save/usermod_v2_auto_save.h @@ -122,9 +122,9 @@ class AutoSaveUsermod : public Usermod { * Da loop. */ void loop() { - if (!autoSaveAfterSec || !enabled || strip.isUpdating() || currentPreset>0) return; // setting 0 as autosave seconds disables autosave - + static unsigned long lastRun = 0; unsigned long now = millis(); + if (!autoSaveAfterSec || !enabled || currentPreset>0 || (strip.isUpdating() && now - lastRun < 240)) return; // setting 0 as autosave seconds disables autosave uint8_t currentMode = strip.getMainSegment().mode; uint8_t currentPalette = strip.getMainSegment().palette; diff --git a/wled00/FX.cpp b/wled00/FX.cpp index 4b7f9ce36..c50b9383f 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -4875,7 +4875,7 @@ uint16_t mode_2DBlackHole(void) { // By: Stepko https://editor.soulma // central white dot SEGMENT.setPixelColorXY(cols/2, rows/2, WHITE); // blur everything a bit - SEGMENT.blur(16); + SEGMENT.blur(cols*rows > 100 ? 16 : 0); return FRAMETIME; } // mode_2DBlackHole() @@ -5671,8 +5671,7 @@ uint16_t mode_2Dsquaredswirl(void) { // By: Mark Kriegsman. https://g const uint8_t kBorderWidth = 2; SEGMENT.fadeToBlackBy(24); - uint8_t blurAmount = SEGMENT.custom3>>1; // reduced resolution slider - SEGMENT.blur(blurAmount); + SEGMENT.blur(SEGMENT.custom3>>1); // Use two out-of-sync sine waves int i = beatsin8(19, kBorderWidth, cols-kBorderWidth); @@ -6461,7 +6460,7 @@ uint16_t mode_2DWaverly(void) { SEGMENT.addPixelColorXY((cols - 1) - i, (rows - 1) - j, ColorFromPalette(SEGPALETTE, map(j, 0, thisMax, 250, 0), 255, LINEARBLEND)); } } - SEGMENT.blur(16); + SEGMENT.blur(cols*rows > 100 ? 16 : 0); return FRAMETIME; } // mode_2DWaverly() diff --git a/wled00/FX_fcn.cpp b/wled00/FX_fcn.cpp index 547145ca5..3ebf0c448 100644 --- a/wled00/FX_fcn.cpp +++ b/wled00/FX_fcn.cpp @@ -1292,7 +1292,7 @@ void WS2812FX::finalizeInit(void) { unsigned start = prevLen; unsigned count = defCounts[(i < defNumCounts) ? i : defNumCounts -1]; prevLen += count; - BusConfig defCfg = BusConfig(DEFAULT_LED_TYPE, defPin, start, count, DEFAULT_LED_COLOR_ORDER, false, 0, RGBW_MODE_MANUAL_ONLY); + BusConfig defCfg = BusConfig(DEFAULT_LED_TYPE, defPin, start, count, DEFAULT_LED_COLOR_ORDER, false, 0, RGBW_MODE_MANUAL_ONLY, 0, useGlobalLedBuffer); if (BusManager::add(defCfg) == -1) break; } } diff --git a/wled00/bus_manager.h b/wled00/bus_manager.h index 3a523cc94..e2c4239d8 100644 --- a/wled00/bus_manager.h +++ b/wled00/bus_manager.h @@ -37,7 +37,7 @@ struct BusConfig { uint8_t milliAmpsPerLed; uint16_t milliAmpsMax; - BusConfig(uint8_t busType, uint8_t* ppins, uint16_t pstart, uint16_t len = 1, uint8_t pcolorOrder = COL_ORDER_GRB, bool rev = false, uint8_t skip = 0, byte aw=RGBW_MODE_MANUAL_ONLY, uint16_t clock_kHz=0U, bool dblBfr=false, uint8_t maPerLed=55, uint16_t maMax=ABL_MILLIAMPS_DEFAULT) + BusConfig(uint8_t busType, uint8_t* ppins, uint16_t pstart, uint16_t len = 1, uint8_t pcolorOrder = COL_ORDER_GRB, bool rev = false, uint8_t skip = 0, byte aw=RGBW_MODE_MANUAL_ONLY, uint16_t clock_kHz=0U, bool dblBfr=false, uint8_t maPerLed=LED_MILLIAMPS_DEFAULT, uint16_t maMax=ABL_MILLIAMPS_DEFAULT) : count(len) , start(pstart) , colorOrder(pcolorOrder) @@ -129,7 +129,7 @@ class Bus { virtual uint32_t getPixelColor(uint16_t pix) { return 0; } virtual void setBrightness(uint8_t b) { _bri = b; }; virtual uint8_t getPins(uint8_t* pinArray) { return 0; } - virtual uint16_t getLength() { return _len; } + virtual uint16_t getLength() { return isOk() ? _len : 0; } virtual void setColorOrder(uint8_t co) {} virtual uint8_t getColorOrder() { return COL_ORDER_RGB; } virtual uint8_t skippedLeds() { return 0; } diff --git a/wled00/colors.cpp b/wled00/colors.cpp index 30d2c069e..55fb5d477 100644 --- a/wled00/colors.cpp +++ b/wled00/colors.cpp @@ -208,13 +208,13 @@ CRGBPalette16 generateRandomPalette(void) //generate fully random palette void colorHStoRGB(uint16_t hue, byte sat, byte* rgb) //hue, sat to rgb { - float h = ((float)hue)/65535.0f; + float h = ((float)hue)/10922.5f; // hue*6/65535 float s = ((float)sat)/255.0f; - int i = floorf(h*6); - float f = h * 6.0f - i; + int i = int(h); + float f = h - i; int p = int(255.0f * (1.0f-s)); - int q = int(255.0f * (1.0f-f*s)); - int t = int(255.0f * (1.0f-(1.0f-f)*s)); + int q = int(255.0f * (1.0f-s*f)); + int t = int(255.0f * (1.0f-s*(1.0f-f))); p = constrain(p, 0, 255); q = constrain(q, 0, 255); t = constrain(t, 0, 255); diff --git a/wled00/const.h b/wled00/const.h index 20c476fd0..0ff70e47d 100644 --- a/wled00/const.h +++ b/wled00/const.h @@ -46,36 +46,58 @@ #ifndef WLED_MAX_BUSSES #ifdef ESP8266 - #define WLED_MAX_BUSSES 3 + #define WLED_MAX_DIGITAL_CHANNELS 3 + #define WLED_MAX_ANALOG_CHANNELS 5 + #define WLED_MAX_BUSSES 4 // will allow 3 digital & 1 analog RGB #define WLED_MIN_VIRTUAL_BUSSES 2 #else #if defined(CONFIG_IDF_TARGET_ESP32C3) // 2 RMT, 6 LEDC, only has 1 I2S but NPB does not support it ATM - #define WLED_MAX_BUSSES 3 // will allow 2 digital & 1 analog (or the other way around) + #define WLED_MAX_BUSSES 4 // will allow 2 digital & 2 analog RGB + #define WLED_MAX_DIGITAL_CHANNELS 2 + #define WLED_MAX_ANALOG_CHANNELS 6 #define WLED_MIN_VIRTUAL_BUSSES 3 #elif defined(CONFIG_IDF_TARGET_ESP32S2) // 4 RMT, 8 LEDC, only has 1 I2S bus, supported in NPB // the 5th bus (I2S) will prevent Audioreactive usermod from functioning (it is last used though) - #define WLED_MAX_BUSSES 7 // will allow 5 digital & 2 analog + #define WLED_MAX_BUSSES 7 // will allow 5 digital & 2 analog RGB + #define WLED_MAX_DIGITAL_CHANNELS 5 + #define WLED_MAX_ANALOG_CHANNELS 8 #define WLED_MIN_VIRTUAL_BUSSES 3 #elif defined(CONFIG_IDF_TARGET_ESP32S3) // 4 RMT, 8 LEDC, has 2 I2S but NPB does not support them ATM - #define WLED_MAX_BUSSES 6 // will allow 4 digital & 2 analog + #define WLED_MAX_BUSSES 6 // will allow 4 digital & 2 analog RGB + #define WLED_MAX_DIGITAL_CHANNELS 4 + #define WLED_MAX_ANALOG_CHANNELS 8 #define WLED_MIN_VIRTUAL_BUSSES 4 #else // the last digital bus (I2S0) will prevent Audioreactive usermod from functioning - #define WLED_MAX_BUSSES 17 - #define WLED_MIN_VIRTUAL_BUSSES 0 + #define WLED_MAX_BUSSES 20 // will allow 17 digital & 3 analog RGB + #define WLED_MAX_DIGITAL_CHANNELS 17 + #define WLED_MAX_ANALOG_CHANNELS 10 + #define WLED_MIN_VIRTUAL_BUSSES 4 #endif #endif #else #ifdef ESP8266 - #if WLED_MAX_BUSES > 5 + #if WLED_MAX_BUSSES > 5 #error Maximum number of buses is 5. #endif + #ifndef WLED_MAX_ANALOG_CHANNELS + #error You must also define WLED_MAX_ANALOG_CHANNELS. + #endif + #ifndef WLED_MAX_DIGITAL_CHANNELS + #error You must also define WLED_MAX_DIGITAL_CHANNELS. + #endif #define WLED_MIN_VIRTUAL_BUSSES (5-WLED_MAX_BUSSES) #else - #if WLED_MAX_BUSES > 17 - #error Maximum number of buses is 17. + #if WLED_MAX_BUSSES > 20 + #error Maximum number of buses is 20. #endif - #define WLED_MIN_VIRTUAL_BUSSES (17-WLED_MAX_BUSSES) + #ifndef WLED_MAX_ANALOG_CHANNELS + #error You must also define WLED_MAX_ANALOG_CHANNELS. + #endif + #ifndef WLED_MAX_DIGITAL_CHANNELS + #error You must also define WLED_MAX_DIGITAL_CHANNELS. + #endif + #define WLED_MIN_VIRTUAL_BUSSES (20-WLED_MAX_BUSSES) #endif #endif @@ -177,6 +199,7 @@ #define USERMOD_ID_BME68X 49 //Usermod "usermod_bme68x.h #define USERMOD_ID_INA226 50 //Usermod "usermod_ina226.h" #define USERMOD_ID_AHT10 51 //Usermod "usermod_aht10.h" +#define USERMOD_ID_LD2410 52 //Usermod "usermod_ld2410.h" //Access point behavior #define AP_BEHAVIOR_BOOT_NO_CONN 0 //Open AP when no connection after boot @@ -328,7 +351,7 @@ #define BTN_TYPE_TOUCH_SWITCH 9 //Ethernet board types -#define WLED_NUM_ETH_TYPES 12 +#define WLED_NUM_ETH_TYPES 13 #define WLED_ETH_NONE 0 #define WLED_ETH_WT32_ETH01 1 @@ -342,6 +365,7 @@ #define WLED_ETH_ABCWLEDV43ETH 9 #define WLED_ETH_SERG74 10 #define WLED_ETH_ESP32_POE_WROVER 11 +#define WLED_ETH_LILYGO_T_POE_PRO 12 //Hue error codes #define HUE_ERROR_INACTIVE 0 @@ -478,6 +502,16 @@ #endif #endif +#ifndef LED_MILLIAMPS_DEFAULT + #define LED_MILLIAMPS_DEFAULT 55 // common WS2812B +#else + #if LED_MILLIAMPS_DEFAULT < 1 || LED_MILLIAMPS_DEFAULT > 100 + #warning "Unusual LED mA current, overriding with default value." + #undef LED_MILLIAMPS_DEFAULT + #define LED_MILLIAMPS_DEFAULT 55 + #endif +#endif + // PWM settings #ifndef WLED_PWM_FREQ #ifdef ESP8266 diff --git a/wled00/data/index.css b/wled00/data/index.css index 6ac3f3a1f..0952cca21 100644 --- a/wled00/data/index.css +++ b/wled00/data/index.css @@ -923,6 +923,7 @@ select.sel-p, select.sel-pl, select.sel-ple { margin: 5px 0; width: 100%; height: 40px; + padding: 0 20px 0 8px; } div.sel-p { position: relative; diff --git a/wled00/data/index.js b/wled00/data/index.js index 1f8a91616..7f4afbc04 100644 --- a/wled00/data/index.js +++ b/wled00/data/index.js @@ -588,7 +588,7 @@ function loadFXData(callback = null) fxdata = []; if (!retry) { retry = true; - setTimeout(loadFXData, 500); // retry + setTimeout(()=>{loadFXData(loadFX);}, 500); // retry } showToast(e, true); }) @@ -1713,9 +1713,7 @@ function requestJson(command=null) fetch(getURL('/json/si'), { method: type, - headers: { - "Content-type": "application/json; charset=UTF-8" - }, + headers: {"Content-Type": "application/json; charset=UTF-8"}, body: req }) .then(res => { @@ -2698,7 +2696,9 @@ function setBalance(b) function rmtTgl(ip,i) { event.preventDefault(); event.stopPropagation(); - fetch(`http://${ip}/win&T=2`, {method: 'get'}) + fetch(`http://${ip}/win&T=2`, { + method: 'get' + }) .then((r)=>{ return r.text(); }) @@ -2790,21 +2790,23 @@ function loadPalettesData(callback = null) function getPalettesData(page, callback) { fetch(getURL(`/json/palx?page=${page}`), { - method: 'get', - headers: { - "Content-type": "application/json; charset=UTF-8" - } + method: 'get' }) .then(res => { if (!res.ok) showErrorToast(); return res.json(); }) .then(json => { + retry = false; palettesData = Object.assign({}, palettesData, json.p); - if (page < json.m) setTimeout(()=>{ getPalettesData(page + 1, callback); }, 50); + if (page < json.m) setTimeout(()=>{ getPalettesData(page + 1, callback); }, 75); else callback(); }) .catch((error)=>{ + if (!retry) { + retry = true; + setTimeout(()=>{getPalettesData(page,callback);}, 500); // retry + } showToast(error, true); }); } @@ -2841,7 +2843,8 @@ function search(field, listId = null) { if (gId("filters").querySelectorAll("input[type=checkbox]:checked").length) return; // filter list items but leave (Default & Solid) always visible - gId(listId).querySelectorAll('.lstI').forEach((listItem,i)=>{ + const listItems = gId("fxlist").querySelectorAll('.lstI'); + listItems.forEach((listItem,i)=>{ if (listId!=='pcont' && i===0) return; const listItemName = listItem.querySelector('.lstIname').innerText.toUpperCase(); const searchIndex = listItemName.indexOf(field.value.toUpperCase()); @@ -3064,7 +3067,7 @@ function size() function togglePcMode(fromB = false) { - let ap = (fromB && !lastinfo) || (lastinfo && lastinfo.wifi && lastinfo.witi.ap); + let ap = (fromB && !lastinfo) || (lastinfo && lastinfo.wifi && lastinfo.wifi.ap); if (fromB) { pcModeA = !pcModeA; localStorage.setItem('pcm', pcModeA); diff --git a/wled00/data/settings_leds.htm b/wled00/data/settings_leds.htm index 15748ddb3..a3f749bc6 100644 --- a/wled00/data/settings_leds.htm +++ b/wled00/data/settings_leds.htm @@ -5,7 +5,7 @@ LED Settings