mirror of
https://github.com/wled/WLED.git
synced 2025-07-24 03:06:36 +00:00
Merge branch 'main' into 0_15
This commit is contained in:
parent
0ab2d18b52
commit
7eae8f68d8
39
CHANGELOG.md
39
CHANGELOG.md
@ -1,5 +1,11 @@
|
||||
## WLED changelog
|
||||
|
||||
#### Build 2402060
|
||||
- WLED version 0.15.0-b1
|
||||
- Harmonic Random Cycle palette (#3729 by @dedehai)
|
||||
- Multi PIR sensor usermod (added support for attaching multiple PIR sensors)
|
||||
- Removed obsolete (and nonfunctional) usermods
|
||||
|
||||
#### Build 2309120 till build 2402010
|
||||
- WLED version 0.15.0-a0
|
||||
- Multi-WiFi support. Add up to 3 (or more via cusom compile) WiFis to connect to
|
||||
@ -84,6 +90,33 @@
|
||||
- send UDP/WS on segment change
|
||||
- pop_back() when removing last segment
|
||||
|
||||
#### Build 2401141
|
||||
- Official release of WLED 0.14.1
|
||||
- Fix for #3566, #3665, #3672
|
||||
- Sorting of palettes in custom palette editor (#3674 by @WoodyLetsCode)
|
||||
|
||||
#### Build 2401060
|
||||
- Version bump: 0.14.1-b3
|
||||
- Global JSON buffer guarding (#3648 by @willmmiles, resolves #3641, #3312, #3367, #3637, #3646, #3447)
|
||||
- Fix for #3632
|
||||
- Custom palette editor mobile UI enhancement (#3617 by @imeszaros)
|
||||
- changelog update
|
||||
|
||||
#### Build 2312290
|
||||
- Fix for #3622, #3613, #3609
|
||||
- Various tweaks and fixes
|
||||
- changelog update
|
||||
|
||||
#### Build 2312230
|
||||
- Version bump: 0.14.1-b2
|
||||
- Fix for Pixel Magic button
|
||||
- Fix for #2922 (option to force WiFi PHY mode to G on ESP8266)
|
||||
- Fix for #3601, #3400 (incorrect sunrise/sunset, #3612 by @softhack007)
|
||||
|
||||
#### Build 2312180
|
||||
- Bugfixes (#3593, #3490, #3573, #3517, #3561, #3555, #3541, #3536, #3515, #3522, #3533, #3508)
|
||||
- Various other internal cleanups and optimisations
|
||||
|
||||
#### Build 2311160
|
||||
- Version bump: 0.14.1-b1
|
||||
- Bugfixes (#3526, #3502, #3496, #3484, #3487, #3445, #3466, #3296, #3382, #3312)
|
||||
@ -516,7 +549,7 @@
|
||||
|
||||
- Added application level pong websockets reply (#2139)
|
||||
- Use AsyncTCP 1.0.3 as it mitigates the flickering issue from 0.13.0-b2
|
||||
- Fixed transition manually updated in preset overriden by field value
|
||||
- Fixed transition manually updated in preset overridden by field value
|
||||
|
||||
#### Build 2108050
|
||||
|
||||
@ -1045,7 +1078,7 @@
|
||||
|
||||
#### Build 2011040
|
||||
|
||||
- Inversed Rain direction (fixes #1147)
|
||||
- Inverted Rain direction (fixes #1147)
|
||||
|
||||
#### Build 2011010
|
||||
|
||||
@ -1256,7 +1289,7 @@
|
||||
|
||||
- Added module info page to web UI
|
||||
- Added realtime override functionality to web UI
|
||||
- Added individial segment power and brightness to web UI
|
||||
- Added individual segment power and brightness to web UI
|
||||
- Added feature to one-click select single segment only by tapping segment name
|
||||
- Removed palette jumping to default if color is changed
|
||||
|
||||
|
2
package-lock.json
generated
2
package-lock.json
generated
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "wled",
|
||||
"version": "0.15.0-a0",
|
||||
"version": "0.15.0-b1",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "wled",
|
||||
"version": "0.15.0-a0",
|
||||
"version": "0.15.0-b1",
|
||||
"description": "Tools for WLED project",
|
||||
"main": "tools/cdata.js",
|
||||
"directories": {
|
||||
|
@ -26,7 +26,7 @@ A fast and feature-rich implementation of an ESP8266/ESP32 webserver to control
|
||||
- Up to 250 user presets to save and load colors/effects easily, supports cycling through them.
|
||||
- Presets can be used to automatically execute API calls
|
||||
- Nightlight function (gradually dims down)
|
||||
- Full OTA software updatability (HTTP + ArduinoOTA), password protectable
|
||||
- Full OTA software updateability (HTTP + ArduinoOTA), password protectable
|
||||
- Configurable analog clock (Cronixie, 7-segment and EleksTube IPS clock support via usermods)
|
||||
- Configurable Auto Brightness limit for safe operation
|
||||
- Filesystem-based config for easier backup of presets and settings
|
||||
|
@ -52,7 +52,7 @@ starlette==0.23.1
|
||||
# via platformio
|
||||
tabulate==0.9.0
|
||||
# via platformio
|
||||
urllib3==1.26.15
|
||||
urllib3==1.26.18
|
||||
# via requests
|
||||
uvicorn==0.20.0
|
||||
# via platformio
|
||||
|
@ -133,7 +133,7 @@ class Animated_Staircase : public Usermod {
|
||||
* received within this time, an object is detected
|
||||
* and the function will return true.
|
||||
*
|
||||
* The speed of sound is 343 meters per second at 20 degress Celcius.
|
||||
* The speed of sound is 343 meters per second at 20 degrees Celsius.
|
||||
* Since the sound has to travel back and forth, the detection
|
||||
* distance for the sensor in cm is (0.0343 * maxTimeUs) / 2.
|
||||
*
|
||||
@ -259,7 +259,7 @@ class Animated_Staircase : public Usermod {
|
||||
}
|
||||
}
|
||||
|
||||
// send sesnor values to JSON API
|
||||
// send sensor values to JSON API
|
||||
void writeSensorsToJson(JsonObject& staircase) {
|
||||
staircase[F("top-sensor")] = topSensorRead;
|
||||
staircase[F("bottom-sensor")] = bottomSensorRead;
|
||||
@ -309,7 +309,7 @@ class Animated_Staircase : public Usermod {
|
||||
seg.setOption(SEG_OPTION_ON, true);
|
||||
}
|
||||
strip.trigger(); // force strip update
|
||||
stateChanged = true; // inform external dvices/UI of change
|
||||
stateChanged = true; // inform external devices/UI of change
|
||||
colorUpdated(CALL_MODE_DIRECT_CHANGE);
|
||||
DEBUG_PRINTLN(F("Animated Staircase disabled."));
|
||||
}
|
||||
@ -492,7 +492,7 @@ class Animated_Staircase : public Usermod {
|
||||
bottomEchoPin = top[FPSTR(_bottomEcho_pin)] | bottomEchoPin;
|
||||
|
||||
topMaxDist = top[FPSTR(_topEchoCm)] | topMaxDist;
|
||||
topMaxDist = min(150,max(30,(int)topMaxDist)); // max distnace ~1.5m (a lag of 9ms may be expected)
|
||||
topMaxDist = min(150,max(30,(int)topMaxDist)); // max distance ~1.5m (a lag of 9ms may be expected)
|
||||
bottomMaxDist = top[FPSTR(_bottomEchoCm)] | bottomMaxDist;
|
||||
bottomMaxDist = min(150,max(30,(int)bottomMaxDist)); // max distance ~1.5m (a lag of 9ms may be expected)
|
||||
|
||||
|
@ -11,7 +11,7 @@ The Animated Staircase can be controlled by the WLED API. Change settings such a
|
||||
speed, on/off time and distance by sending an HTTP request, see below.
|
||||
|
||||
## WLED integration
|
||||
To include this usermod in your WLED setup, you have to be able to [compile WLED from source](https://github.com/Aircoookie/WLED/wiki/Compiling-WLED).
|
||||
To include this usermod in your WLED setup, you have to be able to [compile WLED from source](https://kno.wled.ge/advanced/compiling-wled/).
|
||||
|
||||
Before compiling, you have to make the following modifications:
|
||||
|
||||
@ -38,7 +38,7 @@ Maximum distance for ultrasonic sensor can be configured as the time needed for
|
||||
You _may_ need to use 10k pull-down resistors on the selected PIR pins, depending on the sensor.
|
||||
|
||||
## WLED configuration
|
||||
1. In the WLED UI, confgure a segment for each step. The lowest step of the stairs is the
|
||||
1. In the WLED UI, configure a segment for each step. The lowest step of the stairs is the
|
||||
lowest segment id.
|
||||
2. Save your segments into a preset.
|
||||
3. Ideally, add the preset in the config > LED setup menu to the "apply
|
||||
@ -91,7 +91,7 @@ To enable the usermod again, use `"enabled":true`.
|
||||
Alternatively you can use _Usermod_ Settings page where you can change other parameters as well.
|
||||
|
||||
### Changing animation parameters and detection range of the ultrasonic HC-SR04 sensor
|
||||
Using _Usermod_ Settings page you can define different usermod parameters, includng sensor pins, delay between segment activation etc.
|
||||
Using _Usermod_ Settings page you can define different usermod parameters, including sensor pins, delay between segment activation etc.
|
||||
|
||||
When an ultrasonic sensor is enabled you can enter maximum detection distance in centimeters separately for top and bottom sensors.
|
||||
|
||||
|
@ -9,7 +9,7 @@ The luminance is displayed in both the Info section of the web UI, as well as pu
|
||||
- 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.
|
||||
|
||||
## Compiliation
|
||||
## Compilation
|
||||
|
||||
To enable, compile with `USERMOD_BH1750` defined (e.g. in `platformio_override.ini`)
|
||||
```ini
|
||||
|
@ -25,7 +25,7 @@
|
||||
#define USERMOD_BH1750_FIRST_MEASUREMENT_AT 10000
|
||||
#endif
|
||||
|
||||
// only report if differance grater than offset value
|
||||
// only report if difference grater than offset value
|
||||
#ifndef USERMOD_BH1750_OFFSET_VALUE
|
||||
#define USERMOD_BH1750_OFFSET_VALUE 1
|
||||
#endif
|
||||
|
@ -31,7 +31,7 @@ private:
|
||||
|
||||
// set the default pins based on the architecture, these get overridden by Usermod menu settings
|
||||
#ifdef ESP8266
|
||||
//uint8_t RST_PIN = 16; // Uncoment for Heltec WiFi-Kit-8
|
||||
//uint8_t RST_PIN = 16; // Un-comment for Heltec WiFi-Kit-8
|
||||
#endif
|
||||
bool initDone = false;
|
||||
|
||||
@ -78,7 +78,7 @@ private:
|
||||
static const char _name[];
|
||||
static const char _enabled[];
|
||||
|
||||
// Read the BME280/BMP280 Sensor (which one runs depends on whether Celsius or Farenheit being set in Usermod Menu)
|
||||
// Read the BME280/BMP280 Sensor (which one runs depends on whether Celsius or Fahrenheit being set in Usermod Menu)
|
||||
void UpdateBME280Data(int SensorType)
|
||||
{
|
||||
float _temperature, _humidity, _pressure;
|
||||
|
@ -19,7 +19,7 @@ If you have an ESP32 board, connect the positive side of the battery to ADC1 (GP
|
||||
- 💯 Displays current battery voltage
|
||||
- 🚥 Displays battery level
|
||||
- 🚫 Auto-off with configurable Threshold
|
||||
- 🚨 Low power indicator with many configuration posibilities
|
||||
- 🚨 Low power indicator with many configuration possibilities
|
||||
|
||||
## 🎈 Installation
|
||||
|
||||
@ -41,7 +41,7 @@ define `USERMOD_BATTERY` in `wled00/my_config.h`
|
||||
| `USERMOD_BATTERY_MEASUREMENT_INTERVAL` | ms | battery check interval. defaults to 30 seconds |
|
||||
| `USERMOD_BATTERY_MIN_VOLTAGE` | v | minimum battery voltage. default is 2.6 (18650 battery standard) |
|
||||
| `USERMOD_BATTERY_MAX_VOLTAGE` | v | maximum battery voltage. default is 4.2 (18650 battery standard) |
|
||||
| `USERMOD_BATTERY_TOTAL_CAPACITY` | mAh | the capacity of all cells in parralel sumed up |
|
||||
| `USERMOD_BATTERY_TOTAL_CAPACITY` | mAh | the capacity of all cells in parallel summed up |
|
||||
| `USERMOD_BATTERY_CALIBRATION` | | offset / calibration number, fine tune the measured voltage by the microcontroller |
|
||||
| Auto-Off | --- | --- |
|
||||
| `USERMOD_BATTERY_AUTO_OFF_ENABLED` | true/false | enables auto-off |
|
||||
|
@ -49,7 +49,7 @@
|
||||
#endif
|
||||
|
||||
// how many seconds after boot to take first measurement, 90 seconds
|
||||
// 90 gives enough time to OTA update firmware if this crashses
|
||||
// 90 gives enough time to OTA update firmware if this crashes
|
||||
#ifndef USERMOD_DHT_FIRST_MEASUREMENT_AT
|
||||
#define USERMOD_DHT_FIRST_MEASUREMENT_AT 90000
|
||||
#endif
|
||||
|
@ -46,7 +46,7 @@ class MyExampleUsermod : public Usermod {
|
||||
static const char _enabled[];
|
||||
|
||||
|
||||
// any private methods should go here (non-inline methosd should be defined out of class)
|
||||
// any private methods should go here (non-inline method should be defined out of class)
|
||||
void publishMqtt(const char* state, bool retain = false); // example for publishing MQTT message
|
||||
|
||||
|
||||
|
@ -15,23 +15,23 @@ OneWire oneWire(13);
|
||||
DallasTemperature sensor(&oneWire);
|
||||
long temptimer = millis();
|
||||
long lastMeasure = 0;
|
||||
#define Celsius // Show temperature mesaurement in Celcius otherwise is in Fahrenheit
|
||||
#define Celsius // Show temperature measurement in Celsius otherwise is in Fahrenheit
|
||||
|
||||
// If display does not work or looks corrupted check the
|
||||
// constructor reference:
|
||||
// https://github.com/olikraus/u8g2/wiki/u8x8setupcpp
|
||||
// or check the gallery:
|
||||
// https://github.com/olikraus/u8g2/wiki/gallery
|
||||
// --> First choise of cheap I2C OLED 128X32 0.91"
|
||||
// --> First choice of cheap I2C OLED 128X32 0.91"
|
||||
U8X8_SSD1306_128X32_UNIVISION_HW_I2C u8x8(U8X8_PIN_NONE, U8X8_PIN_SCL, U8X8_PIN_SDA); // Pins are Reset, SCL, SDA
|
||||
// --> Second choise of cheap I2C OLED 128X64 0.96" or 1.3"
|
||||
// --> Second choice of cheap I2C OLED 128X64 0.96" or 1.3"
|
||||
//U8X8_SSD1306_128X64_NONAME_HW_I2C u8x8(U8X8_PIN_NONE, U8X8_PIN_SCL, U8X8_PIN_SDA); // Pins are Reset, SCL, SDA
|
||||
// gets called once at boot. Do all initialization that doesn't depend on
|
||||
// network here
|
||||
void userSetup() {
|
||||
sensor.begin(); //Start Dallas temperature sensor
|
||||
u8x8.begin();
|
||||
//u8x8.setFlipMode(1); //Uncoment if using WLED Wemos shield
|
||||
//u8x8.setFlipMode(1); //Un-comment if using WLED Wemos shield
|
||||
u8x8.setPowerSave(0);
|
||||
u8x8.setContrast(10); //Contrast setup will help to preserve OLED lifetime. In case OLED need to be brighter increase number up to 255
|
||||
u8x8.setFont(u8x8_font_chroma48medium8_r);
|
||||
@ -71,7 +71,7 @@ void userLoop() {
|
||||
if (mqtt != nullptr)
|
||||
{
|
||||
sensor.requestTemperatures();
|
||||
//Gets prefered temperature scale based on selection in definitions section
|
||||
//Gets preferred temperature scale based on selection in definitions section
|
||||
#ifdef Celsius
|
||||
float board_temperature = sensor.getTempCByIndex(0);
|
||||
#else
|
||||
@ -138,11 +138,11 @@ void userLoop() {
|
||||
// First row with Wifi name
|
||||
u8x8.setCursor(1, 0);
|
||||
u8x8.print(knownSsid.substring(0, u8x8.getCols() > 1 ? u8x8.getCols() - 2 : 0));
|
||||
// Print `~` char to indicate that SSID is longer, than owr dicplay
|
||||
// Print `~` char to indicate that SSID is longer than our display
|
||||
if (knownSsid.length() > u8x8.getCols())
|
||||
u8x8.print("~");
|
||||
|
||||
// Second row with IP or Psssword
|
||||
// Second row with IP or Password
|
||||
u8x8.setCursor(1, 1);
|
||||
// Print password in AP mode and if led is OFF.
|
||||
if (apActive && bri == 0)
|
||||
|
@ -10,7 +10,7 @@
|
||||
|
||||
void UpdateBME280Data();
|
||||
|
||||
#define Celsius // Show temperature mesaurement in Celcius otherwise is in Fahrenheit
|
||||
#define Celsius // Show temperature measurement in Celsius otherwise is in Fahrenheit
|
||||
BME280I2C bme; // Default : forced mode, standby time = 1000 ms
|
||||
// Oversampling = pressure ×1, temperature ×1, humidity ×1, filter off,
|
||||
|
||||
@ -20,14 +20,14 @@ uint8_t SDA_PIN = 21;
|
||||
#else //ESP8266 boards
|
||||
uint8_t SCL_PIN = 5;
|
||||
uint8_t SDA_PIN = 4;
|
||||
// uint8_t RST_PIN = 16; // Uncoment for Heltec WiFi-Kit-8
|
||||
// uint8_t RST_PIN = 16; // Un-comment for Heltec WiFi-Kit-8
|
||||
#endif
|
||||
|
||||
//The SCL and SDA pins are defined here.
|
||||
//ESP8266 Wemos D1 mini board use SCL=5 SDA=4 while ESP32 Wemos32 mini board use SCL=22 SDA=21
|
||||
#define U8X8_PIN_SCL SCL_PIN
|
||||
#define U8X8_PIN_SDA SDA_PIN
|
||||
//#define U8X8_PIN_RESET RST_PIN // Uncoment for Heltec WiFi-Kit-8
|
||||
//#define U8X8_PIN_RESET RST_PIN // Un-comment for Heltec WiFi-Kit-8
|
||||
|
||||
// If display does not work or looks corrupted check the
|
||||
// constructor reference:
|
||||
@ -36,9 +36,9 @@ uint8_t SDA_PIN = 4;
|
||||
// https://github.com/olikraus/u8g2/wiki/gallery
|
||||
// --> First choise of cheap I2C OLED 128X32 0.91"
|
||||
U8X8_SSD1306_128X32_UNIVISION_HW_I2C u8x8(U8X8_PIN_NONE, U8X8_PIN_SCL, U8X8_PIN_SDA); // Pins are Reset, SCL, SDA
|
||||
// --> Second choise of cheap I2C OLED 128X64 0.96" or 1.3"
|
||||
// --> Second choice of cheap I2C OLED 128X64 0.96" or 1.3"
|
||||
//U8X8_SSD1306_128X64_NONAME_HW_I2C u8x8(U8X8_PIN_NONE, U8X8_PIN_SCL, U8X8_PIN_SDA); // Pins are Reset, SCL, SDA
|
||||
// --> Third choise of Heltec WiFi-Kit-8 OLED 128X32 0.91"
|
||||
// --> Third choice of Heltec WiFi-Kit-8 OLED 128X32 0.91"
|
||||
//U8X8_SSD1306_128X32_UNIVISION_HW_I2C u8x8(U8X8_PIN_RESET, U8X8_PIN_SCL, U8X8_PIN_SDA); // Constructor for Heltec WiFi-Kit-8
|
||||
// gets called once at boot. Do all initialization that doesn't depend on network here
|
||||
|
||||
@ -181,11 +181,11 @@ void userLoop() {
|
||||
// First row with Wifi name
|
||||
u8x8.setCursor(1, 0);
|
||||
u8x8.print(knownSsid.substring(0, u8x8.getCols() > 1 ? u8x8.getCols() - 2 : 0));
|
||||
// Print `~` char to indicate that SSID is longer, than owr dicplay
|
||||
// Print `~` char to indicate that SSID is longer than our display
|
||||
if (knownSsid.length() > u8x8.getCols())
|
||||
u8x8.print("~");
|
||||
|
||||
// Second row with IP or Psssword
|
||||
// Second row with IP or Password
|
||||
u8x8.setCursor(1, 1);
|
||||
// Print password in AP mode and if led is OFF.
|
||||
if (apActive && bri == 0)
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
**Attention: This usermod compiles only for ESP8266**
|
||||
|
||||
This usermod-v2 modification performs a ping request to a local IP address every 60 seconds. This ensures WLED net services remain accessible in some problematic WLAN environments.
|
||||
This usermod-v2 modification performs a ping request to a local IP address every 60 seconds. This ensures WLED net services remain accessible in some problematic WiFi environments.
|
||||
|
||||
The modification works with static or DHCP IP address configuration.
|
||||
|
||||
@ -24,7 +24,7 @@ The usermod supports the following state changes:
|
||||
|
||||
| JSON key | Value range | Description |
|
||||
|-------------|------------------|---------------------------------|
|
||||
| PingDelayMs | 5000 to 18000000 | Deactivdate/activate the sensor |
|
||||
| PingDelayMs | 5000 to 18000000 | Deactivate/activate the sensor |
|
||||
|
||||
Changes also persist after a reboot.
|
||||
|
||||
|
@ -15,7 +15,7 @@ private:
|
||||
static const char _enabled[];
|
||||
static const char _loopInterval[];
|
||||
|
||||
// any private methods should go here (non-inline methosd should be defined out of class)
|
||||
// any private methods should go here (non-inline method should be defined out of class)
|
||||
void publishMqtt(const char *state, bool retain = false); // example for publishing MQTT message
|
||||
|
||||
public:
|
||||
|
26
usermods/LDR_Dusk_Dawn_v2/README.md
Normal file
26
usermods/LDR_Dusk_Dawn_v2/README.md
Normal file
@ -0,0 +1,26 @@
|
||||
# LDR_Dusk_Dawn_v2
|
||||
This usermod will obtain readings from a Light Dependent Resistor (LDR) and will turn on/off specific presets based on those readings. This is useful for exterior lighting situations where you want the lights to only be on when it is dark out.
|
||||
|
||||
# Installation
|
||||
Add "-D USERMOD_LDR_DUSK_DAWN" to your platformio.ini [common] build_flags and build.
|
||||
|
||||
Example:
|
||||
```
|
||||
[common]
|
||||
build_flags =
|
||||
-D USERMOD_LDR_DUSK_DAWN # Enable LDR Dusk Dawn Usermod
|
||||
```
|
||||
|
||||
# Usermod Settings
|
||||
Setting | Description | Default
|
||||
--- | --- | ---
|
||||
Enabled | Enable/Disable the LDR functionality. | Disabled
|
||||
LDR Pin | The analog capable pin your LDR is connected to. | 34
|
||||
Threshold Minutes | The number of minutes of consistent readings above/below the on/off threshold before the LED state will change. | 5
|
||||
Threshold | The analog read value threshold from the LDR. Readings lower than this number will count towards changing the LED state to off. You can see the current LDR reading by going into the info section when LDR functionality is enabled. | 1000
|
||||
On Preset | The WLED preset to be used for the LED on state. | 1
|
||||
Off Preset | The WLED preset to be used for the LED off state. | 2
|
||||
|
||||
## Author
|
||||
[@jeffwdh](https://github.com/jeffwdh)
|
||||
jeffwdh@tarball.ca
|
153
usermods/LDR_Dusk_Dawn_v2/usermod_LDR_Dusk_Dawn_v2.h
Normal file
153
usermods/LDR_Dusk_Dawn_v2/usermod_LDR_Dusk_Dawn_v2.h
Normal file
@ -0,0 +1,153 @@
|
||||
#pragma once
|
||||
#include "wled.h"
|
||||
|
||||
#ifndef ARDUINO_ARCH_ESP32
|
||||
// 8266 does not support analogRead on user selectable pins
|
||||
#error only ESP32 is supported by usermod LDR_DUSK_DAWN
|
||||
#endif
|
||||
|
||||
class LDR_Dusk_Dawn_v2 : public Usermod {
|
||||
private:
|
||||
// Defaults
|
||||
bool ldrEnabled = false;
|
||||
int ldrPin = 34; //A2 on Adafruit Huzzah32
|
||||
int ldrThresholdMinutes = 5; // How many minutes of readings above/below threshold until it switches LED state
|
||||
int ldrThreshold = 1000; // Readings higher than this number will turn off LED.
|
||||
int ldrOnPreset = 1; // Default "On" Preset
|
||||
int ldrOffPreset = 2; // Default "Off" Preset
|
||||
|
||||
// Variables
|
||||
bool initDone = false;
|
||||
bool ldrEnabledPreviously = false; // Was LDR enabled for the previous check? First check is always no.
|
||||
int ldrOffCount; // Number of readings above the threshold
|
||||
int ldrOnCount; // Number of readings below the threshold
|
||||
int ldrReading = 0; // Last LDR reading
|
||||
int ldrLEDState; // Current LED on/off state
|
||||
unsigned long lastMillis = 0;
|
||||
static const char _name[];
|
||||
|
||||
public:
|
||||
void setup() {
|
||||
// register ldrPin
|
||||
if ((ldrPin >= 0) && (digitalPinToAnalogChannel(ldrPin) >= 0)) {
|
||||
if(!pinManager.allocatePin(ldrPin, false, PinOwner::UM_LDR_DUSK_DAWN)) ldrEnabled = false; // pin already in use -> disable usermod
|
||||
else pinMode(ldrPin, INPUT); // alloc success -> configure pin for input
|
||||
} else ldrEnabled = false; // invalid pin -> disable usermod
|
||||
initDone = true;
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// Only update every 10 seconds
|
||||
if (millis() - lastMillis > 10000) {
|
||||
if ( (ldrEnabled == true)
|
||||
&& (ldrPin >= 0) && (digitalPinToAnalogChannel(ldrPin) >= 0) ) { // make sure that pin is valid for analogread()
|
||||
// Default state is off
|
||||
if (ldrEnabledPreviously == false) {
|
||||
applyPreset(ldrOffPreset);
|
||||
ldrEnabledPreviously = true;
|
||||
ldrLEDState = 0;
|
||||
}
|
||||
|
||||
// Get LDR reading and increment counter by number of seconds since last read
|
||||
ldrReading = analogRead(ldrPin);
|
||||
if (ldrReading <= ldrThreshold) {
|
||||
ldrOnCount = ldrOnCount + 10;
|
||||
ldrOffCount = 0;
|
||||
} else {
|
||||
ldrOffCount = ldrOffCount + 10;
|
||||
ldrOnCount = 0;
|
||||
}
|
||||
|
||||
if (ldrOnCount >= (ldrThresholdMinutes * 60)) {
|
||||
ldrOnCount = 0;
|
||||
// If LEDs were previously off, turn on
|
||||
if (ldrLEDState == 0) {
|
||||
applyPreset(ldrOnPreset);
|
||||
ldrLEDState = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (ldrOffCount >= (ldrThresholdMinutes * 60)) {
|
||||
ldrOffCount = 0;
|
||||
// If LEDs were previously on, turn off
|
||||
if (ldrLEDState == 1) {
|
||||
applyPreset(ldrOffPreset);
|
||||
ldrLEDState = 0;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// LDR is disabled, reset variables to default
|
||||
ldrReading = 0;
|
||||
ldrOnCount = 0;
|
||||
ldrOffCount = 0;
|
||||
ldrLEDState = 0;
|
||||
ldrEnabledPreviously = false;
|
||||
}
|
||||
lastMillis = millis();
|
||||
}
|
||||
}
|
||||
|
||||
void addToConfig(JsonObject& root) {
|
||||
JsonObject top = root.createNestedObject(FPSTR(_name));
|
||||
top["Enabled"] = ldrEnabled;
|
||||
top["LDR Pin"] = ldrPin;
|
||||
top["Threshold Minutes"] = ldrThresholdMinutes;
|
||||
top["Threshold"] = ldrThreshold;
|
||||
top["On Preset"] = ldrOnPreset;
|
||||
top["Off Preset"] = ldrOffPreset;
|
||||
}
|
||||
|
||||
bool readFromConfig(JsonObject& root) {
|
||||
int8_t oldLdrPin = ldrPin;
|
||||
JsonObject top = root[FPSTR(_name)];
|
||||
bool configComplete = !top.isNull();
|
||||
configComplete &= getJsonValue(top["Enabled"], ldrEnabled);
|
||||
configComplete &= getJsonValue(top["LDR Pin"], ldrPin);
|
||||
configComplete &= getJsonValue(top["Threshold Minutes"], ldrThresholdMinutes);
|
||||
configComplete &= getJsonValue(top["Threshold"], ldrThreshold);
|
||||
configComplete &= getJsonValue(top["On Preset"], ldrOnPreset);
|
||||
configComplete &= getJsonValue(top["Off Preset"], ldrOffPreset);
|
||||
|
||||
if (initDone && (ldrPin != oldLdrPin)) {
|
||||
// pin changed - un-register previous pin, register new pin
|
||||
if (oldLdrPin >= 0) pinManager.deallocatePin(oldLdrPin, PinOwner::UM_LDR_DUSK_DAWN);
|
||||
setup(); // setup new pin
|
||||
}
|
||||
return configComplete;
|
||||
}
|
||||
|
||||
void addToJsonInfo(JsonObject& root) {
|
||||
// If "u" object does not exist yet we need to create it
|
||||
JsonObject user = root["u"];
|
||||
if (user.isNull()) user = root.createNestedObject("u");
|
||||
|
||||
JsonArray LDR_Enabled = user.createNestedArray("LDR dusk/dawn enabled");
|
||||
LDR_Enabled.add(ldrEnabled);
|
||||
if (!ldrEnabled) return; // do not add more if usermod is disabled
|
||||
|
||||
JsonArray LDR_Reading = user.createNestedArray("LDR reading");
|
||||
LDR_Reading.add(ldrReading);
|
||||
|
||||
JsonArray LDR_State = user.createNestedArray("LDR turned LEDs on");
|
||||
LDR_State.add(bool(ldrLEDState));
|
||||
|
||||
// Optional debug information:
|
||||
//JsonArray LDR_On_Count = user.createNestedArray("LDR on count");
|
||||
//LDR_On_Count.add(ldrOnCount);
|
||||
|
||||
//JsonArray LDR_Off_Count = user.createNestedArray("LDR off count");
|
||||
//LDR_Off_Count.add(ldrOffCount);
|
||||
|
||||
//bool pinValid = ((ldrPin >= 0) && (digitalPinToAnalogChannel(ldrPin) >= 0));
|
||||
//if (pinManager.getPinOwner(ldrPin) != PinOwner::UM_LDR_DUSK_DAWN) pinValid = false;
|
||||
//JsonArray LDR_valid = user.createNestedArray(F("LDR pin"));
|
||||
//LDR_valid.add(ldrPin);
|
||||
//LDR_valid.add(pinValid ? F(" OK"): F(" invalid"));
|
||||
}
|
||||
|
||||
uint16_t getId() {
|
||||
return USERMOD_ID_LDR_DUSK_DAWN;
|
||||
}
|
||||
};
|
||||
|
||||
const char LDR_Dusk_Dawn_v2::_name[] PROGMEM = "LDR_Dusk_Dawn_v2";
|
@ -23,7 +23,7 @@ You can also use usermod's off timer instead of sensor's. In such case rotate th
|
||||
|
||||
## Usermod installation
|
||||
|
||||
**NOTE:** Usermod has been included in master branch of WLED so it can be compiled in directly just by defining `-D USERMOD_PIRSWITCH` and optionaly `-D PIR_SENSOR_PIN=16` to override default pin. You can also change the default off time by adding `-D PIR_SENSOR_OFF_SEC=30`.
|
||||
**NOTE:** Usermod has been included in master branch of WLED so it can be compiled in directly just by defining `-D USERMOD_PIRSWITCH` and optionally `-D PIR_SENSOR_PIN=16` to override default pin. You can also change the default off time by adding `-D PIR_SENSOR_OFF_SEC=30`.
|
||||
|
||||
## API to enable/disable the PIR sensor from outside. For example from another usermod:
|
||||
|
||||
@ -31,7 +31,7 @@ To query or change the PIR sensor state the methods `bool PIRsensorEnabled()` an
|
||||
|
||||
When the PIR sensor state changes an MQTT message is broadcasted with topic `wled/deviceMAC/motion` and message `on` or `off`.
|
||||
Usermod can also be configured to send just the MQTT message but not change WLED state using settings page as well as responding to motion only at night
|
||||
(assuming NTP and lattitude/longitude are set to determine sunrise/sunset times).
|
||||
(assuming NTP and latitude/longitude are set to determine sunrise/sunset times).
|
||||
|
||||
### There are two options to get access to the usermod instance:
|
||||
|
||||
@ -85,7 +85,7 @@ Have fun - @gegu & @blazoncek
|
||||
|
||||
2021-11
|
||||
* Added information about dynamic configuration options
|
||||
* Added option to temporary enable/disble usermod from WLED UI (Info dialog)
|
||||
* Added option to temporary enable/disable usermod from WLED UI (Info dialog)
|
||||
|
||||
2022-11
|
||||
* Added compile time option for off timer.
|
||||
|
@ -104,7 +104,7 @@ private:
|
||||
|
||||
/**
|
||||
* Read and update PIR sensor state.
|
||||
* Initilize/reset switch off timer
|
||||
* Initialize/reset switch off timer
|
||||
*/
|
||||
bool updatePIRsensorState();
|
||||
|
||||
|
@ -5,7 +5,7 @@ v2 Usermod to to control PWM fan with RPM feedback and temperature control
|
||||
This usermod requires the Dallas Temperature usermod to obtain temperature information. If it's not available, the fan will run at 100% speed.
|
||||
If the fan does not have _tachometer_ (RPM) output you can set the _tachometer-pin_ to -1 to disable that feature.
|
||||
|
||||
You can also set the thershold temperature at which fan runs at lowest speed. If the measured temperature is 3°C greater than the threshold temperature, the fan will run at 100%.
|
||||
You can also set the threshold temperature at which fan runs at lowest speed. If the measured temperature is 3°C greater than the threshold temperature, the fan will run at 100%.
|
||||
|
||||
If the _tachometer_ is supported, the current speed (in RPM) will be displayed on the WLED Info page.
|
||||
|
||||
@ -22,7 +22,7 @@ This includes:
|
||||
* PWM output pin (can be configured at compile time `-D PWM_PIN=xx`)
|
||||
* tachometer input pin (can be configured at compile time `-D TACHO_PIN=xx`)
|
||||
* sampling frequency in seconds
|
||||
* threshold temperature in degees C
|
||||
* threshold temperature in degrees Celsius
|
||||
|
||||
_NOTE:_ You may also need to tweak Dallas Temperature usermod sampling frequency to match PWM fan sampling frequency.
|
||||
|
||||
|
@ -30,7 +30,7 @@
|
||||
#define USERMOD_SN_PHOTORESISTOR_RESISTOR_VALUE 10000.0f
|
||||
#endif
|
||||
|
||||
// only report if differance grater than offset value
|
||||
// only report if difference grater than offset value
|
||||
#ifndef USERMOD_SN_PHOTORESISTOR_OFFSET_VALUE
|
||||
#define USERMOD_SN_PHOTORESISTOR_OFFSET_VALUE 5
|
||||
#endif
|
||||
|
@ -3,7 +3,7 @@
|
||||
* This file allows you to add own functionality to WLED more easily
|
||||
* See: https://github.com/Aircoookie/WLED/wiki/Add-own-functionality
|
||||
* EEPROM bytes 2750+ are reserved for your custom use case. (if you extend #define EEPSIZE in const.h)
|
||||
* bytes 2400+ are currently ununsed, but might be used for future wled features
|
||||
* bytes 2400+ are currently unused, but might be used for future wled features
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -144,7 +144,7 @@ void userLoop() {
|
||||
// First row with Wifi name
|
||||
tft.setCursor(1, 1);
|
||||
tft.print(knownSsid.substring(0, tftcharwidth > 1 ? tftcharwidth - 1 : 0));
|
||||
// Print `~` char to indicate that SSID is longer, than our dicplay
|
||||
// Print `~` char to indicate that SSID is longer than our display
|
||||
if (knownSsid.length() > tftcharwidth)
|
||||
tft.print("~");
|
||||
|
||||
|
@ -18,7 +18,7 @@ Copy the example `platformio_override.ini` to the root directory. This file sho
|
||||
* `USERMOD_DALLASTEMPERATURE` - enables this user mod wled00/usermods_list.cpp
|
||||
* `USERMOD_DALLASTEMPERATURE_MEASUREMENT_INTERVAL` - number of milliseconds between measurements, defaults to 60000 ms (60s)
|
||||
|
||||
All parameters can be configured at runtime via the Usermods settings page, including pin, temperature in degrees Celsius or Farenheit and measurement interval.
|
||||
All parameters can be configured at runtime via the Usermods settings page, including pin, temperature in degrees Celsius or Fahrenheit and measurement interval.
|
||||
|
||||
## Project link
|
||||
|
||||
|
@ -34,30 +34,30 @@ uint8_t DALLAS_PIN =23;
|
||||
uint8_t SCL_PIN = 5;
|
||||
uint8_t SDA_PIN = 4;
|
||||
uint8_t DALLAS_PIN =13;
|
||||
// uint8_t RST_PIN = 16; // Uncoment for Heltec WiFi-Kit-8
|
||||
// uint8_t RST_PIN = 16; // Un-comment for Heltec WiFi-Kit-8
|
||||
#endif
|
||||
|
||||
//The SCL and SDA pins are defined here.
|
||||
//ESP8266 Wemos D1 mini board use SCL=5 SDA=4 while ESP32 Wemos32 mini board use SCL=22 SDA=21
|
||||
#define U8X8_PIN_SCL SCL_PIN
|
||||
#define U8X8_PIN_SDA SDA_PIN
|
||||
//#define U8X8_PIN_RESET RST_PIN // Uncoment for Heltec WiFi-Kit-8
|
||||
//#define U8X8_PIN_RESET RST_PIN // Un-comment for Heltec WiFi-Kit-8
|
||||
|
||||
// Dallas sensor reading timer
|
||||
long temptimer = millis();
|
||||
long lastMeasure = 0;
|
||||
#define Celsius // Show temperature mesaurement in Celcius otherwise is in Fahrenheit
|
||||
#define Celsius // Show temperature measurement in Celsius otherwise is in Fahrenheit
|
||||
|
||||
// If display does not work or looks corrupted check the
|
||||
// constructor reference:
|
||||
// https://github.com/olikraus/u8g2/wiki/u8x8setupcpp
|
||||
// or check the gallery:
|
||||
// https://github.com/olikraus/u8g2/wiki/gallery
|
||||
// --> First choise of cheap I2C OLED 128X32 0.91"
|
||||
// --> First choice of cheap I2C OLED 128X32 0.91"
|
||||
U8X8_SSD1306_128X32_UNIVISION_HW_I2C u8x8(U8X8_PIN_NONE, U8X8_PIN_SCL, U8X8_PIN_SDA); // Pins are Reset, SCL, SDA
|
||||
// --> Second choise of cheap I2C OLED 128X64 0.96" or 1.3"
|
||||
// --> Second choice of cheap I2C OLED 128X64 0.96" or 1.3"
|
||||
//U8X8_SSD1306_128X64_NONAME_HW_I2C u8x8(U8X8_PIN_NONE, U8X8_PIN_SCL, U8X8_PIN_SDA); // Pins are Reset, SCL, SDA
|
||||
// --> Third choise of Heltec WiFi-Kit-8 OLED 128X32 0.91"
|
||||
// --> Third choice of Heltec WiFi-Kit-8 OLED 128X32 0.91"
|
||||
//U8X8_SSD1306_128X32_UNIVISION_HW_I2C u8x8(U8X8_PIN_RESET, U8X8_PIN_SCL, U8X8_PIN_SDA); // Constructor for Heltec WiFi-Kit-8
|
||||
// gets called once at boot. Do all initialization that doesn't depend on network here
|
||||
void userSetup() {
|
||||
@ -97,7 +97,7 @@ void userLoop() {
|
||||
|
||||
//----> Dallas temperature sensor MQTT publishing
|
||||
temptimer = millis();
|
||||
// Timer to publishe new temperature every 60 seconds
|
||||
// Timer to publish new temperature every 60 seconds
|
||||
if (temptimer - lastMeasure > 60000)
|
||||
{
|
||||
lastMeasure = temptimer;
|
||||
@ -106,7 +106,7 @@ void userLoop() {
|
||||
if (mqtt != nullptr)
|
||||
{
|
||||
// Serial.println(Dallas(DALLAS_PIN,0));
|
||||
//Gets prefered temperature scale based on selection in definitions section
|
||||
//Gets preferred temperature scale based on selection in definitions section
|
||||
#ifdef Celsius
|
||||
int16_t board_temperature = Dallas(DALLAS_PIN,0);
|
||||
#else
|
||||
@ -173,11 +173,11 @@ void userLoop() {
|
||||
// First row with Wifi name
|
||||
u8x8.setCursor(1, 0);
|
||||
u8x8.print(knownSsid.substring(0, u8x8.getCols() > 1 ? u8x8.getCols() - 2 : 0));
|
||||
// Print `~` char to indicate that SSID is longer, than owr dicplay
|
||||
// Print `~` char to indicate that SSID is longer than our display
|
||||
if (knownSsid.length() > u8x8.getCols())
|
||||
u8x8.print("~");
|
||||
|
||||
// Second row with IP or Psssword
|
||||
// Second row with IP or Password
|
||||
u8x8.setCursor(1, 1);
|
||||
// Print password in AP mode and if led is OFF.
|
||||
if (apActive && bri == 0)
|
||||
|
@ -6,7 +6,7 @@
|
||||
|
||||
void UpdateBME280Data();
|
||||
|
||||
#define Celsius // Show temperature mesaurement in Celcius otherwise is in Fahrenheit
|
||||
#define Celsius // Show temperature measurement in Celsius otherwise is in Fahrenheit
|
||||
BME280I2C bme; // Default : forced mode, standby time = 1000 ms
|
||||
// Oversampling = pressure ×1, temperature ×1, humidity ×1, filter off,
|
||||
|
||||
@ -16,25 +16,25 @@ uint8_t SDA_PIN = 21;
|
||||
#else //ESP8266 boards
|
||||
uint8_t SCL_PIN = 5;
|
||||
uint8_t SDA_PIN = 4;
|
||||
// uint8_t RST_PIN = 16; // Uncoment for Heltec WiFi-Kit-8
|
||||
// uint8_t RST_PIN = 16; // Un-comment for Heltec WiFi-Kit-8
|
||||
#endif
|
||||
|
||||
//The SCL and SDA pins are defined here.
|
||||
//ESP8266 Wemos D1 mini board use SCL=5 SDA=4 while ESP32 Wemos32 mini board use SCL=22 SDA=21
|
||||
#define U8X8_PIN_SCL SCL_PIN
|
||||
#define U8X8_PIN_SDA SDA_PIN
|
||||
//#define U8X8_PIN_RESET RST_PIN // Uncoment for Heltec WiFi-Kit-8
|
||||
//#define U8X8_PIN_RESET RST_PIN // Un-comment for Heltec WiFi-Kit-8
|
||||
|
||||
// If display does not work or looks corrupted check the
|
||||
// constructor reference:
|
||||
// https://github.com/olikraus/u8g2/wiki/u8x8setupcpp
|
||||
// or check the gallery:
|
||||
// https://github.com/olikraus/u8g2/wiki/gallery
|
||||
// --> First choise of cheap I2C OLED 128X32 0.91"
|
||||
// --> First choice of cheap I2C OLED 128X32 0.91"
|
||||
U8X8_SSD1306_128X32_UNIVISION_HW_I2C u8x8(U8X8_PIN_NONE, U8X8_PIN_SCL, U8X8_PIN_SDA); // Pins are Reset, SCL, SDA
|
||||
// --> Second choise of cheap I2C OLED 128X64 0.96" or 1.3"
|
||||
// --> Second choice of cheap I2C OLED 128X64 0.96" or 1.3"
|
||||
//U8X8_SSD1306_128X64_NONAME_HW_I2C u8x8(U8X8_PIN_NONE, U8X8_PIN_SCL, U8X8_PIN_SDA); // Pins are Reset, SCL, SDA
|
||||
// --> Third choise of Heltec WiFi-Kit-8 OLED 128X32 0.91"
|
||||
// --> Third choice of Heltec WiFi-Kit-8 OLED 128X32 0.91"
|
||||
//U8X8_SSD1306_128X32_UNIVISION_HW_I2C u8x8(U8X8_PIN_RESET, U8X8_PIN_SCL, U8X8_PIN_SDA); // Constructor for Heltec WiFi-Kit-8
|
||||
// gets called once at boot. Do all initialization that doesn't depend on network here
|
||||
|
||||
@ -179,11 +179,11 @@ void userLoop() {
|
||||
// First row with Wifi name
|
||||
u8x8.setCursor(1, 0);
|
||||
u8x8.print(knownSsid.substring(0, u8x8.getCols() > 1 ? u8x8.getCols() - 2 : 0));
|
||||
// Print `~` char to indicate that SSID is longer, than owr dicplay
|
||||
// Print `~` char to indicate that SSID is longer, than our display
|
||||
if (knownSsid.length() > u8x8.getCols())
|
||||
u8x8.print("~");
|
||||
|
||||
// Second row with IP or Psssword
|
||||
// Second row with IP or Password
|
||||
u8x8.setCursor(1, 1);
|
||||
// Print password in AP mode and if led is OFF.
|
||||
if (apActive && bri == 0)
|
||||
|
@ -83,7 +83,7 @@ static bool limiterOn = true;
|
||||
static uint16_t attackTime = 80; // int: attack time in milliseconds. Default 0.08sec
|
||||
static uint16_t decayTime = 1400; // int: decay time in milliseconds. Default 1.40sec
|
||||
// user settable options for FFTResult scaling
|
||||
static uint8_t FFTScalingMode = 3; // 0 none; 1 optimized logarithmic; 2 optimized linear; 3 optimized sqare root
|
||||
static uint8_t FFTScalingMode = 3; // 0 none; 1 optimized logarithmic; 2 optimized linear; 3 optimized square root
|
||||
|
||||
//
|
||||
// AGC presets
|
||||
@ -118,9 +118,9 @@ static float sampleAgc = 0.0f; // Smoothed AGC sample
|
||||
static bool samplePeak = false; // Boolean flag for peak - used in effects. Responding routine may reset this flag. Auto-reset after strip.getMinShowDelay()
|
||||
static uint8_t maxVol = 31; // Reasonable value for constant volume for 'peak detector', as it won't always trigger (deprecated)
|
||||
static uint8_t binNum = 8; // Used to select the bin for FFT based beat detection (deprecated)
|
||||
static bool udpSamplePeak = false; // Boolean flag for peak. Set at the same tiem as samplePeak, but reset by transmitAudioData
|
||||
static bool udpSamplePeak = false; // Boolean flag for peak. Set at the same time as samplePeak, but reset by transmitAudioData
|
||||
static unsigned long timeOfPeak = 0; // time of last sample peak detection.
|
||||
static void detectSamplePeak(void); // peak detection function (needs scaled FFT reasults in vReal[])
|
||||
static void detectSamplePeak(void); // peak detection function (needs scaled FFT results in vReal[])
|
||||
static void autoResetPeak(void); // peak auto-reset function
|
||||
|
||||
|
||||
@ -212,7 +212,7 @@ static float mapf(float x, float in_min, float in_max, float out_min, float out_
|
||||
return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
|
||||
}
|
||||
|
||||
// compute average of several FFT resut bins
|
||||
// compute average of several FFT result bins
|
||||
static float fftAddAvg(int from, int to) {
|
||||
float result = 0.0f;
|
||||
for (int i = from; i <= to; i++) {
|
||||
@ -330,7 +330,7 @@ void FFTcode(void * parameter)
|
||||
*
|
||||
* Andrew's updated mapping of 256 bins down to the 16 result bins with Sample Freq = 10240, samplesFFT = 512 and some overlap.
|
||||
* Based on testing, the lowest/Start frequency is 60 Hz (with bin 3) and a highest/End frequency of 5120 Hz in bin 255.
|
||||
* Now, Take the 60Hz and multiply by 1.320367784 to get the next frequency and so on until the end. Then detetermine the bins.
|
||||
* Now, Take the 60Hz and multiply by 1.320367784 to get the next frequency and so on until the end. Then determine the bins.
|
||||
* End frequency = Start frequency * multiplier ^ 16
|
||||
* Multiplier = (End frequency/ Start frequency) ^ 1/16
|
||||
* Multiplier = 1.320367784
|
||||
@ -389,7 +389,7 @@ void FFTcode(void * parameter)
|
||||
}
|
||||
}
|
||||
|
||||
// post-processing of frequency channels (pink noise adjustment, AGC, smooting, scaling)
|
||||
// post-processing of frequency channels (pink noise adjustment, AGC, smoothing, scaling)
|
||||
postProcessFFTResults((fabsf(sampleAvg) > 0.25f)? true : false , NUM_GEQ_CHANNELS);
|
||||
|
||||
#if defined(WLED_DEBUG) || defined(SR_DEBUG)
|
||||
@ -436,7 +436,7 @@ static void runMicFilter(uint16_t numSamples, float *sampleBuffer) // p
|
||||
// FIR lowpass, to remove high frequency noise
|
||||
float highFilteredSample;
|
||||
if (i < (numSamples-1)) highFilteredSample = beta1*sampleBuffer[i] + beta2*last_vals[0] + beta2*sampleBuffer[i+1]; // smooth out spikes
|
||||
else highFilteredSample = beta1*sampleBuffer[i] + beta2*last_vals[0] + beta2*last_vals[1]; // spcial handling for last sample in array
|
||||
else highFilteredSample = beta1*sampleBuffer[i] + beta2*last_vals[0] + beta2*last_vals[1]; // special handling for last sample in array
|
||||
last_vals[1] = last_vals[0];
|
||||
last_vals[0] = sampleBuffer[i];
|
||||
sampleBuffer[i] = highFilteredSample;
|
||||
@ -640,7 +640,7 @@ class AudioReactive : public Usermod {
|
||||
|
||||
// variables used by getSample() and agcAvg()
|
||||
int16_t micIn = 0; // Current sample starts with negative values and large values, which is why it's 16 bit signed
|
||||
double sampleMax = 0.0; // Max sample over a few seconds. Needed for AGC controler.
|
||||
double sampleMax = 0.0; // Max sample over a few seconds. Needed for AGC controller.
|
||||
double micLev = 0.0; // Used to convert returned value to have '0' as minimum. A leveller
|
||||
float expAdjF = 0.0f; // Used for exponential filter.
|
||||
float sampleReal = 0.0f; // "sampleRaw" as float, to provide bits that are lost otherwise (before amplification by sampleGain or inputLevel). Needed for AGC.
|
||||
@ -763,13 +763,13 @@ class AudioReactive : public Usermod {
|
||||
* 2. we use two setpoints, one at ~60%, and one at ~80% of the maximum signal
|
||||
* 3. the amplification depends on signal level:
|
||||
* a) normal zone - very slow adjustment
|
||||
* b) emergency zome (<10% or >90%) - very fast adjustment
|
||||
* b) emergency zone (<10% or >90%) - very fast adjustment
|
||||
*/
|
||||
void agcAvg(unsigned long the_time)
|
||||
{
|
||||
const int AGC_preset = (soundAgc > 0)? (soundAgc-1): 0; // make sure the _compiler_ knows this value will not change while we are inside the function
|
||||
|
||||
float lastMultAgc = multAgc; // last muliplier used
|
||||
float lastMultAgc = multAgc; // last multiplier used
|
||||
float multAgcTemp = multAgc; // new multiplier
|
||||
float tmpAgc = sampleReal * multAgc; // what-if amplified signal
|
||||
|
||||
@ -809,13 +809,13 @@ class AudioReactive : public Usermod {
|
||||
|
||||
if (((multAgcTemp > 0.085f) && (multAgcTemp < 6.5f)) //integrator anti-windup by clamping
|
||||
&& (multAgc*sampleMax < agcZoneStop[AGC_preset])) //integrator ceiling (>140% of max)
|
||||
control_integrated += control_error * 0.002 * 0.25; // 2ms = intgration time; 0.25 for damping
|
||||
control_integrated += control_error * 0.002 * 0.25; // 2ms = integration time; 0.25 for damping
|
||||
else
|
||||
control_integrated *= 0.9; // spin down that beasty integrator
|
||||
|
||||
// apply PI Control
|
||||
tmpAgc = sampleReal * lastMultAgc; // check "zone" of the signal using previous gain
|
||||
if ((tmpAgc > agcZoneHigh[AGC_preset]) || (tmpAgc < soundSquelch + agcZoneLow[AGC_preset])) { // upper/lower emergy zone
|
||||
if ((tmpAgc > agcZoneHigh[AGC_preset]) || (tmpAgc < soundSquelch + agcZoneLow[AGC_preset])) { // upper/lower energy zone
|
||||
multAgcTemp = lastMultAgc + agcFollowFast[AGC_preset] * agcControlKp[AGC_preset] * control_error;
|
||||
multAgcTemp += agcFollowFast[AGC_preset] * agcControlKi[AGC_preset] * control_integrated;
|
||||
} else { // "normal zone"
|
||||
@ -823,7 +823,7 @@ class AudioReactive : public Usermod {
|
||||
multAgcTemp += agcFollowSlow[AGC_preset] * agcControlKi[AGC_preset] * control_integrated;
|
||||
}
|
||||
|
||||
// limit amplification again - PI controler sometimes "overshoots"
|
||||
// limit amplification again - PI controller sometimes "overshoots"
|
||||
//multAgcTemp = constrain(multAgcTemp, 0.015625f, 32.0f); // 1/64 < multAgcTemp < 32
|
||||
if (multAgcTemp > 32.0f) multAgcTemp = 32.0f;
|
||||
if (multAgcTemp < 1.0f/64.0f) multAgcTemp = 1.0f/64.0f;
|
||||
@ -853,7 +853,7 @@ class AudioReactive : public Usermod {
|
||||
void getSample()
|
||||
{
|
||||
float sampleAdj; // Gain adjusted sample value
|
||||
float tmpSample; // An interim sample variable used for calculatioins.
|
||||
float tmpSample; // An interim sample variable used for calculations.
|
||||
const float weighting = 0.2f; // Exponential filter weighting. Will be adjustable in a future release.
|
||||
const int AGC_preset = (soundAgc > 0)? (soundAgc-1): 0; // make sure the _compiler_ knows this value will not change while we are inside the function
|
||||
|
||||
@ -1308,7 +1308,7 @@ class AudioReactive : public Usermod {
|
||||
// complain when audio userloop has been delayed for long time. Currently we need userloop running between 500 and 1500 times per second.
|
||||
// softhack007 disabled temporarily - avoid serial console spam with MANY leds and low FPS
|
||||
//if ((userloopDelay > 65) && !disableSoundProcessing && (audioSyncEnabled == 0)) {
|
||||
//DEBUG_PRINTF("[AR userLoop] hickup detected -> was inactive for last %d millis!\n", userloopDelay);
|
||||
//DEBUG_PRINTF("[AR userLoop] hiccup detected -> was inactive for last %d millis!\n", userloopDelay);
|
||||
//}
|
||||
#endif
|
||||
|
||||
@ -1525,7 +1525,7 @@ class AudioReactive : public Usermod {
|
||||
} else {
|
||||
// Analog or I2S digital input
|
||||
if (audioSource && (audioSource->isInitialized())) {
|
||||
// audio source sucessfully configured
|
||||
// audio source successfully configured
|
||||
if (audioSource->getType() == AudioSource::Type_I2SAdc) {
|
||||
infoArr.add(F("ADC analog"));
|
||||
} else {
|
||||
|
@ -44,7 +44,7 @@
|
||||
// benefit: analog mic inputs will be sampled contiously -> better response times and less "glitches"
|
||||
// WARNING: this option WILL lock-up your device in case that any other analogRead() operation is performed;
|
||||
// for example if you want to read "analog buttons"
|
||||
//#define I2S_GRAB_ADC1_COMPLETELY // (experimental) continously sample analog ADC microphone. WARNING will cause analogRead() lock-up
|
||||
//#define I2S_GRAB_ADC1_COMPLETELY // (experimental) continuously sample analog ADC microphone. WARNING will cause analogRead() lock-up
|
||||
|
||||
// data type requested from the I2S driver - currently we always use 32bit
|
||||
//#define I2S_USE_16BIT_SAMPLES // (experimental) define this to request 16bit - more efficient but possibly less compatible
|
||||
@ -378,7 +378,7 @@ class I2SSource : public AudioSource {
|
||||
};
|
||||
|
||||
/* ES7243 Microphone
|
||||
This is an I2S microphone that requires ininitialization over
|
||||
This is an I2S microphone that requires initialization over
|
||||
I2C before I2S data can be received
|
||||
*/
|
||||
class ES7243 : public I2SSource {
|
||||
@ -429,8 +429,8 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
/* ES8388 Sound Modude
|
||||
This is an I2S sound processing unit that requires ininitialization over
|
||||
/* ES8388 Sound Module
|
||||
This is an I2S sound processing unit that requires initialization over
|
||||
I2C before I2S data can be received.
|
||||
*/
|
||||
class ES8388Source : public I2SSource {
|
||||
@ -475,7 +475,7 @@ class ES8388Source : public I2SSource {
|
||||
// The mics *and* line-in are BOTH connected to LIN2/RIN2 on the AudioKit
|
||||
// so there's no way to completely eliminate the mics. It's also hella noisy.
|
||||
// Line-in works OK on the AudioKit, generally speaking, as the mics really need
|
||||
// amplification to be noticable in a quiet room. If you're in a very loud room,
|
||||
// amplification to be noticeable in a quiet room. If you're in a very loud room,
|
||||
// the mics on the AudioKit WILL pick up sound even in line-in mode.
|
||||
// TL;DR: Don't use the AudioKit for anything, use the LyraT.
|
||||
//
|
||||
|
@ -1,6 +1,6 @@
|
||||
# Audioreactive usermod
|
||||
|
||||
Enabless controlling LEDs via audio input. Audio source can be a microphone or analog-in (AUX) using an appropriate adapter.
|
||||
Enables controlling LEDs via audio input. Audio source can be a microphone or analog-in (AUX) using an appropriate adapter.
|
||||
Supported microphones range from analog (MAX4466, MAX9814, ...) to digital (INMP441, ICS-43434, ...).
|
||||
|
||||
Does audio processing and provides data structure that specially written effects can use.
|
||||
@ -19,7 +19,7 @@ This usermod is an evolution of [SR-WLED](https://github.com/atuline/WLED), and
|
||||
## Supported MCUs
|
||||
This audioreactive usermod works best on "classic ESP32" (dual core), and on ESP32-S3 which also has dual core and hardware floating point support.
|
||||
|
||||
It will compile succesfully for ESP32-S2 and ESP32-C3, however might not work well, as other WLED functions will become slow. Audio processing requires a lot of computing power, which can be problematic on smaller MCUs like -S2 and -C3.
|
||||
It will compile successfully for ESP32-S2 and ESP32-C3, however might not work well, as other WLED functions will become slow. Audio processing requires a lot of computing power, which can be problematic on smaller MCUs like -S2 and -C3.
|
||||
|
||||
Analog audio is only possible on "classic" ESP32, but not on other MCUs like ESP32-S3.
|
||||
|
||||
@ -35,7 +35,7 @@ Customised _arduinoFFT_ library for use with this usermod can be found at https:
|
||||
|
||||
### using latest (develop) _arduinoFFT_ library
|
||||
Alternatively, you can use the latest arduinoFFT development version.
|
||||
ArduinoFFT `develop` library is slightly more accurate, and slighly faster than our customised library, however also needs additional 2kB RAM.
|
||||
ArduinoFFT `develop` library is slightly more accurate, and slightly faster than our customised library, however also needs additional 2kB RAM.
|
||||
|
||||
* `build_flags` = `-D USERMOD_AUDIOREACTIVE` `-D UM_AUDIOREACTIVE_USE_NEW_FFT`
|
||||
* `lib_deps`= `https://github.com/kosme/arduinoFFT#develop @ 1.9.2`
|
||||
@ -68,7 +68,7 @@ You can use the following additional flags in your `build_flags`
|
||||
* `-D SR_GAIN=x` : Default "gain" setting (60)
|
||||
* `-D I2S_USE_RIGHT_CHANNEL`: Use RIGHT instead of LEFT channel (not recommended unless you strictly need this).
|
||||
* `-D I2S_USE_16BIT_SAMPLES`: Use 16bit instead of 32bit for internal sample buffers. Reduces sampling quality, but frees some RAM ressources (not recommended unless you absolutely need this).
|
||||
* `-D I2S_GRAB_ADC1_COMPLETELY`: Experimental: continously sample analog ADC microphone. Only effective on ESP32. WARNING this _will_ cause conflicts(lock-up) with any analogRead() call.
|
||||
* `-D I2S_GRAB_ADC1_COMPLETELY`: Experimental: continuously sample analog ADC microphone. Only effective on ESP32. WARNING this _will_ cause conflicts(lock-up) with any analogRead() call.
|
||||
* `-D MIC_LOGGER` : (debugging) Logs samples from the microphone to serial USB. Use with serial plotter (Arduino IDE)
|
||||
* `-D SR_DEBUG` : (debugging) Additional error diagnostics and debug info on serial USB.
|
||||
|
||||
|
@ -50,5 +50,5 @@ This usermod listens on `[mqttDeviceTopic]/switch/0/set` (where 0 is replaced wi
|
||||
Feedback about the current state is provided at `[mqttDeviceTopic]/switch/0/state`.
|
||||
|
||||
### Home Assistant auto-discovery
|
||||
Auto-discovery information is automatically published and you shoudn't have to do anything to register the switches in Home Assistant.
|
||||
Auto-discovery information is automatically published and you shouldn't have to do anything to register the switches in Home Assistant.
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
This usermod-v2 modification allows the connection of multiple relays, each with individual delay and on/off mode.
|
||||
Usermod supports PCF8574 I2C port expander to reduce GPIO use.
|
||||
PCF8574 supports 8 outputs and each output corresponds to a relay in WLED (relay 0 = port 0, etc). I you are using more than 8 relays with multiple PCF8574 make sure their addresses are set conscutively (e.g. 0x20 and 0x21). You can set address of first expander in settings.
|
||||
PCF8574 supports 8 outputs and each output corresponds to a relay in WLED (relay 0 = port 0, etc). I you are using more than 8 relays with multiple PCF8574 make sure their addresses are set in sequence (e.g. 0x20 and 0x21). You can set address of first expander in settings.
|
||||
(**NOTE:** Will require Wire library and global I2C pins defined.)
|
||||
|
||||
## HTTP API
|
||||
|
@ -220,7 +220,7 @@ class MultiRelay : public Usermod {
|
||||
};
|
||||
|
||||
|
||||
// class implementetion
|
||||
// class implementation
|
||||
|
||||
void MultiRelay::publishMqtt(int relay) {
|
||||
#ifndef WLED_DISABLE_MQTT
|
||||
@ -388,7 +388,7 @@ void MultiRelay::switchRelay(uint8_t relay, bool mode) {
|
||||
if (relay>=MULTI_RELAY_MAX_RELAYS || _relay[relay].pin<0) return;
|
||||
_relay[relay].state = mode;
|
||||
if (usePcf8574 && _relay[relay].pin >= 100) {
|
||||
// we need to send all ouputs at the same time
|
||||
// we need to send all outputs at the same time
|
||||
uint8_t state = 0;
|
||||
for (int i=0; i<MULTI_RELAY_MAX_RELAYS; i++) {
|
||||
if (_relay[i].pin < 100) continue;
|
||||
|
@ -2,7 +2,7 @@
|
||||
The (un)official usermod to get the best out of the QuinLED-An-Penta (https://quinled.info/quinled-an-penta/), e.g. using the OLED and the SHT30 temperature/humidity sensor.
|
||||
|
||||
## Requirements
|
||||
* "u8gs" by olikraus, v2.28 or higher: https://github.com/olikraus/u8g2
|
||||
* "u8g2" by olikraus, v2.28 or higher: https://github.com/olikraus/u8g2
|
||||
* "SHT85" by Rob Tillaart, v0.2 or higher: https://github.com/RobTillaart/SHT85
|
||||
|
||||
## Usermod installation
|
||||
|
@ -17,7 +17,7 @@ The number of individual LEDs per segment. 7 segments per digit.
|
||||
#### perPeriod -- ssLEDPerPeriod
|
||||
The number of individual LEDs per period. A ':' (colon) has two periods.
|
||||
#### startIdx -- ssStartLED
|
||||
Index of the LED the display starts at. Enabless a seven segment display to be in the middle of a string.
|
||||
Index of the LED the display starts at. Enables a seven segment display to be in the middle of a string.
|
||||
#### timeEnable -- ssTimeEnabled
|
||||
When true, when displayMask is configured for a time output and no message is set, the time will be displayed.
|
||||
#### scrollSpd -- ssScrollSpeed
|
||||
|
@ -409,7 +409,7 @@ public:
|
||||
|
||||
if (mqttGroupTopic[0] != 0)
|
||||
{
|
||||
//subcribe for sevenseg messages on the group topic
|
||||
//subscribe for sevenseg messages on the group topic
|
||||
sprintf_P(subBuffer, PSTR("%s/%S/+/set"), mqttGroupTopic, _str_sevenSeg);
|
||||
mqtt->subscribe(subBuffer, 2);
|
||||
}
|
||||
@ -417,7 +417,7 @@ public:
|
||||
|
||||
bool onMqttMessage(char *topic, char *payload)
|
||||
{
|
||||
//If topic beings iwth sevenSeg cut it off, otherwise not our message.
|
||||
//If topic beings with sevenSeg cut it off, otherwise not our message.
|
||||
size_t topicPrefixLen = strlen_P(PSTR("/sevenSeg/"));
|
||||
if (strncmp_P(topic, PSTR("/sevenSeg/"), topicPrefixLen) == 0)
|
||||
topic += topicPrefixLen;
|
||||
|
@ -480,14 +480,14 @@ public:
|
||||
|
||||
if (mqttGroupTopic[0] != 0)
|
||||
{
|
||||
//subcribe for sevenseg messages on the group topic
|
||||
//subscribe for sevenseg messages on the group topic
|
||||
sprintf_P(subBuffer, PSTR("%s/%S/+/set"), mqttGroupTopic, _str_name);
|
||||
mqtt->subscribe(subBuffer, 2);
|
||||
}
|
||||
}
|
||||
|
||||
bool onMqttMessage(char *topic, char *payload) {
|
||||
//If topic beings iwth sevenSeg cut it off, otherwise not our message.
|
||||
//If topic begins with sevenSeg cut it off, otherwise not our message.
|
||||
size_t topicPrefixLen = strlen_P(PSTR("/wledSS/"));
|
||||
if (strncmp_P(topic, PSTR("/wledSS/"), topicPrefixLen) == 0) {
|
||||
topic += topicPrefixLen;
|
||||
|
@ -290,7 +290,7 @@ void ShtUsermod::loop()
|
||||
/**
|
||||
* Whenever MQTT is connected, publish HA autodiscovery topics.
|
||||
*
|
||||
* Is only donce once.
|
||||
* Is only done once.
|
||||
*
|
||||
* @see Usermod::onMqttConnect()
|
||||
* @see UsermodManager::onMqttConnect()
|
||||
|
@ -23,7 +23,7 @@ private:
|
||||
unsigned char Enc_B;
|
||||
unsigned char Enc_A_prev = 0;
|
||||
|
||||
// private class memebers configurable by Usermod Settings (defaults set inside readFromConfig())
|
||||
// private class members configurable by Usermod Settings (defaults set inside readFromConfig())
|
||||
int8_t pins[3]; // pins[0] = DT from encoder, pins[1] = CLK from encoder, pins[2] = CLK from encoder (optional)
|
||||
int fadeAmount; // how many points to fade the Neopixel with each step
|
||||
|
||||
@ -162,7 +162,7 @@ public:
|
||||
* - configComplete is used to return false if any value is missing, not just if the main object is missing
|
||||
* - The defaults are loaded every time readFromConfig() is run, not just once after boot
|
||||
*
|
||||
* This ensures that missing values are added to the config, with their default values, in the rare but plauible cases of:
|
||||
* This ensures that missing values are added to the config, with their default values, in the rare but plausible cases of:
|
||||
* - a single value being missing at boot, e.g. if the Usermod was upgraded and a new setting was added
|
||||
* - a single value being missing after boot (e.g. if the cfg.json was manually edited and a value was removed)
|
||||
*
|
||||
|
@ -101,7 +101,7 @@ class AutoSaveUsermod : public Usermod {
|
||||
// network here
|
||||
void setup() {
|
||||
#ifdef USERMOD_FOUR_LINE_DISPLAY
|
||||
// This Usermod has enhanced funcionality if
|
||||
// This Usermod has enhanced functionality if
|
||||
// FourLineDisplayUsermod is available.
|
||||
display = (FourLineDisplayUsermod*) usermods.lookup(USERMOD_ID_FOUR_LINE_DISP);
|
||||
#endif
|
||||
@ -148,7 +148,7 @@ class AutoSaveUsermod : public Usermod {
|
||||
|
||||
if (autoSaveAfter && now > autoSaveAfter) {
|
||||
autoSaveAfter = 0;
|
||||
// Time to auto save. You may have some flickry?
|
||||
// Time to auto save. You may have some flickery?
|
||||
saveSettings();
|
||||
displayOverlay();
|
||||
}
|
||||
|
@ -6,7 +6,7 @@
|
||||
#include "4LD_wled_fonts.c"
|
||||
|
||||
#ifndef FLD_ESP32_NO_THREADS
|
||||
#define FLD_ESP32_USE_THREADS // comment out to use 0.13.x behviour without parallel update task - slower, but more robust. May delay other tasks like LEDs or audioreactive!!
|
||||
#define FLD_ESP32_USE_THREADS // comment out to use 0.13.x behaviour without parallel update task - slower, but more robust. May delay other tasks like LEDs or audioreactive!!
|
||||
#endif
|
||||
|
||||
//
|
||||
@ -243,7 +243,7 @@ class FourLineDisplayUsermod : public Usermod {
|
||||
*/
|
||||
void setMarkLine(byte newMarkLineNum, byte newMarkColNum);
|
||||
|
||||
//Draw the arrow for the current setting beiong changed
|
||||
//Draw the arrow for the current setting being changed
|
||||
void drawArrow();
|
||||
|
||||
//Display the current effect or palette (desiredEntry)
|
||||
@ -793,7 +793,7 @@ void FourLineDisplayUsermod::setMarkLine(byte newMarkLineNum, byte newMarkColNum
|
||||
markColNum = newMarkColNum;
|
||||
}
|
||||
|
||||
//Draw the arrow for the current setting beiong changed
|
||||
//Draw the arrow for the current setting being changed
|
||||
void FourLineDisplayUsermod::drawArrow() {
|
||||
#if defined(ARDUINO_ARCH_ESP32) && defined(FLD_ESP32_USE_THREADS)
|
||||
unsigned long now = millis();
|
||||
@ -1066,7 +1066,7 @@ void FourLineDisplayUsermod::networkOverlay(const char* line1, long showHowLong)
|
||||
bool FourLineDisplayUsermod::handleButton(uint8_t b) {
|
||||
yield();
|
||||
if (!enabled
|
||||
|| b // butto 0 only
|
||||
|| b // button 0 only
|
||||
|| buttonType[b] == BTN_TYPE_SWITCH
|
||||
|| buttonType[b] == BTN_TYPE_NONE
|
||||
|| buttonType[b] == BTN_TYPE_RESERVED
|
||||
|
@ -10,7 +10,7 @@ curl --location --request GET 'http://[]/printer/objects/query?virtual_sdcard=pr
|
||||
## Usage
|
||||
Compile the source with the buildflag `-D USERMOD_KLIPPER_PERCENTAGE` added.
|
||||
|
||||
You can also use the WLBD bot in the Discord by simply extending an exsisting build enviroment:
|
||||
You can also use the WLBD bot in the Discord by simply extending an existing build environment:
|
||||
```
|
||||
[env:esp32klipper]
|
||||
extends = env:esp32dev
|
||||
@ -23,7 +23,7 @@ build_flags = ${common.build_flags_esp32} -D USERMOD_KLIPPER_PERCENTAGE
|
||||
Checkbox to enable or disable the overlay
|
||||
|
||||
### Klipper IP:
|
||||
IP adress of your Klipper instance you want to poll. ESP has to be restarted after change
|
||||
IP address of your Klipper instance you want to poll. ESP has to be restarted after change
|
||||
|
||||
### Direction :
|
||||
0 = normal
|
||||
|
@ -79,7 +79,7 @@ public:
|
||||
httpGet(wifiClient, errorMessage);
|
||||
if (strcmp(errorMessage, "") == 0)
|
||||
{
|
||||
PSRAMDynamicJsonDocument klipperDoc(4096); // in practive about 2673
|
||||
PSRAMDynamicJsonDocument klipperDoc(4096); // in practice about 2673
|
||||
DeserializationError error = deserializeJson(klipperDoc, wifiClient);
|
||||
if (error)
|
||||
{
|
||||
|
@ -7,4 +7,4 @@ Contains a modification to use WLED in combination with the Ping Pong Ball LED C
|
||||
To install this Usermod, you instruct PlatformIO to compile the Project with the USERMOD_PING_PONG_CLOCK flag.
|
||||
WLED then automatically provides you with various settings on the Usermod Page.
|
||||
|
||||
Note: Depending on the size of your clock, you may have to update the led indices for the indivdual numbers and the base indices.
|
||||
Note: Depending on the size of your clock, you may have to update the led indices for the individual numbers and the base indices.
|
||||
|
@ -18,15 +18,15 @@ private:
|
||||
|
||||
// ---- Variables for correct LED numbering below, edit only if your clock is built different ----
|
||||
|
||||
int baseH = 43; // Adress for the one place of the hours
|
||||
int baseHH = 7; // Adress for the tens place of the hours
|
||||
int baseM = 133; // Adress for the one place of the minutes
|
||||
int baseMM = 97; // Adress for the tens place of the minutes
|
||||
int colon1 = 79; // Adress for the first colon led
|
||||
int colon2 = 80; // Adress for the second colon led
|
||||
int baseH = 43; // Address for the one place of the hours
|
||||
int baseHH = 7; // Address for the tens place of the hours
|
||||
int baseM = 133; // Address for the one place of the minutes
|
||||
int baseMM = 97; // Address for the tens place of the minutes
|
||||
int colon1 = 79; // Address for the first colon led
|
||||
int colon2 = 80; // Address for the second colon led
|
||||
|
||||
// Matrix for the illumination of the numbers
|
||||
// Note: These only define the increments of the base adress. e.g. to define the second Minute you have to add the baseMM to every led position
|
||||
// Note: These only define the increments of the base address. e.g. to define the second Minute you have to add the baseMM to every led position
|
||||
const int numbers[10][10] =
|
||||
{
|
||||
{ 0, 1, 4, 6, 13, 15, 18, 19, -1, -1 }, // 0: null
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
//
|
||||
// Inspired by the original v2 usermods
|
||||
// * usermod_v2_rotaty_encoder_ui
|
||||
// * usermod_v2_rotary_encoder_ui
|
||||
//
|
||||
// v2 usermod that provides a rotary encoder-based UI.
|
||||
//
|
||||
@ -99,7 +99,7 @@ static int re_qstringCmp(const void *ap, const void *bp) {
|
||||
// Lowercase
|
||||
bVal -= 32;
|
||||
}
|
||||
// Relly we shouldn't ever get to '\0'
|
||||
// Really we shouldn't ever get to '\0'
|
||||
if (aVal == '"' || bVal == '"' || aVal == '\0' || bVal == '\0') {
|
||||
// We're done. one is a substring of the other
|
||||
// or something happenend and the quote didn't stop us.
|
||||
@ -596,7 +596,7 @@ void RotaryEncoderUIUsermod::loop()
|
||||
bool changedState = false;
|
||||
char lineBuffer[64];
|
||||
do {
|
||||
// finde new state
|
||||
// find new state
|
||||
switch (newState) {
|
||||
case 0: strcpy_P(lineBuffer, PSTR("Brightness")); changedState = true; break;
|
||||
case 1: if (!extractModeSlider(effectCurrent, 0, lineBuffer, 63)) newState++; else changedState = true; break; // speed
|
||||
|
@ -8,7 +8,7 @@ active: enable/disable usermod
|
||||
diplayItIs: enable/disable display of "Es ist" on the clock
|
||||
ledOffset: number of LEDs before the wordclock LEDs
|
||||
|
||||
### Update for alternatative wiring pattern
|
||||
### Update for alternative wiring pattern
|
||||
Based on this fantastic work I added an alternative wiring pattern.
|
||||
The original used a long wire to connect DO to DI, from one line to the next line.
|
||||
|
||||
|
@ -7,8 +7,8 @@
|
||||
* See: https://github.com/Aircoookie/WLED/wiki/Add-own-functionality
|
||||
*
|
||||
* This usermod can be used to drive a wordclock with a 11x10 pixel matrix with WLED. There are also 4 additional dots for the minutes.
|
||||
* The visualisation is desribed in 4 mask with LED numbers (single dots for minutes, minutes, hours and "clock/Uhr").
|
||||
* There are 2 parameters to chnage the behaviour:
|
||||
* The visualisation is described in 4 mask with LED numbers (single dots for minutes, minutes, hours and "clock/Uhr").
|
||||
* There are 2 parameters to change the behaviour:
|
||||
*
|
||||
* active: enable/disable usermod
|
||||
* diplayItIs: enable/disable display of "Es ist" on the clock.
|
||||
|
@ -1,6 +1,6 @@
|
||||
# Controlling Wiz lights
|
||||
|
||||
Enabless controlling [WiZ](https://www.wizconnected.com/en/consumer/) lights that are part of the same network as the WLED controller.
|
||||
Enables controlling [WiZ](https://www.wizconnected.com/en/consumer/) lights that are part of the same network as the WLED controller.
|
||||
|
||||
The mod takes the colors from the first few pixels and sends them to the lights.
|
||||
|
||||
@ -8,7 +8,7 @@ The mod takes the colors from the first few pixels and sends them to the lights.
|
||||
|
||||
- Interval (ms)
|
||||
- How frequently to update the WiZ lights, in milliseconds.
|
||||
- Setting it too low may causse the ESP to become unresponsive.
|
||||
- Setting it too low may cause the ESP to become unresponsive.
|
||||
- Send Delay (ms)
|
||||
- An optional millisecond delay after updating each WiZ light.
|
||||
- Can help smooth out effects when using a large number of WiZ lights
|
||||
|
@ -51,7 +51,7 @@ uint16_t triwave16(uint16_t in) {
|
||||
* Generates a tristate square wave w/ attac & decay
|
||||
* @param x input value 0-255
|
||||
* @param pulsewidth 0-127
|
||||
* @param attdec attac & decay, max. pulsewidth / 2
|
||||
* @param attdec attack & decay, max. pulsewidth / 2
|
||||
* @returns signed waveform value
|
||||
*/
|
||||
int8_t tristate_square8(uint8_t x, uint8_t pulsewidth, uint8_t attdec) {
|
||||
@ -1239,7 +1239,7 @@ uint16_t mode_fireworks() {
|
||||
if (SEGMENT.is2D()) SEGMENT.setPixelColorXY(x, y, col);
|
||||
else SEGMENT.setPixelColor(index, col);
|
||||
SEGENV.aux1 = SEGENV.aux0; // old spark
|
||||
SEGENV.aux0 = index; // remember where spark occured
|
||||
SEGENV.aux0 = index; // remember where spark occurred
|
||||
}
|
||||
}
|
||||
return FRAMETIME;
|
||||
@ -1272,8 +1272,8 @@ uint16_t mode_rain() {
|
||||
SEGENV.aux0++; // increase spark index
|
||||
SEGENV.aux1++;
|
||||
}
|
||||
if (SEGENV.aux0 == 0) SEGENV.aux0 = UINT16_MAX; // reset previous spark positiom
|
||||
if (SEGENV.aux1 == 0) SEGENV.aux0 = UINT16_MAX; // reset previous spark positiom
|
||||
if (SEGENV.aux0 == 0) SEGENV.aux0 = UINT16_MAX; // reset previous spark position
|
||||
if (SEGENV.aux1 == 0) SEGENV.aux0 = UINT16_MAX; // reset previous spark position
|
||||
if (SEGENV.aux0 >= width*height) SEGENV.aux0 = 0; // ignore
|
||||
if (SEGENV.aux1 >= width*height) SEGENV.aux1 = 0;
|
||||
}
|
||||
@ -3777,7 +3777,7 @@ uint16_t mode_tetrix(void) {
|
||||
}
|
||||
|
||||
if (drop->step == 0) { // init brick
|
||||
// speed calcualtion: a single brick should reach bottom of strip in X seconds
|
||||
// speed calculation: a single brick should reach bottom of strip in X seconds
|
||||
// if the speed is set to 1 this should take 5s and at 255 it should take 0.25s
|
||||
// as this is dependant on SEGLEN it should be taken into account and the fact that effect runs every FRAMETIME s
|
||||
int speed = SEGMENT.speed ? SEGMENT.speed : random8(1,255);
|
||||
@ -3860,7 +3860,7 @@ static const char _data_FX_MODE_PLASMA[] PROGMEM = "Plasma@Phase,!;!;!";
|
||||
|
||||
/*
|
||||
* Percentage display
|
||||
* Intesity values from 0-100 turn on the leds.
|
||||
* Intensity values from 0-100 turn on the leds.
|
||||
*/
|
||||
uint16_t mode_percent(void) {
|
||||
|
||||
@ -3913,7 +3913,7 @@ static const char _data_FX_MODE_PERCENT[] PROGMEM = "Percent@,% of fill,,,,One c
|
||||
|
||||
/*
|
||||
* Modulates the brightness similar to a heartbeat
|
||||
* (unimplemented?) tries to draw an ECG aproximation on a 2D matrix
|
||||
* (unimplemented?) tries to draw an ECG approximation on a 2D matrix
|
||||
*/
|
||||
uint16_t mode_heartbeat(void) {
|
||||
uint8_t bpm = 40 + (SEGMENT.speed >> 3);
|
||||
@ -4593,7 +4593,7 @@ uint16_t mode_tv_simulator(void) {
|
||||
// how much time is elapsed ?
|
||||
tvSimulator->elapsed = strip.now - tvSimulator->startTime;
|
||||
|
||||
// fade from prev volor to next color
|
||||
// fade from prev color to next color
|
||||
if (tvSimulator->elapsed < tvSimulator->fadeTime) {
|
||||
r = map(tvSimulator->elapsed, 0, tvSimulator->fadeTime, tvSimulator->pr, nr);
|
||||
g = map(tvSimulator->elapsed, 0, tvSimulator->fadeTime, tvSimulator->pg, ng);
|
||||
@ -6498,7 +6498,7 @@ uint16_t mode_gravcenter(void) { // Gravcenter. By Andrew Tuline.
|
||||
SEGMENT.fade_out(251); // 30%
|
||||
|
||||
float segmentSampleAvg = volumeSmth * (float)SEGMENT.intensity / 255.0f;
|
||||
segmentSampleAvg *= 0.125; // divide by 8, to compensate for later "sensitivty" upscaling
|
||||
segmentSampleAvg *= 0.125; // divide by 8, to compensate for later "sensitivity" upscaling
|
||||
|
||||
float mySampleAvg = mapf(segmentSampleAvg*2.0, 0, 32, 0, (float)SEGLEN/2.0f); // map to pixels available in current segment
|
||||
uint16_t tempsamp = constrain(mySampleAvg, 0, SEGLEN/2); // Keep the sample from overflowing.
|
||||
@ -6550,7 +6550,7 @@ uint16_t mode_gravcentric(void) { // Gravcentric. By Andrew
|
||||
SEGMENT.fade_out(253); // 50%
|
||||
|
||||
float segmentSampleAvg = volumeSmth * (float)SEGMENT.intensity / 255.0f;
|
||||
segmentSampleAvg *= 0.125f; // divide by 8, to compensate for later "sensitivty" upscaling
|
||||
segmentSampleAvg *= 0.125f; // divide by 8, to compensate for later "sensitivity" upscaling
|
||||
|
||||
float mySampleAvg = mapf(segmentSampleAvg*2.0, 0.0f, 32.0f, 0.0f, (float)SEGLEN/2.0f); // map to pixels availeable in current segment
|
||||
int tempsamp = constrain(mySampleAvg, 0, SEGLEN/2); // Keep the sample from overflowing.
|
||||
@ -6599,7 +6599,7 @@ uint16_t mode_gravimeter(void) { // Gravmeter. By Andrew Tuline.
|
||||
SEGMENT.fade_out(249); // 25%
|
||||
|
||||
float segmentSampleAvg = volumeSmth * (float)SEGMENT.intensity / 255.0;
|
||||
segmentSampleAvg *= 0.25; // divide by 4, to compensate for later "sensitivty" upscaling
|
||||
segmentSampleAvg *= 0.25; // divide by 4, to compensate for later "sensitivity" upscaling
|
||||
|
||||
float mySampleAvg = mapf(segmentSampleAvg*2.0, 0, 64, 0, (SEGLEN-1)); // map to pixels availeable in current segment
|
||||
int tempsamp = constrain(mySampleAvg,0,SEGLEN-1); // Keep the sample from overflowing.
|
||||
@ -6699,7 +6699,7 @@ uint16_t mode_midnoise(void) { // Midnoise. By Andrew Tuline.
|
||||
SEGMENT.fade_out(SEGMENT.speed);
|
||||
|
||||
float tmpSound2 = volumeSmth * (float)SEGMENT.intensity / 256.0; // Too sensitive.
|
||||
tmpSound2 *= (float)SEGMENT.intensity / 128.0; // Reduce sensitity/length.
|
||||
tmpSound2 *= (float)SEGMENT.intensity / 128.0; // Reduce sensitivity/length.
|
||||
|
||||
int maxLen = mapf(tmpSound2, 0, 127, 0, SEGLEN/2);
|
||||
if (maxLen >SEGLEN/2) maxLen = SEGLEN/2;
|
||||
@ -7110,7 +7110,7 @@ uint16_t mode_freqmatrix(void) { // Freqmatrix. By Andreas Plesch
|
||||
|
||||
if (FFT_MajorPeak > MAX_FREQUENCY) FFT_MajorPeak = 1;
|
||||
// MajorPeak holds the freq. value which is most abundant in the last sample.
|
||||
// With our sampling rate of 10240Hz we have a usable freq range from roughtly 80Hz to 10240/2 Hz
|
||||
// With our sampling rate of 10240Hz we have a usable freq range from roughly 80Hz to 10240/2 Hz
|
||||
// we will treat everything with less than 65Hz as 0
|
||||
|
||||
if (FFT_MajorPeak < 80) {
|
||||
@ -7131,7 +7131,7 @@ uint16_t mode_freqmatrix(void) { // Freqmatrix. By Andreas Plesch
|
||||
|
||||
return FRAMETIME;
|
||||
} // mode_freqmatrix()
|
||||
static const char _data_FX_MODE_FREQMATRIX[] PROGMEM = "Freqmatrix@Speed,Sound effect,Low bin,High bin,Sensivity;;;1f;m12=3,si=0"; // Corner, Beatsin
|
||||
static const char _data_FX_MODE_FREQMATRIX[] PROGMEM = "Freqmatrix@Speed,Sound effect,Low bin,High bin,Sensitivity;;;1f;m12=3,si=0"; // Corner, Beatsin
|
||||
|
||||
|
||||
//////////////////////
|
||||
@ -7215,7 +7215,7 @@ uint16_t mode_freqwave(void) { // Freqwave. By Andreas Pleschun
|
||||
|
||||
if (FFT_MajorPeak > MAX_FREQUENCY) FFT_MajorPeak = 1.0f;
|
||||
// MajorPeak holds the freq. value which is most abundant in the last sample.
|
||||
// With our sampling rate of 10240Hz we have a usable freq range from roughtly 80Hz to 10240/2 Hz
|
||||
// With our sampling rate of 10240Hz we have a usable freq range from roughly 80Hz to 10240/2 Hz
|
||||
// we will treat everything with less than 65Hz as 0
|
||||
|
||||
if (FFT_MajorPeak < 80) {
|
||||
@ -7262,7 +7262,7 @@ uint16_t mode_gravfreq(void) { // Gravfreq. By Andrew Tuline.
|
||||
SEGMENT.fade_out(250);
|
||||
|
||||
float segmentSampleAvg = volumeSmth * (float)SEGMENT.intensity / 255.0f;
|
||||
segmentSampleAvg *= 0.125f; // divide by 8, to compensate for later "sensitivty" upscaling
|
||||
segmentSampleAvg *= 0.125f; // divide by 8, to compensate for later "sensitivity" upscaling
|
||||
|
||||
float mySampleAvg = mapf(segmentSampleAvg*2.0f, 0,32, 0, (float)SEGLEN/2.0f); // map to pixels availeable in current segment
|
||||
int tempsamp = constrain(mySampleAvg,0,SEGLEN/2); // Keep the sample from overflowing.
|
||||
@ -7290,7 +7290,7 @@ uint16_t mode_gravfreq(void) { // Gravfreq. By Andrew Tuline.
|
||||
|
||||
return FRAMETIME;
|
||||
} // mode_gravfreq()
|
||||
static const char _data_FX_MODE_GRAVFREQ[] PROGMEM = "Gravfreq@Rate of fall,Sensivity;!,!;!;1f;ix=128,m12=0,si=0"; // Pixels, Beatsin
|
||||
static const char _data_FX_MODE_GRAVFREQ[] PROGMEM = "Gravfreq@Rate of fall,Sensitivity;!,!;!;1f;ix=128,m12=0,si=0"; // Pixels, Beatsin
|
||||
|
||||
|
||||
//////////////////////
|
||||
@ -7882,7 +7882,7 @@ static const char _data_FX_MODE_2DWAVINGCELL[] PROGMEM = "Waving Cell@!,,Amplitu
|
||||
static const char _data_RESERVED[] PROGMEM = "RSVD";
|
||||
|
||||
// add (or replace reserved) effect mode and data into vector
|
||||
// use id==255 to find unallocatd gaps (with "Reserved" data string)
|
||||
// use id==255 to find unallocated gaps (with "Reserved" data string)
|
||||
// if vector size() is smaller than id (single) data is appended at the end (regardless of id)
|
||||
void WS2812FX::addEffect(uint8_t id, mode_ptr mode_fn, const char *mode_name) {
|
||||
if (id == 255) { // find empty slot
|
||||
|
@ -437,7 +437,7 @@ typedef struct Segment {
|
||||
uint8_t _briT; // temporary brightness
|
||||
uint8_t _cctT; // temporary CCT
|
||||
CRGBPalette16 _palT; // temporary palette
|
||||
uint8_t _prevPaletteBlends; // number of previous palette blends (there are max 255 belnds possible)
|
||||
uint8_t _prevPaletteBlends; // number of previous palette blends (there are max 255 blends possible)
|
||||
unsigned long _start; // must accommodate millis()
|
||||
uint16_t _dur;
|
||||
Transition(uint16_t dur=750)
|
||||
|
@ -236,7 +236,7 @@ CRGBPalette16 IRAM_ATTR &Segment::loadPalette(CRGBPalette16 &targetPalette, uint
|
||||
CRGB sec = gamma32(colors[1]);
|
||||
CRGB ter = gamma32(colors[2]);
|
||||
targetPalette = CRGBPalette16(ter,sec,prim); break;}
|
||||
case 5: {//primary + secondary (+tert if not off), more distinct
|
||||
case 5: {//primary + secondary (+tertiary if not off), more distinct
|
||||
CRGB prim = gamma32(colors[0]);
|
||||
CRGB sec = gamma32(colors[1]);
|
||||
if (colors[2]) {
|
||||
@ -275,7 +275,7 @@ CRGBPalette16 IRAM_ATTR &Segment::loadPalette(CRGBPalette16 &targetPalette, uint
|
||||
|
||||
void Segment::startTransition(uint16_t dur) {
|
||||
if (dur == 0) {
|
||||
if (isInTransition()) _t->_dur = dur; // this will stop transition in next handleTransisiton()
|
||||
if (isInTransition()) _t->_dur = dur; // this will stop transition in next handleTransition()
|
||||
return;
|
||||
}
|
||||
if (isInTransition()) return; // already in transition no need to store anything
|
||||
@ -1228,7 +1228,7 @@ uint32_t IRAM_ATTR WS2812FX::getPixelColor(uint16_t i) {
|
||||
}
|
||||
|
||||
void WS2812FX::show(void) {
|
||||
// avoid race condition, caputre _callback value
|
||||
// avoid race condition, capture _callback value
|
||||
show_callback callback = _callback;
|
||||
if (callback) callback();
|
||||
|
||||
@ -1255,7 +1255,7 @@ bool WS2812FX::isUpdating() {
|
||||
|
||||
/**
|
||||
* Returns the refresh rate of the LED strip. Useful for finding out whether a given setup is fast enough.
|
||||
* Only updates on show() or is set to 0 fps if last show is more than 2 secs ago, so accurary varies
|
||||
* Only updates on show() or is set to 0 fps if last show is more than 2 secs ago, so accuracy varies
|
||||
*/
|
||||
uint16_t WS2812FX::getFps() {
|
||||
if (millis() - _lastShow > 2000) return 0;
|
||||
|
@ -242,7 +242,7 @@ class BusDigital : public Bus {
|
||||
uint8_t* chan = (uint8_t*) &c;
|
||||
for (uint_fast8_t i=0; i<4; i++) {
|
||||
uint_fast16_t val = chan[i];
|
||||
chan[i] = ((val << 8) + restoreBri) / (restoreBri + 1); //adding _bri slighly improves recovery / stops degradation on re-scale
|
||||
chan[i] = ((val << 8) + restoreBri) / (restoreBri + 1); //adding _bri slightly improves recovery / stops degradation on re-scale
|
||||
}
|
||||
}
|
||||
return c;
|
||||
|
@ -74,17 +74,17 @@
|
||||
#define I_32_RN_NEO_3 21
|
||||
#define I_32_I0_NEO_3 22
|
||||
#define I_32_I1_NEO_3 23
|
||||
#define I_32_BB_NEO_3 24 // bitbangging on ESP32 not recommended
|
||||
#define I_32_BB_NEO_3 24 // bitbanging on ESP32 not recommended
|
||||
//RGBW
|
||||
#define I_32_RN_NEO_4 25
|
||||
#define I_32_I0_NEO_4 26
|
||||
#define I_32_I1_NEO_4 27
|
||||
#define I_32_BB_NEO_4 28 // bitbangging on ESP32 not recommended
|
||||
#define I_32_BB_NEO_4 28 // bitbanging on ESP32 not recommended
|
||||
//400Kbps
|
||||
#define I_32_RN_400_3 29
|
||||
#define I_32_I0_400_3 30
|
||||
#define I_32_I1_400_3 31
|
||||
#define I_32_BB_400_3 32 // bitbangging on ESP32 not recommended
|
||||
#define I_32_BB_400_3 32 // bitbanging on ESP32 not recommended
|
||||
//TM1814 (RGBW)
|
||||
#define I_32_RN_TM1_4 33
|
||||
#define I_32_I0_TM1_4 34
|
||||
|
@ -188,7 +188,6 @@ void handleAnalog(uint8_t b)
|
||||
//while(strip.isUpdating() && (millis() - wait_started < STRIP_WAIT_TIME)) {
|
||||
// delay(1);
|
||||
//}
|
||||
//if (strip.isUpdating()) return; // give up
|
||||
|
||||
oldRead[b] = aRead;
|
||||
|
||||
@ -388,7 +387,7 @@ void handleIO()
|
||||
if (!offMode) {
|
||||
#ifdef ESP8266
|
||||
// turn off built-in LED if strip is turned off
|
||||
// this will break digital bus so will need to be reinitialised on On
|
||||
// this will break digital bus so will need to be re-initialised on On
|
||||
PinOwner ledPinOwner = pinManager.getPinOwner(LED_BUILTIN);
|
||||
if (!strip.isOffRefreshRequired() && (ledPinOwner == PinOwner::None || ledPinOwner == PinOwner::BusDigital)) {
|
||||
pinMode(LED_BUILTIN, OUTPUT);
|
||||
@ -405,4 +404,4 @@ void handleIO()
|
||||
}
|
||||
offMode = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -339,7 +339,7 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
|
||||
PinManagerPinType i2c[2] = { { i2c_sda, true }, { i2c_scl, true } };
|
||||
if (i2c_scl >= 0 && i2c_sda >= 0 && pinManager.allocateMultiplePins(i2c, 2, PinOwner::HW_I2C)) {
|
||||
#ifdef ESP32
|
||||
if (!Wire.setPins(i2c_sda, i2c_scl)) { i2c_scl = i2c_sda = -1; } // this will fail if Wire is initilised (Wire.begin() called prior)
|
||||
if (!Wire.setPins(i2c_sda, i2c_scl)) { i2c_scl = i2c_sda = -1; } // this will fail if Wire is initialised (Wire.begin() called prior)
|
||||
else Wire.begin();
|
||||
#else
|
||||
Wire.begin(i2c_sda, i2c_scl);
|
||||
|
@ -154,6 +154,7 @@
|
||||
#define USERMOD_ID_KLIPPER 40 //Usermod Klipper percentage
|
||||
#define USERMOD_ID_WIREGUARD 41 //Usermod "wireguard.h"
|
||||
#define USERMOD_ID_INTERNAL_TEMPERATURE 42 //Usermod "usermod_internal_temperature.h"
|
||||
#define USERMOD_ID_LDR_DUSK_DAWN 43 //Usermod "usermod_LDR_Dusk_Dawn_v2.h"
|
||||
#define USERMOD_ID_ANIMARTRIX 44 //Usermod "usermod_v2_animartrix.h"
|
||||
|
||||
//Access point behavior
|
||||
@ -215,8 +216,8 @@
|
||||
#define DMX_MODE_MULTIPLE_RGB 4 //every LED is addressed with its own RGB (ledCount * 3 channels)
|
||||
#define DMX_MODE_MULTIPLE_DRGB 5 //every LED is addressed with its own RGB and share a master dimmer (ledCount * 3 + 1 channels)
|
||||
#define DMX_MODE_MULTIPLE_RGBW 6 //every LED is addressed with its own RGBW (ledCount * 4 channels)
|
||||
#define DMX_MODE_EFFECT_SEGMENT 8 //trigger standalone effects of WLED (15 channels per segement)
|
||||
#define DMX_MODE_EFFECT_SEGMENT_W 9 //trigger standalone effects of WLED (18 channels per segement)
|
||||
#define DMX_MODE_EFFECT_SEGMENT 8 //trigger standalone effects of WLED (15 channels per segment)
|
||||
#define DMX_MODE_EFFECT_SEGMENT_W 9 //trigger standalone effects of WLED (18 channels per segment)
|
||||
#define DMX_MODE_PRESET 10 //apply presets (1 channel)
|
||||
|
||||
//Light capability byte (unused) 0bRCCCTTTT
|
||||
@ -341,7 +342,7 @@
|
||||
#define SEG_DIFFERS_OPT 0x02 // all segment options except: selected, reset & transitional
|
||||
#define SEG_DIFFERS_COL 0x04 // colors
|
||||
#define SEG_DIFFERS_FX 0x08 // effect/mode parameters
|
||||
#define SEG_DIFFERS_BOUNDS 0x10 // segment start/stop ounds
|
||||
#define SEG_DIFFERS_BOUNDS 0x10 // segment start/stop bounds
|
||||
#define SEG_DIFFERS_GSO 0x20 // grouping, spacing & offset
|
||||
#define SEG_DIFFERS_SEL 0x80 // selected
|
||||
|
||||
@ -366,7 +367,7 @@
|
||||
#define ERR_FS_PLOAD 12 // It was attempted to load a preset that does not exist
|
||||
#define ERR_FS_IRLOAD 13 // It was attempted to load an IR JSON cmd, but the "ir.json" file does not exist
|
||||
#define ERR_FS_RMLOAD 14 // It was attempted to load an remote JSON cmd, but the "remote.json" file does not exist
|
||||
#define ERR_FS_GENERAL 19 // A general unspecified filesystem error occured
|
||||
#define ERR_FS_GENERAL 19 // A general unspecified filesystem error occurred
|
||||
#define ERR_OVERTEMP 30 // An attached temperature sensor has measured above threshold temperature (not implemented)
|
||||
#define ERR_OVERCURRENT 31 // An attached current sensor has measured a current above the threshold (not implemented)
|
||||
#define ERR_UNDERVOLT 32 // An attached voltmeter has measured a voltage below the threshold (not implemented)
|
||||
@ -395,7 +396,8 @@
|
||||
#define SUBPAGE_JS 254
|
||||
#define SUBPAGE_WELCOME 255
|
||||
|
||||
#define NTP_PACKET_SIZE 48
|
||||
#define NTP_PACKET_SIZE 48 // size of NTP receive buffer
|
||||
#define NTP_MIN_PACKET_SIZE 48 // min expected size - NTP v4 allows for "extended information" appended to the standard fields
|
||||
|
||||
//maximum number of rendered LEDs - this does not have to match max. physical LEDs, e.g. if there are virtual busses
|
||||
#ifndef MAX_LEDS
|
||||
@ -483,8 +485,8 @@
|
||||
|
||||
//this is merely a default now and can be changed at runtime
|
||||
#ifndef LEDPIN
|
||||
#if defined(ESP8266) || (defined(ARDUINO_ARCH_ESP32) && defined(WLED_USE_PSRAM)) || defined(CONFIG_IDF_TARGET_ESP32C3)
|
||||
#define LEDPIN 2 // GPIO2 (D4) on Wemod D1 mini compatible boards
|
||||
#if defined(ESP8266) || (defined(ARDUINO_ARCH_ESP32) && defined(WLED_USE_PSRAM)) || defined(CONFIG_IDF_TARGET_ESP32C3) || defined(ARDUINO_ESP32_PICO)
|
||||
#define LEDPIN 2 // GPIO2 (D4) on Wemos D1 mini compatible boards, and on boards where GPIO16 is not available
|
||||
#else
|
||||
#define LEDPIN 16 // aligns with GPIO2 (D4) on Wemos D1 mini32 compatible boards
|
||||
#endif
|
||||
@ -508,7 +510,7 @@
|
||||
#define PIN_TIMEOUT 900000 // time in ms after which the PIN will be required again, 15 minutes
|
||||
|
||||
// HW_PIN_SCL & HW_PIN_SDA are used for information in usermods settings page and usermods themselves
|
||||
// which GPIO pins are actually used in a hardwarea layout (controller board)
|
||||
// which GPIO pins are actually used in a hardware layout (controller board)
|
||||
#if defined(I2CSCLPIN) && !defined(HW_PIN_SCL)
|
||||
#define HW_PIN_SCL I2CSCLPIN
|
||||
#endif
|
||||
@ -531,7 +533,7 @@
|
||||
#endif
|
||||
|
||||
// HW_PIN_SCLKSPI & HW_PIN_MOSISPI & HW_PIN_MISOSPI are used for information in usermods settings page and usermods themselves
|
||||
// which GPIO pins are actually used in a hardwarea layout (controller board)
|
||||
// which GPIO pins are actually used in a hardware layout (controller board)
|
||||
#if defined(SPISCLKPIN) && !defined(HW_PIN_CLOCKSPI)
|
||||
#define HW_PIN_CLOCKSPI SPISCLKPIN
|
||||
#endif
|
||||
|
@ -506,7 +506,7 @@
|
||||
console.log('Error: ', e); console.log(' Status: ', this.status);
|
||||
//Show some error notification for some time
|
||||
setTimeout(()=>{
|
||||
//Remove it when time has pased
|
||||
//Remove it when time has passed
|
||||
}, 1000);
|
||||
});
|
||||
req.open("POST", "/upload");
|
||||
@ -554,7 +554,7 @@
|
||||
paletteArray.push({"palette":[0,70,70,70,255,70,70,70]});
|
||||
}
|
||||
|
||||
//Get static palettes from localStorage and do some magic to reformat them into the same format as the pallete JSONs
|
||||
//Get static palettes from localStorage and do some magic to reformat them into the same format as the palette JSONs
|
||||
//This code excludes any objects with "non valid integer colors", i.e. r, c1, c2, c3 and such
|
||||
//This code also fixes potentially broken palettes which doesn't end on 255
|
||||
//The code finally also removes any representations of the custom palettes, since we read them from file
|
||||
|
@ -1534,9 +1534,9 @@ function readState(s,command=false)
|
||||
// - For AC effects (id<128) 2 sliders and 3 colors and the palette will be shown
|
||||
// - For SR effects (id>128) 5 sliders and 3 colors and the palette will be shown
|
||||
// If effective (@)
|
||||
// - a ; seperates slider controls (left) from color controls (middle) and palette control (right)
|
||||
// - a ; separates slider controls (left) from color controls (middle) and palette control (right)
|
||||
// - if left, middle or right is empty no controls are shown
|
||||
// - a , seperates slider controls (max 5) or color controls (max 3). Palette has only one value
|
||||
// - a , separates slider controls (max 5) or color controls (max 3). Palette has only one value
|
||||
// - a ! means that the default is used.
|
||||
// - For sliders: Effect speeds, Effect intensity, Custom 1, Custom 2, Custom 3
|
||||
// - For colors: Fx color, Background color, Custom
|
||||
|
@ -54,7 +54,7 @@
|
||||
let mW = leds[2]; // matrix width
|
||||
let mH = leds[3]; // matrix height
|
||||
let pPL = Math.min(c.width / mW, c.height / mH); // pixels per LED (width of circle)
|
||||
let lOf = Math.floor((c.width - pPL*mW)/2); //left offeset (to center matrix)
|
||||
let lOf = Math.floor((c.width - pPL*mW)/2); //left offset (to center matrix)
|
||||
var i = 4;
|
||||
for (y=0.5;y<mH;y++) for (x=0.5; x<mW; x++) {
|
||||
ctx.fillStyle = `rgb(${leds[i]},${leds[i+1]},${leds[i+2]})`;
|
||||
|
@ -69,7 +69,7 @@ function getPixelRGBValues(base64Image) {
|
||||
let sizeY = szY.value;
|
||||
|
||||
if (color != accentColor || sizeX < 1 || sizeY < 1){
|
||||
//image will not be rezised Set desitred size to original size
|
||||
//image will not be resized Set desired size to original size
|
||||
sizeX = image.width;
|
||||
sizeY = image.height;
|
||||
//failsafe for not generating huge images automatically
|
||||
@ -153,7 +153,7 @@ function getPixelRGBValues(base64Image) {
|
||||
let curentColorIndex = 0
|
||||
let commandArray = [];
|
||||
|
||||
//For evry pixel in the LED array
|
||||
//For every pixel in the LED array
|
||||
for (let i = 0; i < maxi; i++) {
|
||||
let pixel = ledRGBValues[i];
|
||||
let r = pixel[0];
|
||||
|
@ -81,7 +81,7 @@
|
||||
<button type=submit id="b" onclick="window.location=getURL('/')">Back</button>
|
||||
<button type="submit" onclick="window.location=getURL('/settings/wifi')">WiFi Setup</button>
|
||||
<button type="submit" onclick="window.location=getURL('/settings/leds')">LED Preferences</button>
|
||||
<button id="2dbtn" style="display:none;" type="submit" onclick="window.location=getURL('/settings/2D')">2D Configuration</button>
|
||||
<button id="2dbtn" type="submit" onclick="window.location=getURL('/settings/2D')">2D Configuration</button>
|
||||
<button type="submit" onclick="window.location=getURL('/settings/ui')">User Interface</button>
|
||||
<button id="dmxbtn" style="display:none;" type="submit" onclick="window.location=getURL('/settings/dmx')">DMX Output</button>
|
||||
<button type="submit" onclick="window.location=getURL('/settings/sync')">Sync Interfaces</button>
|
||||
|
@ -389,7 +389,7 @@
|
||||
${i+1}:
|
||||
<select name="LT${i}" onchange="UI(true)">${i>=maxB ? '' :
|
||||
'<option value="22" selected>WS281x</option>\
|
||||
<option value="30">SK6812 RGBW</option>\
|
||||
<option value="30">SK6812/WS2814 RGBW</option>\
|
||||
<option value="31">TM1814</option>\
|
||||
<option value="24">400kHz</option>\
|
||||
<option value="25">TM1829</option>\
|
||||
|
@ -183,8 +183,8 @@
|
||||
<option value="6">US-MST/MDT</option>
|
||||
<option value="7">US-AZ</option>
|
||||
<option value="8">US-PST/PDT</option>
|
||||
<option value="9">CST(AWST)</option>
|
||||
<option value="10">JST(KST)</option>
|
||||
<option value="9">CST (AWST, PHST)</option>
|
||||
<option value="10">JST (KST)</option>
|
||||
<option value="11">AEST/AEDT</option>
|
||||
<option value="12">NZST/NZDT</option>
|
||||
<option value="13">North Korea</option>
|
||||
|
@ -33,7 +33,7 @@
|
||||
).reduce(
|
||||
// Filter out duplicate SSIDs. Since it is sorted by signal
|
||||
// strength, the strongest signal will be kept in the
|
||||
// order it orginally appeared in the array.
|
||||
// order it as originally appeared in the array.
|
||||
(unique, other) => {
|
||||
if(!unique.some(obj => obj.ssid === other.ssid)) {
|
||||
unique.push(other);
|
||||
|
@ -210,7 +210,7 @@ void sendImprovInfoResponse() {
|
||||
//Use serverDescription if it has been changed from the default "WLED", else mDNS name
|
||||
bool useMdnsName = (strcmp(serverDescription, "WLED") == 0 && strlen(cmDNS) > 0);
|
||||
char vString[20];
|
||||
sprintf_P(vString, PSTR("0.15.0-a0/%i"), VERSION);
|
||||
sprintf_P(vString, PSTR("0.15.0-b1/%i"), VERSION);
|
||||
const char *str[4] = {"WLED", vString, bString, useMdnsName ? cmDNS : serverDescription};
|
||||
|
||||
sendImprovRPCResult(ImprovRPCType::Request_Info, 4, str);
|
||||
|
@ -233,7 +233,7 @@ bool deserializeSegment(JsonObject elem, byte it, byte presetId)
|
||||
getVal(elem["c1"], &seg.custom1);
|
||||
getVal(elem["c2"], &seg.custom2);
|
||||
uint8_t cust3 = seg.custom3;
|
||||
getVal(elem["c3"], &cust3); // we can't pass reference to bifield
|
||||
getVal(elem["c3"], &cust3); // we can't pass reference to bitfield
|
||||
seg.custom3 = constrain(cust3, 0, 31);
|
||||
|
||||
seg.check1 = getBoolVal(elem["o1"], seg.check1);
|
||||
@ -899,7 +899,7 @@ void serializePalettes(JsonObject root, int page)
|
||||
curPalette.add("c2");
|
||||
curPalette.add("c1");
|
||||
break;
|
||||
case 5: //primary + secondary (+tert if not off), more distinct
|
||||
case 5: //primary + secondary (+tertiary if not off), more distinct
|
||||
curPalette.add("c1");
|
||||
curPalette.add("c1");
|
||||
curPalette.add("c1");
|
||||
|
@ -199,6 +199,9 @@ void handleNetworkTime()
|
||||
{
|
||||
if (millis() - ntpPacketSentTime > 10000)
|
||||
{
|
||||
#ifdef ARDUINO_ARCH_ESP32 // I had problems using udp.flush() on 8266
|
||||
while (ntpUdp.parsePacket() > 0) ntpUdp.flush(); // flush any existing packets
|
||||
#endif
|
||||
sendNTPPacket();
|
||||
ntpPacketSentTime = millis();
|
||||
}
|
||||
@ -239,16 +242,38 @@ void sendNTPPacket()
|
||||
ntpUdp.endPacket();
|
||||
}
|
||||
|
||||
static bool isValidNtpResponse(byte * ntpPacket) {
|
||||
// Perform a few validity checks on the packet
|
||||
// based on https://github.com/taranais/NTPClient/blob/master/NTPClient.cpp
|
||||
if((ntpPacket[0] & 0b11000000) == 0b11000000) return false; //reject LI=UNSYNC
|
||||
// if((ntpPacket[0] & 0b00111000) >> 3 < 0b100) return false; //reject Version < 4
|
||||
if((ntpPacket[0] & 0b00000111) != 0b100) return false; //reject Mode != Server
|
||||
if((ntpPacket[1] < 1) || (ntpPacket[1] > 15)) return false; //reject invalid Stratum
|
||||
if( ntpPacket[16] == 0 && ntpPacket[17] == 0 &&
|
||||
ntpPacket[18] == 0 && ntpPacket[19] == 0 &&
|
||||
ntpPacket[20] == 0 && ntpPacket[21] == 0 &&
|
||||
ntpPacket[22] == 0 && ntpPacket[23] == 0) //reject ReferenceTimestamp == 0
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool checkNTPResponse()
|
||||
{
|
||||
int cb = ntpUdp.parsePacket();
|
||||
if (!cb) return false;
|
||||
if (cb < NTP_MIN_PACKET_SIZE) {
|
||||
#ifdef ARDUINO_ARCH_ESP32 // I had problems using udp.flush() on 8266
|
||||
if (cb > 0) ntpUdp.flush(); // this avoids memory leaks on esp32
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t ntpPacketReceivedTime = millis();
|
||||
DEBUG_PRINT(F("NTP recv, l="));
|
||||
DEBUG_PRINTLN(cb);
|
||||
byte pbuf[NTP_PACKET_SIZE];
|
||||
ntpUdp.read(pbuf, NTP_PACKET_SIZE); // read the packet into the buffer
|
||||
if (!isValidNtpResponse(pbuf)) return false; // verify we have a valid response to client
|
||||
|
||||
Toki::Time arrived = toki.fromNTP(pbuf + 32);
|
||||
Toki::Time departed = toki.fromNTP(pbuf + 40);
|
||||
@ -422,8 +447,8 @@ void checkTimers()
|
||||
}
|
||||
|
||||
#define ZENITH -0.83
|
||||
// get sunrise (or sunset) time (in minutes) for a given day at a given geo location
|
||||
int getSunriseUTC(int year, int month, int day, float lat, float lon, bool sunset=false) {
|
||||
// get sunrise (or sunset) time (in minutes) for a given day at a given geo location. Returns >= INT16_MAX in case of "no sunset"
|
||||
static int getSunriseUTC(int year, int month, int day, float lat, float lon, bool sunset=false) {
|
||||
//1. first calculate the day of the year
|
||||
float N1 = 275 * month / 9;
|
||||
float N2 = (month + 9) / 12;
|
||||
@ -457,8 +482,8 @@ int getSunriseUTC(int year, int month, int day, float lat, float lon, bool sunse
|
||||
|
||||
//7a. calculate the Sun's local hour angle
|
||||
float cosH = (sinf(DEG_TO_RAD*ZENITH) - (sinDec * sinf(DEG_TO_RAD*lat))) / (cosDec * cosf(DEG_TO_RAD*lat));
|
||||
if ((cosH > 1.0f) && !sunset) return 0; // the sun never rises on this location (on the specified date)
|
||||
if ((cosH < -1.0f) && sunset) return 0; // the sun never sets on this location (on the specified date)
|
||||
if ((cosH > 1.0f) && !sunset) return INT16_MAX; // the sun never rises on this location (on the specified date)
|
||||
if ((cosH < -1.0f) && sunset) return INT16_MAX; // the sun never sets on this location (on the specified date)
|
||||
|
||||
//7b. finish calculating H and convert into hours
|
||||
float H = sunset ? RAD_TO_DEG*acosf(cosH) : 360 - RAD_TO_DEG*acosf(cosH);
|
||||
@ -474,6 +499,7 @@ int getSunriseUTC(int year, int month, int day, float lat, float lon, bool sunse
|
||||
return UT*60;
|
||||
}
|
||||
|
||||
#define SUNSET_MAX (24*60) // 1day = max expected absolute value for sun offset in minutes
|
||||
// calculate sunrise and sunset (if longitude and latitude are set)
|
||||
void calculateSunriseAndSunset() {
|
||||
if ((int)(longitude*10.) || (int)(latitude*10.)) {
|
||||
@ -484,8 +510,19 @@ void calculateSunriseAndSunset() {
|
||||
tim_0.tm_sec = 0;
|
||||
tim_0.tm_isdst = 0;
|
||||
|
||||
int minUTC = getSunriseUTC(year(localTime), month(localTime), day(localTime), latitude, longitude);
|
||||
if (minUTC) {
|
||||
// Due to limited accuracy, its possible to get a bad sunrise/sunset displayed as "00:00" (see issue #3601)
|
||||
// So in case of invalid result, we try to use the sunset/sunrise of previous day. Max 3 days back, this worked well in all cases I tried.
|
||||
// When latitude = 66,6 (N or S), the functions sometimes returns 2147483647, so this "unexpected large" is another condition for retry
|
||||
int minUTC = 0;
|
||||
int retryCount = 0;
|
||||
do {
|
||||
time_t theDay = localTime - retryCount * 86400; // one day back = 86400 seconds
|
||||
minUTC = getSunriseUTC(year(theDay), month(theDay), day(theDay), latitude, longitude, false);
|
||||
DEBUG_PRINT(F("* sunrise (minutes from UTC) = ")); DEBUG_PRINTLN(minUTC);
|
||||
retryCount ++;
|
||||
} while ((abs(minUTC) > SUNSET_MAX) && (retryCount <= 3));
|
||||
|
||||
if (abs(minUTC) <= SUNSET_MAX) {
|
||||
// there is a sunrise
|
||||
if (minUTC < 0) minUTC += 24*60; // add a day if negative
|
||||
tim_0.tm_hour = minUTC / 60;
|
||||
@ -496,8 +533,15 @@ void calculateSunriseAndSunset() {
|
||||
sunrise = 0;
|
||||
}
|
||||
|
||||
minUTC = getSunriseUTC(year(localTime), month(localTime), day(localTime), latitude, longitude, true);
|
||||
if (minUTC) {
|
||||
retryCount = 0;
|
||||
do {
|
||||
time_t theDay = localTime - retryCount * 86400; // one day back = 86400 seconds
|
||||
minUTC = getSunriseUTC(year(theDay), month(theDay), day(theDay), latitude, longitude, true);
|
||||
DEBUG_PRINT(F("* sunset (minutes from UTC) = ")); DEBUG_PRINTLN(minUTC);
|
||||
retryCount ++;
|
||||
} while ((abs(minUTC) > SUNSET_MAX) && (retryCount <= 3));
|
||||
|
||||
if (abs(minUTC) <= SUNSET_MAX) {
|
||||
// there is a sunset
|
||||
if (minUTC < 0) minUTC += 24*60; // add a day if negative
|
||||
tim_0.tm_hour = minUTC / 60;
|
||||
|
@ -60,7 +60,8 @@ enum struct PinOwner : uint8_t {
|
||||
UM_BME280 = USERMOD_ID_BME280, // 0x1E // Usermod "usermod_bme280.h -- Uses "standard" HW_I2C pins
|
||||
UM_Audioreactive = USERMOD_ID_AUDIOREACTIVE, // 0x20 // Usermod "audio_reactive.h"
|
||||
UM_SdCard = USERMOD_ID_SD_CARD, // 0x25 // Usermod "usermod_sd_card.h"
|
||||
UM_PWM_OUTPUTS = USERMOD_ID_PWM_OUTPUTS // 0x26 // Usermod "usermod_pwm_outputs.h"
|
||||
UM_PWM_OUTPUTS = USERMOD_ID_PWM_OUTPUTS, // 0x26 // Usermod "usermod_pwm_outputs.h"
|
||||
UM_LDR_DUSK_DAWN = USERMOD_ID_LDR_DUSK_DAWN // 0x2B // Usermod "usermod_LDR_Dusk_Dawn_v2.h"
|
||||
};
|
||||
static_assert(0u == static_cast<uint8_t>(PinOwner::None), "PinOwner::None must be zero, so default array initialization works as expected");
|
||||
|
||||
|
@ -217,7 +217,7 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
|
||||
}
|
||||
BusManager::updateColorOrderMap(com);
|
||||
|
||||
// upate other pins
|
||||
// update other pins
|
||||
int hw_ir_pin = request->arg(F("IR")).toInt();
|
||||
if (pinManager.allocatePin(hw_ir_pin,false, PinOwner::IR)) {
|
||||
irPin = hw_ir_pin;
|
||||
@ -443,7 +443,7 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
|
||||
|
||||
//start ntp if not already connected
|
||||
if (ntpEnabled && WLED_CONNECTED && !ntpConnected) ntpConnected = ntpUdp.begin(ntpLocalPort);
|
||||
ntpLastSyncTime = 0; // force new NTP query
|
||||
ntpLastSyncTime = NTP_NEVER; // force new NTP query
|
||||
|
||||
longitude = request->arg(F("LN")).toFloat();
|
||||
latitude = request->arg(F("LT")).toFloat();
|
||||
@ -700,10 +700,10 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
|
||||
DEBUG_PRINTLN(value);
|
||||
} else {
|
||||
// we are using a hidden field with the same name as our parameter (!before the actual parameter!)
|
||||
// to describe the type of parameter (text,float,int), for boolean patameters the first field contains "off"
|
||||
// to describe the type of parameter (text,float,int), for boolean parameters the first field contains "off"
|
||||
// so checkboxes have one or two fields (first is always "false", existence of second depends on checkmark and may be "true")
|
||||
if (subObj[name].isNull()) {
|
||||
// the first occurence of the field describes the parameter type (used in next loop)
|
||||
// the first occurrence of the field describes the parameter type (used in next loop)
|
||||
if (value == "false") subObj[name] = false; // checkboxes may have only one field
|
||||
else subObj[name] = value;
|
||||
} else {
|
||||
|
@ -28,7 +28,7 @@
|
||||
#define BREAKFORMAT SERIAL_8N1
|
||||
|
||||
bool dmxStarted = false;
|
||||
int sendPin = 2; //dafault on ESP8266
|
||||
int sendPin = 2; //default on ESP8266
|
||||
|
||||
//DMX value array and size. Entry 0 will hold startbyte
|
||||
uint8_t dmxDataStore[dmxMaxChannel] = {};
|
||||
|
@ -34,7 +34,7 @@
|
||||
#define DS1307_CTRL_ID 0x68
|
||||
|
||||
// PUBLIC FUNCTIONS
|
||||
time_t DS1307RTC::get() // Aquire data from buffer and convert to time_t
|
||||
time_t DS1307RTC::get() // Acquire data from buffer and convert to time_t
|
||||
{
|
||||
tmElements_t tm;
|
||||
if (read(tm) == false) return 0;
|
||||
@ -48,7 +48,7 @@ bool DS1307RTC::set(time_t t)
|
||||
return write(tm);
|
||||
}
|
||||
|
||||
// Aquire data from the RTC chip in BCD format
|
||||
// Acquire data from the RTC chip in BCD format
|
||||
bool DS1307RTC::read(tmElements_t &tm)
|
||||
{
|
||||
uint8_t sec;
|
||||
|
@ -101,9 +101,9 @@ int year(time_t t) { // the year for the given time
|
||||
|
||||
/*============================================================================*/
|
||||
/* functions to convert to and from system time */
|
||||
/* These are for interfacing with time serivces and are not normally needed in a sketch */
|
||||
/* These are for interfacing with time services and are not normally needed in a sketch */
|
||||
|
||||
// leap year calulator expects year argument as years offset from 1970
|
||||
// leap year calculator expects year argument as years offset from 1970
|
||||
#define LEAP_YEAR(Y) ( ((1970+Y)>0) && !((1970+Y)%4) && ( ((1970+Y)%100) || !((1970+Y)%400) ) )
|
||||
|
||||
static const uint8_t monthDays[]={31,28,31,30,31,30,31,31,30,31,30,31}; // API starts months from 1, this array starts from 0
|
||||
@ -193,7 +193,7 @@ time_t makeTime(tmElements_t &tm){
|
||||
}
|
||||
|
||||
time_t getUnixTime(int hr,int min,int sec,int dy, int mnth, int yr){
|
||||
// year can be given as full four digit year or two digts (2010 or 10 for 2010);
|
||||
// year can be given as full four digit year or two digits (2010 or 10 for 2010);
|
||||
//it is converted to years since 1970
|
||||
if( yr > 99)
|
||||
yr = yr - 1970;
|
||||
|
@ -11,7 +11,7 @@
|
||||
|
||||
#include "Timezone.h"
|
||||
|
||||
//THIS LINE WAS ADDED FOR COMPATIBILY WITH THE WLED DEPENDENCY STRUCTURE. REMOVE IF YOU USE IT OUTSIDE OF WLED!
|
||||
//THIS LINE WAS ADDED FOR COMPATIBILITY WITH THE WLED DEPENDENCY STRUCTURE. REMOVE IF YOU USE IT OUTSIDE OF WLED!
|
||||
#include "../time/TimeLib.h"
|
||||
|
||||
#ifdef __AVR__
|
||||
|
@ -56,7 +56,7 @@ void notify(byte callMode, bool followUp)
|
||||
//3: supports FX intensity, 24 byte packet 4: supports transitionDelay 5: sup palette
|
||||
//6: supports timebase syncing, 29 byte packet 7: supports tertiary color 8: supports sys time sync, 36 byte packet
|
||||
//9: supports sync groups, 37 byte packet 10: supports CCT, 39 byte packet 11: per segment options, variable packet length (40+MAX_NUM_SEGMENTS*3)
|
||||
//12: enhanced effct sliders, 2D & mapping options
|
||||
//12: enhanced effect sliders, 2D & mapping options
|
||||
udpOut[11] = 12;
|
||||
col = mainseg.colors[1];
|
||||
udpOut[12] = R(col);
|
||||
|
@ -19,7 +19,7 @@ bool UsermodManager::handleButton(uint8_t b) {
|
||||
bool UsermodManager::getUMData(um_data_t **data, uint8_t mod_id) {
|
||||
for (byte i = 0; i < numMods; i++) {
|
||||
if (mod_id > 0 && ums[i]->getId() != mod_id) continue; // only get data form requested usermod if provided
|
||||
if (ums[i]->getUMData(data)) return true; // if usermod does provide data return immediately (only one usermod can povide data at one time)
|
||||
if (ums[i]->getUMData(data)) return true; // if usermod does provide data return immediately (only one usermod can provide data at one time)
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -197,6 +197,10 @@
|
||||
#include "../usermods/mpu6050_imu/usermod_gyro_surge.h"
|
||||
#endif
|
||||
|
||||
#ifdef USERMOD_LDR_DUSK_DAWN
|
||||
#include "../usermods/LDR_Dusk_Dawn_v2/usermod_LDR_Dusk_Dawn_v2.h"
|
||||
#endif
|
||||
|
||||
void registerUsermods()
|
||||
{
|
||||
/*
|
||||
@ -381,4 +385,8 @@ void registerUsermods()
|
||||
#ifdef USERMOD_GYRO_SURGE
|
||||
static GyroSurge gyro_surge; usermods.add(&gyro_surge);
|
||||
#endif
|
||||
|
||||
#ifdef USERMOD_LDR_DUSK_DAWN
|
||||
usermods.add(new LDR_Dusk_Dawn_v2());
|
||||
#endif
|
||||
}
|
||||
|
@ -157,9 +157,9 @@ bool oappendi(int i)
|
||||
bool oappend(const char* txt)
|
||||
{
|
||||
uint16_t len = strlen(txt);
|
||||
if (olen + len >= SETTINGS_STACK_BUF_SIZE) {
|
||||
if ((obuf == nullptr) || (olen + len >= SETTINGS_STACK_BUF_SIZE)) { // sanity checks
|
||||
#ifdef WLED_DEBUG
|
||||
DEBUG_PRINT(F("oappend() buffer overflow. Cannnot append "));
|
||||
DEBUG_PRINT(F("oappend() buffer overflow. Cannot append "));
|
||||
DEBUG_PRINT(len); DEBUG_PRINT(F(" bytes \t\""));
|
||||
DEBUG_PRINT(txt); DEBUG_PRINTLN(F("\""));
|
||||
#endif
|
||||
@ -245,7 +245,7 @@ void releaseJSONBufferLock()
|
||||
|
||||
|
||||
// extracts effect mode (or palette) name from names serialized string
|
||||
// caller must provide large enough buffer for name (incluing SR extensions)!
|
||||
// caller must provide large enough buffer for name (including SR extensions)!
|
||||
uint8_t extractModeName(uint8_t mode, const char *src, char *dest, uint8_t maxLen)
|
||||
{
|
||||
if (src == JSON_mode_names || src == nullptr) {
|
||||
|
@ -132,7 +132,7 @@ void WLED::loop()
|
||||
if (lastMqttReconnectAttempt > millis()) {
|
||||
rolloverMillis++;
|
||||
lastMqttReconnectAttempt = 0;
|
||||
ntpLastSyncTime = 0;
|
||||
ntpLastSyncTime = NTP_NEVER; // force new NTP query
|
||||
strip.restartRuntime();
|
||||
}
|
||||
if (millis() - lastMqttReconnectAttempt > 30000 || lastMqttReconnectAttempt == 0) { // lastMqttReconnectAttempt==0 forces immediate broadcast
|
||||
@ -399,6 +399,11 @@ void WLED::setup()
|
||||
DEBUG_PRINTLN(F("PSRAM not used."));
|
||||
#endif
|
||||
#endif
|
||||
#if defined(ARDUINO_ESP32_PICO)
|
||||
// special handling for PICO-D4: gpio16+17 are in use for onboard SPI FLASH (not PSRAM)
|
||||
managed_pin_type pins[] = { {16, true}, {17, true} };
|
||||
pinManager.allocateMultiplePins(pins, sizeof(pins)/sizeof(managed_pin_type), PinOwner::SPI_RAM);
|
||||
#endif
|
||||
|
||||
//DEBUG_PRINT(F("LEDs inited. heap usage ~"));
|
||||
//DEBUG_PRINTLN(heapPreAlloc - ESP.getFreeHeap());
|
||||
|
@ -8,7 +8,7 @@
|
||||
*/
|
||||
|
||||
// version code in format yymmddb (b = daily build)
|
||||
#define VERSION 2402010
|
||||
#define VERSION 2402060
|
||||
|
||||
//uncomment this if you have a "my_config.h" file you'd like to use
|
||||
//#define WLED_USE_MY_CONFIG
|
||||
@ -156,7 +156,7 @@
|
||||
// ESP32-WROVER features SPI RAM (aka PSRAM) which can be allocated using ps_malloc()
|
||||
// we can create custom PSRAMDynamicJsonDocument to use such feature (replacing DynamicJsonDocument)
|
||||
// The following is a construct to enable code to compile without it.
|
||||
// There is a code thet will still not use PSRAM though:
|
||||
// There is a code that will still not use PSRAM though:
|
||||
// AsyncJsonResponse is a derived class that implements DynamicJsonDocument (AsyncJson-v6.h)
|
||||
#if defined(ARDUINO_ARCH_ESP32) && defined(BOARD_HAS_PSRAM) && defined(WLED_USE_PSRAM)
|
||||
struct PSRAM_Allocator {
|
||||
@ -417,7 +417,7 @@ WLED_GLOBAL bool arlsForceMaxBri _INIT(false); // enable to f
|
||||
#endif
|
||||
WLED_GLOBAL uint16_t e131ProxyUniverse _INIT(0); // output this E1.31 (sACN) / ArtNet universe via MAX485 (0 = disabled)
|
||||
#endif
|
||||
WLED_GLOBAL uint16_t e131Universe _INIT(1); // settings for E1.31 (sACN) protocol (only DMX_MODE_MULTIPLE_* can span over consequtive universes)
|
||||
WLED_GLOBAL uint16_t e131Universe _INIT(1); // settings for E1.31 (sACN) protocol (only DMX_MODE_MULTIPLE_* can span over consecutive universes)
|
||||
WLED_GLOBAL uint16_t e131Port _INIT(5568); // DMX in port. E1.31 default is 5568, Art-Net is 6454
|
||||
WLED_GLOBAL byte e131Priority _INIT(0); // E1.31 port priority (if != 0 priority handling is active)
|
||||
WLED_GLOBAL E131Priority highPriority _INIT(3); // E1.31 highest priority tracking, init = timeout in seconds
|
||||
@ -566,7 +566,7 @@ WLED_GLOBAL byte colNlT[] _INIT_N(({ 0, 0, 0, 0 })); // current nightligh
|
||||
WLED_GLOBAL unsigned long lastOnTime _INIT(0);
|
||||
WLED_GLOBAL bool offMode _INIT(!turnOnAtBoot);
|
||||
WLED_GLOBAL byte bri _INIT(briS); // global brightness (set)
|
||||
WLED_GLOBAL byte briOld _INIT(0); // global brightnes while in transition loop (previous iteration)
|
||||
WLED_GLOBAL byte briOld _INIT(0); // global brightness while in transition loop (previous iteration)
|
||||
WLED_GLOBAL byte briT _INIT(0); // global brightness during transition
|
||||
WLED_GLOBAL byte briLast _INIT(128); // brightness before turned off. Used for toggle function
|
||||
WLED_GLOBAL byte whiteLast _INIT(128); // white channel before turned off. Used for toggle function
|
||||
@ -668,10 +668,11 @@ WLED_GLOBAL DNSServer dnsServer;
|
||||
#ifndef WLED_LON
|
||||
#define WLED_LON 0.0f
|
||||
#endif
|
||||
#define NTP_NEVER 999000000L
|
||||
WLED_GLOBAL bool ntpConnected _INIT(false);
|
||||
WLED_GLOBAL time_t localTime _INIT(0);
|
||||
WLED_GLOBAL unsigned long ntpLastSyncTime _INIT(999000000L);
|
||||
WLED_GLOBAL unsigned long ntpPacketSentTime _INIT(999000000L);
|
||||
WLED_GLOBAL unsigned long ntpLastSyncTime _INIT(NTP_NEVER);
|
||||
WLED_GLOBAL unsigned long ntpPacketSentTime _INIT(NTP_NEVER);
|
||||
WLED_GLOBAL IPAddress ntpServerIP;
|
||||
WLED_GLOBAL uint16_t ntpLocalPort _INIT(2390);
|
||||
WLED_GLOBAL uint16_t rolloverMillis _INIT(0);
|
||||
|
@ -523,7 +523,12 @@ void serveSettingsJS(AsyncWebServerRequest* request)
|
||||
strcat_P(buf,PSTR("function GetV(){var d=document;"));
|
||||
getSettingsJS(subPage, buf+strlen(buf)); // this may overflow by 35bytes!!!
|
||||
strcat_P(buf,PSTR("}"));
|
||||
request->send(200, "application/javascript", buf);
|
||||
|
||||
AsyncWebServerResponse *response;
|
||||
response = request->beginResponse(200, "application/javascript", buf);
|
||||
response->addHeader(F("Cache-Control"),"no-store");
|
||||
response->addHeader(F("Expires"),"0");
|
||||
request->send(response);
|
||||
}
|
||||
|
||||
|
||||
|
@ -30,7 +30,7 @@ void wsEvent(AsyncWebSocket * server, AsyncWebSocketClient * client, AwsEventTyp
|
||||
{
|
||||
if (len > 0 && len < 10 && data[0] == 'p') {
|
||||
// application layer ping/pong heartbeat.
|
||||
// client-side socket layer ping packets are unresponded (investigate)
|
||||
// client-side socket layer ping packets are unanswered (investigate)
|
||||
client->text(F("pong"));
|
||||
return;
|
||||
}
|
||||
|
@ -238,8 +238,8 @@ void getSettingsJS(byte subPage, char* dest)
|
||||
|
||||
if (subPage == SUBPAGE_MENU)
|
||||
{
|
||||
#ifndef WLED_DISABLE_2D // include only if 2D is compiled in
|
||||
oappend(PSTR("gId('2dbtn').style.display='';"));
|
||||
#ifdef WLED_DISABLE_2D // include only if 2D is not compiled in
|
||||
oappend(PSTR("gId('2dbtn').style.display='none';"));
|
||||
#endif
|
||||
#ifdef WLED_ENABLE_DMX // include only if DMX is enabled
|
||||
oappend(PSTR("gId('dmxbtn').style.display='';"));
|
||||
|
Loading…
x
Reference in New Issue
Block a user