Merge branch 'master' into dev

Conflicts:
	CHANGELOG.md
	package.json
	platformio.ini
	usermods/Temperature/usermod_temperature.h
	wled00/FX.cpp
	wled00/FX.h
	wled00/FX_fcn.cpp
	wled00/cfg.cpp
	wled00/data/index.js
	wled00/data/settings_leds.htm
	wled00/data/settings_time.htm
	wled00/data/style.css
	wled00/html_other.h
	wled00/html_settings.h
	wled00/html_ui.h
	wled00/ntp.cpp
	wled00/usermods_list.cpp
	wled00/wled.cpp
	wled00/wled.h
This commit is contained in:
Blaz Kristan 2021-04-14 18:19:51 +02:00
commit 29e048af7b
29 changed files with 1179 additions and 886 deletions

View File

@ -2,11 +2,30 @@
### Builds after release 0.12.0 ### Builds after release 0.12.0
#### Build 2104141
- Reduced memory usage by 540b by switching to a different trigonometric approximation
#### Build 2104140
- Added dynamic location-based Sunrise/Sunset macros (PR #1889)
- Improved seasonal background handling (PR #1890)
- Fixed instance discovery not working if MQTT not compiled in
- Fixed Button, IR, Relay pin not assigned by default (resolves #1891)
#### Build 2104120
- Added switch support (button macro is switch closing action, long press macro switch opening)
- Replaced Circus effect with new Running Dual effect (Circus is Tricolor Chase with Red/White/Black)
- Fixed ledmap with multiple segments (PR #1864)
#### Build 2104030 #### Build 2104030
- Fixed ESP32 crash on Drip effect with reversed segment (#1854) - Fixed ESP32 crash on Drip effect with reversed segment (#1854)
- Added flag `WLED_DISABLE_BROWNOUT_DET` to disable ESP32 brownout detector (off by default) - Added flag `WLED_DISABLE_BROWNOUT_DET` to disable ESP32 brownout detector (off by default)
### WLED release 0.12.0
#### Build 2104020 #### Build 2104020
- Allow clearing button/IR/relay pin on platforms that don't support negative numbers - Allow clearing button/IR/relay pin on platforms that don't support negative numbers

View File

@ -178,7 +178,7 @@ upload_speed = 115200
lib_compat_mode = strict lib_compat_mode = strict
lib_deps = lib_deps =
fastled/FastLED @ 3.3.2 fastled/FastLED @ 3.3.2
NeoPixelBus @ 2.6.0 NeoPixelBus @ ^2.6.0
ESPAsyncTCP @ 1.2.0 ESPAsyncTCP @ 1.2.0
ESPAsyncUDP ESPAsyncUDP
AsyncTCP @ 1.0.3 AsyncTCP @ 1.0.3
@ -188,10 +188,10 @@ lib_deps =
#For use of the TTGO T-Display ESP32 Module with integrated TFT display uncomment the following line #For use of the TTGO T-Display ESP32 Module with integrated TFT display uncomment the following line
#TFT_eSPI #TFT_eSPI
#For use SSD1306 OLED display uncomment following #For use SSD1306 OLED display uncomment following
#U8g2@~2.27.2 U8g2@~2.27.2
#For Dallas sensor uncomment following 2 lines #For Dallas sensor uncomment following 2 lines
#OneWire@~2.3.5 OneWire@~2.3.5
#milesburton/DallasTemperature@^3.9.0 milesburton/DallasTemperature@^3.9.0
#For BME280 sensor uncomment following #For BME280 sensor uncomment following
#BME280@~3.0.0 #BME280@~3.0.0
; adafruit/Adafruit BMP280 Library @ 2.1.0 ; adafruit/Adafruit BMP280 Library @ 2.1.0
@ -400,31 +400,7 @@ build_flags = ${common.build_flags_esp32} ${common.debug_flags} ${common.build_f
# codm pixel controller board configurations # codm pixel controller board configurations
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
[env:codm-controller-0.4] [env:codm-controller-0.6]
board = esp_wroom_02
platform = ${common.platform_wled_default}
platform_packages = ${common.platform_packages}
board_build.ldscript = ${common.ldscript_2m512k}
build_unflags = ${common.build_unflags}
build_flags = ${common.build_flags_esp8266} -D LEDPIN=3
[env:codm-controller-0.4-WS2801]
board = esp_wroom_02
platform = ${common.platform_wled_default}
platform_packages = ${common.platform_packages}
board_build.ldscript = ${common.ldscript_2m512k}
build_unflags = ${common.build_unflags}
build_flags = ${common.build_flags_esp8266} -D USE_WS2801 -D CLKPIN=13 -D DATAPIN=3
[env:codm-controller-0.4-APA102]
board = esp_wroom_02
platform = ${common.platform_wled_default}
platform_packages = ${common.platform_packages}
board_build.ldscript = ${common.ldscript_2m512k}
build_unflags = ${common.build_unflags}
build_flags = ${common.build_flags_esp8266} -D USE_APA102 -D CLKPIN=13 -D DATAPIN=3
[env:codm-controller-0.5]
board = esp_wroom_02 board = esp_wroom_02
platform = ${common.platform_wled_default} platform = ${common.platform_wled_default}
platform_packages = ${common.platform_packages} platform_packages = ${common.platform_packages}
@ -432,18 +408,10 @@ board_build.ldscript = ${common.ldscript_2m512k}
build_unflags = ${common.build_unflags} build_unflags = ${common.build_unflags}
build_flags = ${common.build_flags_esp8266} build_flags = ${common.build_flags_esp8266}
[env:codm-controller-0.5-WS2801] [env:codm-controller-0.6-rev2]
board = esp_wroom_02 board = esp_wroom_02
platform = ${common.platform_wled_default} platform = ${common.platform_wled_default}
platform_packages = ${common.platform_packages} platform_packages = ${common.platform_packages}
board_build.ldscript = ${common.ldscript_2m512k} board_build.ldscript = ${common.ldscript_4m1m}
build_unflags = ${common.build_unflags} build_unflags = ${common.build_unflags}
build_flags = ${common.build_flags_esp8266} -D USE_WS2801 #-D CLKPIN=0 -D DATAPIN=2 build_flags = ${common.build_flags_esp8266}
[env:codm-controller-0.5-APA102]
board = esp_wroom_02
platform = ${common.platform_wled_default}
platform_packages = ${common.platform_packages}
board_build.ldscript = ${common.ldscript_2m512k}
build_unflags = ${common.build_unflags}
build_flags = ${common.build_flags_esp8266} -D USE_APA102 #-D CLKPIN=0 -D DATAPIN=2

6
tools/WLED_ESP32_8MB.csv Normal file
View File

@ -0,0 +1,6 @@
# Name, Type, SubType, Offset, Size, Flags
nvs, data, nvs, 0x9000, 0x5000,
otadata, data, ota, 0xe000, 0x2000,
app0, app, ota_0, 0x10000, 0x200000,
app1, app, ota_1, 0x210000,0x200000,
spiffs, data, spiffs, 0x410000,0x3F0000,
1 # Name Type SubType Offset Size Flags
2 nvs data nvs 0x9000 0x5000
3 otadata data ota 0xe000 0x2000
4 app0 app ota_0 0x10000 0x200000
5 app1 app ota_1 0x210000 0x200000
6 spiffs data spiffs 0x410000 0x3F0000

View File

@ -93,8 +93,8 @@ or remove them and put everything on one line.
| segment-delay-ms | Delay (milliseconds) between switching on/off each step | 150 | | segment-delay-ms | Delay (milliseconds) between switching on/off each step | 150 |
| on-time-s | Time (seconds) the stairs stay lit after last detection | 5 | | on-time-s | Time (seconds) the stairs stay lit after last detection | 5 |
| bottom-echo-us | Detection range of ultrasonic sensor | 1749 | | bottom-echo-us | Detection range of ultrasonic sensor | 1749 |
| bottomsensor | Manually trigger a down to up animation via API | false | | bottom-sensor | Manually trigger a down to up animation via API | false |
| topsensor | Manually trigger an up to down animation via API | false | | top-sensor | Manually trigger an up to down animation via API | false |
To read the current settings, open a browser to `http://xxx.xxx.xxx.xxx/json/state` (use your WLED To read the current settings, open a browser to `http://xxx.xxx.xxx.xxx/json/state` (use your WLED
@ -108,8 +108,8 @@ The staircase settings and sensor states are inside the WLED status element:
"enabled": true, "enabled": true,
"segment-delay-ms": 150, "segment-delay-ms": 150,
"on-time-s": 5, "on-time-s": 5,
"bottomsensor": false, "bottom-sensor": false,
"topsensor": false "tops-ensor": false
}, },
} }
``` ```
@ -187,7 +187,7 @@ the API. To simulate triggering the bottom sensor, use:
```bash ```bash
curl -X POST -H "Content-Type: application/json" \ curl -X POST -H "Content-Type: application/json" \
-d '{"staircase":{"bottomsensor":true}}' \ -d '{"staircase":{"bottom-sensor":true}}' \
xxx.xxx.xxx.xxx/json/state xxx.xxx.xxx.xxx/json/state
``` ```
@ -195,7 +195,7 @@ Likewise, to trigger the top sensor, use:
```bash ```bash
curl -X POST -H "Content-Type: application/json" \ curl -X POST -H "Content-Type: application/json" \
-d '{"staircase":{"topsensor":true}}' \ -d '{"staircase":{"top-sensor":true}}' \
xxx.xxx.xxx.xxx/json/state xxx.xxx.xxx.xxx/json/state
``` ```

View File

@ -12,10 +12,11 @@ private:
// User-defined configuration // User-defined configuration
#define Celsius // Show temperature mesaurement in Celcius. Comment out for Fahrenheit #define Celsius // Show temperature mesaurement in Celcius. Comment out for Fahrenheit
#define TemperatureDecimals 1 // Number of decimal places in published temperaure values #define TemperatureDecimals 1 // Number of decimal places in published temperaure values
#define HumidityDecimals 0 // Number of decimal places in published humidity values #define HumidityDecimals 2 // Number of decimal places in published humidity values
#define PressureDecimals 2 // Number of decimal places in published pressure values #define PressureDecimals 2 // Number of decimal places in published pressure values
#define TemperatureInterval 5 // Interval to measure temperature (and humidity, dew point if available) in seconds #define TemperatureInterval 5 // Interval to measure temperature (and humidity, dew point if available) in seconds
#define PressureInterval 300 // Interval to measure pressure in seconds #define PressureInterval 300 // Interval to measure pressure in seconds
#define PublishAlways 0 // Publish values even when they have not changed
// Sanity checks // Sanity checks
#if !defined(TemperatureDecimals) || TemperatureDecimals < 0 #if !defined(TemperatureDecimals) || TemperatureDecimals < 0
@ -33,6 +34,9 @@ private:
#if !defined(PressureInterval) || PressureInterval < 0 #if !defined(PressureInterval) || PressureInterval < 0
#define PressureInterval TemperatureInterval #define PressureInterval TemperatureInterval
#endif #endif
#if !defined(PublishAlways)
#define PublishAlways 0
#endif
#ifdef ARDUINO_ARCH_ESP32 // ESP32 boards #ifdef ARDUINO_ARCH_ESP32 // ESP32 boards
uint8_t SCL_PIN = 22; uint8_t SCL_PIN = 22;
@ -58,7 +62,7 @@ private:
BME280I2C bme{settings}; BME280I2C bme{settings};
uint8_t SensorType; uint8_t sensorType;
// Measurement timers // Measurement timers
long timer; long timer;
@ -66,11 +70,11 @@ private:
long lastPressureMeasure = 0; long lastPressureMeasure = 0;
// Current sensor values // Current sensor values
float SensorTemperature; float sensorTemperature;
float SensorHumidity; float sensorHumidity;
float SensorHeatIndex; float sensorHeatIndex;
float SensorDewPoint; float sensorDewPoint;
float SensorPressure; float sensorPressure;
// Track previous sensor values // Track previous sensor values
float lastTemperature; float lastTemperature;
float lastHumidity; float lastHumidity;
@ -96,13 +100,13 @@ private:
bme.read(_pressure, _temperature, _humidity, tempUnit, presUnit); bme.read(_pressure, _temperature, _humidity, tempUnit, presUnit);
SensorTemperature = _temperature; sensorTemperature = _temperature;
SensorHumidity = _humidity; sensorHumidity = _humidity;
SensorPressure = _pressure; sensorPressure = _pressure;
if (SensorType == 1) if (sensorType == 1)
{ {
SensorHeatIndex = EnvironmentCalculations::HeatIndex(_temperature, _humidity, envTempUnit); sensorHeatIndex = EnvironmentCalculations::HeatIndex(_temperature, _humidity, envTempUnit);
SensorDewPoint = EnvironmentCalculations::DewPoint(_temperature, _humidity, envTempUnit); sensorDewPoint = EnvironmentCalculations::DewPoint(_temperature, _humidity, envTempUnit);
} }
} }
@ -113,7 +117,7 @@ public:
if (!bme.begin()) if (!bme.begin())
{ {
SensorType = 0; sensorType = 0;
Serial.println("Could not find BME280I2C sensor!"); Serial.println("Could not find BME280I2C sensor!");
} }
else else
@ -121,15 +125,15 @@ public:
switch (bme.chipModel()) switch (bme.chipModel())
{ {
case BME280::ChipModel_BME280: case BME280::ChipModel_BME280:
SensorType = 1; sensorType = 1;
Serial.println("Found BME280 sensor! Success."); Serial.println("Found BME280 sensor! Success.");
break; break;
case BME280::ChipModel_BMP280: case BME280::ChipModel_BMP280:
SensorType = 2; sensorType = 2;
Serial.println("Found BMP280 sensor! No Humidity available."); Serial.println("Found BMP280 sensor! No Humidity available.");
break; break;
default: default:
SensorType = 0; sensorType = 0;
Serial.println("Found UNKNOWN sensor! Error!"); Serial.println("Found UNKNOWN sensor! Error!");
} }
} }
@ -139,7 +143,7 @@ public:
{ {
// BME280 sensor MQTT publishing // BME280 sensor MQTT publishing
// Check if sensor present and MQTT Connected, otherwise it will crash the MCU // Check if sensor present and MQTT Connected, otherwise it will crash the MCU
if (SensorType != 0 && mqtt != nullptr) if (sensorType != 0 && mqtt != nullptr)
{ {
// Timer to fetch new temperature, humidity and pressure data at intervals // Timer to fetch new temperature, humidity and pressure data at intervals
timer = millis(); timer = millis();
@ -148,48 +152,48 @@ public:
{ {
lastTemperatureMeasure = timer; lastTemperatureMeasure = timer;
UpdateBME280Data(SensorType); UpdateBME280Data(sensorType);
float Temperature = roundf(SensorTemperature * pow(10, TemperatureDecimals)) / pow(10, TemperatureDecimals); float temperature = roundf(sensorTemperature * pow(10, TemperatureDecimals)) / pow(10, TemperatureDecimals);
float Humidity, HeatIndex, DewPoint; float humidity, heatIndex, dewPoint;
// If temperature has changed since last measure, create string populated with device topic // If temperature has changed since last measure, create string populated with device topic
// from the UI and values read from sensor, then publish to broker // from the UI and values read from sensor, then publish to broker
if (Temperature != lastTemperature) if (temperature != lastTemperature || PublishAlways)
{ {
String topic = String(mqttDeviceTopic) + "/temperature"; String topic = String(mqttDeviceTopic) + "/temperature";
mqttTemperaturePub = mqtt->publish(topic.c_str(), 0, false, String(Temperature, TemperatureDecimals).c_str()); mqttTemperaturePub = mqtt->publish(topic.c_str(), 0, false, String(temperature, TemperatureDecimals).c_str());
} }
lastTemperature = Temperature; // Update last sensor temperature for next loop lastTemperature = temperature; // Update last sensor temperature for next loop
if (SensorType == 1) // Only if sensor is a BME280 if (sensorType == 1) // Only if sensor is a BME280
{ {
Humidity = roundf(SensorHumidity * pow(10, HumidityDecimals)) / pow(10, HumidityDecimals); humidity = roundf(sensorHumidity * pow(10, HumidityDecimals)) / pow(10, HumidityDecimals);
HeatIndex = roundf(SensorHeatIndex * pow(10, TemperatureDecimals)) / pow(10, TemperatureDecimals); heatIndex = roundf(sensorHeatIndex * pow(10, TemperatureDecimals)) / pow(10, TemperatureDecimals);
DewPoint = roundf(SensorDewPoint * pow(10, TemperatureDecimals)) / pow(10, TemperatureDecimals); dewPoint = roundf(sensorDewPoint * pow(10, TemperatureDecimals)) / pow(10, TemperatureDecimals);
if (Humidity != lastHumidity) if (humidity != lastHumidity || PublishAlways)
{ {
String topic = String(mqttDeviceTopic) + "/humidity"; String topic = String(mqttDeviceTopic) + "/humidity";
mqtt->publish(topic.c_str(), 0, false, String(Humidity, HumidityDecimals).c_str()); mqtt->publish(topic.c_str(), 0, false, String(humidity, HumidityDecimals).c_str());
} }
if (HeatIndex != lastHeatIndex) if (heatIndex != lastHeatIndex || PublishAlways)
{ {
String topic = String(mqttDeviceTopic) + "/heat_index"; String topic = String(mqttDeviceTopic) + "/heat_index";
mqtt->publish(topic.c_str(), 0, false, String(HeatIndex, TemperatureDecimals).c_str()); mqtt->publish(topic.c_str(), 0, false, String(heatIndex, TemperatureDecimals).c_str());
} }
if (DewPoint != lastDewPoint) if (dewPoint != lastDewPoint || PublishAlways)
{ {
String topic = String(mqttDeviceTopic) + "/dew_point"; String topic = String(mqttDeviceTopic) + "/dew_point";
mqtt->publish(topic.c_str(), 0, false, String(DewPoint, TemperatureDecimals).c_str()); mqtt->publish(topic.c_str(), 0, false, String(dewPoint, TemperatureDecimals).c_str());
} }
lastHumidity = Humidity; lastHumidity = humidity;
lastHeatIndex = HeatIndex; lastHeatIndex = heatIndex;
lastDewPoint = DewPoint; lastDewPoint = dewPoint;
} }
} }
@ -197,15 +201,15 @@ public:
{ {
lastPressureMeasure = timer; lastPressureMeasure = timer;
float Pressure = roundf(SensorPressure * pow(10, PressureDecimals)) / pow(10, PressureDecimals); float pressure = roundf(sensorPressure * pow(10, PressureDecimals)) / pow(10, PressureDecimals);
if (Pressure != lastPressure) if (pressure != lastPressure || PublishAlways)
{ {
String topic = String(mqttDeviceTopic) + "/pressure"; String topic = String(mqttDeviceTopic) + "/pressure";
mqttPressurePub = mqtt->publish(topic.c_str(), 0, true, String(Pressure, PressureDecimals).c_str()); mqttPressurePub = mqtt->publish(topic.c_str(), 0, true, String(pressure, PressureDecimals).c_str());
} }
lastPressure = Pressure; lastPressure = pressure;
} }
} }
} }

View File

@ -39,7 +39,7 @@ default_envs = d1_mini
... ...
[common] [common]
... ...
lib_deps_external = lib_deps =
... ...
#For use SSD1306 OLED display uncomment following #For use SSD1306 OLED display uncomment following
U8g2@~2.27.3 U8g2@~2.27.3

View File

@ -0,0 +1,35 @@
# Description
That usermod implements support of simple hand gestures with VL53L0X sensor: on/off and brightness correction.
It can be useful for kitchen strips to avoid any touches.
- on/off - just swipe a hand below your sensor ("shortPressAction" is called and can be customized through WLED macros)
- brightness correction - keep your hand below sensor for 1 second to switch to "brightness" mode.
Configure brightness by changing distance to the sensor (see parameters below for customization).
"macroLongPress" is also called here.
## Installation
1. Attach VL53L0X sensor to i2c pins according to default pins for your board.
2. Add `-D USERMOD_VL53L0X_GESTURES` to your build flags at platformio.ini (plaformio_override.ini) for needed environment.
In my case, for example: `build_flags = ${common.build_flags_esp8266} -D RLYPIN=12 -D USERMOD_VL53L0X_GESTURES`
3. Add "pololu/VL53L0X" dependency below to `lib_deps` like this:
```ini
lib_deps = ${env.lib_deps}
pololu/VL53L0X @ ^1.3.0
```
My entire `platformio_override.ini` for example (for nodemcu board):
```ini
[platformio]
default_envs = nodemcu
[env:nodemcu]
board = nodemcu
platform = ${common.platform_wled_default}
platform_packages = ${common.platform_packages}
board_build.ldscript = ${common.ldscript_4m1m}
build_unflags = ${common.build_unflags}
build_flags = ${common.build_flags_esp8266} -D RLYPIN=12 -D USERMOD_VL53L0X_GESTURES
lib_deps = ${env.lib_deps}
pololu/VL53L0X @ ^1.3.0
```

View File

@ -0,0 +1,121 @@
/*
* That usermod implements support of simple hand gestures with VL53L0X sensor: on/off and brightness correction.
* It can be useful for kitchen strips to avoid any touches.
* - on/off - just swipe a hand below your sensor ("shortPressAction" is called and can be customized through WLED macros)
* - brightness correction - keep your hand below sensor for 1 second to switch to "brightness" mode.
* Configure brightness by changing distance to the sensor (see parameters below for customization).
* "macroLongPress" is also called here.
*
* Enabling this mod usermod:
* 1. Attach VL53L0X sensor to i2c pins according to default pins for your board.
* 2. Add "-D USERMOD_VL53L0X_GESTURES" to your build flags at platformio.ini (plaformio_override.ini) for needed environment.
* In my case, for example: build_flags = ${common.build_flags_esp8266} -D RLYPIN=12 -D USERMOD_VL53L0X_GESTURES
* 3. Add "pololu/VL53L0X" dependency to lib_deps like this:
* lib_deps = ${env.lib_deps}
* pololu/VL53L0X @ ^1.3.0
*/
#pragma once
#include "wled.h"
#include <Wire.h>
#include <VL53L0X.h>
#ifndef VL53L0X_MAX_RANGE_MM
#define VL53L0X_MAX_RANGE_MM 230 // max height in millimiters to react for motions
#endif
#ifndef VL53L0X_MIN_RANGE_OFFSET
#define VL53L0X_MIN_RANGE_OFFSET 60 // minimal range in millimiters that sensor can detect. Used in long motions to correct brightnes calculation.
#endif
#ifndef VL53L0X_DELAY_MS
#define VL53L0X_DELAY_MS 100 // how often to get data from sensor
#endif
#ifndef VL53L0X_LONG_MOTION_DELAY_MS
#define VL53L0X_LONG_MOTION_DELAY_MS 1000 // how often to get data from sensor
#endif
class UsermodVL53L0XGestures : public Usermod {
private:
//Private class members. You can declare variables and functions only accessible to your usermod here
unsigned long lastTime = 0;
VL53L0X sensor;
bool wasMotionBefore = false;
bool isLongMotion = false;
unsigned long motionStartTime = 0;
public:
void setup() {
Wire.begin();
sensor.setTimeout(150);
if (!sensor.init())
{
DEBUG_PRINTLN(F("Failed to detect and initialize VL53L0X sensor!"));
} else {
sensor.setMeasurementTimingBudget(20000); // set high speed mode
}
}
void loop() {
if (millis() - lastTime > VL53L0X_DELAY_MS)
{
lastTime = millis();
int range = sensor.readRangeSingleMillimeters();
DEBUG_PRINTF(F("range: %d, brightness: %d"), range, bri);
if (range < VL53L0X_MAX_RANGE_MM)
{
if (!wasMotionBefore)
{
motionStartTime = millis();
DEBUG_PRINTF(F("motionStartTime: %d"), motionStartTime);
}
wasMotionBefore = true;
if (millis() - motionStartTime > VL53L0X_LONG_MOTION_DELAY_MS) //long motion
{
DEBUG_PRINTF(F("long motion: %d"), motionStartTime);
if (!isLongMotion)
{
if (macroLongPress)
{
applyMacro(macroLongPress);
}
isLongMotion = true;
}
// set brightness according to range
bri = (VL53L0X_MAX_RANGE_MM - max(range, VL53L0X_MIN_RANGE_OFFSET)) * 255 / (VL53L0X_MAX_RANGE_MM - VL53L0X_MIN_RANGE_OFFSET);
DEBUG_PRINTF(F("new brightness: %d"), bri);
colorUpdated(1);
}
} else if (wasMotionBefore) { //released
long dur = millis() - motionStartTime;
if (!isLongMotion)
{ //short press
DEBUG_PRINTF(F("shortPressAction..."));
shortPressAction();
}
wasMotionBefore = false;
isLongMotion = false;
}
}
}
/*
* getId() allows you to optionally give your V2 usermod an unique ID (please define it in const.h!).
* This could be used in the future for the system to determine whether your usermod is installed.
*/
uint16_t getId()
{
return USERMOD_ID_VL53L0X;
}
};

View File

@ -4,7 +4,7 @@ default_envs = d1_mini
[env:esp32dev] [env:esp32dev]
board = esp32dev board = esp32dev
platform = espressif32@3.1.1 platform = espressif32@3.2
build_unflags = ${common.build_unflags} build_unflags = ${common.build_unflags}
build_flags = build_flags =
${common.build_flags_esp32} ${common.build_flags_esp32}

View File

@ -418,28 +418,45 @@ uint16_t WS2812FX::mode_theater_chase_rainbow(void) {
/* /*
* Running lights effect with smooth sine transition base. * Running lights effect with smooth sine transition base.
*/ */
uint16_t WS2812FX::running_base(bool saw) { uint16_t WS2812FX::running_base(bool saw, bool dual=false) {
uint8_t x_scale = SEGMENT.intensity >> 2; uint8_t x_scale = SEGMENT.intensity >> 2;
uint32_t counter = (now * SEGMENT.speed) >> 9; uint32_t counter = (now * SEGMENT.speed) >> 9;
for(uint16_t i = 0; i < SEGLEN; i++) { for(uint16_t i = 0; i < SEGLEN; i++) {
uint8_t s = 0; uint16_t a = i*x_scale - counter;
uint8_t a = i*x_scale - counter;
if (saw) { if (saw) {
a &= 0xFF;
if (a < 16) if (a < 16)
{ {
a = 192 + a*8; a = 192 + a*8;
} else { } else {
a = map(a,16,255,64,192); a = map(a,16,255,64,192);
} }
a = 255 - a;
} }
s = sin8(a); uint8_t s = dual ? sin_gap(a) : sin8(a);
setPixelColor(i, color_blend(color_from_palette(i, true, PALETTE_SOLID_WRAP, 0), SEGCOLOR(1), s)); uint32_t ca = color_blend(SEGCOLOR(1), color_from_palette(i, true, PALETTE_SOLID_WRAP, 0), s);
if (dual) {
uint16_t b = (SEGLEN-1-i)*x_scale - counter;
uint8_t t = sin_gap(b);
uint32_t cb = color_blend(SEGCOLOR(1), color_from_palette(i, true, PALETTE_SOLID_WRAP, 2), t);
ca = color_blend(ca, cb, 127);
}
setPixelColor(i, ca);
} }
return FRAMETIME; return FRAMETIME;
} }
/*
* Running lights in opposite directions.
* Idea: Make the gap width controllable with a third slider in the future
*/
uint16_t WS2812FX::mode_running_dual(void) {
return running_base(false, true);
}
/* /*
* Running lights effect with smooth sine transition. * Running lights effect with smooth sine transition.
*/ */
@ -1306,14 +1323,6 @@ uint16_t WS2812FX::tricolor_chase(uint32_t color1, uint32_t color2) {
} }
/*
* Alternating white/red/black pixels running. PLACEHOLDER
*/
uint16_t WS2812FX::mode_circus_combustus(void) {
return tricolor_chase(RED, WHITE);
}
/* /*
* Tricolor chase mode * Tricolor chase mode
*/ */
@ -3074,8 +3083,9 @@ uint16_t WS2812FX::mode_drip(void)
if (drops[j].pos < 0) drops[j].pos = 0; if (drops[j].pos < 0) drops[j].pos = 0;
drops[j].vel += gravity; // gravity is negative drops[j].vel += gravity; // gravity is negative
for (uint8_t i=1;i<7-drops[j].colIndex;i++) { // some minor math so we don't expand bouncing droplets for (uint16_t i=1;i<7-drops[j].colIndex;i++) { // some minor math so we don't expand bouncing droplets
setPixelColor(constrain(uint16_t(drops[j].pos)+i,0,SEGLEN-1),color_blend(BLACK,SEGCOLOR(0),drops[j].col/i)); //spread pixel with fade while falling uint16_t pos = constrain(uint16_t(drops[j].pos) +i, 0, SEGLEN-1); //this is BAD, returns a pos >= SEGLEN occasionally
setPixelColor(pos,color_blend(BLACK,SEGCOLOR(0),drops[j].col/i)); //spread pixel with fade while falling
} }
if (drops[j].colIndex > 2) { // during bounce, some water is on the floor if (drops[j].colIndex > 2) { // during bounce, some water is on the floor

View File

@ -166,7 +166,7 @@
#define FX_MODE_POLICE_ALL 49 #define FX_MODE_POLICE_ALL 49
#define FX_MODE_TWO_DOTS 50 #define FX_MODE_TWO_DOTS 50
#define FX_MODE_TWO_AREAS 51 #define FX_MODE_TWO_AREAS 51
#define FX_MODE_CIRCUS_COMBUSTUS 52 #define FX_MODE_RUNNING_DUAL 52
#define FX_MODE_HALLOWEEN 53 #define FX_MODE_HALLOWEEN 53
#define FX_MODE_TRICOLOR_CHASE 54 #define FX_MODE_TRICOLOR_CHASE 54
#define FX_MODE_TRICOLOR_WIPE 55 #define FX_MODE_TRICOLOR_WIPE 55
@ -504,7 +504,7 @@ class WS2812FX {
_mode[FX_MODE_POLICE_ALL] = &WS2812FX::mode_police_all; _mode[FX_MODE_POLICE_ALL] = &WS2812FX::mode_police_all;
_mode[FX_MODE_TWO_DOTS] = &WS2812FX::mode_two_dots; _mode[FX_MODE_TWO_DOTS] = &WS2812FX::mode_two_dots;
_mode[FX_MODE_TWO_AREAS] = &WS2812FX::mode_two_areas; _mode[FX_MODE_TWO_AREAS] = &WS2812FX::mode_two_areas;
_mode[FX_MODE_CIRCUS_COMBUSTUS] = &WS2812FX::mode_circus_combustus; _mode[FX_MODE_RUNNING_DUAL] = &WS2812FX::mode_running_dual;
_mode[FX_MODE_HALLOWEEN] = &WS2812FX::mode_halloween; _mode[FX_MODE_HALLOWEEN] = &WS2812FX::mode_halloween;
_mode[FX_MODE_TRICOLOR_CHASE] = &WS2812FX::mode_tricolor_chase; _mode[FX_MODE_TRICOLOR_CHASE] = &WS2812FX::mode_tricolor_chase;
_mode[FX_MODE_TRICOLOR_WIPE] = &WS2812FX::mode_tricolor_wipe; _mode[FX_MODE_TRICOLOR_WIPE] = &WS2812FX::mode_tricolor_wipe;
@ -633,6 +633,7 @@ class WS2812FX {
getMainSegmentId(void), getMainSegmentId(void),
gamma8(uint8_t), gamma8(uint8_t),
gamma8_cal(uint8_t, float), gamma8_cal(uint8_t, float),
sin_gap(uint16_t),
get_random_wheel_index(uint8_t); get_random_wheel_index(uint8_t);
int8_t int8_t
@ -720,7 +721,7 @@ class WS2812FX {
mode_police_all(void), mode_police_all(void),
mode_two_dots(void), mode_two_dots(void),
mode_two_areas(void), mode_two_areas(void),
mode_circus_combustus(void), mode_running_dual(void),
mode_bicolor_chase(void), mode_bicolor_chase(void),
mode_tricolor_chase(void), mode_tricolor_chase(void),
mode_tricolor_wipe(void), mode_tricolor_wipe(void),
@ -818,7 +819,7 @@ class WS2812FX {
color_wipe(bool, bool), color_wipe(bool, bool),
dynamic(bool), dynamic(bool),
scan(bool), scan(bool),
running_base(bool), running_base(bool,bool),
larson_scanner(bool), larson_scanner(bool),
sinelon_base(bool,bool), sinelon_base(bool,bool),
dissolve(uint32_t), dissolve(uint32_t),
@ -872,7 +873,7 @@ const char JSON_mode_names[] PROGMEM = R"=====([
"Sparkle","Sparkle Dark","Sparkle+","Strobe","Strobe Rainbow","Strobe Mega","Blink Rainbow","Android","Chase","Chase Random", "Sparkle","Sparkle Dark","Sparkle+","Strobe","Strobe Rainbow","Strobe Mega","Blink Rainbow","Android","Chase","Chase Random",
"Chase Rainbow","Chase Flash","Chase Flash Rnd","Rainbow Runner","Colorful","Traffic Light","Sweep Random","Running 2","Aurora","Stream", "Chase Rainbow","Chase Flash","Chase Flash Rnd","Rainbow Runner","Colorful","Traffic Light","Sweep Random","Running 2","Aurora","Stream",
"Scanner","Lighthouse","Fireworks","Rain","Tetrix","Fire Flicker","Gradient","Loading","Police","Police All", "Scanner","Lighthouse","Fireworks","Rain","Tetrix","Fire Flicker","Gradient","Loading","Police","Police All",
"Two Dots","Two Areas","Circus","Halloween","Tri Chase","Tri Wipe","Tri Fade","Lightning","ICU","Multi Comet", "Two Dots","Two Areas","Running Dual","Halloween","Tri Chase","Tri Wipe","Tri Fade","Lightning","ICU","Multi Comet",
"Scanner Dual","Stream 2","Oscillate","Pride 2015","Juggle","Palette","Fire 2012","Colorwaves","Bpm","Fill Noise", "Scanner Dual","Stream 2","Oscillate","Pride 2015","Juggle","Palette","Fire 2012","Colorwaves","Bpm","Fill Noise",
"Noise 1","Noise 2","Noise 3","Noise 4","Colortwinkles","Lake","Meteor","Meteor Smooth","Railway","Ripple", "Noise 1","Noise 2","Noise 3","Noise 4","Colortwinkles","Lake","Meteor","Meteor Smooth","Railway","Ripple",
"Twinklefox","Twinklecat","Halloween Eyes","Solid Pattern","Solid Pattern Tri","Spots","Spots Fade","Glitter","Candle","Fireworks Starburst", "Twinklefox","Twinklecat","Halloween Eyes","Solid Pattern","Solid Pattern Tri","Spots","Spots Fade","Glitter","Candle","Fireworks Starburst",

View File

@ -207,7 +207,7 @@ void WS2812FX::setPixelColor(uint16_t i, byte r, byte g, byte b, byte w)
for (uint16_t j = 0; j < SEGMENT.grouping; j++) { for (uint16_t j = 0; j < SEGMENT.grouping; j++) {
uint16_t indexSet = realIndex + (IS_REVERSE ? -j : j); uint16_t indexSet = realIndex + (IS_REVERSE ? -j : j);
if (indexSet >= SEGMENT.start && indexSet < SEGMENT.stop) { // watch for group out of bounds condition if (indexSet >= SEGMENT.start && indexSet < SEGMENT.stop) {
if (IS_MIRROR) { //set the corresponding mirrored pixel if (IS_MIRROR) { //set the corresponding mirrored pixel
uint16_t indexMir = SEGMENT.stop + SEGMENT.start - indexSet - 1; uint16_t indexMir = SEGMENT.stop + SEGMENT.start - indexSet - 1;
if (indexMir < customMappingSize) indexMir = customMappingTable[indexMir]; if (indexMir < customMappingSize) indexMir = customMappingTable[indexMir];
@ -765,6 +765,12 @@ uint16_t WS2812FX::triwave16(uint16_t in)
return 0xFFFF - (in - 0x8000)*2; return 0xFFFF - (in - 0x8000)*2;
} }
uint8_t WS2812FX::sin_gap(uint16_t in) {
if (in & 0x100) return 0;
//if (in > 255) return 0;
return sin8(in + 192); //correct phase shift of sine so that it starts and stops at 0
}
/* /*
* Generates a tristate square wave w/ attac & decay * Generates a tristate square wave w/ attac & decay
* @param x input value 0-255 * @param x input value 0-255

View File

@ -4,6 +4,8 @@
* Physical IO * Physical IO
*/ */
#define WLED_DEBOUNCE_THRESHOLD 50 //only consider button input of at least 50ms as valid (debouncing)
void shortPressAction() void shortPressAction()
{ {
if (!macroButton) if (!macroButton)
@ -25,10 +27,42 @@ bool isButtonPressed()
} }
void handleSwitch()
{
if (buttonPressedBefore != isButtonPressed()) {
buttonPressedTime = millis();
buttonPressedBefore = !buttonPressedBefore;
}
if (buttonLongPressed == buttonPressedBefore) return;
if (millis() - buttonPressedTime > WLED_DEBOUNCE_THRESHOLD) { //fire edge event only after 50ms without change (debounce)
if (buttonPressedBefore) { //LOW, falling edge, switch closed
if (macroButton) applyPreset(macroButton);
else { //turn on
if (!bri) {toggleOnOff(); colorUpdated(NOTIFIER_CALL_MODE_BUTTON);}
}
} else { //HIGH, rising edge, switch opened
if (macroLongPress) applyPreset(macroLongPress);
else { //turn off
if (bri) {toggleOnOff(); colorUpdated(NOTIFIER_CALL_MODE_BUTTON);}
}
}
buttonLongPressed = buttonPressedBefore; //save the last "long term" switch state
}
}
void handleButton() void handleButton()
{ {
if (btnPin<0 || !buttonEnabled) return; if (btnPin<0 || buttonType < BTN_TYPE_PUSH) return;
if (buttonType == BTN_TYPE_SWITCH) { //button is not momentary, but switch. This is only suitable on pins whose on-boot state does not matter (NO gpio0)
handleSwitch(); return;
}
//momentary button logic
if (isButtonPressed()) //pressed if (isButtonPressed()) //pressed
{ {
if (!buttonPressedBefore) buttonPressedTime = millis(); if (!buttonPressedBefore) buttonPressedTime = millis();
@ -48,7 +82,7 @@ void handleButton()
else if (!isButtonPressed() && buttonPressedBefore) //released else if (!isButtonPressed() && buttonPressedBefore) //released
{ {
long dur = millis() - buttonPressedTime; long dur = millis() - buttonPressedTime;
if (dur < 50) {buttonPressedBefore = false; return;} //too short "press", debounce if (dur < WLED_DEBOUNCE_THRESHOLD) {buttonPressedBefore = false; return;} //too short "press", debounce
bool doublePress = buttonWaitTime; bool doublePress = buttonWaitTime;
buttonWaitTime = 0; buttonWaitTime = 0;

View File

@ -141,9 +141,9 @@ void deserializeConfig() {
if (hw_led["rev"]) busses.getBus(0)->reversed = true; //set 0.11 global reversed setting for first bus if (hw_led["rev"]) busses.getBus(0)->reversed = true; //set 0.11 global reversed setting for first bus
JsonObject hw_btn_ins_0 = hw[F("btn")][F("ins")][0]; JsonObject hw_btn_ins_0 = hw[F("btn")][F("ins")][0];
CJSON(buttonEnabled, hw_btn_ins_0["type"]); CJSON(buttonType, hw_btn_ins_0["type"]);
int hw_btn_pin = hw_btn_ins_0["pin"][0]; int hw_btn_pin = hw_btn_ins_0["pin"][0];
if (hw_btn_pin>=0 && pinManager.allocatePin(hw_btn_pin,false)) { if (pinManager.allocatePin(hw_btn_pin,false)) {
btnPin = hw_btn_pin; btnPin = hw_btn_pin;
pinMode(btnPin, INPUT_PULLUP); pinMode(btnPin, INPUT_PULLUP);
} else { } else {
@ -159,7 +159,7 @@ void deserializeConfig() {
#ifndef WLED_DISABLE_INFRARED #ifndef WLED_DISABLE_INFRARED
int hw_ir_pin = hw["ir"]["pin"] | -1; // 4 int hw_ir_pin = hw["ir"]["pin"] | -1; // 4
if (hw_ir_pin >=0 && pinManager.allocatePin(hw_ir_pin,false)) { if (pinManager.allocatePin(hw_ir_pin,false)) {
irPin = hw_ir_pin; irPin = hw_ir_pin;
} else { } else {
irPin = -1; irPin = -1;
@ -484,7 +484,7 @@ void serializeConfig() {
// button BTNPIN // button BTNPIN
JsonObject hw_btn_ins_0 = hw_btn_ins.createNestedObject(); JsonObject hw_btn_ins_0 = hw_btn_ins.createNestedObject();
hw_btn_ins_0["type"] = (buttonEnabled) ? BTN_TYPE_PUSH : BTN_TYPE_NONE; hw_btn_ins_0["type"] = buttonType;
JsonArray hw_btn_ins_0_pin = hw_btn_ins_0.createNestedArray("pin"); JsonArray hw_btn_ins_0_pin = hw_btn_ins_0.createNestedArray("pin");
hw_btn_ins_0_pin.add(btnPin); hw_btn_ins_0_pin.add(btnPin);

View File

@ -34,6 +34,7 @@
#define USERMOD_ID_AUTO_SAVE 9 //Usermod "usermod_v2_auto_save.h" #define USERMOD_ID_AUTO_SAVE 9 //Usermod "usermod_v2_auto_save.h"
#define USERMOD_ID_DHT 10 //Usermod "usermod_dht.h" #define USERMOD_ID_DHT 10 //Usermod "usermod_dht.h"
#define USERMOD_ID_MODE_SORT 11 //Usermod "usermod_v2_mode_sort.h" #define USERMOD_ID_MODE_SORT 11 //Usermod "usermod_v2_mode_sort.h"
#define USERMOD_ID_VL53L0X 12 //Usermod "usermod_vl53l0x_gestures.h"
//Access point behavior //Access point behavior
#define AP_BEHAVIOR_BOOT_NO_CONN 0 //Open AP when no connection after boot #define AP_BEHAVIOR_BOOT_NO_CONN 0 //Open AP when no connection after boot
@ -136,7 +137,7 @@
#define BTN_TYPE_RESERVED 1 #define BTN_TYPE_RESERVED 1
#define BTN_TYPE_PUSH 2 #define BTN_TYPE_PUSH 2
#define BTN_TYPE_PUSH_ACT_HIGH 3 //not implemented #define BTN_TYPE_PUSH_ACT_HIGH 3 //not implemented
#define BTN_TYPE_SWITCH 4 //not implemented #define BTN_TYPE_SWITCH 4
#define BTN_TYPE_SWITCH_ACT_HIGH 5 //not implemented #define BTN_TYPE_SWITCH_ACT_HIGH 5 //not implemented
//Ethernet board types //Ethernet board types

View File

@ -150,12 +150,12 @@ function loadBg(iUrl)
if (iUrl == "") { if (iUrl == "") {
var today = new Date(); var today = new Date();
var hol = [ var hol = [
[0,11,24,5,"https://aircoookie.github.io/xmas.png"], // christmas [0,11,24,4,"https://aircoookie.github.io/xmas.png"], // christmas
[0,2,17,1,"https://images.alphacoders.com/491/491123.jpg"], // st. Patrick's day [0,2,17,1,"https://images.alphacoders.com/491/491123.jpg"], // st. Patrick's day
[2022,3,16,3,"https://aircoookie.github.io/easter.png"], [2022,3,17,2,"https://aircoookie.github.io/easter.png"],
[2023,3,8,3,"https://aircoookie.github.io/easter.png"], [2023,3,9,2,"https://aircoookie.github.io/easter.png"],
[2024,2,30,3,"https://aircoookie.github.io/easter.png"] [2024,2,31,2,"https://aircoookie.github.io/easter.png"]
] ];
for (var i=0; i<hol.length; i++) { for (var i=0; i<hol.length; i++) {
var yr = hol[i][0]==0 ? today.getFullYear() : hol[i][0]; var yr = hol[i][0]==0 ? today.getFullYear() : hol[i][0];
var hs = new Date(yr,hol[i][1],hol[i][2]); var hs = new Date(yr,hol[i][1],hol[i][2]);

View File

@ -18,7 +18,12 @@ function GetV(){var d=document;}
</div> </div>
<h2>Sync setup</h2> <h2>Sync setup</h2>
<h3>Button setup</h3> <h3>Button setup</h3>
On/Off button enabled: <input type="checkbox" name="BT"><br> Button type:
<select name=BT>
<option value=0>Disabled</option>
<option value=2>Pushbutton</option>
<option value=4>Switch</option>
</select><br>
Infrared remote: Infrared remote:
<select name=IR> <select name=IR>
<option value=0>Disabled</option> <option value=0>Disabled</option>

View File

@ -27,7 +27,7 @@
ldS(); ldS();
} }
function check(o,k) { function check(o,k) {
var n = o.name.substr(-6); var n = o.name.replace("[]","").substr(-4);
if (o.type=="number" && n.substr(0,4)=="_pin") { if (o.type=="number" && n.substr(0,4)=="_pin") {
for (var i=0; i<pins.length; i++) { for (var i=0; i<pins.length; i++) {
if (k==pinO[i]) continue; if (k==pinO[i]) continue;

View File

@ -221,9 +221,10 @@ var d=document;function H(){window.open("https://github.com/Aircoookie/WLED/wiki
id="form_s" name="Sf" method="post"><div class="toprow"><div class="helpB"> id="form_s" name="Sf" method="post"><div class="toprow"><div class="helpB">
<button type="button" onclick="H()">?</button></div><button type="button" <button type="button" onclick="H()">?</button></div><button type="button"
onclick="B()">Back</button><button type="submit">Save</button><hr></div><h2> onclick="B()">Back</button><button type="submit">Save</button><hr></div><h2>
Sync setup</h2><h3>Button setup</h3>On/Off button enabled: <input Sync setup</h2><h3>Button setup</h3>Button type: <select name="BT"><option
type="checkbox" name="BT"><br>Infrared remote: <select name="IR"><option value="0">Disabled</option><option value="2">Pushbutton</option><option
value="0">Disabled</option><option value="1">24-key RGB</option><option value="4">Switch</option></select><br>Infrared remote: <select name="IR"><option
value="0">Disabled</option><option value="1">24-key RGB</option><option
value="2">24-key with CT</option><option value="3">40-key blue</option><option value="2">24-key with CT</option><option value="3">40-key blue</option><option
value="4">44-key RGB</option><option value="5">21-key RGB</option><option value="4">44-key RGB</option><option value="5">21-key RGB</option><option
value="6">6-key black</option><option value="7">9-key red</option></select><br> value="6">6-key black</option><option value="7">9-key red</option></select><br>

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,6 @@
#include "src/dependencies/timezone/Timezone.h" #include "src/dependencies/timezone/Timezone.h"
#include "wled.h" #include "wled.h"
#include "wled_math.h"
/* /*
* Acquires time from NTP server * Acquires time from NTP server
@ -316,8 +317,8 @@ void checkTimers()
// get sunrise (or sunset) time (in minutes) for a given day at a given geo location // 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) { int getSunriseUTC(int year, int month, int day, float lat, float lon, bool sunset=false) {
//1. first calculate the day of the year //1. first calculate the day of the year
float N1 = floor(275 * month / 9); float N1 = 275 * month / 9;
float N2 = floor((month + 9) / 12); float N2 = (month + 9) / 12;
float N3 = (1 + floor((year - 4 * floor(year / 4) + 2) / 3)); float N3 = (1 + floor((year - 4 * floor(year / 4) + 2) / 3));
float N = N1 - (N2 * N3) + day - 30; float N = N1 - (N2 * N3) + day - 30;
@ -329,10 +330,10 @@ int getSunriseUTC(int year, int month, int day, float lat, float lon, bool sunse
float M = (0.9856 * t) - 3.289; float M = (0.9856 * t) - 3.289;
//4. calculate the Sun's true longitude //4. calculate the Sun's true longitude
float L = fmod(M + (1.916 * sin(DEG_TO_RAD*M)) + (0.020 * sin(2*DEG_TO_RAD*M)) + 282.634, 360.0); float L = fmod(M + (1.916 * sin_t(DEG_TO_RAD*M)) + (0.020 * sin_t(2*DEG_TO_RAD*M)) + 282.634, 360.0);
//5a. calculate the Sun's right ascension //5a. calculate the Sun's right ascension
float RA = fmod(RAD_TO_DEG*atan(0.91764 * tan(DEG_TO_RAD*L)), 360.0); float RA = fmod(RAD_TO_DEG*atan_t(0.91764 * tan_t(DEG_TO_RAD*L)), 360.0);
//5b. right ascension value needs to be in the same quadrant as L //5b. right ascension value needs to be in the same quadrant as L
float Lquadrant = floor( L/90) * 90; float Lquadrant = floor( L/90) * 90;
@ -343,16 +344,16 @@ int getSunriseUTC(int year, int month, int day, float lat, float lon, bool sunse
RA /= 15.; RA /= 15.;
//6. calculate the Sun's declination //6. calculate the Sun's declination
float sinDec = 0.39782 * sin(DEG_TO_RAD*L); float sinDec = 0.39782 * sin_t(DEG_TO_RAD*L);
float cosDec = cos(asin(sinDec)); float cosDec = cos_t(asin_t(sinDec));
//7a. calculate the Sun's local hour angle //7a. calculate the Sun's local hour angle
float cosH = (sin(DEG_TO_RAD*ZENITH) - (sinDec * sin(DEG_TO_RAD*lat))) / (cosDec * cos(DEG_TO_RAD*lat)); float cosH = (sin_t(DEG_TO_RAD*ZENITH) - (sinDec * sin_t(DEG_TO_RAD*lat))) / (cosDec * cos_t(DEG_TO_RAD*lat));
if (cosH > 1 && !sunset) return 0; // the sun never rises on this location (on the specified date) if (cosH > 1 && !sunset) return 0; // the sun never rises on this location (on the specified date)
if (cosH < -1 && sunset) return 0; // the sun never sets on this location (on the specified date) if (cosH < -1 && sunset) return 0; // the sun never sets on this location (on the specified date)
//7b. finish calculating H and convert into hours //7b. finish calculating H and convert into hours
float H = sunset ? RAD_TO_DEG*acos(cosH) : 360 - RAD_TO_DEG*acos(cosH); float H = sunset ? RAD_TO_DEG*acos_t(cosH) : 360 - RAD_TO_DEG*acos_t(cosH);
H /= 15.; H /= 15.;
//8. calculate local mean time of rising/setting //8. calculate local mean time of rising/setting

View File

@ -197,7 +197,7 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
//SYNC //SYNC
if (subPage == 4) if (subPage == 4)
{ {
buttonEnabled = request->hasArg(F("BT")); buttonType = request->arg(F("BT")).toInt();
irEnabled = request->arg(F("IR")).toInt(); irEnabled = request->arg(F("IR")).toInt();
int t = request->arg(F("UP")).toInt(); int t = request->arg(F("UP")).toInt();
if (t > 0) udpPort = t; if (t > 0) udpPort = t;

View File

@ -45,6 +45,11 @@
#include "../usermods/DHT/usermod_dht.h" #include "../usermods/DHT/usermod_dht.h"
#endif #endif
#ifdef USERMOD_VL53L0X_GESTURES
#include <Wire.h> //it's needed here to correctly resolve dependencies
#include "../usermods/VL53L0X_gestures/usermod_vl53l0x_gestures.h"
#endif
void registerUsermods() void registerUsermods()
{ {
/* /*
@ -87,4 +92,8 @@ void registerUsermods()
#ifdef USERMOD_DHT #ifdef USERMOD_DHT
usermods.add(new UsermodDHT()); usermods.add(new UsermodDHT());
#endif #endif
#ifdef USERMOD_VL53L0X_GESTURES
usermods.add(new UsermodVL53L0XGestures());
#endif
} }

View File

@ -239,7 +239,7 @@ void WLED::loop()
lastMqttReconnectAttempt = 0; lastMqttReconnectAttempt = 0;
} }
if (millis() - lastMqttReconnectAttempt > 30000) { if (millis() - lastMqttReconnectAttempt > 30000) {
lastMqttReconnectAttempt = millis(); // don't do it in initMqtt() since MQTT may be disabled lastMqttReconnectAttempt = millis();
initMqtt(); initMqtt();
yield(); yield();
// refresh WLED nodes list // refresh WLED nodes list
@ -441,7 +441,8 @@ void WLED::beginStrip()
if (rlyPin>=0) digitalWrite(rlyPin, (bri ? rlyMde : !rlyMde)); if (rlyPin>=0) digitalWrite(rlyPin, (bri ? rlyMde : !rlyMde));
// disable button if it is "pressed" unintentionally // disable button if it is "pressed" unintentionally
if (btnPin>=0 && isButtonPressed()) buttonEnabled = false; if (btnPin>=0 && buttonType == BTN_TYPE_PUSH && isButtonPressed())
buttonType = BTN_TYPE_NONE;
} }
void WLED::initAP(bool resetAP) void WLED::initAP(bool resetAP)

View File

@ -8,7 +8,7 @@
*/ */
// version code in format yymmddb (b = daily build) // version code in format yymmddb (b = daily build)
#define VERSION 2104121 #define VERSION 2104141
//uncomment this if you have a "my_config.h" file you'd like to use //uncomment this if you have a "my_config.h" file you'd like to use
//#define WLED_USE_MY_CONFIG //#define WLED_USE_MY_CONFIG
@ -182,12 +182,12 @@ WLED_GLOBAL char otaPass[33] _INIT(DEFAULT_OTA_PASS);
// Hardware CONFIG (only changeble HERE, not at runtime) // Hardware CONFIG (only changeble HERE, not at runtime)
// LED strip pin, button pin and IR pin changeable in NpbWrapper.h! // LED strip pin, button pin and IR pin changeable in NpbWrapper.h!
#ifndef BTNPIN #ifndef BTNPIN
WLED_GLOBAL int8_t btnPin _INIT(-1); WLED_GLOBAL int8_t btnPin _INIT(0);
#else #else
WLED_GLOBAL int8_t btnPin _INIT(BTNPIN); WLED_GLOBAL int8_t btnPin _INIT(BTNPIN);
#endif #endif
#ifndef RLYPIN #ifndef RLYPIN
WLED_GLOBAL int8_t rlyPin _INIT(-1); WLED_GLOBAL int8_t rlyPin _INIT(12);
#else #else
WLED_GLOBAL int8_t rlyPin _INIT(RLYPIN); WLED_GLOBAL int8_t rlyPin _INIT(RLYPIN);
#endif #endif
@ -198,7 +198,7 @@ WLED_GLOBAL bool rlyMde _INIT(true);
WLED_GLOBAL bool rlyMde _INIT(RLYMDE); WLED_GLOBAL bool rlyMde _INIT(RLYMDE);
#endif #endif
#ifndef IRPIN #ifndef IRPIN
WLED_GLOBAL int8_t irPin _INIT(-1); WLED_GLOBAL int8_t irPin _INIT(4);
#else #else
WLED_GLOBAL int8_t irPin _INIT(IRPIN); WLED_GLOBAL int8_t irPin _INIT(IRPIN);
#endif #endif
@ -253,7 +253,7 @@ WLED_GLOBAL NodesMap Nodes;
WLED_GLOBAL bool nodeListEnabled _INIT(true); WLED_GLOBAL bool nodeListEnabled _INIT(true);
WLED_GLOBAL bool nodeBroadcastEnabled _INIT(true); WLED_GLOBAL bool nodeBroadcastEnabled _INIT(true);
WLED_GLOBAL bool buttonEnabled _INIT(true); WLED_GLOBAL byte buttonType _INIT(BTN_TYPE_PUSH);
WLED_GLOBAL byte irEnabled _INIT(0); // Infrared receiver WLED_GLOBAL byte irEnabled _INIT(0); // Infrared receiver
WLED_GLOBAL uint16_t udpPort _INIT(21324); // WLED notifier default port WLED_GLOBAL uint16_t udpPort _INIT(21324); // WLED notifier default port

View File

@ -93,7 +93,7 @@ void loadSettingsFromEEPROM()
notifyButton = EEPROM.read(230); notifyButton = EEPROM.read(230);
notifyTwice = EEPROM.read(231); notifyTwice = EEPROM.read(231);
buttonEnabled = EEPROM.read(232); buttonType = EEPROM.read(232) ? BTN_TYPE_PUSH : BTN_TYPE_NONE;
staticIP[0] = EEPROM.read(234); staticIP[0] = EEPROM.read(234);
staticIP[1] = EEPROM.read(235); staticIP[1] = EEPROM.read(235);

71
wled00/wled_math.h Normal file
View File

@ -0,0 +1,71 @@
#ifndef WLED_MATH_H
#define WLED_MATH_H
/*
* Contains some trigonometric functions.
* The ANSI C equivalents are likely faster, but using any sin/cos/tan function incurs a memory penalty of 460 bytes on ESP8266, likely for lookup tables.
* This implementation has no extra static memory usage.
*
* Source of the cos_t() function: https://web.eecs.utk.edu/~azh/blog/cosine.html (cos_taylor_literal_6terms)
*/
#include <Arduino.h> //PI constant
#define modd(x, y) ((x) - (int)((x) / (y)) * (y))
double cos_t(double x)
{
x = modd(x, TWO_PI);
char sign = 1;
if (x > PI)
{
x -= PI;
sign = -1;
}
double xx = x * x;
return sign * (1 - ((xx) / (2)) + ((xx * xx) / (24)) - ((xx * xx * xx) / (720)) + ((xx * xx * xx * xx) / (40320)) - ((xx * xx * xx * xx * xx) / (3628800)) + ((xx * xx * xx * xx * xx * xx) / (479001600)));
}
double sin_t(double x) {
return cos_t(HALF_PI - x);
}
double tan_t(double x) {
double c = cos_t(x);
if (c==0.0) return 0;
return sin_t(x) / c;
}
//https://stackoverflow.com/questions/3380628
// Absolute error <= 6.7e-5
float acos_t(float x) {
float negate = float(x < 0);
x = std::abs(x);
float ret = -0.0187293;
ret = ret * x;
ret = ret + 0.0742610;
ret = ret * x;
ret = ret - 0.2121144;
ret = ret * x;
ret = ret + HALF_PI;
ret = ret * sqrt(1.0-x);
ret = ret - 2 * negate * ret;
return negate * PI + ret;
}
float asin_t(float x) {
return HALF_PI - acos_t(x);
}
//https://stackoverflow.com/a/42542593
#define A 0.0776509570923569
#define B -0.287434475393028
#define C ((HALF_PI/2) - A - B)
double atan_t(double x) {
double xx = x * x;
return ((A*xx + B)*xx + C)*x;
}
#endif

View File

@ -394,7 +394,7 @@ void getSettingsJS(byte subPage, char* dest)
if (subPage == 4) if (subPage == 4)
{ {
sappend('c',SET_F("BT"),buttonEnabled); sappend('v',SET_F("BT"),buttonType);
sappend('v',SET_F("IR"),irEnabled); sappend('v',SET_F("IR"),irEnabled);
sappend('v',SET_F("UP"),udpPort); sappend('v',SET_F("UP"),udpPort);
sappend('v',SET_F("U2"),udpPort2); sappend('v',SET_F("U2"),udpPort2);