Merge remote-tracking branch 'origin/master' into codegen-html
This commit is contained in:
commit
00f00b8198
Binary file not shown.
27
CHANGELOG.md
27
CHANGELOG.md
@ -2,6 +2,33 @@
|
||||
|
||||
### Development versions after 0.10.0 release
|
||||
|
||||
#### Build 2006060
|
||||
|
||||
- Added five effects by Andrew Tuline (Phased, Phased Noise, Sine, Noise Pal and Twinkleup)
|
||||
- Added two new effects by Aircoookie (Sunrise and Flow)
|
||||
- Added US-style sequence to traffic light effect
|
||||
- Merged pull request #964 adding 9 key IR remote
|
||||
|
||||
#### Build 2005280
|
||||
|
||||
- Added v2 usermod API
|
||||
- Added v2 example usermod `usermod_v2_example` in the usermods folder as prelimary documentation
|
||||
- Added DS18B20 Temperature usermod with Info page support
|
||||
- Disabled MQTT on ESP01 build to make room in flash
|
||||
|
||||
#### Build 2005230
|
||||
|
||||
- Fixed TPM2
|
||||
|
||||
#### Build 2005220
|
||||
|
||||
- Added TPM2.NET protocol support (need to set WLED broadcast UDP port to 65506)
|
||||
- Added TPM2 protocol support via Serial
|
||||
- Support up to 6553 seconds preset cycle durations (backend, NOT yet in UI)
|
||||
- Merged pull request #591 fixing WS2801 color order
|
||||
- Merged pull request #858 adding fully featured travis builds
|
||||
- Merged pull request #862 adding DMX proxy feature
|
||||
|
||||
#### Build 2005100
|
||||
|
||||
- Update to Espalexa v2.4.6 (+1.6kB free heap memory)
|
||||
|
BIN
images/macbook-pro-space-gray-on-the-wooden-table.webp
Normal file
BIN
images/macbook-pro-space-gray-on-the-wooden-table.webp
Normal file
Binary file not shown.
After Width: | Height: | Size: 284 KiB |
BIN
images/walking-with-iphone-x.webp
Normal file
BIN
images/walking-with-iphone-x.webp
Normal file
Binary file not shown.
After Width: | Height: | Size: 155 KiB |
Before Width: | Height: | Size: 46 KiB After Width: | Height: | Size: 46 KiB |
@ -74,6 +74,8 @@ arduino_core_develop = https://github.com/platformio/platform-espressif8266#deve
|
||||
arduino_core_git = https://github.com/platformio/platform-espressif8266#feature/stage
|
||||
|
||||
# Platform to use for ESP8266
|
||||
platform_wled_default = ${common.arduino_core_2_7_1}
|
||||
# We use 2.7.0+ on analog boards because of PWM flicker fix
|
||||
platform_latest = ${common.arduino_core_2_7_1}
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
@ -165,6 +167,8 @@ lib_deps =
|
||||
AsyncTCP@1.0.3
|
||||
Esp Async WebServer@1.2.0
|
||||
IRremoteESP8266@2.7.3
|
||||
#For use of the TTGO T-Display ESP32 Module with integrated TFT display uncomment the following line
|
||||
#TFT_eSPI
|
||||
#For use SSD1306 OLED display uncomment following
|
||||
#U8g2@~2.27.2
|
||||
#For Dallas sensor uncomment following 2 lines
|
||||
@ -180,51 +184,51 @@ lib_ignore =
|
||||
|
||||
[env:nodemcuv2]
|
||||
board = nodemcuv2
|
||||
platform = ${common.platform_latest}
|
||||
platform = ${common.platform_wled_default}
|
||||
board_build.ldscript = ${common.ldscript_4m1m}
|
||||
build_flags = ${common.build_flags_esp8266}
|
||||
|
||||
[env:esp01]
|
||||
board = esp01
|
||||
platform = ${common.platform_latest}
|
||||
platform = ${common.platform_wled_default}
|
||||
board_build.ldscript = ${common.ldscript_512k}
|
||||
build_flags = ${common.build_flags_esp8266} -D WLED_DISABLE_OTA -D WLED_DISABLE_ALEXA -D WLED_DISABLE_BLYNK
|
||||
-D WLED_DISABLE_CRONIXIE -D WLED_DISABLE_HUESYNC -D WLED_DISABLE_INFRARED
|
||||
-D WLED_DISABLE_CRONIXIE -D WLED_DISABLE_HUESYNC -D WLED_DISABLE_INFRARED -D WLED_DISABLE_MQTT
|
||||
|
||||
[env:esp01_1m_ota]
|
||||
board = esp01_1m
|
||||
platform = ${common.platform_latest}
|
||||
platform = ${common.platform_wled_default}
|
||||
board_build.ldscript = ${common.ldscript_1m0m}
|
||||
build_flags = ${common.build_flags_esp8266} -D WLED_DISABLE_ALEXA -D WLED_DISABLE_BLYNK -D WLED_DISABLE_CRONIXIE -D WLED_DISABLE_HUESYNC -D WLED_DISABLE_INFRARED
|
||||
build_flags = ${common.build_flags_esp8266} -D WLED_DISABLE_ALEXA -D WLED_DISABLE_BLYNK -D WLED_DISABLE_CRONIXIE -D WLED_DISABLE_HUESYNC -D WLED_DISABLE_INFRARED -D WLED_DISABLE_MQTT
|
||||
|
||||
[env:esp01_1m_full]
|
||||
board = esp01_1m
|
||||
platform = ${common.platform_latest}
|
||||
platform = ${common.platform_wled_default}
|
||||
board_build.ldscript = ${common.ldscript_1m0m}
|
||||
build_flags = ${common.build_flags_esp8266} -D WLED_DISABLE_OTA
|
||||
|
||||
[env:esp07]
|
||||
board = esp07
|
||||
platform = ${common.platform_latest}
|
||||
platform = ${common.platform_wled_default}
|
||||
board_build.ldscript = ${common.ldscript_4m1m}
|
||||
build_flags = ${common.build_flags_esp8266}
|
||||
|
||||
[env:d1_mini]
|
||||
board = d1_mini
|
||||
platform = ${common.platform_latest}
|
||||
upload_speed = 921500
|
||||
platform = ${common.platform_wled_default}
|
||||
upload_speed = 921600
|
||||
board_build.ldscript = ${common.ldscript_4m1m}
|
||||
build_flags = ${common.build_flags_esp8266}
|
||||
|
||||
[env:heltec_wifi_kit_8]
|
||||
board = d1_mini
|
||||
platform = ${common.platform_latest}
|
||||
platform = ${common.platform_wled_default}
|
||||
board_build.ldscript = ${common.ldscript_4m1m}
|
||||
build_flags = ${common.build_flags_esp8266}
|
||||
|
||||
[env:h803wf]
|
||||
board = d1_mini
|
||||
platform = ${common.platform_latest}
|
||||
platform = ${common.platform_wled_default}
|
||||
board_build.ldscript = ${common.ldscript_4m1m}
|
||||
build_flags = ${common.build_flags_esp8266} -D LEDPIN=1 -D WLED_DISABLE_INFRARED
|
||||
|
||||
@ -267,7 +271,7 @@ build_flags = ${common.build_flags_esp8266} -D WLED_USE_ANALOG_LEDS -D WLED_USE_
|
||||
[env:d1_mini_debug]
|
||||
board = d1_mini
|
||||
build_type = debug
|
||||
platform = ${common.platform_latest}
|
||||
platform = ${common.platform_wled_default}
|
||||
board_build.ldscript = ${common.ldscript_4m1m}
|
||||
build_flags = ${common.build_flags_esp8266} ${common.debug_flags}
|
||||
|
||||
@ -276,7 +280,7 @@ board = d1_mini
|
||||
upload_protocol = espota
|
||||
# exchange for your WLED IP
|
||||
upload_port = "10.10.1.27"
|
||||
platform = ${common.platform_latest}
|
||||
platform = ${common.platform_wled_default}
|
||||
board_build.ldscript = ${common.ldscript_4m1m}
|
||||
build_flags = ${common.build_flags_esp8266}
|
||||
|
||||
|
50
readme.md
50
readme.md
@ -1,16 +1,17 @@
|
||||
![WLED logo](https://raw.githubusercontent.com/Aircoookie/WLED/master/wled_logo.png)
|
||||
<p align="center">
|
||||
<img src="/images/wled_logo.png">
|
||||
<a href="https://github.com/Aircoookie/WLED/releases"><img src="https://img.shields.io/github/release/Aircoookie/WLED.svg?style=flat-square"></a>
|
||||
<a href="https://wled.discourse.group"><img src="https://img.shields.io/discourse/topics?colorB=blue&label=forum&server=https%3A%2F%2Fwled.discourse.group%2F&style=flat-square"></a>
|
||||
<a href="https://discord.gg/KuqP7NE"><img src="https://img.shields.io/discord/473448917040758787.svg?colorB=blue&label=discord&style=flat-square"></a>
|
||||
<a href="https://github.com/Aircoookie/WLED/wiki"><img src="https://img.shields.io/badge/quick_start-wiki-blue.svg?style=flat-square"></a>
|
||||
<a href="https://github.com/Aircoookie/WLED-App"><img src="https://img.shields.io/badge/app-wled-blue.svg?style=flat-square"></a>
|
||||
</p>
|
||||
|
||||
[![](https://img.shields.io/github/release/Aircoookie/WLED.svg?style=flat-square)](https://github.com/Aircoookie/WLED/releases)
|
||||
[![](https://img.shields.io/discourse/topics?colorB=blue&label=forum&server=https%3A%2F%2Fwled.discourse.group%2F&style=flat-square)](https://wled.discourse.group)
|
||||
[![](https://img.shields.io/discord/473448917040758787.svg?colorB=blue&label=discord&style=flat-square)](https://discord.gg/KuqP7NE)
|
||||
[![](https://img.shields.io/badge/quick_start-wiki-blue.svg?style=flat-square)](https://github.com/Aircoookie/WLED/wiki)
|
||||
[![](https://img.shields.io/badge/app-wled-blue.svg?style=flat-square)](https://github.com/Aircoookie/WLED-App)
|
||||
# 👋 Welcome to my project WLED!
|
||||
|
||||
## Welcome to my project WLED!
|
||||
A fast and feature-rich implementation of an ESP8266/ESP32 webserver to control NeoPixel (WS2812B, WS2811, SK6812, APA102) LEDs or also SPI based chipsets like the WS2801!
|
||||
|
||||
A fast and feature-rich implementation of an ESP8266/ESP32 webserver to control NeoPixel (WS2812B, WS2811, SK6812, APA102) LEDs!
|
||||
|
||||
### Features:
|
||||
## ⚙️ Features
|
||||
- WS2812FX library integrated for over 100 special effects
|
||||
- FastLED noise effects and 50 palettes
|
||||
- Modern UI with color, effect and segment controls
|
||||
@ -25,7 +26,7 @@ A fast and feature-rich implementation of an ESP8266/ESP32 webserver to control
|
||||
- Configurable analog clock + support for the Cronixie kit by Diamex
|
||||
- Configurable Auto Brightness limit for safer operation
|
||||
|
||||
### Supported light control interfaces:
|
||||
## 💡 Supported light control interfaces
|
||||
- WLED app for Android and iOS
|
||||
- JSON and HTTP request APIs
|
||||
- MQTT
|
||||
@ -40,7 +41,7 @@ A fast and feature-rich implementation of an ESP8266/ESP32 webserver to control
|
||||
- Infrared remotes (24-key RGB, receiver required)
|
||||
- Simple timers/schedules (time from NTP, timezones/DST supported)
|
||||
|
||||
### Quick start guide and documentation:
|
||||
## 📲 Quick start guide and documentation
|
||||
|
||||
See the [wiki](https://github.com/Aircoookie/WLED/wiki)!
|
||||
|
||||
@ -54,18 +55,39 @@ Russian speakers, check out the videos by Room31:
|
||||
[WLED Firmware Overview: Interface and Settings](https://youtu.be/h7lKsczEI7E)
|
||||
[ESP8266 based LED controller for WS2812b strip. WLED Firmware + OpenHAB](https://youtu.be/K4ioTt3XvGc)
|
||||
|
||||
### Other
|
||||
## 🖼️ Images
|
||||
<img src="/images/macbook-pro-space-gray-on-the-wooden-table.webp" width="50%"><img src="/images/walking-with-iphone-x.webp" width="50%">
|
||||
|
||||
## 💾 Compatible LED Strips
|
||||
Type | Voltage | Comments
|
||||
|---|---|---|
|
||||
WS2812B | 5v |
|
||||
WS2813 | 5v |
|
||||
SK6812 | 5v | RGBW
|
||||
APA102 | 5v | C/D
|
||||
WS2801 | 5v | C/D
|
||||
LPD8806 | 5v | C/D
|
||||
TM1814 | 12v | RGBW
|
||||
WS2811 | 12v | 3-LED segments
|
||||
WS2815 | 12v |
|
||||
GS8208 | 12v |
|
||||
|
||||
## ✌️ Other
|
||||
|
||||
Licensed under the MIT license
|
||||
Credits [here](https://github.com/Aircoookie/WLED/wiki/Contributors-&-About)!
|
||||
|
||||
Uses Linearicons by Perxis!
|
||||
|
||||
Join the Discord [server](https://discord.gg/KuqP7NE) to discuss everything about WLED!
|
||||
Join the Discord server to discuss everything about WLED!
|
||||
|
||||
[![WLED Discord](https://discordapp.com/api/guilds/473448917040758787/widget.png?style=banner2)](https://discord.gg/KuqP7NE)
|
||||
|
||||
Check out the WLED [Discourse forum](https://wled.discourse.group)!
|
||||
You can also send me mails to [dev.aircoookie@gmail.com](mailto:dev.aircoookie@gmail.com), but please only do so if you want to talk to me privately.
|
||||
If WLED really brightens up your every day, you can [![](https://img.shields.io/badge/send%20me%20a%20small%20gift-paypal-blue.svg?style=flat-square)](https://paypal.me/aircoookie)
|
||||
|
||||
|
||||
*Disclaimer:*
|
||||
If you are sensitive to photoeleptic seizures it is not recommended that you use this software.
|
||||
In case you still want to try, don't use strobe, lighting or noise modes or high effect speed settings.
|
||||
|
10
usermods/EXAMPLE_v2/readme.md
Normal file
10
usermods/EXAMPLE_v2/readme.md
Normal file
@ -0,0 +1,10 @@
|
||||
# Usermods API v2 example usermod
|
||||
|
||||
In this usermod file you can find the documentation on how to take advantage of the new version 2 usermods!
|
||||
|
||||
## Installation
|
||||
|
||||
Copy `usermod_v2_example.h` to the wled00 directory.
|
||||
Uncomment the corresponding lines in `usermods_list.h` and compile!
|
||||
_(You shouldn't need to actually install this, it does nothing useful)_
|
||||
|
119
usermods/EXAMPLE_v2/usermod_v2_example.h
Normal file
119
usermods/EXAMPLE_v2/usermod_v2_example.h
Normal file
@ -0,0 +1,119 @@
|
||||
#pragma once
|
||||
|
||||
#include "wled.h"
|
||||
|
||||
/*
|
||||
* Usermods allow you to add own functionality to WLED more easily
|
||||
* See: https://github.com/Aircoookie/WLED/wiki/Add-own-functionality
|
||||
*
|
||||
* This is an example for a v2 usermod.
|
||||
* v2 usermods are class inheritance based and can (but don't have to) implement more functions, each of them is shown in this example.
|
||||
* Multiple v2 usermods can be added to one compilation easily.
|
||||
*
|
||||
* Creating a usermod:
|
||||
* This file serves as an example. If you want to create a usermod, it is recommended to use usermod_v2_empty.h from the usermods folder as a template.
|
||||
* Please remember to rename the class and file to a descriptive name.
|
||||
* You may also use multiple .h and .cpp files.
|
||||
*
|
||||
* Using a usermod:
|
||||
* 1. Copy the usermod into the sketch folder (same folder as wled00.ino)
|
||||
* 2. Register the usermod by adding #include "usermod_filename.h" in the top and registerUsermod(new MyUsermodClass()) in the bottom of usermods_list.cpp
|
||||
*/
|
||||
|
||||
//class name. Use something descriptive and leave the ": public Usermod" part :)
|
||||
class MyExampleUsermod : public Usermod {
|
||||
private:
|
||||
//Private class members. You can declare variables and functions only accessible to your usermod here
|
||||
unsigned long lastTime = 0;
|
||||
public:
|
||||
//Functions called by WLED
|
||||
|
||||
/*
|
||||
* setup() is called once at boot. WiFi is not yet connected at this point.
|
||||
* You can use it to initialize variables, sensors or similar.
|
||||
*/
|
||||
void setup() {
|
||||
//Serial.println("Hello from my usermod!");
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* connected() is called every time the WiFi is (re)connected
|
||||
* Use it to initialize network interfaces
|
||||
*/
|
||||
void connected() {
|
||||
//Serial.println("Connected to WiFi!");
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* loop() is called continuously. Here you can check for events, read sensors, etc.
|
||||
*
|
||||
* Tips:
|
||||
* 1. You can use "if (WLED_CONNECTED)" to check for a successful network connection.
|
||||
* Additionally, "if (WLED_MQTT_CONNECTED)" is available to check for a connection to an MQTT broker.
|
||||
*
|
||||
* 2. Try to avoid using the delay() function. NEVER use delays longer than 10 milliseconds.
|
||||
* Instead, use a timer check as shown here.
|
||||
*/
|
||||
void loop() {
|
||||
if (millis() - lastTime > 1000) {
|
||||
//Serial.println("I'm alive!");
|
||||
lastTime = millis();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* addToJsonInfo() can be used to add custom entries to the /json/info part of the JSON API.
|
||||
* Creating an "u" object allows you to add custom key/value pairs to the Info section of the WLED web UI.
|
||||
* Below it is shown how this could be used for e.g. a light sensor
|
||||
*/
|
||||
/*
|
||||
void addToJsonInfo(JsonObject& root)
|
||||
{
|
||||
int reading = 20;
|
||||
//this code adds "u":{"Light":[20," lux"]} to the info object
|
||||
JsonObject user = root["u"];
|
||||
if (user.isNull()) user = root.createNestedObject("u");
|
||||
|
||||
JsonArray lightArr = user.createNestedArray("Light"); //name
|
||||
lightArr.add(reading); //value
|
||||
lightArr.add(" lux"); //unit
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* addToJsonState() can be used to add custom entries to the /json/state part of the JSON API (state object).
|
||||
* Values in the state object may be modified by connected clients
|
||||
*/
|
||||
void addToJsonState(JsonObject& root)
|
||||
{
|
||||
//root["user0"] = userVar0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* readFromJsonState() can be used to receive data clients send to the /json/state part of the JSON API (state object).
|
||||
* Values in the state object may be modified by connected clients
|
||||
*/
|
||||
void readFromJsonState(JsonObject& root)
|
||||
{
|
||||
userVar0 = root["user0"] | userVar0; //if "user0" key exists in JSON, update, else keep old value
|
||||
//if (root["bri"] == 255) Serial.println(F("Don't burn down your garage!"));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* 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_EXAMPLE;
|
||||
}
|
||||
|
||||
//More methods can be added in the future, this example will then be extended.
|
||||
//Your usermod will remain compatible as it does not need to implement all methods from the Usermod base class!
|
||||
};
|
17
usermods/Fix_unreachable_webserver/readme.md
Normal file
17
usermods/Fix_unreachable_webserver/readme.md
Normal file
@ -0,0 +1,17 @@
|
||||
# Fix unreachable Webserver
|
||||
|
||||
This modification performs a ping request to the local IP address every 60 seconds. By this procedure the web server remains accessible in some problematic WLAN environments.
|
||||
|
||||
The modification works with static or DHCP IP address configuration
|
||||
|
||||
_Story:_
|
||||
|
||||
Unfortunately, with all ESP projects where a web server or other network services are running, I have the problem that after some time the web server is no longer accessible. Now I found out that the connection is at least reestablished when a ping request is executed by the device.
|
||||
|
||||
With this modification, in the worst case, the network functions are not available for 60 seconds until the next ping request.
|
||||
|
||||
## Installation
|
||||
|
||||
Copy and replace the file `usermod.cpp` in wled00 directory.
|
||||
|
||||
|
43
usermods/Fix_unreachable_webserver/usermod.cpp
Normal file
43
usermods/Fix_unreachable_webserver/usermod.cpp
Normal file
@ -0,0 +1,43 @@
|
||||
#include "wled.h"
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#include <ping.h>
|
||||
|
||||
const int PingDelayMs = 60000;
|
||||
long lastCheckTime = 0;
|
||||
bool connectedWiFi = false;
|
||||
ping_option pingOpt;
|
||||
|
||||
//Use userVar0 and userVar1 (API calls &U0=,&U1=, uint16_t)
|
||||
|
||||
//gets called once at boot. Do all initialization that doesn't depend on network here
|
||||
void userSetup()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
//gets called every time WiFi is (re-)connected. Initialize own network interfaces here
|
||||
void userConnected()
|
||||
{
|
||||
connectedWiFi = true;
|
||||
// initialize ping_options structure
|
||||
memset(&pingOpt, 0, sizeof(struct ping_option));
|
||||
pingOpt.count = 1;
|
||||
pingOpt.ip = WiFi.localIP();
|
||||
}
|
||||
|
||||
//loop. You can use "if (WLED_CONNECTED)" to check for successful connection
|
||||
void userLoop()
|
||||
{
|
||||
if (connectedWiFi && millis()-lastCheckTime > PingDelayMs)
|
||||
{
|
||||
ping_start(&pingOpt);
|
||||
lastCheckTime = millis();
|
||||
}
|
||||
}
|
77
usermods/TTGO-T-Display/README.md
Normal file
77
usermods/TTGO-T-Display/README.md
Normal file
@ -0,0 +1,77 @@
|
||||
# TTGO T-Display ESP32 with 240x135 TFT via SPI with TFT_eSPI
|
||||
This usermod allows use of the TTGO T-Display ESP32 module with integrated 240x135 display
|
||||
for controlling WLED and showing the following information:
|
||||
* Current SSID
|
||||
* IP address if obtained
|
||||
* in AP mode and turned off lightning AP password is shown
|
||||
* Current effect
|
||||
* Current palette
|
||||
|
||||
Usermod based on a rework of the ssd1306_i2c_oled_u8g2 usermod from the WLED repo.
|
||||
|
||||
## Hardware
|
||||
![Hardware](assets/ttgo_hardware1.png)
|
||||
|
||||
## Github reference for TTGO-Tdisplay
|
||||
|
||||
* [TTGO T-Display](https://github.com/Xinyuan-LilyGO/TTGO-T-Display)
|
||||
|
||||
## Requirements
|
||||
Functionality checked with:
|
||||
* TTGO T-Display
|
||||
* PlatformIO
|
||||
* Group of 4 individual Neopixels from Adafruit, and a full string of 68 LEDs.
|
||||
|
||||
## Platformio Requirements
|
||||
### Platformio.ini changes
|
||||
Under the root folder of the project, in the `platformio.ini` file, uncomment the `TFT_eSPI` line within the [common] section, under `lib_deps`:
|
||||
```ini
|
||||
# platformio.ini
|
||||
...
|
||||
[common]
|
||||
...
|
||||
lib_deps =
|
||||
...
|
||||
#For use of the TTGO T-Display ESP32 Module with integrated TFT display uncomment the following line
|
||||
#TFT_eSPI
|
||||
...
|
||||
```
|
||||
|
||||
Also, while in the `platformio.ini` file, you must change the environment setup to build for just the esp32dev platform as follows:
|
||||
|
||||
Comment out the line described below:
|
||||
```ini
|
||||
# Travis CI binaries (comment this out when building for single board)
|
||||
; default_envs = travis_esp8266, esp01, esp01_1m_ota, travis_esp32
|
||||
```
|
||||
and UNCOMMENT the following line in the 'Single binaries' section:
|
||||
```ini
|
||||
default_envs = esp32dev
|
||||
```
|
||||
Save the `platformio.ini` file. Once this is saved, the required library files should be automatically downloaded for modifications in a later step.
|
||||
|
||||
### Platformio_overrides.ini (added)
|
||||
Copy the `platformio_overrides.ini` file which is contained in the `usermods/TTGO-T-Display/` folder into the root of your project folder. This file contains an override that remaps the button pin of WLED to use the on-board button to the right of the USB-C connector (when viewed with the port oriented downward - see hardware photo).
|
||||
|
||||
### TFT_eSPI Library Adjustments (board selection)
|
||||
We need to modify a file in the `TFT_eSPI` library to select the correct board. If you followed the directions to modify and save the `platformio.ini` file above, the `User_Setup_Select.h` file can be found in the `/.pio/libdeps/esp32dev/TFT_eSPI_ID1559` folder.
|
||||
|
||||
Modify the `User_Setup_Select.h` file as follows:
|
||||
* Comment out the following line (which is the 'default' setup file):
|
||||
```ini
|
||||
//#include <User_Setup.h> // Default setup is root library folder
|
||||
```
|
||||
* Uncomment the following line (which points to the setup file for the TTGO T-Display):
|
||||
```ini
|
||||
#include <User_Setups/Setup25_TTGO_T_Display.h> // Setup file for ESP32 and TTGO T-Display ST7789V SPI bus TFT
|
||||
```
|
||||
|
||||
Run the build and it should complete correctly. If you see a failure like this:
|
||||
```ini
|
||||
xtensa-esp32-elf-g++: error: wled00\wled00.ino.cpp: No such file or directory
|
||||
xtensa-esp32-elf-g++: fatal error: no input files
|
||||
```
|
||||
Just try building again - I find that sometimes this happens on the first build attempt and subsequent attempts will build correctly.
|
||||
|
||||
## Arduino IDE
|
||||
- UNTESTED
|
BIN
usermods/TTGO-T-Display/assets/ttgo_hardware1.png
Normal file
BIN
usermods/TTGO-T-Display/assets/ttgo_hardware1.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 686 KiB |
8
usermods/TTGO-T-Display/platformio_override.ini
Normal file
8
usermods/TTGO-T-Display/platformio_override.ini
Normal file
@ -0,0 +1,8 @@
|
||||
[env:esp32dev]
|
||||
build_flags = ${common.build_flags_esp32}
|
||||
; PIN defines - uncomment and change, if needed:
|
||||
; -D LEDPIN=2
|
||||
-D BTNPIN=35
|
||||
; -D IR_PIN=4
|
||||
; -D RLYPIN=12
|
||||
; -D RLYMDE=1
|
214
usermods/TTGO-T-Display/usermod.cpp
Normal file
214
usermods/TTGO-T-Display/usermod.cpp
Normal file
@ -0,0 +1,214 @@
|
||||
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
/*
|
||||
* Pin 2 of the TTGO T-Display serves as the data line for the LED string.
|
||||
* Pin 35 is set up as the button pin in the platformio_overrides.ini file.
|
||||
* The button can be set up via the macros section in the web interface.
|
||||
* I use the button to cycle between presets.
|
||||
* The Pin 35 button is the one on the RIGHT side of the USB-C port on the board,
|
||||
* when the port is oriented downwards. See readme.md file for photo.
|
||||
* The display is set up to turn off after 5 minutes, and turns on automatically
|
||||
* when a change in the dipslayed info is detected (within a 5 second interval).
|
||||
*/
|
||||
|
||||
|
||||
//Use userVar0 and userVar1 (API calls &U0=,&U1=, uint16_t)
|
||||
|
||||
#include "wled.h"
|
||||
#include <TFT_eSPI.h>
|
||||
#include <SPI.h>
|
||||
#include "WiFi.h"
|
||||
#include <Wire.h>
|
||||
|
||||
#ifndef TFT_DISPOFF
|
||||
#define TFT_DISPOFF 0x28
|
||||
#endif
|
||||
|
||||
#ifndef TFT_SLPIN
|
||||
#define TFT_SLPIN 0x10
|
||||
#endif
|
||||
|
||||
#define TFT_MOSI 19
|
||||
#define TFT_SCLK 18
|
||||
#define TFT_CS 5
|
||||
#define TFT_DC 16
|
||||
#define TFT_RST 23
|
||||
|
||||
#define TFT_BL 4 // Display backlight control pin
|
||||
#define ADC_EN 14 // Used for enabling battery voltage measurements - not used in this program
|
||||
|
||||
TFT_eSPI tft = TFT_eSPI(135, 240); // Invoke custom library
|
||||
|
||||
//gets called once at boot. Do all initialization that doesn't depend on network here
|
||||
void userSetup() {
|
||||
Serial.begin(115200);
|
||||
Serial.println("Start");
|
||||
tft.init();
|
||||
tft.setRotation(3); //Rotation here is set up for the text to be readable with the port on the left. Use 1 to flip.
|
||||
tft.fillScreen(TFT_BLACK);
|
||||
tft.setTextSize(2);
|
||||
tft.setTextColor(TFT_WHITE);
|
||||
tft.setCursor(1, 10);
|
||||
tft.setTextDatum(MC_DATUM);
|
||||
tft.setTextSize(2);
|
||||
tft.print("Loading...");
|
||||
|
||||
if (TFT_BL > 0) { // TFT_BL has been set in the TFT_eSPI library in the User Setup file TTGO_T_Display.h
|
||||
pinMode(TFT_BL, OUTPUT); // Set backlight pin to output mode
|
||||
digitalWrite(TFT_BL, HIGH); // Turn backlight on.
|
||||
}
|
||||
|
||||
// tft.setRotation(3);
|
||||
}
|
||||
|
||||
// gets called every time WiFi is (re-)connected. Initialize own network
|
||||
// interfaces here
|
||||
void userConnected() {}
|
||||
|
||||
// needRedraw marks if redraw is required to prevent often redrawing.
|
||||
bool needRedraw = true;
|
||||
|
||||
// Next variables hold the previous known values to determine if redraw is
|
||||
// required.
|
||||
String knownSsid = "";
|
||||
IPAddress knownIp;
|
||||
uint8_t knownBrightness = 0;
|
||||
uint8_t knownMode = 0;
|
||||
uint8_t knownPalette = 0;
|
||||
uint8_t tftcharwidth = 19; // Number of chars that fit on screen with text size set to 2
|
||||
|
||||
long lastUpdate = 0;
|
||||
long lastRedraw = 0;
|
||||
bool displayTurnedOff = false;
|
||||
// How often we are redrawing screen
|
||||
#define USER_LOOP_REFRESH_RATE_MS 5000
|
||||
|
||||
void userLoop() {
|
||||
|
||||
// Check if we time interval for redrawing passes.
|
||||
if (millis() - lastUpdate < USER_LOOP_REFRESH_RATE_MS) {
|
||||
return;
|
||||
}
|
||||
lastUpdate = millis();
|
||||
|
||||
// Turn off display after 5 minutes with no change.
|
||||
if(!displayTurnedOff && millis() - lastRedraw > 5*60*1000) {
|
||||
digitalWrite(TFT_BL, LOW); // Turn backlight off.
|
||||
displayTurnedOff = true;
|
||||
}
|
||||
|
||||
// Check if values which are shown on display changed from the last time.
|
||||
if (((apActive) ? String(apSSID) : WiFi.SSID()) != knownSsid) {
|
||||
needRedraw = true;
|
||||
} else if (knownIp != (apActive ? IPAddress(4, 3, 2, 1) : WiFi.localIP())) {
|
||||
needRedraw = true;
|
||||
} else if (knownBrightness != bri) {
|
||||
needRedraw = true;
|
||||
} else if (knownMode != strip.getMode()) {
|
||||
needRedraw = true;
|
||||
} else if (knownPalette != strip.getSegment(0).palette) {
|
||||
needRedraw = true;
|
||||
}
|
||||
|
||||
if (!needRedraw) {
|
||||
return;
|
||||
}
|
||||
needRedraw = false;
|
||||
|
||||
if (displayTurnedOff)
|
||||
{
|
||||
digitalWrite(TFT_BL, TFT_BACKLIGHT_ON); // Turn backlight on.
|
||||
displayTurnedOff = false;
|
||||
}
|
||||
lastRedraw = millis();
|
||||
|
||||
// Update last known values.
|
||||
#if defined(ESP8266)
|
||||
knownSsid = apActive ? WiFi.softAPSSID() : WiFi.SSID();
|
||||
#else
|
||||
knownSsid = WiFi.SSID();
|
||||
#endif
|
||||
knownIp = apActive ? IPAddress(4, 3, 2, 1) : WiFi.localIP();
|
||||
knownBrightness = bri;
|
||||
knownMode = strip.getMode();
|
||||
knownPalette = strip.getSegment(0).palette;
|
||||
|
||||
tft.fillScreen(TFT_BLACK);
|
||||
tft.setTextSize(2);
|
||||
// First row with Wifi name
|
||||
tft.setCursor(1, 10);
|
||||
tft.print(knownSsid.substring(0, tftcharwidth > 1 ? tftcharwidth - 1 : 0));
|
||||
// Print `~` char to indicate that SSID is longer, than our dicplay
|
||||
if (knownSsid.length() > tftcharwidth)
|
||||
tft.print("~");
|
||||
|
||||
// Second row with IP or Psssword
|
||||
tft.setCursor(1, 40);
|
||||
// Print password in AP mode and if led is OFF.
|
||||
if (apActive && bri == 0)
|
||||
tft.print(apPass);
|
||||
else
|
||||
tft.print(knownIp);
|
||||
|
||||
// Third row with mode name
|
||||
tft.setCursor(1, 70);
|
||||
uint8_t qComma = 0;
|
||||
bool insideQuotes = false;
|
||||
uint8_t printedChars = 0;
|
||||
char singleJsonSymbol;
|
||||
// Find the mode name in JSON
|
||||
for (size_t i = 0; i < strlen_P(JSON_mode_names); i++) {
|
||||
singleJsonSymbol = pgm_read_byte_near(JSON_mode_names + i);
|
||||
switch (singleJsonSymbol) {
|
||||
case '"':
|
||||
insideQuotes = !insideQuotes;
|
||||
break;
|
||||
case '[':
|
||||
case ']':
|
||||
break;
|
||||
case ',':
|
||||
qComma++;
|
||||
default:
|
||||
if (!insideQuotes || (qComma != knownMode))
|
||||
break;
|
||||
tft.print(singleJsonSymbol);
|
||||
printedChars++;
|
||||
}
|
||||
if ((qComma > knownMode) || (printedChars > tftcharwidth - 1))
|
||||
break;
|
||||
}
|
||||
// Fourth row with palette name
|
||||
tft.setCursor(1, 100);
|
||||
qComma = 0;
|
||||
insideQuotes = false;
|
||||
printedChars = 0;
|
||||
// Looking for palette name in JSON.
|
||||
for (size_t i = 0; i < strlen_P(JSON_palette_names); i++) {
|
||||
singleJsonSymbol = pgm_read_byte_near(JSON_palette_names + i);
|
||||
switch (singleJsonSymbol) {
|
||||
case '"':
|
||||
insideQuotes = !insideQuotes;
|
||||
break;
|
||||
case '[':
|
||||
case ']':
|
||||
break;
|
||||
case ',':
|
||||
qComma++;
|
||||
default:
|
||||
if (!insideQuotes || (qComma != knownPalette))
|
||||
break;
|
||||
tft.print(singleJsonSymbol);
|
||||
printedChars++;
|
||||
}
|
||||
// The following is modified from the code from the u8g2/u8g8 based code (knownPalette was knownMode)
|
||||
if ((qComma > knownPalette) || (printedChars > tftcharwidth - 1))
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
40
usermods/Temperature/readme.md
Normal file
40
usermods/Temperature/readme.md
Normal file
@ -0,0 +1,40 @@
|
||||
# Temperature usermod
|
||||
|
||||
Based on the excellent `QuinLED_Dig_Uno_Temp_MQTT` by srg74!
|
||||
This usermod will read from an attached DS18B20 temperature sensor (as available on the QuinLED Dig-Uno)
|
||||
The temperature is displayed both in the Info section of the web UI as well as published to the `/temperature` MQTT topic if enabled.
|
||||
This usermod will be expanded with support for different sensor types in the future.
|
||||
|
||||
## Installation
|
||||
|
||||
Copy `usermod_temperature.h` to the wled00 directory.
|
||||
Uncomment the corresponding lines in `usermods_list.h` and compile!
|
||||
If this is the only v2 usermod you plan to use, you can alternatively replace `usermods_list.h` in wled00 with the one in this folder.
|
||||
|
||||
## Project link
|
||||
|
||||
* [QuinLED-Dig-Uno](https://quinled.info/2018/09/15/quinled-dig-uno/) - Project link
|
||||
|
||||
### PlatformIO requirements
|
||||
|
||||
You might have to uncomment `DallasTemperature@~3.8.0`,`OneWire@~2.3.5 under` `[common]` section in `platformio.ini`:
|
||||
|
||||
```ini
|
||||
# platformio.ini
|
||||
...
|
||||
[platformio]
|
||||
...
|
||||
; default_envs = esp07
|
||||
default_envs = d1_mini
|
||||
...
|
||||
[common]
|
||||
...
|
||||
lib_deps_external =
|
||||
...
|
||||
#For use SSD1306 OLED display uncomment following
|
||||
U8g2@~2.27.3
|
||||
#For Dallas sensor uncomment following 2 lines
|
||||
DallasTemperature@~3.8.0
|
||||
OneWire@~2.3.5
|
||||
...
|
||||
```
|
79
usermods/Temperature/usermod_temperature.h
Normal file
79
usermods/Temperature/usermod_temperature.h
Normal file
@ -0,0 +1,79 @@
|
||||
#pragma once
|
||||
|
||||
#include "wled.h"
|
||||
|
||||
#include <DallasTemperature.h> //DS18B20
|
||||
|
||||
//Pin defaults for QuinLed Dig-Uno
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
#define TEMPERATURE_PIN 18
|
||||
#else //ESP8266 boards
|
||||
#define TEMPERATURE_PIN 14
|
||||
#endif
|
||||
|
||||
#define TEMP_CELSIUS // Comment out for Fahrenheit
|
||||
|
||||
#define MEASUREMENT_INTERVAL 60000 //1 Minute
|
||||
|
||||
OneWire oneWire(TEMPERATURE_PIN);
|
||||
DallasTemperature sensor(&oneWire);
|
||||
|
||||
class UsermodTemperature : public Usermod {
|
||||
private:
|
||||
//set last reading as "40 sec before boot", so first reading is taken after 20 sec
|
||||
unsigned long lastMeasurement = UINT32_MAX - 40000;
|
||||
float temperature = 0.0f;
|
||||
public:
|
||||
void getReading() {
|
||||
sensor.requestTemperatures();
|
||||
#ifdef TEMP_CELSIUS
|
||||
temperature = sensor.getTempCByIndex(0);
|
||||
#else
|
||||
temperature = sensor.getTempFByIndex(0);
|
||||
#endif
|
||||
}
|
||||
|
||||
void setup() {
|
||||
sensor.begin();
|
||||
sensor.setResolution(9);
|
||||
}
|
||||
|
||||
void loop() {
|
||||
if (millis() - lastMeasurement > MEASUREMENT_INTERVAL)
|
||||
{
|
||||
getReading();
|
||||
|
||||
if (WLED_MQTT_CONNECTED) {
|
||||
char subuf[38];
|
||||
strcpy(subuf, mqttDeviceTopic);
|
||||
strcat(subuf, "/temperature");
|
||||
mqtt->publish(subuf, 0, true, String(temperature).c_str());
|
||||
}
|
||||
lastMeasurement = millis();
|
||||
}
|
||||
}
|
||||
|
||||
void addToJsonInfo(JsonObject& root) {
|
||||
JsonObject user = root["u"];
|
||||
if (user.isNull()) user = root.createNestedObject("u");
|
||||
|
||||
JsonArray temp = user.createNestedArray("Temperature");
|
||||
if (temperature == DEVICE_DISCONNECTED_C) {
|
||||
temp.add(0);
|
||||
temp.add(" Sensor Error!");
|
||||
return;
|
||||
}
|
||||
|
||||
temp.add(temperature);
|
||||
#ifdef TEMP_CELSIUS
|
||||
temp.add("°C");
|
||||
#else
|
||||
temp.add("°F");
|
||||
#endif
|
||||
}
|
||||
|
||||
uint16_t getId()
|
||||
{
|
||||
return USERMOD_ID_TEMPERATURE;
|
||||
}
|
||||
};
|
25
usermods/Temperature/usermods_list.cpp
Normal file
25
usermods/Temperature/usermods_list.cpp
Normal file
@ -0,0 +1,25 @@
|
||||
#include "wled.h"
|
||||
/*
|
||||
* Register your v2 usermods here!
|
||||
*/
|
||||
|
||||
/*
|
||||
* Add/uncomment your usermod filename here (and once more below)
|
||||
* || || ||
|
||||
* \/ \/ \/
|
||||
*/
|
||||
//#include "usermod_v2_example.h"
|
||||
#include "usermod_temperature.h"
|
||||
//#include "usermod_v2_empty.h"
|
||||
|
||||
void registerUsermods()
|
||||
{
|
||||
/*
|
||||
* Add your usermod class name here
|
||||
* || || ||
|
||||
* \/ \/ \/
|
||||
*/
|
||||
//usermods.add(new MyExampleUsermod());
|
||||
usermods.add(new UsermodTemperature());
|
||||
//usermods.add(new UsermodRenameMe());
|
||||
}
|
@ -7,7 +7,7 @@ If you have created an usermod that you believe is useful (for example to suppor
|
||||
In order for other people to be able to have fun with your usermod, please keep these points in mind:
|
||||
|
||||
- Create a folder in this folder with a descriptive name (for example `usermod_ds18b20_temp_sensor_mqtt`)
|
||||
- Include your custom `usermod.cpp` file
|
||||
- Include your custom files
|
||||
- If your usermod requires changes to other WLED files, please write a `readme.md` outlining the steps one has to take to use the usermod
|
||||
- Create a pull request!
|
||||
- If your feature is useful for the majority of WLED users, I will consider adding it to the base code!
|
||||
@ -15,4 +15,7 @@ In order for other people to be able to have fun with your usermod, please keep
|
||||
While I do my best to not break too much, keep in mind that as WLED is being updated, usermods might break.
|
||||
I am not actively maintaining any usermod in this directory, that is your responsibility as the creator of the usermod.
|
||||
|
||||
For new usermods, I would recommend trying out the new v2 usermod API, which allows installing multiple usermods at once and new functions!
|
||||
You can take a look at `EXAMPLE_v2` for some documentation and at `Temperature` for a completed v2 usermod!
|
||||
|
||||
Thank you for your help :)
|
||||
|
211
usermods/rotary_encoder_change_brightness/usermode_rotary_set.h
Normal file
211
usermods/rotary_encoder_change_brightness/usermode_rotary_set.h
Normal file
@ -0,0 +1,211 @@
|
||||
#pragma once
|
||||
|
||||
#include "wled.h"
|
||||
|
||||
//v2 usermod that allows to change brightness and color using a rotary encoder,
|
||||
//change between modes by pressing a button (many encoder have one included)
|
||||
class RotaryEncoderSet : public Usermod
|
||||
{
|
||||
private:
|
||||
//Private class members. You can declare variables and functions only accessible to your usermod here
|
||||
unsigned long lastTime = 0;
|
||||
/*
|
||||
** Rotary Encoder Example
|
||||
** Use the Sparkfun Rotary Encoder to vary brightness of LED
|
||||
**
|
||||
** Sample the encoder at 500Hz using the millis() function
|
||||
*/
|
||||
|
||||
int fadeAmount = 5; // how many points to fade the Neopixel with each step
|
||||
unsigned long currentTime;
|
||||
unsigned long loopTime;
|
||||
const int pinA = 5; // DT from encoder
|
||||
const int pinB = 18; // CLK from encoder
|
||||
const int pinC = 23; // SW from encoder
|
||||
unsigned char select_state = 0; // 0 = brightness 1 = color
|
||||
unsigned char button_state = HIGH;
|
||||
unsigned char prev_button_state = HIGH;
|
||||
CRGB fastled_col;
|
||||
CHSV prim_hsv;
|
||||
int16_t new_val;
|
||||
|
||||
unsigned char Enc_A;
|
||||
unsigned char Enc_B;
|
||||
unsigned char Enc_A_prev = 0;
|
||||
|
||||
public:
|
||||
//Functions called by WLED
|
||||
|
||||
/*
|
||||
* setup() is called once at boot. WiFi is not yet connected at this point.
|
||||
* You can use it to initialize variables, sensors or similar.
|
||||
*/
|
||||
void setup()
|
||||
{
|
||||
//Serial.println("Hello from my usermod!");
|
||||
pinMode(pinA, INPUT_PULLUP);
|
||||
pinMode(pinB, INPUT_PULLUP);
|
||||
pinMode(pinC, INPUT_PULLUP);
|
||||
currentTime = millis();
|
||||
loopTime = currentTime;
|
||||
}
|
||||
|
||||
/*
|
||||
* connected() is called every time the WiFi is (re)connected
|
||||
* Use it to initialize network interfaces
|
||||
*/
|
||||
void connected()
|
||||
{
|
||||
//Serial.println("Connected to WiFi!");
|
||||
}
|
||||
|
||||
/*
|
||||
* loop() is called continuously. Here you can check for events, read sensors, etc.
|
||||
*
|
||||
* Tips:
|
||||
* 1. You can use "if (WLED_CONNECTED)" to check for a successful network connection.
|
||||
* Additionally, "if (WLED_MQTT_CONNECTED)" is available to check for a connection to an MQTT broker.
|
||||
*
|
||||
* 2. Try to avoid using the delay() function. NEVER use delays longer than 10 milliseconds.
|
||||
* Instead, use a timer check as shown here.
|
||||
*/
|
||||
void loop()
|
||||
{
|
||||
currentTime = millis(); // get the current elapsed time
|
||||
|
||||
if (currentTime >= (loopTime + 2)) // 2ms since last check of encoder = 500Hz
|
||||
{
|
||||
button_state = digitalRead(pinC);
|
||||
if (prev_button_state != button_state)
|
||||
{
|
||||
if (button_state == LOW)
|
||||
{
|
||||
if (select_state == 1)
|
||||
{
|
||||
select_state = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
select_state = 1;
|
||||
}
|
||||
prev_button_state = button_state;
|
||||
}
|
||||
else
|
||||
{
|
||||
prev_button_state = button_state;
|
||||
}
|
||||
}
|
||||
int Enc_A = digitalRead(pinA); // Read encoder pins
|
||||
int Enc_B = digitalRead(pinB);
|
||||
if ((!Enc_A) && (Enc_A_prev))
|
||||
{ // A has gone from high to low
|
||||
if (Enc_B == HIGH)
|
||||
{ // B is high so clockwise
|
||||
if (select_state == 0)
|
||||
{
|
||||
if (bri + fadeAmount <= 255)
|
||||
bri += fadeAmount; // increase the brightness, dont go over 255
|
||||
}
|
||||
else
|
||||
{
|
||||
fastled_col.red = col[0];
|
||||
fastled_col.green = col[1];
|
||||
fastled_col.blue = col[2];
|
||||
prim_hsv = rgb2hsv_approximate(fastled_col);
|
||||
new_val = (int16_t)prim_hsv.h + fadeAmount;
|
||||
if (new_val > 255)
|
||||
new_val -= 255; // roll-over if bigger than 255
|
||||
if (new_val < 0)
|
||||
new_val += 255; // roll-over if smaller than 0
|
||||
prim_hsv.h = (byte)new_val;
|
||||
hsv2rgb_rainbow(prim_hsv, fastled_col);
|
||||
col[0] = fastled_col.red;
|
||||
col[1] = fastled_col.green;
|
||||
col[2] = fastled_col.blue;
|
||||
}
|
||||
}
|
||||
else if (Enc_B == LOW)
|
||||
{ // B is low so counter-clockwise
|
||||
if (select_state == 0)
|
||||
{
|
||||
if (bri - fadeAmount >= 0)
|
||||
bri -= fadeAmount; // decrease the brightness, dont go below 0
|
||||
}
|
||||
else
|
||||
{
|
||||
fastled_col.red = col[0];
|
||||
fastled_col.green = col[1];
|
||||
fastled_col.blue = col[2];
|
||||
prim_hsv = rgb2hsv_approximate(fastled_col);
|
||||
new_val = (int16_t)prim_hsv.h - fadeAmount;
|
||||
if (new_val > 255)
|
||||
new_val -= 255; // roll-over if bigger than 255
|
||||
if (new_val < 0)
|
||||
new_val += 255; // roll-over if smaller than 0
|
||||
prim_hsv.h = (byte)new_val;
|
||||
hsv2rgb_rainbow(prim_hsv, fastled_col);
|
||||
col[0] = fastled_col.red;
|
||||
col[1] = fastled_col.green;
|
||||
col[2] = fastled_col.blue;
|
||||
}
|
||||
}
|
||||
//call for notifier -> 0: init 1: direct change 2: button 3: notification 4: nightlight 5: other (No notification)
|
||||
// 6: fx changed 7: hue 8: preset cycle 9: blynk 10: alexa
|
||||
colorUpdated(NOTIFIER_CALL_MODE_BUTTON);
|
||||
updateInterfaces()
|
||||
}
|
||||
Enc_A_prev = Enc_A; // Store value of A for next time
|
||||
loopTime = currentTime; // Updates loopTime
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* addToJsonInfo() can be used to add custom entries to the /json/info part of the JSON API.
|
||||
* Creating an "u" object allows you to add custom key/value pairs to the Info section of the WLED web UI.
|
||||
* Below it is shown how this could be used for e.g. a light sensor
|
||||
*/
|
||||
/*
|
||||
void addToJsonInfo(JsonObject& root)
|
||||
{
|
||||
int reading = 20;
|
||||
//this code adds "u":{"Light":[20," lux"]} to the info object
|
||||
JsonObject user = root["u"];
|
||||
if (user.isNull()) user = root.createNestedObject("u");
|
||||
|
||||
JsonArray lightArr = user.createNestedArray("Light"); //name
|
||||
lightArr.add(reading); //value
|
||||
lightArr.add(" lux"); //unit
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
* addToJsonState() can be used to add custom entries to the /json/state part of the JSON API (state object).
|
||||
* Values in the state object may be modified by connected clients
|
||||
*/
|
||||
void addToJsonState(JsonObject &root)
|
||||
{
|
||||
//root["user0"] = userVar0;
|
||||
}
|
||||
|
||||
/*
|
||||
* readFromJsonState() can be used to receive data clients send to the /json/state part of the JSON API (state object).
|
||||
* Values in the state object may be modified by connected clients
|
||||
*/
|
||||
void readFromJsonState(JsonObject &root)
|
||||
{
|
||||
userVar0 = root["user0"] | userVar0; //if "user0" key exists in JSON, update, else keep old value
|
||||
//if (root["bri"] == 255) Serial.println(F("Don't burn down your garage!"));
|
||||
}
|
||||
|
||||
/*
|
||||
* 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 0xABCD;
|
||||
}
|
||||
|
||||
//More methods can be added in the future, this example will then be extended.
|
||||
//Your usermod will remain compatible as it does not need to implement all methods from the Usermod base class!
|
||||
};
|
206
wled00/FX.cpp
206
wled00/FX.cpp
@ -869,6 +869,7 @@ uint16_t WS2812FX::mode_traffic_light(void) {
|
||||
if (now - SEGENV.step > mdelay)
|
||||
{
|
||||
SEGENV.aux0++;
|
||||
if (SEGENV.aux0 == 1 && SEGMENT.intensity > 140) SEGENV.aux0 = 2; //skip Red + Amber, to get US-style sequence
|
||||
if (SEGENV.aux0 > 3) SEGENV.aux0 = 0;
|
||||
SEGENV.step = now;
|
||||
}
|
||||
@ -3334,3 +3335,208 @@ uint16_t WS2812FX::mode_solid_glitter()
|
||||
}
|
||||
return FRAMETIME;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Mode simulates a gradual sunrise
|
||||
*/
|
||||
uint16_t WS2812FX::mode_sunrise() {
|
||||
//speed 0 - static sun
|
||||
//speed 1 - 120: sunrise time in minutes
|
||||
//speed 121 - 240 : sunset time in minutes - 120;
|
||||
//speed above: "breathing" rise and set
|
||||
if (SEGENV.call == 0 || SEGMENT.speed != SEGENV.aux0) {
|
||||
SEGENV.step = millis(); //save starting time, millis() because now can change from sync
|
||||
SEGENV.aux0 = SEGMENT.speed;
|
||||
}
|
||||
|
||||
fill(0);
|
||||
uint16_t stage = 0xFFFF;
|
||||
|
||||
uint32_t s10SinceStart = (millis() - SEGENV.step) /100; //tenths of seconds
|
||||
|
||||
if (SEGMENT.speed > 120) { //quick sunrise and sunset
|
||||
uint16_t counter = (now >> 1) * (((SEGMENT.speed -120) >> 1) +1);
|
||||
stage = triwave16(counter);
|
||||
} else if (SEGMENT.speed) { //sunrise
|
||||
uint8_t durMins = SEGMENT.speed;
|
||||
if (durMins > 60) durMins -= 60;
|
||||
uint32_t s10Target = durMins * 600;
|
||||
if (s10SinceStart > s10Target) s10SinceStart = s10Target;
|
||||
stage = map(s10SinceStart, 0, s10Target, 0, 0xFFFF);
|
||||
if (SEGMENT.speed > 60) stage = 0xFFFF - stage; //sunset
|
||||
}
|
||||
|
||||
for (uint16_t i = 0; i <= SEGLEN/2; i++)
|
||||
{
|
||||
//default palette is Fire
|
||||
uint32_t c = color_from_palette(0, false, true, 255); //background
|
||||
|
||||
uint16_t wave = triwave16((i * stage) / SEGLEN);
|
||||
|
||||
wave = (wave >> 8) + ((wave * SEGMENT.intensity) >> 15);
|
||||
|
||||
if (wave > 240) { //clipped, full white sun
|
||||
c = color_from_palette( 240, false, true, 255);
|
||||
} else { //transition
|
||||
c = color_from_palette(wave, false, true, 255);
|
||||
}
|
||||
setPixelColor(i, c);
|
||||
setPixelColor(SEGLEN - i - 1, c);
|
||||
}
|
||||
|
||||
return FRAMETIME;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Effects by Andrew Tuline
|
||||
*/
|
||||
uint16_t WS2812FX::phased_base(uint8_t moder) { // We're making sine waves here. By Andrew Tuline.
|
||||
|
||||
uint8_t allfreq = 16; // Base frequency.
|
||||
//float* phasePtr = reinterpret_cast<float*>(SEGENV.step); // Phase change value gets calculated.
|
||||
static float phase = 0;//phasePtr[0];
|
||||
uint8_t cutOff = (255-SEGMENT.intensity); // You can change the number of pixels. AKA INTENSITY (was 192).
|
||||
uint8_t modVal = 5;//SEGMENT.fft1/8+1; // You can change the modulus. AKA FFT1 (was 5).
|
||||
|
||||
uint8_t index = now/64; // Set color rotation speed
|
||||
phase += SEGMENT.speed/32.0; // You can change the speed of the wave. AKA SPEED (was .4)
|
||||
//phasePtr[0] = phase;
|
||||
|
||||
for (int i = 0; i < SEGLEN; i++) {
|
||||
if (moder == 1) modVal = (inoise8(i*10 + i*10) /16); // Let's randomize our mod length with some Perlin noise.
|
||||
uint16_t val = (i+1) * allfreq; // This sets the frequency of the waves. The +1 makes sure that leds[0] is used.
|
||||
if (modVal == 0) modVal = 1;
|
||||
val += phase * (i % modVal +1) /2; // This sets the varying phase change of the waves. By Andrew Tuline.
|
||||
uint8_t b = cubicwave8(val); // Now we make an 8 bit sinewave.
|
||||
b = (b > cutOff) ? (b - cutOff) : 0; // A ternary operator to cutoff the light.
|
||||
setPixelColor(i, color_blend(SEGCOLOR(1), color_from_palette(index, false, false, 0), b));
|
||||
index += 256 / SEGLEN;
|
||||
}
|
||||
|
||||
return FRAMETIME;
|
||||
}
|
||||
|
||||
|
||||
|
||||
uint16_t WS2812FX::mode_phased(void) {
|
||||
return phased_base(0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
uint16_t WS2812FX::mode_phased_noise(void) {
|
||||
return phased_base(1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
uint16_t WS2812FX::mode_twinkleup(void) { // A very short twinkle routine with fade-in and dual controls. By Andrew Tuline.
|
||||
random16_set_seed(535); // The randomizer needs to be re-set each time through the loop in order for the same 'random' numbers to be the same each time through.
|
||||
|
||||
for (int i = 0; i<SEGLEN; i++) {
|
||||
uint8_t ranstart = random8(); // The starting value (aka brightness) for each pixel. Must be consistent each time through the loop for this to work.
|
||||
uint8_t pixBri = sin8(ranstart + 16 * now/(256-SEGMENT.speed));
|
||||
if (random8() > SEGMENT.intensity) pixBri = 0;
|
||||
setPixelColor(i, color_blend(SEGCOLOR(1), color_from_palette(i*20, false, PALETTE_SOLID_WRAP, 0), pixBri));
|
||||
}
|
||||
|
||||
return FRAMETIME;
|
||||
}
|
||||
|
||||
|
||||
// Peaceful noise that's slow and with gradually changing palettes. Does not support WLED palettes or default colours or controls.
|
||||
uint16_t WS2812FX::mode_noisepal(void) { // Slow noise palette by Andrew Tuline.
|
||||
uint16_t scale = 15 + (SEGMENT.intensity >> 2); //default was 30
|
||||
//#define scale 30
|
||||
|
||||
uint16_t dataSize = sizeof(CRGBPalette16) * 2; //allocate space for 2 Palettes
|
||||
if (!SEGENV.allocateData(dataSize)) return mode_static(); //allocation failed
|
||||
|
||||
CRGBPalette16* palettes = reinterpret_cast<CRGBPalette16*>(SEGENV.data);
|
||||
|
||||
uint16_t changePaletteMs = 4000 + SEGMENT.speed *10; //between 4 - 6.5sec
|
||||
if (millis() - SEGENV.step > changePaletteMs)
|
||||
{
|
||||
SEGENV.step = millis();
|
||||
|
||||
uint8_t baseI = random8();
|
||||
palettes[1] = CRGBPalette16(CHSV(baseI+random8(64), 255, random8(128,255)), CHSV(baseI+128, 255, random8(128,255)), CHSV(baseI+random8(92), 192, random8(128,255)), CHSV(baseI+random8(92), 255, random8(128,255)));
|
||||
}
|
||||
|
||||
CRGB color;
|
||||
|
||||
//EVERY_N_MILLIS(10) { //(don't have to time this, effect function is only called every 24ms)
|
||||
nblendPaletteTowardPalette(palettes[0], palettes[1], 48); // Blend towards the target palette over 48 iterations.
|
||||
|
||||
if (SEGMENT.palette > 0) palettes[0] = currentPalette;
|
||||
|
||||
for(int i = 0; i < SEGLEN; i++) {
|
||||
uint8_t index = inoise8(i*scale, SEGENV.aux0+i*scale); // Get a value from the noise function. I'm using both x and y axis.
|
||||
color = ColorFromPalette(palettes[0], index, 255, LINEARBLEND); // Use the my own palette.
|
||||
setPixelColor(i, color.red, color.green, color.blue);
|
||||
}
|
||||
|
||||
SEGENV.aux0 += beatsin8(10,1,4); // Moving along the distance. Vary it a bit with a sine wave.
|
||||
|
||||
return FRAMETIME;
|
||||
}
|
||||
|
||||
|
||||
// Sine waves that have controllable phase change speed, frequency and cutoff. By Andrew Tuline.
|
||||
// SEGMENT.speed ->Speed, SEGMENT.intensity -> Frequency (SEGMENT.fft1 -> Color change, SEGMENT.fft2 -> PWM cutoff)
|
||||
//
|
||||
uint16_t WS2812FX::mode_sinewave(void) { // Adjustable sinewave. By Andrew Tuline
|
||||
//#define qsuba(x, b) ((x>b)?x-b:0) // Analog Unsigned subtraction macro. if result <0, then => 0
|
||||
|
||||
uint16_t colorIndex = now /32;//(256 - SEGMENT.fft1); // Amount of colour change.
|
||||
|
||||
SEGENV.step += SEGMENT.speed/16; // Speed of animation.
|
||||
uint16_t freq = SEGMENT.intensity/4;//SEGMENT.fft2/8; // Frequency of the signal.
|
||||
|
||||
for (int i=0; i<SEGLEN; i++) { // For each of the LED's in the strand, set a brightness based on a wave as follows:
|
||||
int pixBri = cubicwave8((i*freq)+SEGENV.step);//qsuba(cubicwave8((i*freq)+SEGENV.step), (255-SEGMENT.intensity)); // qsub sets a minimum value called thiscutoff. If < thiscutoff, then bright = 0. Otherwise, bright = 128 (as defined in qsub)..
|
||||
//setPixCol(i, i*colorIndex/255, pixBri);
|
||||
setPixelColor(i, color_blend(SEGCOLOR(1), color_from_palette(i*colorIndex/255, false, PALETTE_SOLID_WRAP, 0), pixBri));
|
||||
}
|
||||
|
||||
return FRAMETIME;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Best of both worlds from Palette and Spot effects. By Aircoookie
|
||||
*/
|
||||
uint16_t WS2812FX::mode_flow(void)
|
||||
{
|
||||
uint16_t counter = 0;
|
||||
if (SEGMENT.speed != 0)
|
||||
{
|
||||
counter = now * ((SEGMENT.speed >> 2) +1);
|
||||
counter = counter >> 8;
|
||||
}
|
||||
|
||||
uint16_t maxZones = SEGLEN / 6; //only looks good if each zone has at least 6 LEDs
|
||||
uint16_t zones = (SEGMENT.intensity * maxZones) >> 8;
|
||||
if (zones & 0x01) zones++; //zones must be even
|
||||
if (zones < 2) zones = 2;
|
||||
uint16_t zoneLen = SEGLEN / zones;
|
||||
uint16_t offset = (SEGLEN - zones * zoneLen) >> 1;
|
||||
|
||||
fill(color_from_palette(-counter, false, true, 255));
|
||||
|
||||
for (uint16_t z = 0; z < zones; z++)
|
||||
{
|
||||
uint16_t pos = offset + z * zoneLen;
|
||||
for (uint16_t i = 0; i < zoneLen; i++)
|
||||
{
|
||||
uint8_t colorIndex = (i * 255 / zoneLen) - counter;
|
||||
uint16_t led = (z & 0x01) ? i : (zoneLen -1) -i;
|
||||
if (IS_REVERSE) led = (zoneLen -1) -led;
|
||||
setPixelColor(pos + led, color_from_palette(colorIndex, false, true, 255));
|
||||
}
|
||||
}
|
||||
|
||||
return FRAMETIME;
|
||||
}
|
||||
|
32
wled00/FX.h
32
wled00/FX.h
@ -98,7 +98,7 @@
|
||||
#define IS_REVERSE ((SEGMENT.options & REVERSE ) == REVERSE )
|
||||
#define IS_SELECTED ((SEGMENT.options & SELECTED ) == SELECTED )
|
||||
|
||||
#define MODE_COUNT 104
|
||||
#define MODE_COUNT 111
|
||||
|
||||
#define FX_MODE_STATIC 0
|
||||
#define FX_MODE_BLINK 1
|
||||
@ -204,6 +204,13 @@
|
||||
#define FX_MODE_PACIFICA 101
|
||||
#define FX_MODE_CANDLE_MULTI 102
|
||||
#define FX_MODE_SOLID_GLITTER 103
|
||||
#define FX_MODE_SUNRISE 104
|
||||
#define FX_MODE_PHASED 105
|
||||
#define FX_MODE_TWINKLEUP 106
|
||||
#define FX_MODE_NOISEPAL 107
|
||||
#define FX_MODE_SINEWAVE 108
|
||||
#define FX_MODE_PHASEDNOISE 109
|
||||
#define FX_MODE_FLOW 110
|
||||
|
||||
class WS2812FX {
|
||||
typedef uint16_t (WS2812FX::*mode_ptr)(void);
|
||||
@ -396,6 +403,13 @@ class WS2812FX {
|
||||
_mode[FX_MODE_PACIFICA] = &WS2812FX::mode_pacifica;
|
||||
_mode[FX_MODE_CANDLE_MULTI] = &WS2812FX::mode_candle_multi;
|
||||
_mode[FX_MODE_SOLID_GLITTER] = &WS2812FX::mode_solid_glitter;
|
||||
_mode[FX_MODE_SUNRISE] = &WS2812FX::mode_sunrise;
|
||||
_mode[FX_MODE_PHASED] = &WS2812FX::mode_phased;
|
||||
_mode[FX_MODE_TWINKLEUP] = &WS2812FX::mode_twinkleup;
|
||||
_mode[FX_MODE_NOISEPAL] = &WS2812FX::mode_noisepal;
|
||||
_mode[FX_MODE_SINEWAVE] = &WS2812FX::mode_sinewave;
|
||||
_mode[FX_MODE_PHASEDNOISE] = &WS2812FX::mode_phased_noise;
|
||||
_mode[FX_MODE_FLOW] = &WS2812FX::mode_flow;
|
||||
|
||||
_brightness = DEFAULT_BRIGHTNESS;
|
||||
currentPalette = CRGBPalette16(CRGB::Black);
|
||||
@ -461,7 +475,7 @@ class WS2812FX {
|
||||
uint32_t
|
||||
timebase,
|
||||
color_wheel(uint8_t),
|
||||
color_from_palette(uint16_t, bool, bool, uint8_t, uint8_t pbri = 255),
|
||||
color_from_palette(uint16_t, bool mapping, bool wrap, uint8_t mcol, uint8_t pbri = 255),
|
||||
color_blend(uint32_t,uint32_t,uint8_t),
|
||||
gamma32(uint32_t),
|
||||
getLastShow(void),
|
||||
@ -583,7 +597,14 @@ class WS2812FX {
|
||||
mode_heartbeat(void),
|
||||
mode_pacifica(void),
|
||||
mode_candle_multi(void),
|
||||
mode_solid_glitter(void);
|
||||
mode_solid_glitter(void),
|
||||
mode_sunrise(void),
|
||||
mode_phased(void),
|
||||
mode_twinkleup(void),
|
||||
mode_noisepal(void),
|
||||
mode_sinewave(void),
|
||||
mode_phased_noise(void),
|
||||
mode_flow(void);
|
||||
|
||||
private:
|
||||
NeoPixelWrapper *bus;
|
||||
@ -630,7 +651,8 @@ class WS2812FX {
|
||||
running(uint32_t, uint32_t),
|
||||
tricolor_chase(uint32_t, uint32_t),
|
||||
twinklefox_base(bool),
|
||||
spots_base(uint16_t);
|
||||
spots_base(uint16_t),
|
||||
phased_base(uint8_t);
|
||||
|
||||
CRGB twinklefox_one_twinkle(uint32_t ms, uint8_t salt, bool cat);
|
||||
CRGB pacifica_one_layer(uint16_t i, CRGBPalette16& p, uint16_t cistart, uint16_t wavescale, uint8_t bri, uint16_t ioff);
|
||||
@ -669,7 +691,7 @@ const char JSON_mode_names[] PROGMEM = R"=====([
|
||||
"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",
|
||||
"Fireworks 1D","Bouncing Balls","Sinelon","Sinelon Dual","Sinelon Rainbow","Popcorn","Drip","Plasma","Percent","Ripple Rainbow",
|
||||
"Heartbeat","Pacifica","Candle Multi", "Solid Glitter"
|
||||
"Heartbeat","Pacifica","Candle Multi", "Solid Glitter","Sunrise","Phased","Twinkleup","Noise Pal", "Sine","Phased Noise","Flow"
|
||||
])=====";
|
||||
|
||||
|
||||
|
@ -707,26 +707,28 @@ void WS2812FX::handle_palette(void)
|
||||
_segment_index_palette_last = _segment_index;
|
||||
|
||||
byte paletteIndex = SEGMENT.palette;
|
||||
if (SEGMENT.mode == FX_MODE_GLITTER && paletteIndex == 0) paletteIndex = 11;
|
||||
if (paletteIndex == 0) //default palette. Differs depending on effect
|
||||
{
|
||||
switch (SEGMENT.mode)
|
||||
{
|
||||
case FX_MODE_FIRE_2012 : paletteIndex = 35; break; //heat palette
|
||||
case FX_MODE_COLORWAVES : paletteIndex = 26; break; //landscape 33
|
||||
case FX_MODE_FILLNOISE8 : paletteIndex = 9; break; //ocean colors
|
||||
case FX_MODE_NOISE16_1 : paletteIndex = 20; break; //Drywet
|
||||
case FX_MODE_NOISE16_2 : paletteIndex = 43; break; //Blue cyan yellow
|
||||
case FX_MODE_NOISE16_3 : paletteIndex = 35; break; //heat palette
|
||||
case FX_MODE_NOISE16_4 : paletteIndex = 26; break; //landscape 33
|
||||
case FX_MODE_GLITTER : paletteIndex = 11; break; //rainbow colors
|
||||
case FX_MODE_SUNRISE : paletteIndex = 35; break; //heat palette
|
||||
case FX_MODE_FLOW : paletteIndex = 6; break; //party
|
||||
}
|
||||
}
|
||||
if (SEGMENT.mode >= FX_MODE_METEOR && paletteIndex == 0) paletteIndex = 4;
|
||||
|
||||
switch (paletteIndex)
|
||||
{
|
||||
case 0: {//default palette. Differs depending on effect
|
||||
switch (SEGMENT.mode)
|
||||
{
|
||||
case FX_MODE_FIRE_2012 : load_gradient_palette(22); break;//heat palette
|
||||
case FX_MODE_COLORWAVES : load_gradient_palette(13); break;//landscape 33
|
||||
case FX_MODE_FILLNOISE8 : targetPalette = OceanColors_p; break;
|
||||
case FX_MODE_NOISE16_1 : load_gradient_palette(17); break;//Drywet
|
||||
case FX_MODE_NOISE16_2 : load_gradient_palette(30); break;//Blue cyan yellow
|
||||
case FX_MODE_NOISE16_3 : load_gradient_palette(22); break;//heat palette
|
||||
case FX_MODE_NOISE16_4 : load_gradient_palette(13); break;//landscape 33
|
||||
//case FX_MODE_GLITTER : targetPalette = RainbowColors_p; break;
|
||||
|
||||
default: targetPalette = PartyColors_p; break;//palette, bpm
|
||||
}
|
||||
break;}
|
||||
case 0: //default palette. Exceptions for specific effects above
|
||||
targetPalette = PartyColors_p; break;
|
||||
case 1: {//periodically replace palette with a random one. Doesn't work with multiple FastLED segments
|
||||
if (!singleSegmentMode)
|
||||
{
|
||||
@ -778,7 +780,7 @@ void WS2812FX::handle_palette(void)
|
||||
case 12: //Rainbow stripe colors
|
||||
targetPalette = RainbowStripeColors_p; break;
|
||||
default: //progmem palettes
|
||||
load_gradient_palette(SEGMENT.palette -13);
|
||||
load_gradient_palette(paletteIndex -13);
|
||||
}
|
||||
|
||||
if (singleSegmentMode && paletteFade) //only blend if just one segment uses FastLED mode
|
||||
|
@ -71,6 +71,14 @@
|
||||
#define BPIN 5 //B pin for analog LED strip
|
||||
#define WPIN 15 //W pin for analog LED strip
|
||||
#define W2PIN 12 //W2 pin for analog LED strip
|
||||
#elif defined(WLED_USE_PLJAKOBS_PCB)
|
||||
// PWM pins - to use with esp_rgbww_controller from patrickjahns/pljakobs (https://github.com/pljakobs/esp_rgbww_controller)
|
||||
#define RPIN 12 //R pin for analog LED strip
|
||||
#define GPIN 13 //G pin for analog LED strip
|
||||
#define BPIN 14 //B pin for analog LED strip
|
||||
#define WPIN 4 //W pin for analog LED strip
|
||||
#define W2PIN 5 //W2 pin for analog LED strip
|
||||
#undef IR_PIN
|
||||
#else
|
||||
//PWM pins - PINs 5,12,13,15 are used with Magic Home LED Controller
|
||||
#define RPIN 5 //R pin for analog LED strip
|
||||
|
@ -10,6 +10,15 @@
|
||||
#define DEFAULT_AP_PASS "wled1234"
|
||||
#define DEFAULT_OTA_PASS "wledota"
|
||||
|
||||
//increase if you need more
|
||||
#define WLED_MAX_USERMODS 4
|
||||
|
||||
//Usermod IDs
|
||||
#define USERMOD_ID_RESERVED 0 //Unused. Might indicate no usermod present
|
||||
#define USERMOD_ID_UNSPECIFIED 1 //Default value for a general user mod that does not specify a custom ID
|
||||
#define USERMOD_ID_EXAMPLE 2 //Usermod "usermod_v2_example.h"
|
||||
#define USERMOD_ID_TEMPERATURE 3 //Usermod "usermod_temperature.h"
|
||||
|
||||
//Access point behavior
|
||||
#define AP_BEHAVIOR_BOOT_NO_CONN 0 //Open AP when no connection after boot
|
||||
#define AP_BEHAVIOR_NO_CONN 1 //Open when no connection (either after boot or if connection is lost)
|
||||
@ -44,6 +53,7 @@
|
||||
#define REALTIME_MODE_E131 4
|
||||
#define REALTIME_MODE_ADALIGHT 5
|
||||
#define REALTIME_MODE_ARTNET 6
|
||||
#define REALTIME_MODE_TPM2NET 7
|
||||
|
||||
//realtime override modes
|
||||
#define REALTIME_OVERRIDE_NONE 0
|
||||
|
@ -927,7 +927,7 @@ input[type=number]::-webkit-outer-spin-button {
|
||||
</label><br>
|
||||
First preset: <input id="cycs" class="noslide" type="number" min="1" max="14" value="1"><br>
|
||||
Last preset: <input id="cyce" class="noslide" type="number" min="2" max="15" value="3"><br>
|
||||
Time per preset: <input id="cyct" class="noslide" type="number" min="0.2" max="65.5" step="0.1" value="1.2">s<br>
|
||||
Time per preset: <input id="cyct" class="noslide" type="number" min="0.2" max="6553.5" step="0.1" value="1.2">s<br>
|
||||
Transition: <input id="cyctt" class="noslide" type="number" min="0" max="65.5" step="0.1" value="0.7">s
|
||||
</div>
|
||||
</div>
|
||||
|
@ -57,8 +57,10 @@ void onHueData(void* arg, AsyncClient* client, void *data, size_t len);
|
||||
|
||||
//ir.cpp
|
||||
bool decodeIRCustom(uint32_t code);
|
||||
void applyRepeatActions();
|
||||
void relativeChange(byte* property, int8_t amount, byte lowerBoundary = 0, byte higherBoundary = 0xFF);
|
||||
void changeEffectSpeed(int8_t amount);
|
||||
void changeBrightness(int8_t amount);
|
||||
void changeEffectIntensity(int8_t amount);
|
||||
void decodeIR(uint32_t code);
|
||||
void decodeIR24(uint32_t code);
|
||||
@ -68,6 +70,7 @@ void decodeIR40(uint32_t code);
|
||||
void decodeIR44(uint32_t code);
|
||||
void decodeIR21(uint32_t code);
|
||||
void decodeIR6(uint32_t code);
|
||||
void decodeIR9(uint32_t code);
|
||||
|
||||
void initIR();
|
||||
void handleIR();
|
||||
@ -77,7 +80,6 @@ void handleIR();
|
||||
#include "src/dependencies/json/ArduinoJson-v6.h"
|
||||
#include "src/dependencies/json/AsyncJson-v6.h"
|
||||
#include "FX.h"
|
||||
// TODO: AsynicWebServerRequest conflict?
|
||||
|
||||
void deserializeSegment(JsonObject elem, byte it);
|
||||
bool deserializeState(JsonObject root);
|
||||
@ -140,6 +142,40 @@ void realtimeLock(uint32_t timeoutMs, byte md = REALTIME_MODE_GENERIC);
|
||||
void handleNotifications();
|
||||
void setRealtimePixel(uint16_t i, byte r, byte g, byte b, byte w);
|
||||
|
||||
//um_manager.cpp
|
||||
class Usermod {
|
||||
public:
|
||||
virtual void loop() {}
|
||||
virtual void setup() {}
|
||||
virtual void connected() {}
|
||||
virtual void addToJsonState(JsonObject& obj) {}
|
||||
virtual void addToJsonInfo(JsonObject& obj) {}
|
||||
virtual void readFromJsonState(JsonObject& obj) {}
|
||||
virtual uint16_t getId() {return USERMOD_ID_UNSPECIFIED;}
|
||||
};
|
||||
|
||||
class UsermodManager {
|
||||
private:
|
||||
Usermod* ums[WLED_MAX_USERMODS];
|
||||
byte numMods = 0;
|
||||
|
||||
public:
|
||||
void loop();
|
||||
|
||||
void setup();
|
||||
void connected();
|
||||
|
||||
void addToJsonState(JsonObject& obj);
|
||||
void addToJsonInfo(JsonObject& obj);
|
||||
void readFromJsonState(JsonObject& obj);
|
||||
|
||||
bool add(Usermod* um);
|
||||
byte getModCount();
|
||||
};
|
||||
|
||||
//usermods_list.cpp
|
||||
void registerUsermods();
|
||||
|
||||
//usermod.cpp
|
||||
void userSetup();
|
||||
void userConnected();
|
||||
@ -175,8 +211,8 @@ String dmxProcessor(const String& var);
|
||||
void serveSettings(AsyncWebServerRequest* request);
|
||||
|
||||
//xml.cpp
|
||||
char* XML_response(AsyncWebServerRequest *request, char* dest = nullptr);
|
||||
char* URL_response(AsyncWebServerRequest *request);
|
||||
void XML_response(AsyncWebServerRequest *request, char* dest = nullptr);
|
||||
void URL_response(AsyncWebServerRequest *request);
|
||||
void sappend(char stype, const char* key, int val);
|
||||
void sappends(char stype, const char* key, char* val);
|
||||
void getSettingsJS(byte subPage, char* dest);
|
||||
|
2153
wled00/html_ui.h
2153
wled00/html_ui.h
File diff suppressed because it is too large
Load Diff
150
wled00/ir.cpp
150
wled00/ir.cpp
@ -15,6 +15,8 @@ decode_results results;
|
||||
|
||||
unsigned long irCheckedTime = 0;
|
||||
uint32_t lastValidCode = 0;
|
||||
byte lastRepeatableAction = ACTION_NONE;
|
||||
uint8_t lastRepeatableValue = 0;
|
||||
uint16_t irTimesRepeated = 0;
|
||||
uint8_t lastIR6ColourIdx = 0;
|
||||
|
||||
@ -36,7 +38,7 @@ bool decodeIRCustom(uint32_t code)
|
||||
}
|
||||
|
||||
|
||||
//relatively change brightness, minumum A=5
|
||||
|
||||
void relativeChange(byte* property, int8_t amount, byte lowerBoundary, byte higherBoundary)
|
||||
{
|
||||
int16_t new_val = (int16_t) *property + amount;
|
||||
@ -45,6 +47,16 @@ void relativeChange(byte* property, int8_t amount, byte lowerBoundary, byte high
|
||||
*property = (byte)constrain(new_val,0.1,255.1);
|
||||
}
|
||||
|
||||
void changeBrightness(int8_t amount)
|
||||
{
|
||||
int16_t new_val = bri + amount;
|
||||
if (new_val < 5) new_val = 5; //minimum brightness A=5
|
||||
bri = (byte)constrain(new_val,0.1,255.1);
|
||||
if(amount > 0) lastRepeatableAction = ACTION_BRIGHT_UP;
|
||||
if(amount < 0) lastRepeatableAction = ACTION_BRIGHT_DOWN;
|
||||
lastRepeatableValue = amount;
|
||||
}
|
||||
|
||||
void changeEffectSpeed(int8_t amount)
|
||||
{
|
||||
if (effectCurrent != 0) {
|
||||
@ -65,6 +77,10 @@ void changeEffectSpeed(int8_t amount)
|
||||
col[1] = fastled_col.green;
|
||||
col[2] = fastled_col.blue;
|
||||
}
|
||||
|
||||
if(amount > 0) lastRepeatableAction = ACTION_SPEED_UP;
|
||||
if(amount < 0) lastRepeatableAction = ACTION_SPEED_DOWN;
|
||||
lastRepeatableValue = amount;
|
||||
}
|
||||
|
||||
void changeEffectIntensity(int8_t amount)
|
||||
@ -85,6 +101,10 @@ void changeEffectIntensity(int8_t amount)
|
||||
col[1] = fastled_col.green;
|
||||
col[2] = fastled_col.blue;
|
||||
}
|
||||
|
||||
if(amount > 0) lastRepeatableAction = ACTION_INTENSITY_UP;
|
||||
if(amount < 0) lastRepeatableAction = ACTION_INTENSITY_DOWN;
|
||||
lastRepeatableValue = amount;
|
||||
}
|
||||
|
||||
void decodeIR(uint32_t code)
|
||||
@ -92,14 +112,61 @@ void decodeIR(uint32_t code)
|
||||
if (code == 0xFFFFFFFF) //repeated code, continue brightness up/down
|
||||
{
|
||||
irTimesRepeated++;
|
||||
if (lastValidCode == IR24_BRIGHTER || lastValidCode == IR40_BPLUS )
|
||||
{
|
||||
relativeChange(&bri, 10); colorUpdated(NOTIFIER_CALL_MODE_BUTTON);
|
||||
applyRepeatActions();
|
||||
return;
|
||||
}
|
||||
lastValidCode = 0; irTimesRepeated = 0;
|
||||
if (decodeIRCustom(code)) return;
|
||||
if (code > 0xFFFFFF) return; //invalid code
|
||||
else if (code > 0xF70000 && code < 0xF80000) decodeIR24(code); //is in 24-key remote range
|
||||
else if (code > 0xFF0000) {
|
||||
switch (irEnabled) {
|
||||
case 1: decodeIR24OLD(code); break; // white 24-key remote (old) - it sends 0xFF0000 values
|
||||
case 2: decodeIR24CT(code); break; // white 24-key remote with CW, WW, CT+ and CT- keys
|
||||
case 3: decodeIR40(code); break; // blue 40-key remote with 25%, 50%, 75% and 100% keys
|
||||
case 4: decodeIR44(code); break; // white 44-key remote with color-up/down keys and DIY1 to 6 keys
|
||||
case 5: decodeIR21(code); break; // white 21-key remote
|
||||
case 6: decodeIR6(code); break; // black 6-key learning remote defaults: "CH" controls brightness,
|
||||
// "VOL +" controls effect, "VOL -" controls colour/palette, "MUTE"
|
||||
// sets bright plain white
|
||||
case 7: decodeIR9(code); break;
|
||||
default: return;
|
||||
}
|
||||
else if (lastValidCode == IR24_DARKER || lastValidCode == IR40_BMINUS )
|
||||
}
|
||||
if (nightlightActive && bri == 0) nightlightActive = false;
|
||||
colorUpdated(NOTIFIER_CALL_MODE_BUTTON); //for notifier, IR is considered a button input
|
||||
//code <= 0xF70000 also invalid
|
||||
}
|
||||
|
||||
void applyRepeatActions(){
|
||||
|
||||
if (lastRepeatableAction == ACTION_BRIGHT_UP)
|
||||
{
|
||||
relativeChange(&bri, -10, 5); colorUpdated(NOTIFIER_CALL_MODE_BUTTON);
|
||||
changeBrightness(lastRepeatableValue); colorUpdated(NOTIFIER_CALL_MODE_BUTTON);
|
||||
}
|
||||
else if (lastRepeatableAction == ACTION_BRIGHT_DOWN )
|
||||
{
|
||||
changeBrightness(lastRepeatableValue); colorUpdated(NOTIFIER_CALL_MODE_BUTTON);
|
||||
}
|
||||
|
||||
if (lastRepeatableAction == ACTION_SPEED_UP)
|
||||
{
|
||||
changeEffectSpeed(lastRepeatableValue); colorUpdated(NOTIFIER_CALL_MODE_BUTTON);
|
||||
}
|
||||
else if (lastRepeatableAction == ACTION_SPEED_DOWN )
|
||||
{
|
||||
changeEffectSpeed(lastRepeatableValue); colorUpdated(NOTIFIER_CALL_MODE_BUTTON);
|
||||
}
|
||||
|
||||
if (lastRepeatableAction == ACTION_INTENSITY_UP)
|
||||
{
|
||||
changeEffectIntensity(lastRepeatableValue); colorUpdated(NOTIFIER_CALL_MODE_BUTTON);
|
||||
}
|
||||
else if (lastRepeatableAction == ACTION_INTENSITY_DOWN )
|
||||
{
|
||||
changeEffectIntensity(lastRepeatableValue); colorUpdated(NOTIFIER_CALL_MODE_BUTTON);
|
||||
}
|
||||
|
||||
if (lastValidCode == IR40_WPLUS)
|
||||
{
|
||||
relativeChangeWhite(10); colorUpdated(NOTIFIER_CALL_MODE_BUTTON);
|
||||
@ -114,37 +181,14 @@ void decodeIR(uint32_t code)
|
||||
nightlightStartTime = millis();
|
||||
colorUpdated(NOTIFIER_CALL_MODE_BUTTON);
|
||||
}
|
||||
return;
|
||||
}
|
||||
lastValidCode = 0; irTimesRepeated = 0;
|
||||
|
||||
if (decodeIRCustom(code)) return;
|
||||
if (code > 0xFFFFFF) return; //invalid code
|
||||
else if (code > 0xF70000 && code < 0xF80000) decodeIR24(code); //is in 24-key remote range
|
||||
else if (code > 0xFF0000) {
|
||||
switch (irEnabled) {
|
||||
case 1: decodeIR24OLD(code); break; // white 24-key remote (old) - it sends 0xFF0000 values
|
||||
case 2: decodeIR24CT(code); break; // white 24-key remote with CW, WW, CT+ and CT- keys
|
||||
case 3: decodeIR40(code); break; // blue 40-key remote with 25%, 50%, 75% and 100% keys
|
||||
case 4: decodeIR44(code); break; // white 44-key remote with color-up/down keys and DIY1 to 6 keys
|
||||
case 5: decodeIR21(code); break; // white 21-key remote
|
||||
case 6: decodeIR6(code); break; // black 6-key learning remote defaults: "CH" controls brightness,
|
||||
// "VOL +" controls effect, "VOL -" controls colour/palette, "MUTE"
|
||||
// sets bright plain white
|
||||
default: return;
|
||||
}
|
||||
}
|
||||
if (nightlightActive && bri == 0) nightlightActive = false;
|
||||
colorUpdated(NOTIFIER_CALL_MODE_BUTTON); //for notifier, IR is considered a button input
|
||||
//code <= 0xF70000 also invalid
|
||||
}
|
||||
|
||||
|
||||
void decodeIR24(uint32_t code)
|
||||
{
|
||||
switch (code) {
|
||||
case IR24_BRIGHTER : relativeChange(&bri, 10); break;
|
||||
case IR24_DARKER : relativeChange(&bri, -10, 5); break;
|
||||
case IR24_BRIGHTER : changeBrightness(10); break;
|
||||
case IR24_DARKER : changeBrightness(-10); break;
|
||||
case IR24_OFF : briLast = bri; bri = 0; break;
|
||||
case IR24_ON : bri = briLast; break;
|
||||
case IR24_RED : colorFromUint32(COLOR_RED); break;
|
||||
@ -175,8 +219,8 @@ void decodeIR24(uint32_t code)
|
||||
void decodeIR24OLD(uint32_t code)
|
||||
{
|
||||
switch (code) {
|
||||
case IR24_OLD_BRIGHTER : relativeChange(&bri, 10); break;
|
||||
case IR24_OLD_DARKER : relativeChange(&bri, -10, 5); break;
|
||||
case IR24_OLD_BRIGHTER : changeBrightness(10); break;
|
||||
case IR24_OLD_DARKER : changeBrightness(-10); break;
|
||||
case IR24_OLD_OFF : briLast = bri; bri = 0; break;
|
||||
case IR24_OLD_ON : bri = briLast; break;
|
||||
case IR24_OLD_RED : colorFromUint32(COLOR_RED); break;
|
||||
@ -208,8 +252,8 @@ void decodeIR24OLD(uint32_t code)
|
||||
void decodeIR24CT(uint32_t code)
|
||||
{
|
||||
switch (code) {
|
||||
case IR24_CT_BRIGHTER : relativeChange(&bri, 10); break;
|
||||
case IR24_CT_DARKER : relativeChange(&bri, -10, 5); break;
|
||||
case IR24_CT_BRIGHTER : changeBrightness(10); break;
|
||||
case IR24_CT_DARKER : changeBrightness(-10); break;
|
||||
case IR24_CT_OFF : briLast = bri; bri = 0; break;
|
||||
case IR24_CT_ON : bri = briLast; break;
|
||||
case IR24_CT_RED : colorFromUint32(COLOR_RED); break;
|
||||
@ -243,8 +287,8 @@ void decodeIR24CT(uint32_t code)
|
||||
void decodeIR40(uint32_t code)
|
||||
{
|
||||
switch (code) {
|
||||
case IR40_BPLUS : relativeChange(&bri, 10); break;
|
||||
case IR40_BMINUS : relativeChange(&bri, -10, 5); break;
|
||||
case IR40_BPLUS : changeBrightness(10); break;
|
||||
case IR40_BMINUS : changeBrightness(-10); break;
|
||||
case IR40_OFF : briLast = bri; bri = 0; break;
|
||||
case IR40_ON : bri = briLast; break;
|
||||
case IR40_RED : colorFromUint24(COLOR_RED); break;
|
||||
@ -300,8 +344,8 @@ void decodeIR40(uint32_t code)
|
||||
void decodeIR44(uint32_t code)
|
||||
{
|
||||
switch (code) {
|
||||
case IR44_BPLUS : relativeChange(&bri, 10); break;
|
||||
case IR44_BMINUS : relativeChange(&bri, -10, 5); break;
|
||||
case IR44_BPLUS : changeBrightness(10); break;
|
||||
case IR44_BMINUS : changeBrightness(-10); break;
|
||||
case IR44_OFF : briLast = bri; bri = 0; break;
|
||||
case IR44_ON : bri = briLast; break;
|
||||
case IR44_RED : colorFromUint24(COLOR_RED); break;
|
||||
@ -363,8 +407,8 @@ void decodeIR44(uint32_t code)
|
||||
void decodeIR21(uint32_t code)
|
||||
{
|
||||
switch (code) {
|
||||
case IR21_BRIGHTER: relativeChange(&bri, 10); break;
|
||||
case IR21_DARKER: relativeChange(&bri, -10, 5); break;
|
||||
case IR21_BRIGHTER: changeBrightness(10); break;
|
||||
case IR21_DARKER: changeBrightness(-10); break;
|
||||
case IR21_OFF: briLast = bri; bri = 0; break;
|
||||
case IR21_ON: bri = briLast; break;
|
||||
case IR21_RED: colorFromUint32(COLOR_RED); break;
|
||||
@ -392,9 +436,9 @@ void decodeIR21(uint32_t code)
|
||||
void decodeIR6(uint32_t code)
|
||||
{
|
||||
switch (code) {
|
||||
case IR6_POWER: toggleOnOff(); break;
|
||||
case IR6_CHANNEL_UP: relativeChange(&bri, 10); break;
|
||||
case IR6_CHANNEL_DOWN: relativeChange(&bri, -10, 5); break;
|
||||
case IR6_POWER: toggleOnOff(); break;
|
||||
case IR6_CHANNEL_UP: changeBrightness(10); break;
|
||||
case IR6_CHANNEL_DOWN: changeBrightness(-10); break;
|
||||
case IR6_VOLUME_UP: relativeChange(&effectCurrent, 1, 0, MODE_COUNT); break; // next effect
|
||||
case IR6_VOLUME_DOWN: // next palette
|
||||
relativeChange(&effectPalette, 1, 0, strip.getPaletteCount() -1);
|
||||
@ -421,6 +465,24 @@ void decodeIR6(uint32_t code)
|
||||
lastValidCode = code;
|
||||
}
|
||||
|
||||
void decodeIR9(uint32_t code)
|
||||
{
|
||||
switch (code) {
|
||||
case IR9_POWER : toggleOnOff(); break;
|
||||
case IR9_A : if (!applyPreset(1)) effectCurrent = FX_MODE_COLORTWINKLE; break;
|
||||
case IR9_B : if (!applyPreset(2)) effectCurrent = FX_MODE_RAINBOW_CYCLE; break;
|
||||
case IR9_C : if (!applyPreset(3)) effectCurrent = FX_MODE_BREATH; break;
|
||||
case IR9_UP : changeBrightness(16); break;
|
||||
case IR9_DOWN : changeBrightness(-16); break;
|
||||
//case IR9_UP : changeEffectIntensity(16); break;
|
||||
//case IR9_DOWN : changeEffectIntensity(-16); break;
|
||||
case IR9_LEFT : changeEffectSpeed(-16); break;
|
||||
case IR9_RIGHT : changeEffectSpeed(16); break;
|
||||
case IR9_SELECT : relativeChange(&effectCurrent, 1, 0, MODE_COUNT); break;
|
||||
default: return;
|
||||
}
|
||||
lastValidCode = code;
|
||||
}
|
||||
|
||||
void initIR()
|
||||
{
|
||||
|
@ -13,6 +13,15 @@
|
||||
#define IR6_VOLUME_DOWN 0xFF2FD0
|
||||
#define IR6_MUTE 0xFFAF50
|
||||
|
||||
#define IR9_POWER 0xFF629D
|
||||
#define IR9_A 0xFF22DD
|
||||
#define IR9_B 0xFF02FD
|
||||
#define IR9_C 0xFFC23D
|
||||
#define IR9_LEFT 0xFF30CF
|
||||
#define IR9_RIGHT 0xFF7A85
|
||||
#define IR9_UP 0xFF9867
|
||||
#define IR9_DOWN 0xFF38C7
|
||||
#define IR9_SELECT 0xFF18E7
|
||||
|
||||
//Infrared codes for 24-key remote from http://woodsgood.ca/projects/2015/02/13/rgb-led-strip-controllers-ir-codes/
|
||||
#define IR24_BRIGHTER 0xF700FF
|
||||
@ -229,3 +238,12 @@
|
||||
#define COLOR2_NEUTRALWHITE 0xFF000000
|
||||
#define COLOR2_COLDWHITE 0xFF7F7F7F
|
||||
#define COLOR2_COLDWHITE2 0xFFFFFFFF
|
||||
|
||||
#define ACTION_NONE 0
|
||||
#define ACTION_BRIGHT_UP 1
|
||||
#define ACTION_BRIGHT_DOWN 2
|
||||
#define ACTION_SPEED_UP 3
|
||||
#define ACTION_SPEED_DOWN 4
|
||||
#define ACTION_INTENSITY_UP 5
|
||||
#define ACTION_INTENSITY_DOWN 6
|
||||
#define ACTION_POWER 7
|
@ -110,11 +110,7 @@ bool deserializeState(JsonObject root)
|
||||
presetCycleMin = ccnf["min"] | presetCycleMin;
|
||||
presetCycleMax = ccnf["max"] | presetCycleMax;
|
||||
tr = ccnf["time"] | -1;
|
||||
if (tr >= 2)
|
||||
{
|
||||
presetCycleTime = tr;
|
||||
presetCycleTime *= 100;
|
||||
}
|
||||
if (tr >= 2) presetCycleTime = tr;
|
||||
|
||||
JsonObject nl = root["nl"];
|
||||
nightlightActive = nl["on"] | nightlightActive;
|
||||
@ -172,6 +168,8 @@ bool deserializeState(JsonObject root)
|
||||
}
|
||||
}
|
||||
|
||||
usermods.readFromJsonState(root);
|
||||
|
||||
colorUpdated(noNotification ? NOTIFIER_CALL_MODE_NO_NOTIFY : NOTIFIER_CALL_MODE_DIRECT_CHANGE);
|
||||
|
||||
//write presets to flash directly?
|
||||
@ -237,11 +235,13 @@ void serializeState(JsonObject root)
|
||||
root["pss"] = savedPresets;
|
||||
root["pl"] = (presetCyclingEnabled) ? 0: -1;
|
||||
|
||||
//temporary for preser cycle
|
||||
usermods.addToJsonState(root);
|
||||
|
||||
//temporary for preset cycle
|
||||
JsonObject ccnf = root.createNestedObject("ccnf");
|
||||
ccnf["min"] = presetCycleMin;
|
||||
ccnf["max"] = presetCycleMax;
|
||||
ccnf["time"] = presetCycleTime/100;
|
||||
ccnf["time"] = presetCycleTime;
|
||||
|
||||
JsonObject nl = root.createNestedObject("nl");
|
||||
nl["on"] = nightlightActive;
|
||||
@ -319,8 +319,9 @@ void serializeInfo(JsonObject root)
|
||||
case REALTIME_MODE_UDP: root["lm"] = "UDP"; break;
|
||||
case REALTIME_MODE_HYPERION: root["lm"] = "Hyperion"; break;
|
||||
case REALTIME_MODE_E131: root["lm"] = "E1.31"; break;
|
||||
case REALTIME_MODE_ADALIGHT: root["lm"] = F("USB Adalight");
|
||||
case REALTIME_MODE_ADALIGHT: root["lm"] = F("USB Adalight/TPM2"); break;
|
||||
case REALTIME_MODE_ARTNET: root["lm"] = "Art-Net"; break;
|
||||
case REALTIME_MODE_TPM2NET: root["lm"] = F("tpm2.net"); break;
|
||||
}
|
||||
|
||||
if (realtimeIP[0] == 0)
|
||||
@ -366,6 +367,8 @@ void serializeInfo(JsonObject root)
|
||||
root["freeheap"] = ESP.getFreeHeap();
|
||||
root["uptime"] = millis()/1000 + rolloverMillis*4294967;
|
||||
|
||||
usermods.addToJsonInfo(root);
|
||||
|
||||
byte os = 0;
|
||||
#ifdef WLED_DEBUG
|
||||
os = 0x80;
|
||||
|
@ -251,11 +251,12 @@ void handleNightlight()
|
||||
}
|
||||
|
||||
//also handle preset cycle here
|
||||
if (presetCyclingEnabled && (millis() - presetCycledTime > presetCycleTime))
|
||||
if (presetCyclingEnabled && (millis() - presetCycledTime > (100*presetCycleTime)))
|
||||
{
|
||||
if (presetCycCurr < presetCycleMin) presetCycCurr = presetCycleMin;
|
||||
applyPreset(presetCycCurr,presetApplyBri);
|
||||
presetCycCurr++; if (presetCycCurr > presetCycleMax) presetCycCurr = presetCycleMin;
|
||||
if (presetCycCurr > 25) presetCycCurr = 1;
|
||||
if (presetCycCurr > 16) presetCycCurr = 1;
|
||||
colorUpdated(NOTIFIER_CALL_MODE_PRESET_CYCLE);
|
||||
presetCycledTime = millis();
|
||||
}
|
||||
|
@ -76,7 +76,7 @@ void onMqttMessage(char* topic, char* payload, AsyncMqttClientMessageProperties
|
||||
void publishMqtt()
|
||||
{
|
||||
doPublishMqtt = false;
|
||||
if (mqtt == nullptr || !mqtt->connected()) return;
|
||||
if (!WLED_MQTT_CONNECTED) return;
|
||||
DEBUG_PRINTLN("Publish MQTT");
|
||||
|
||||
char s[10];
|
||||
|
@ -468,7 +468,7 @@ bool handleSet(AsyncWebServerRequest *request, const String& req)
|
||||
pos = req.indexOf("PT="); //sets cycle time in ms
|
||||
if (pos > 0) {
|
||||
int v = getNumVal(&req, pos);
|
||||
if (v > 49) presetCycleTime = v;
|
||||
if (v > 100) presetCycleTime = v/100;
|
||||
}
|
||||
|
||||
pos = req.indexOf("PA="); //apply brightness from preset
|
||||
|
256
wled00/udp.cpp
256
wled00/udp.cpp
@ -1,7 +1,7 @@
|
||||
#include "wled.h"
|
||||
|
||||
/*
|
||||
* UDP sync notifier
|
||||
* UDP sync notifier / Realtime / Hyperion / TPM2.NET
|
||||
*/
|
||||
|
||||
#define WLEDPACKETSIZE 29
|
||||
@ -89,6 +89,16 @@ void realtimeLock(uint32_t timeoutMs, byte md)
|
||||
}
|
||||
|
||||
|
||||
#define TMP2NET_OUT_PORT 65442
|
||||
|
||||
void sendTPM2Ack() {
|
||||
notifierUdp.beginPacket(notifierUdp.remoteIP(), TMP2NET_OUT_PORT);
|
||||
uint8_t response_ack = 0xac;
|
||||
notifierUdp.write(&response_ack, 1);
|
||||
notifierUdp.endPacket();
|
||||
}
|
||||
|
||||
|
||||
void handleNotifications()
|
||||
{
|
||||
//send second notification if enabled
|
||||
@ -139,121 +149,151 @@ void handleNotifications()
|
||||
}
|
||||
|
||||
//notifier and UDP realtime
|
||||
if (packetSize > UDP_IN_MAXSIZE) return;
|
||||
if(packetSize && notifierUdp.remoteIP() != WiFi.localIP()) //don't process broadcasts we send ourselves
|
||||
if (!packetSize || packetSize > UDP_IN_MAXSIZE) return;
|
||||
if (notifierUdp.remoteIP() == WiFi.localIP()) return; //don't process broadcasts we send ourselves
|
||||
|
||||
uint8_t udpIn[packetSize];
|
||||
notifierUdp.read(udpIn, packetSize);
|
||||
|
||||
//wled notifier, block if realtime packets active
|
||||
if (udpIn[0] == 0 && !realtimeMode && receiveNotifications)
|
||||
{
|
||||
uint8_t udpIn[packetSize];
|
||||
notifierUdp.read(udpIn, packetSize);
|
||||
//ignore notification if received within a second after sending a notification ourselves
|
||||
if (millis() - notificationSentTime < 1000) return;
|
||||
if (udpIn[1] > 199) return; //do not receive custom versions
|
||||
|
||||
//wled notifier, block if realtime packets active
|
||||
if (udpIn[0] == 0 && !realtimeMode && receiveNotifications)
|
||||
bool someSel = (receiveNotificationBrightness || receiveNotificationColor || receiveNotificationEffects);
|
||||
//apply colors from notification
|
||||
if (receiveNotificationColor || !someSel)
|
||||
{
|
||||
//ignore notification if received within a second after sending a notification ourselves
|
||||
if (millis() - notificationSentTime < 1000) return;
|
||||
if (udpIn[1] > 199) return; //do not receive custom versions
|
||||
|
||||
bool someSel = (receiveNotificationBrightness || receiveNotificationColor || receiveNotificationEffects);
|
||||
//apply colors from notification
|
||||
if (receiveNotificationColor || !someSel)
|
||||
col[0] = udpIn[3];
|
||||
col[1] = udpIn[4];
|
||||
col[2] = udpIn[5];
|
||||
if (udpIn[11] > 0) //sending module's white val is intended
|
||||
{
|
||||
col[0] = udpIn[3];
|
||||
col[1] = udpIn[4];
|
||||
col[2] = udpIn[5];
|
||||
if (udpIn[11] > 0) //sending module's white val is intended
|
||||
col[3] = udpIn[10];
|
||||
if (udpIn[11] > 1)
|
||||
{
|
||||
col[3] = udpIn[10];
|
||||
if (udpIn[11] > 1)
|
||||
{
|
||||
colSec[0] = udpIn[12];
|
||||
colSec[1] = udpIn[13];
|
||||
colSec[2] = udpIn[14];
|
||||
colSec[3] = udpIn[15];
|
||||
}
|
||||
if (udpIn[11] > 5)
|
||||
{
|
||||
uint32_t t = (udpIn[25] << 24) | (udpIn[26] << 16) | (udpIn[27] << 8) | (udpIn[28]);
|
||||
t += 2;
|
||||
t -= millis();
|
||||
strip.timebase = t;
|
||||
}
|
||||
if (udpIn[11] > 6)
|
||||
{
|
||||
strip.setColor(2, udpIn[20], udpIn[21], udpIn[22], udpIn[23]); //tertiary color
|
||||
}
|
||||
colSec[0] = udpIn[12];
|
||||
colSec[1] = udpIn[13];
|
||||
colSec[2] = udpIn[14];
|
||||
colSec[3] = udpIn[15];
|
||||
}
|
||||
if (udpIn[11] > 5)
|
||||
{
|
||||
uint32_t t = (udpIn[25] << 24) | (udpIn[26] << 16) | (udpIn[27] << 8) | (udpIn[28]);
|
||||
t += 2;
|
||||
t -= millis();
|
||||
strip.timebase = t;
|
||||
}
|
||||
if (udpIn[11] > 6)
|
||||
{
|
||||
strip.setColor(2, udpIn[20], udpIn[21], udpIn[22], udpIn[23]); //tertiary color
|
||||
}
|
||||
}
|
||||
|
||||
//apply effects from notification
|
||||
if (udpIn[11] < 200 && (receiveNotificationEffects || !someSel))
|
||||
{
|
||||
if (udpIn[8] < strip.getModeCount()) effectCurrent = udpIn[8];
|
||||
effectSpeed = udpIn[9];
|
||||
if (udpIn[11] > 2) effectIntensity = udpIn[16];
|
||||
if (udpIn[11] > 4 && udpIn[19] < strip.getPaletteCount()) effectPalette = udpIn[19];
|
||||
}
|
||||
|
||||
if (udpIn[11] > 3)
|
||||
{
|
||||
transitionDelayTemp = ((udpIn[17] << 0) & 0xFF) + ((udpIn[18] << 8) & 0xFF00);
|
||||
}
|
||||
|
||||
nightlightActive = udpIn[6];
|
||||
if (nightlightActive) nightlightDelayMins = udpIn[7];
|
||||
|
||||
if (receiveNotificationBrightness || !someSel) bri = udpIn[2];
|
||||
colorUpdated(NOTIFIER_CALL_MODE_NOTIFICATION);
|
||||
|
||||
} else if (udpIn[0] > 0 && udpIn[0] < 5 && receiveDirect) //1 warls //2 drgb //3 drgbw
|
||||
{
|
||||
realtimeIP = notifierUdp.remoteIP();
|
||||
DEBUG_PRINTLN(notifierUdp.remoteIP());
|
||||
if (packetSize < 2) return;
|
||||
|
||||
if (udpIn[1] == 0)
|
||||
{
|
||||
realtimeTimeout = 0;
|
||||
return;
|
||||
} else {
|
||||
realtimeLock(udpIn[1]*1000 +1, REALTIME_MODE_UDP);
|
||||
}
|
||||
if (realtimeOverride) return;
|
||||
|
||||
if (udpIn[0] == 1) //warls
|
||||
{
|
||||
for (uint16_t i = 2; i < packetSize -3; i += 4)
|
||||
{
|
||||
setRealtimePixel(udpIn[i], udpIn[i+1], udpIn[i+2], udpIn[i+3], 0);
|
||||
}
|
||||
} else if (udpIn[0] == 2) //drgb
|
||||
{
|
||||
uint16_t id = 0;
|
||||
for (uint16_t i = 2; i < packetSize -2; i += 3)
|
||||
{
|
||||
setRealtimePixel(id, udpIn[i], udpIn[i+1], udpIn[i+2], 0);
|
||||
|
||||
id++; if (id >= ledCount) break;
|
||||
}
|
||||
} else if (udpIn[0] == 3) //drgbw
|
||||
{
|
||||
uint16_t id = 0;
|
||||
for (uint16_t i = 2; i < packetSize -3; i += 4)
|
||||
{
|
||||
setRealtimePixel(id, udpIn[i], udpIn[i+1], udpIn[i+2], udpIn[i+3]);
|
||||
|
||||
id++; if (id >= ledCount) break;
|
||||
}
|
||||
} else if (udpIn[0] == 4) //dnrgb
|
||||
{
|
||||
uint16_t id = ((udpIn[3] << 0) & 0xFF) + ((udpIn[2] << 8) & 0xFF00);
|
||||
for (uint16_t i = 4; i < packetSize -2; i += 3)
|
||||
{
|
||||
if (id >= ledCount) break;
|
||||
setRealtimePixel(id, udpIn[i], udpIn[i+1], udpIn[i+2], 0);
|
||||
id++;
|
||||
}
|
||||
}
|
||||
strip.show();
|
||||
}
|
||||
|
||||
//apply effects from notification
|
||||
if (udpIn[11] < 200 && (receiveNotificationEffects || !someSel))
|
||||
{
|
||||
if (udpIn[8] < strip.getModeCount()) effectCurrent = udpIn[8];
|
||||
effectSpeed = udpIn[9];
|
||||
if (udpIn[11] > 2) effectIntensity = udpIn[16];
|
||||
if (udpIn[11] > 4 && udpIn[19] < strip.getPaletteCount()) effectPalette = udpIn[19];
|
||||
}
|
||||
|
||||
if (udpIn[11] > 3)
|
||||
{
|
||||
transitionDelayTemp = ((udpIn[17] << 0) & 0xFF) + ((udpIn[18] << 8) & 0xFF00);
|
||||
}
|
||||
|
||||
nightlightActive = udpIn[6];
|
||||
if (nightlightActive) nightlightDelayMins = udpIn[7];
|
||||
|
||||
if (receiveNotificationBrightness || !someSel) bri = udpIn[2];
|
||||
colorUpdated(NOTIFIER_CALL_MODE_NOTIFICATION);
|
||||
|
||||
}
|
||||
if (!receiveDirect) return;
|
||||
|
||||
//TPM2.NET
|
||||
if (udpIn[0] == 0x9c)
|
||||
{
|
||||
byte tpmType = udpIn[1];
|
||||
if (tpmType == 0xaa) { //TPM2.NET polling, expect answer
|
||||
sendTPM2Ack(); return;
|
||||
}
|
||||
if (tpmType != 0xda) return; //return if notTPM2.NET data
|
||||
|
||||
realtimeIP = notifierUdp.remoteIP();
|
||||
realtimeLock(realtimeTimeoutMs, REALTIME_MODE_TPM2NET);
|
||||
if (realtimeOverride) return;
|
||||
|
||||
uint16_t frameSize = (udpIn[2] << 8) + udpIn[3];
|
||||
byte packetNum = udpIn[4]; //starts with 1!
|
||||
byte numPackets = udpIn[5];
|
||||
|
||||
uint16_t id = ((tpmFirstFrameSize/3)*(packetNum-1)) / 3; //start LED
|
||||
for (uint16_t i = 6; i < frameSize + 4; i += 3)
|
||||
{
|
||||
setRealtimePixel(id, udpIn[i], udpIn[i+1], udpIn[i+2], 0);
|
||||
id++; if (id >= ledCount) break;
|
||||
}
|
||||
if (packetNum == 1) tpmFirstFrameSize = frameSize;
|
||||
if (packetNum == numPackets) {strip.show(); } //show if last packet
|
||||
}
|
||||
|
||||
//UDP realtime: 1 warls 2 drgb 3 drgbw
|
||||
if (udpIn[0] > 0 && udpIn[0] < 5)
|
||||
{
|
||||
realtimeIP = notifierUdp.remoteIP();
|
||||
DEBUG_PRINTLN(notifierUdp.remoteIP());
|
||||
if (packetSize < 2) return;
|
||||
|
||||
if (udpIn[1] == 0)
|
||||
{
|
||||
realtimeTimeout = 0;
|
||||
return;
|
||||
} else {
|
||||
realtimeLock(udpIn[1]*1000 +1, REALTIME_MODE_UDP);
|
||||
}
|
||||
if (realtimeOverride) return;
|
||||
|
||||
if (udpIn[0] == 1) //warls
|
||||
{
|
||||
for (uint16_t i = 2; i < packetSize -3; i += 4)
|
||||
{
|
||||
setRealtimePixel(udpIn[i], udpIn[i+1], udpIn[i+2], udpIn[i+3], 0);
|
||||
}
|
||||
} else if (udpIn[0] == 2) //drgb
|
||||
{
|
||||
uint16_t id = 0;
|
||||
for (uint16_t i = 2; i < packetSize -2; i += 3)
|
||||
{
|
||||
setRealtimePixel(id, udpIn[i], udpIn[i+1], udpIn[i+2], 0);
|
||||
|
||||
id++; if (id >= ledCount) break;
|
||||
}
|
||||
} else if (udpIn[0] == 3) //drgbw
|
||||
{
|
||||
uint16_t id = 0;
|
||||
for (uint16_t i = 2; i < packetSize -3; i += 4)
|
||||
{
|
||||
setRealtimePixel(id, udpIn[i], udpIn[i+1], udpIn[i+2], udpIn[i+3]);
|
||||
|
||||
id++; if (id >= ledCount) break;
|
||||
}
|
||||
} else if (udpIn[0] == 4) //dnrgb
|
||||
{
|
||||
uint16_t id = ((udpIn[3] << 0) & 0xFF) + ((udpIn[2] << 8) & 0xFF00);
|
||||
for (uint16_t i = 4; i < packetSize -2; i += 3)
|
||||
{
|
||||
if (id >= ledCount) break;
|
||||
setRealtimePixel(id, udpIn[i], udpIn[i+1], udpIn[i+2], 0);
|
||||
id++;
|
||||
}
|
||||
}
|
||||
strip.show();
|
||||
}
|
||||
}
|
||||
|
||||
|
23
wled00/um_manager.cpp
Normal file
23
wled00/um_manager.cpp
Normal file
@ -0,0 +1,23 @@
|
||||
#include "wled.h"
|
||||
/*
|
||||
* Registration and management utility for v2 usermods
|
||||
*/
|
||||
|
||||
//Usermod Manager internals
|
||||
void UsermodManager::loop() { for (byte i = 0; i < numMods; i++) ums[i]->loop(); }
|
||||
|
||||
void UsermodManager::setup() { for (byte i = 0; i < numMods; i++) ums[i]->setup(); }
|
||||
void UsermodManager::connected() { for (byte i = 0; i < numMods; i++) ums[i]->connected(); }
|
||||
|
||||
void UsermodManager::addToJsonState(JsonObject& obj) { for (byte i = 0; i < numMods; i++) ums[i]->addToJsonState(obj); }
|
||||
void UsermodManager::addToJsonInfo(JsonObject& obj) { for (byte i = 0; i < numMods; i++) ums[i]->addToJsonInfo(obj); }
|
||||
void UsermodManager::readFromJsonState(JsonObject& obj) { for (byte i = 0; i < numMods; i++) ums[i]->readFromJsonState(obj); }
|
||||
|
||||
bool UsermodManager::add(Usermod* um)
|
||||
{
|
||||
if (numMods >= WLED_MAX_USERMODS || um == nullptr) return false;
|
||||
ums[numMods] = um;
|
||||
numMods++;
|
||||
}
|
||||
|
||||
byte UsermodManager::getModCount() {return numMods;}
|
@ -1,9 +1,11 @@
|
||||
#include "wled.h"
|
||||
/*
|
||||
* This file allows you to add own functionality to WLED more easily
|
||||
* This v1 usermod 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
|
||||
* If you just need 8 bytes, use 2551-2559 (you do not need to increase EEPSIZE)
|
||||
*
|
||||
* Consider the v2 usermod API if you need a more advanced feature set!
|
||||
*/
|
||||
|
||||
//Use userVar0 and userVar1 (API calls &U0=,&U1=, uint16_t)
|
||||
|
18
wled00/usermod_v2_empty.h
Normal file
18
wled00/usermod_v2_empty.h
Normal file
@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
|
||||
#include "wled.h"
|
||||
|
||||
//This is an empty v2 usermod template. Please see the file usermod_v2_example.h in the EXAMPLE_v2 usermod folder for documentation on the functions you can use!
|
||||
|
||||
class UsermodRenameMe : public Usermod {
|
||||
private:
|
||||
|
||||
public:
|
||||
void setup() {
|
||||
|
||||
}
|
||||
|
||||
void loop() {
|
||||
|
||||
}
|
||||
};
|
26
wled00/usermods_list.cpp
Normal file
26
wled00/usermods_list.cpp
Normal file
@ -0,0 +1,26 @@
|
||||
#include "wled.h"
|
||||
/*
|
||||
* Register your v2 usermods here!
|
||||
* (for v1 usermods using just usermod.cpp, you can ignore this file)
|
||||
*/
|
||||
|
||||
/*
|
||||
* Add/uncomment your usermod filename here (and once more below)
|
||||
* || || ||
|
||||
* \/ \/ \/
|
||||
*/
|
||||
//#include "usermod_v2_example.h"
|
||||
//#include "usermod_temperature.h"
|
||||
//#include "usermod_v2_empty.h"
|
||||
|
||||
void registerUsermods()
|
||||
{
|
||||
/*
|
||||
* Add your usermod class name here
|
||||
* || || ||
|
||||
* \/ \/ \/
|
||||
*/
|
||||
//usermods.add(new MyExampleUsermod());
|
||||
//usermods.add(new UsermodTemperature());
|
||||
//usermods.add(new UsermodRenameMe());
|
||||
}
|
@ -51,6 +51,7 @@ void WLED::loop()
|
||||
handleDMX();
|
||||
#endif
|
||||
userLoop();
|
||||
usermods.loop();
|
||||
|
||||
yield();
|
||||
handleIO();
|
||||
@ -94,35 +95,29 @@ void WLED::loop()
|
||||
initMqtt();
|
||||
}
|
||||
|
||||
|
||||
// DEBUG serial logging
|
||||
#ifdef WLED_DEBUG
|
||||
if (millis() - debugTime > 9999) {
|
||||
DEBUG_PRINTLN("---DEBUG INFO---");
|
||||
DEBUG_PRINT("Runtime: ");
|
||||
DEBUG_PRINTLN(millis());
|
||||
DEBUG_PRINT("Unix time: ");
|
||||
DEBUG_PRINTLN(now());
|
||||
DEBUG_PRINT("Free heap: ");
|
||||
DEBUG_PRINTLN(ESP.getFreeHeap());
|
||||
DEBUG_PRINT("Wifi state: ");
|
||||
DEBUG_PRINTLN(WiFi.status());
|
||||
DEBUG_PRINT("Runtime: "); DEBUG_PRINTLN(millis());
|
||||
DEBUG_PRINT("Unix time: "); DEBUG_PRINTLN(now());
|
||||
DEBUG_PRINT("Free heap: "); DEBUG_PRINTLN(ESP.getFreeHeap());
|
||||
DEBUG_PRINT("Wifi state: "); DEBUG_PRINTLN(WiFi.status());
|
||||
|
||||
if (WiFi.status() != lastWifiState) {
|
||||
wifiStateChangedTime = millis();
|
||||
}
|
||||
lastWifiState = WiFi.status();
|
||||
DEBUG_PRINT("State time: ");
|
||||
DEBUG_PRINTLN(wifiStateChangedTime);
|
||||
DEBUG_PRINT("NTP last sync: ");
|
||||
DEBUG_PRINTLN(ntpLastSyncTime);
|
||||
DEBUG_PRINT("Client IP: ");
|
||||
DEBUG_PRINTLN(WiFi.localIP());
|
||||
DEBUG_PRINT("Loops/sec: ");
|
||||
DEBUG_PRINTLN(loops / 10);
|
||||
DEBUG_PRINT("State time: "); DEBUG_PRINTLN(wifiStateChangedTime);
|
||||
DEBUG_PRINT("NTP last sync: "); DEBUG_PRINTLN(ntpLastSyncTime);
|
||||
DEBUG_PRINT("Client IP: "); DEBUG_PRINTLN(WiFi.localIP());
|
||||
DEBUG_PRINT("Loops/sec: "); DEBUG_PRINTLN(loops / 10);
|
||||
loops = 0;
|
||||
debugTime = millis();
|
||||
}
|
||||
loops++;
|
||||
#endif // WLED_DEBU
|
||||
#endif // WLED_DEBUG
|
||||
}
|
||||
|
||||
void WLED::setup()
|
||||
@ -156,6 +151,7 @@ void WLED::setup()
|
||||
int heapPreAlloc = ESP.getFreeHeap();
|
||||
DEBUG_PRINT("heap ");
|
||||
DEBUG_PRINTLN(ESP.getFreeHeap());
|
||||
registerUsermods();
|
||||
|
||||
strip.init(EEPROM.read(372), ledCount, EEPROM.read(2204)); // init LEDs quickly
|
||||
strip.setBrightness(0);
|
||||
@ -174,6 +170,7 @@ void WLED::setup()
|
||||
loadSettingsFromEEPROM(true);
|
||||
beginStrip();
|
||||
userSetup();
|
||||
usermods.setup();
|
||||
if (strcmp(clientSSID, DEFAULT_CLIENT_SSID) == 0)
|
||||
showWelcomePage = true;
|
||||
WiFi.persistent(false);
|
||||
@ -449,6 +446,7 @@ void WLED::handleConnection()
|
||||
DEBUG_PRINTLN(WiFi.localIP());
|
||||
initInterfaces();
|
||||
userConnected();
|
||||
usermods.connected();
|
||||
|
||||
// shut down AP
|
||||
if (apBehavior != AP_BEHAVIOR_ALWAYS && apActive) {
|
||||
|
@ -8,7 +8,7 @@
|
||||
*/
|
||||
|
||||
// version code in format yymmddb (b = daily build)
|
||||
#define VERSION 2005100
|
||||
#define VERSION 2006060
|
||||
|
||||
// ESP8266-01 (blue) got too little storage space to work with all features of WLED. To use it, you must use ESP8266 Arduino Core v2.4.2 and the setting 512K(No SPIFFS).
|
||||
|
||||
@ -25,7 +25,9 @@
|
||||
//#define WLED_DISABLE_CRONIXIE // saves 3kb
|
||||
//#define WLED_DISABLE_HUESYNC // saves 4kb
|
||||
//#define WLED_DISABLE_INFRARED // there is no pin left for this on ESP8266-01, saves 12kb
|
||||
#define WLED_ENABLE_MQTT // saves 12kb
|
||||
#ifndef WLED_DISABLE_MQTT
|
||||
#define WLED_ENABLE_MQTT // saves 12kb
|
||||
#endif
|
||||
#define WLED_ENABLE_ADALIGHT // saves 500b only
|
||||
//#define WLED_ENABLE_DMX // uses 3.5kb (use LEDPIN other than 2)
|
||||
|
||||
@ -415,7 +417,7 @@ WLED_GLOBAL bool blynkEnabled _INIT(false);
|
||||
// preset cycling
|
||||
WLED_GLOBAL bool presetCyclingEnabled _INIT(false);
|
||||
WLED_GLOBAL byte presetCycleMin _INIT(1), presetCycleMax _INIT(5);
|
||||
WLED_GLOBAL uint16_t presetCycleTime _INIT(1250);
|
||||
WLED_GLOBAL uint16_t presetCycleTime _INIT(12);
|
||||
WLED_GLOBAL unsigned long presetCycledTime _INIT(0);
|
||||
WLED_GLOBAL byte presetCycCurr _INIT(presetCycleMin);
|
||||
WLED_GLOBAL bool presetApplyBri _INIT(true);
|
||||
@ -426,6 +428,7 @@ WLED_GLOBAL byte realtimeMode _INIT(REALTIME_MODE_INACTIVE);
|
||||
WLED_GLOBAL byte realtimeOverride _INIT(REALTIME_OVERRIDE_NONE);
|
||||
WLED_GLOBAL IPAddress realtimeIP _INIT((0, 0, 0, 0));
|
||||
WLED_GLOBAL unsigned long realtimeTimeout _INIT(0);
|
||||
WLED_GLOBAL uint16_t tpmFirstFrameSize _INIT(0);
|
||||
|
||||
// mqtt
|
||||
WLED_GLOBAL long lastMqttReconnectAttempt _INIT(0);
|
||||
@ -490,6 +493,9 @@ WLED_GLOBAL bool e131NewData _INIT(false);
|
||||
// led fx library object
|
||||
WLED_GLOBAL WS2812FX strip _INIT(WS2812FX());
|
||||
|
||||
// Usermod manager
|
||||
WLED_GLOBAL UsermodManager usermods _INIT(UsermodManager());
|
||||
|
||||
// debug macro variable definitions
|
||||
#ifdef WLED_DEBUG
|
||||
WLED_GLOBAL unsigned long debugTime _INIT(0);
|
||||
@ -501,6 +507,7 @@ WLED_GLOBAL WS2812FX strip _INIT(WS2812FX());
|
||||
|
||||
#define WLED_CONNECTED (WiFi.status() == WL_CONNECTED)
|
||||
#define WLED_WIFI_CONFIGURED (strlen(clientSSID) >= 1 && strcmp(clientSSID, DEFAULT_CLIENT_SSID) != 0)
|
||||
#define WLED_MQTT_CONNECTED (mqtt != nullptr && mqtt->connected())
|
||||
|
||||
// append new c string to temp buffer efficiently
|
||||
bool oappend(const char* txt);
|
||||
|
@ -7,7 +7,7 @@
|
||||
*/
|
||||
|
||||
//eeprom Version code, enables default settings instead of 0 init on update
|
||||
#define EEPVER 20
|
||||
#define EEPVER 21
|
||||
//0 -> old version, default
|
||||
//1 -> 0.4p 1711272 and up
|
||||
//2 -> 0.4p 1711302 and up
|
||||
@ -29,6 +29,7 @@
|
||||
//18-> 0.9.1-e131
|
||||
//19-> 0.9.1n
|
||||
//20-> 0.9.1p
|
||||
//21-> 0.10.1p
|
||||
|
||||
void commit()
|
||||
{
|
||||
@ -547,6 +548,7 @@ void loadSettingsFromEEPROM(bool first)
|
||||
{
|
||||
presetCyclingEnabled = EEPROM.read(2205);
|
||||
presetCycleTime = EEPROM.read(2206) + ((EEPROM.read(2207) << 8) & 0xFF00);
|
||||
if (lastEEPROMversion < 21) presetCycleTime /= 100; //was stored in ms, now is in tenths of a second
|
||||
presetCycleMin = EEPROM.read(2208);
|
||||
presetCycleMax = EEPROM.read(2209);
|
||||
presetApplyBri = EEPROM.read(2210);
|
||||
@ -581,8 +583,10 @@ void loadSettingsFromEEPROM(bool first)
|
||||
EEPROM.write(2550, DMXStartLED);
|
||||
#endif
|
||||
|
||||
//user MOD memory
|
||||
//2944 - 3071 reserved
|
||||
//Usermod memory
|
||||
//2551 - 2559 reserved for Usermods, usable by default
|
||||
//2560 - 2943 usable, NOT reserved (need to increase EEPSIZE accordingly, new WLED core features may override this section)
|
||||
//2944 - 3071 reserved for Usermods (need to increase EEPSIZE to 3072 in const.h)
|
||||
|
||||
overlayCurrent = overlayDefault;
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
#include "wled.h"
|
||||
|
||||
/*
|
||||
* Adalight handler
|
||||
* Adalight and TPM2 handler
|
||||
*/
|
||||
|
||||
enum class AdaState {
|
||||
@ -13,7 +13,10 @@ enum class AdaState {
|
||||
Header_CountCheck,
|
||||
Data_Red,
|
||||
Data_Green,
|
||||
Data_Blue
|
||||
Data_Blue,
|
||||
TPM2_Header_Type,
|
||||
TPM2_Header_CountHi,
|
||||
TPM2_Header_CountLo
|
||||
};
|
||||
|
||||
void handleSerial()
|
||||
@ -33,6 +36,9 @@ void handleSerial()
|
||||
switch (state) {
|
||||
case AdaState::Header_A:
|
||||
if (next == 'A') state = AdaState::Header_d;
|
||||
else if (next == 0xC9) { //TPM2 start byte
|
||||
state = AdaState::TPM2_Header_Type;
|
||||
}
|
||||
break;
|
||||
case AdaState::Header_d:
|
||||
if (next == 'd') state = AdaState::Header_a;
|
||||
@ -57,6 +63,20 @@ void handleSerial()
|
||||
if (check == next) state = AdaState::Data_Red;
|
||||
else state = AdaState::Header_A;
|
||||
break;
|
||||
case AdaState::TPM2_Header_Type:
|
||||
state = AdaState::Header_A; //(unsupported) TPM2 command or invalid type
|
||||
if (next == 0xDA) state = AdaState::TPM2_Header_CountHi; //TPM2 data
|
||||
else if (next == 0xAA) Serial.write(0xAC); //TPM2 ping
|
||||
break;
|
||||
case AdaState::TPM2_Header_CountHi:
|
||||
pixel = 0;
|
||||
count = (next * 0x100) /3;
|
||||
state = AdaState::TPM2_Header_CountLo;
|
||||
break;
|
||||
case AdaState::TPM2_Header_CountLo:
|
||||
count += next /3;
|
||||
state = AdaState::Data_Red;
|
||||
break;
|
||||
case AdaState::Data_Red:
|
||||
red = next;
|
||||
state = AdaState::Data_Green;
|
||||
|
@ -5,7 +5,7 @@
|
||||
*/
|
||||
|
||||
//build XML response to HTTP /win API request
|
||||
char* XML_response(AsyncWebServerRequest *request, char* dest)
|
||||
void XML_response(AsyncWebServerRequest *request, char* dest)
|
||||
{
|
||||
char sbuf[(dest == nullptr)?1024:1]; //allocate local buffer if none passed
|
||||
obuf = (dest == nullptr)? sbuf:dest;
|
||||
@ -77,7 +77,7 @@ char* XML_response(AsyncWebServerRequest *request, char* dest)
|
||||
mesg += ".";
|
||||
mesg += realtimeIP[i];
|
||||
}
|
||||
} else if (realtimeMode == REALTIME_MODE_UDP || realtimeMode == REALTIME_MODE_HYPERION) {
|
||||
} else if (realtimeMode == REALTIME_MODE_UDP || realtimeMode == REALTIME_MODE_HYPERION || realtimeMode == REALTIME_MODE_TPM2NET) {
|
||||
mesg += "UDP from ";
|
||||
mesg += realtimeIP[0];
|
||||
for (int i = 1; i < 4; i++)
|
||||
@ -100,9 +100,9 @@ char* XML_response(AsyncWebServerRequest *request, char* dest)
|
||||
if (request != nullptr) request->send(200, "text/xml", obuf);
|
||||
}
|
||||
|
||||
char* URL_response(AsyncWebServerRequest *request)
|
||||
void URL_response(AsyncWebServerRequest *request)
|
||||
{
|
||||
char sbuf[256]; //allocate local buffer if none passed
|
||||
char sbuf[256];
|
||||
char s2buf[100];
|
||||
obuf = s2buf;
|
||||
olen = 0;
|
||||
|
Loading…
Reference in New Issue
Block a user