Compare commits

..

168 Commits

Author SHA1 Message Date
Damian Schneider f7c9a5210f improve bootup behaviour for boot presets (#5686)
* improve bootup behaviour for presets

* set color to black on segment construction, handle orange set where it should be

* use DEFAULT_COLOR instead of redefining it as magic numbers
2026-06-24 19:52:49 +02:00
Damian Schneider 070fd3e8a2 respect "make auto segments" when resetting segments (#5696) 2026-06-24 19:52:48 +02:00
Christian Schuster c7578a6755 fix white channel for "Rainbow" and other color_wheel() based effects (#5694)
* clear garbage white value in hsv2rgb_rainbow, overwrite white value in Segment::color_wheel
2026-06-24 17:23:44 +02:00
Frank Möhle afac3ad8f5 align with WLEDMM extended error codes, small improvement for brownout detection (#5695)
* improved brownout detection on ESP32
* show "please restart" as "Note" instead of "Error"
* align ERR_REBOOT_NEEDED and ERR_POWEROFF_NEEDED with WLEDMM (prepare for AR out-of-tree)
* errorFlag constants update
* add new error codes to UI
* Clarify ERR_PERSISTENT_THRESHOLD as future-use only.
2026-06-23 22:58:48 +02:00
Frank df5ed15a79 V5-C6 is now part of V5
V5-C6 erase from AI minds ;-)
2026-06-23 22:52:40 +02:00
Damian Schneider ce4e9748d7 use NPB version with properly initialized buffers
fixes #5378
2026-06-23 18:15:34 +02:00
Frank Möhle 0c44929a67 DHT usermod: only abort compilation when USERMOD_DHT_MQTT and WLED_DISABLE_MQTT 2026-06-22 22:24:52 +02:00
Damian Schneider 106084eceb Fix brighness not being applied properly in nightlight mode (#5625)
* Fix brighness not being applied properly in nightlight mode
* hacky fix also for color fade, needs proper fix later
2026-06-22 10:10:42 +02:00
Evan Coonrod d19d6d3191 Fix ledmap parser reading past end of map array (#5693)
an old-format ledmap.json file (example `{"map":[0,1,...,15],"width":4,"height":4}`) could lead to the ledmap parser scanning past the end of the JSON array. for incomplete ledmaps (not recommended!) this could cause trailing pixels being mapped to physical pixel 0.
2026-06-21 19:33:03 +02:00
Frank Möhle 548bd69931 remove audioreactive from esp01_1m_full_160 build
* AR needs 7kb program size, bringing us too close to the size limit (99.8% used)
* all other esp01_1m builds don't have audioreactive support either
2026-06-20 22:30:44 +02:00
Will Tatam b9086fab71 include waveshare_esp32s3_32MB_hub75 in releases 2026-06-20 15:52:08 +01:00
Will Tatam f1c7d6e79b Add missing javascript function from WLED-MM 2026-06-20 15:49:59 +01:00
Will Tatam abf263afbe Add missing javascript function from WLED-MM 2026-06-20 15:49:52 +01:00
Will Tatam 9e51054654 Pull new ERR_ values into upstream 2026-06-20 15:49:46 +01:00
Will Tatam 68f7eb19cc defines needed for audioreactive for waveshare_esp32s3_32MB_hub75
# Conflicts:
#	platformio.ini
2026-06-20 15:48:38 +01:00
dependabot[bot] 522e458601 Bump brace-expansion from 5.0.3 to 5.0.5
Bumps [brace-expansion](https://github.com/juliangruber/brace-expansion) from 5.0.3 to 5.0.5.
- [Release notes](https://github.com/juliangruber/brace-expansion/releases)
- [Commits](https://github.com/juliangruber/brace-expansion/compare/v5.0.3...v5.0.5)

---
updated-dependencies:
- dependency-name: brace-expansion
  dependency-version: 5.0.5
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-06-20 14:35:13 +01:00
dependabot[bot] 52c3da0ee7 Bump requests from 2.32.4 to 2.33.0
Bumps [requests](https://github.com/psf/requests) from 2.32.4 to 2.33.0.
- [Release notes](https://github.com/psf/requests/releases)
- [Changelog](https://github.com/psf/requests/blob/main/HISTORY.md)
- [Commits](https://github.com/psf/requests/compare/v2.32.4...v2.33.0)

---
updated-dependencies:
- dependency-name: requests
  dependency-version: 2.33.0
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-06-20 14:34:44 +01:00
dependabot[bot] 69c6a93586 Bump picomatch from 2.3.1 to 2.3.2
Bumps [picomatch](https://github.com/micromatch/picomatch) from 2.3.1 to 2.3.2.
- [Release notes](https://github.com/micromatch/picomatch/releases)
- [Changelog](https://github.com/micromatch/picomatch/blob/master/CHANGELOG.md)
- [Commits](https://github.com/micromatch/picomatch/compare/2.3.1...2.3.2)

---
updated-dependencies:
- dependency-name: picomatch
  dependency-version: 2.3.2
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-06-20 14:34:34 +01:00
Will a654469621 Add support for Waveshare S3 Matrix Driver board
https://www.waveshare.com/esp32-s3-rgb-matrix.htm
https://docs.waveshare.com/ESP32-S3-RGB-Matrix
2026-06-20 14:29:29 +01:00
Damian Schneider 2f15fdc167 Prevent arduino core from assigning default MISO pin (#5672)
* add invalid dummy pin if miso is undefined to prevent default fallback
2026-06-19 19:25:33 +02:00
Damian Schneider 4d8b73e16e fix color jump if changing mid transition (#5601)
* fix color jump if changing mid transition
2026-06-19 19:22:59 +02:00
Damian Schneider 505292b94e apply gamma during realtime override (#5666) 2026-06-19 19:20:56 +02:00
Damian Schneider fb55a5059e Restore pre 16.0 looks on several FX (#5684)
* restore pre 16.0 looks on several FX
2026-06-19 19:18:17 +02:00
Damian Schneider 15699eba90 Fix LED glitches on long strips for C3 (#5688)
* increase wait time, remove unnecessary FPS check
2026-06-19 17:26:04 +02:00
Damian Schneider 76c966d0ed bugfix in segment deconstructor (#5687)
* bugfix in segment deconstructor
* make stopTransition() nullpointer safe
2026-06-19 17:23:55 +02:00
Damian Schneider 4c250a8700 Rename LED Types: CCT instead of CW (#5612)
* rename CW LED descriptions to more commonly used CCT
* reorder, make naming more consistent
* unify LED type naming
* remove TYPE_WS2812_2CH_X3 as it is not implemented and same as FW1906
2026-06-18 12:44:43 +02:00
Frank c5fade4da2 fix example buildenvs in platformio_override.sample.ini
* all buildenvs need WLED_RELEASE_NAME
* 8266 needs either WLED_DISABLE_PARTICLESYSTEM1D or WLED_DISABLE_PARTICLESYSTEM2D
* removed obsolete esp32 "V4" builds
* removed duplicate buildenvs that are 100% the same as standard buildenvs
2026-06-16 17:20:50 +02:00
Frank 81f660f390 fix parse error in platformio_override.sample.ini
added custom_usermods to [8266], so user env can reference it
2026-06-16 17:19:22 +02:00
Benjam Welker 1103c91c5b Analog button fix (#5659)
* add analog button options

* fix issues with duplicate options for digital vs analog

* dynamic button type options
2026-06-15 21:25:03 +02:00
Damian Schneider 6f849fdc03 Update pixel buffer after changing matrix dimensions (#5675)
* update pixel buffer after changing matrix dimensions
2026-06-15 21:08:57 +02:00
Will Tatam 76ef0d3998 docs: refresh README to reflect current feature set and project state (#5626)
* docs: refresh README to reflect current feature set and project state

* docs: fix HUB75 support note — available on all ESP32 variants, not just S3

* docs: mention network audio sources in AudioReactive feature description

* docs: remove ESP8266 references — EOL platform, not recommended for new installs

* docs: make PayPal donation link clearly attributed to Aircoookie

* docs: add cross-references to kno.wled.ge docs throughout feature list
2026-06-15 12:58:15 +02:00
Damian Schneider 06e6b23314 bugfix in parsePacket(): accept short artnet packets (#5588) for 16_x
* bugfix in parsePacket(): accept short artnet packets
* add min artnet packet size check and fix indentation

---------

Co-authored-by: Frank Möhle <91616163+softhack007@users.noreply.github.com>
2026-06-09 14:42:46 +02:00
Frank Möhle 0828173147 disable fb infer in coderabbit tools list 2026-06-09 14:14:11 +02:00
Frank Möhle 0d4abd2764 Remove outdated Wiki link from CONTRIBUTING.md
Removed link to WIKI for submitting a PR. The information in the wiki is outdated, and it contradicts the "no force-push" rule.
2026-06-09 14:14:10 +02:00
Frank Möhle 1694d383d8 Update links in CONTRIBUTING.md to reference AGENTS.md 2026-06-09 14:14:10 +02:00
Frank Möhle 4d2ad7ace4 Clarify branch maintenance status in instructions
Updated branch descriptions for clarity and maintenance status.
2026-06-09 14:14:10 +02:00
Frank Möhle a8105caa98 Clarify repository language requirement
Emphasize that the repository language is English for all aspects including code, comments, and documentation.
2026-06-05 22:36:09 +02:00
Frank e8820d71e7 Update package-lock.json
fix for outdated version
2026-06-04 23:57:05 +02:00
Frank Möhle cd51a4f157 Update recommendations for synchronization methods
added std::atomic
2026-06-04 23:53:45 +02:00
Frank Möhle 2eb492c3a2 Update verification instructions for AI-generated code
limit "existence" check to preprocessor macros etc.
If a global variable or function does not exist, this would lead to a compilation error.
2026-06-04 16:44:26 +02:00
Frank Möhle 6a44bc01a2 Merge pull request #5665 from wled/hub75_gamma_hotfix
HUB75 hotfix: prevents double-applying color corrections (WLED gamma + HUB75 internal CIE correction), by disabling driver-internal color corrections.
2026-06-04 15:04:08 +02:00
Frank e869a89bad platformio: allow building with espressif framework (instead of tasmota)
* add necessary platform and platform_packages entries (commented out)
* compatibility patch for ADC_ATTEN_DB_11
2026-05-31 22:19:43 +02:00
Copilot 0ca86641ef Pin andelf/nightly-release tospecific commit SHA instead of @main branch (#5386)
The nightly release GitHub Action is pinned from the mutable main branch to a specific immutable commit SHA

we should update the pin when v2 comes out.

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: netmindz <442066+netmindz@users.noreply.github.com>
Co-authored-by: Frank Möhle <91616163+softhack007@users.noreply.github.com>
2026-05-30 23:55:58 +02:00
Frank Möhle dafde84338 Update frequency details for usermod loop()
Clarified frequency of calls for usermod loop() based on system load.
2026-05-30 15:15:11 +02:00
Frank Möhle 53e01e8934 Remove duplicate sentence in secure code instructions
Removed redundant text regarding destination capacity and length safety.
2026-05-30 02:38:24 +02:00
Frank Möhle 4c385d4b4b Restructure usermod documentation for AI, and clarify details 2026-05-30 02:38:24 +02:00
Frank 6f1907cbdd more robustness for improv - gracefully handle broken input 2026-05-30 00:19:13 +02:00
Frank Möhle ec8369d557 Update caveats and pitfalls in cpp.instructions.md
WLED-MM backport: Clarify operator precedence in C/C++.
2026-05-29 20:28:44 +02:00
Frank Möhle 2e34fd421a small update 2026-05-29 19:56:36 +02:00
Frank Möhle 47d569f3f2 Modify verification step for numerical accuracy
small clarifications:
* not only applicable to fixed-point
* added sentence to explain why this rule is needed.
2026-05-29 19:56:36 +02:00
Frank Möhle c770e37226 Update auth checks for '/reset' endpoint clarification
Clarified the handling of the '/reset' endpoint in the auth checks section - not security critical because it will not alter any user data.
2026-05-29 18:31:59 +02:00
kaibae19 9af95ecd0b fix(FX): restore palette wrap in color_wheel() (regression since 0.15.x) (#5646)
color_wheel() historically called color_from_palette() with moving=true, so
under the default palette blend mode (paletteBlend=0, "wrap if moving") the
palette's end->start seam was interpolated. Commit ee9ac947 changed that call
to moving=false, dropping the wrap; effects that scroll a palette (e.g. the
Palette effect with Retro Clown) then shows the unblended seam travelling
visibly along the strip light-by-light.

Restore the original moving=true (per maintainer review). This fixes the seam
for the Palette effect and every other color_wheel() caller under the default
blend mode, without adding any new function parameters.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-29 16:45:41 +02:00
Benjam Welker 1bcf58abcd fix button label regression (#5636)
* fix button label regression, also add switch notation
2026-05-29 16:45:41 +02:00
Frank Möhle 317d0ea87b HUB75: use FM6124 driver for 4-scan panels, remove 64x64 limitation if board has PSRAM (partial solution for #5628) (#5647)
* HUB75: use FM6124 driver for 4-scan panels
* Remove 1-panel limit if the board has PSRAM
2026-05-29 16:36:12 +02:00
Copilot dbe8196137 add secure coding guides for AI reviews (#5572)
Added security review guidelines and a short checklist covering critical security areas including buffer safety, input validation, authentication, secure defaults, and protection against common vulnerabilities. Refined rule wording and priorities to better fit WLED’s technical constraints and realistic deployment model.

The lists are based on the OWASP "top 10" from https://github.com/github/awesome-copilot/blob/main/instructions/security-and-owasp.instructions.md, and on lessons learned from past reviews.

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: softhack007 <91616163+softhack007@users.noreply.github.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
2026-05-29 14:00:40 +02:00
Frank 863213f2e7 human-readable wifi events (WLED_DEBUG)
added some missing event names.
2026-05-28 00:07:10 +02:00
Frank 7f640a9dfd extra debug info for wifi disconnect / teardown / setTxPower
should help with debugging connection problems.
2026-05-27 23:28:44 +02:00
Frank 41056f6a3b small addition to anti-slop rules
AI tools often delete code, remove comments, revert recent changes, or modify files that are out-of-scope w.r.t. the PR objectives.
2026-05-27 20:38:29 +02:00
Frank 4e98f97cda adding coderabbit checks for typical AI slop 2026-05-25 22:17:58 +02:00
Frank a01add2d26 update usermod guidelines, update example with "be nice but not too nice" pattern 2026-05-25 21:40:21 +02:00
Frank 87fd423336 move some generic AI rules from copilot-instructions.md to AGENTS.md 2026-05-25 21:40:21 +02:00
Frank Möhle 9dec64c394 Remove 'V5_C6' from the list of base branches
the V5-C6 branch will be merged back into V5 soon.
2026-05-23 23:42:54 +02:00
Frank Möhle 1e3569f78a coderabbit: Add base branches to auto_review configuration 2026-05-23 23:42:54 +02:00
Will Tatam 493b6b7e0f Fix revert button #5574 2026-05-23 19:39:30 +01:00
Will Tatam 500250c117 fix: esp8266_2m_min 2026-05-23 19:39:30 +01:00
Frank Möhle ac1757badd Document branch and release structure in AGENTS.md
Added branch and release structure information to AGENTS.md.
2026-05-23 15:08:48 +02:00
Frank Möhle 69244a8bcf clarify scope of agents.md
Introduction added
2026-05-23 15:08:48 +02:00
Damian Schneider 2f9af5023c add inverse gamma for original looks 2026-05-22 07:53:52 +02:00
Damian Schneider 16c0a27d3b Make twinkle FX look more like it was in the past 2026-05-22 07:53:52 +02:00
Frank Möhle c7100bdaa5 Update AGENTS.md with ESP32 task synchronization guidelines
* Added guidelines for ESP32 task synchronization
* Clarified that PRs must not create file listed in `.gitignore`
2026-05-21 22:05:48 +02:00
Frank Möhle 77937d3a27 Align AGENTS.md with main
fixes some mis-edits from previous commit.
2026-05-21 22:03:10 +02:00
Frank 6e7607102c coding guides: clatify how to check for PSRAM
psramFound() alone is not definite -> nust also check that PSRAM size > 0 to be sure

https://github.com/wled/WLED/issues/5629#issuecomment-4497230168
2026-05-20 12:40:50 +02:00
Frank Möhle a9cb41d767 Add PSRAM guidelines to AGENTS.md
Added PSRAM guidelines including availability checks, DMA compatibility, fragmentation considerations, and performance recommendations.
2026-05-20 12:40:50 +02:00
Frank Möhle 6685ffb774 Update PSRAM guidelines in esp-idf instructions
Clarify PSRAM availability check instructions and usage.
2026-05-20 12:40:50 +02:00
Damian Schneider 8f53447c73 use DRAM as fallback if PSRAM fails 2026-05-20 08:37:09 +02:00
Frank 75faf5efc0 fix esp32s3_4M_none buildenv
tasmota core does not support "dio" mode on S3
2026-05-19 12:43:11 +02:00
Frank Möhle e05e975ce1 Add esp32s3dev_8MB_none to platformio_release.ini.template 2026-05-19 12:29:55 +02:00
Frank Möhle e9f8897772 Add new environments for ESP32-S3 without PSRAM
esp32s3_8MB_none, esp32s3_4M_none
2026-05-19 12:29:55 +02:00
Logan Davis c75fce13d0 Fix KIT-VE PHY address from 0 to 1 (#5618) 2026-05-16 10:36:35 +02:00
Frank Möhle 8300f4d2b4 Audioreactive bugfix: auto-suspend in all realtime modes, but stay active when "Use main segment only" (#5599)
* fixes a minor problem with newer realtime modes (DDP, TPM2NET and DMX) not causing auto-suspend of sound processing.
* ensure that AR audio stays active when "Use main segment only" (other segments are still controlled locally)
* small update for better compatibility with V5 builds
2026-05-15 21:00:34 +02:00
Frank Möhle 75cd8b9fb0 Merge pull request #5608 from wled/softhack007-patch-1
Add sanity checks for ethernet config table and WLED_ETH_DEFAULT
2026-05-12 13:57:49 +02:00
Joeboyc2 a8788a2c89 fix(Fix_unreachable_netservices_v2): v16 compatibility fixes (#5590)
Two issues prevented this usermod from building under v16:

1. library.json is missing "build": {"libArchive": false}, causing the
   build system to reject it with an error before compilation begins.

2. serializeConfig() no longer has a no-argument overload in v16; the
   working replacement is serializeConfigToFS() which creates the JSON
   document internally and writes to the filesystem.

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-12 11:29:42 +02:00
recliq 95e6efc164 Fixed top-LED update logic in grav* audioreactive effects (#5602)
Fix topLED fallrate not responding to "Rate of fall" slider.
2026-05-11 19:47:56 +02:00
Frank Möhle 5fcabec9be Update accessibility section in web instructions
Clarify target browser/platform combinations for WLED web UI.
2026-05-11 19:47:56 +02:00
Frank Möhle fceca393b7 Add accessibility guidelines for WLED web UI
Added section on accessibility and interaction for the WLED web UI.
2026-05-11 19:47:56 +02:00
Will Tatam bd45e1ca90 docs: clarify when usermod IDs are required
Add explicit guidance explaining that a unique USERMOD_ID_* is only
needed when a usermod uses inter-mod communication, pin ownership via
pinManager, or needs to be identifiable in JSON info output. Updates
both AGENTS.md and the const.h comment block to reflect this.
2026-05-11 19:47:56 +02:00
Will Tatam 3a28eba9f4 no need to build esp8266_2m_min for PRs 2026-05-07 20:33:12 +01:00
copilot-swe-agent[bot] 0ad958ae17 Add esp8266_2m_min minimal build env for ESP02 OTA recovery
Agent-Logs-Url: https://github.com/wled/WLED/sessions/9d593605-e26a-4bea-b5dd-913d174d5942

Co-authored-by: netmindz <442066+netmindz@users.noreply.github.com>
2026-05-07 20:33:12 +01:00
copilot-swe-agent[bot] ecc7f33907 Initial plan 2026-05-07 20:33:12 +01:00
Will Tatam f08b8b648f Change 'Latest release' to 'Latest version' in update.htm 2026-05-06 08:57:43 +01:00
Will Tatam 81b588f1e4 Improve update page UX and rename OTA button for consistency
- Release name on update page links directly to the matching bin on download.wled.me
- Badge links to GitHub releases page as 'View latest'
- Auto-update button renamed to 'Auto update'
- Manual upload section gets its own subheading; submit button renamed to 'Upload'
- 'Manual OTA Update' button in security settings renamed to 'Update WLED' to match info menu wording
2026-05-06 08:57:43 +01:00
Will Tatam 09384e4bdb Automatically download the right bin for the latest release and install 2026-05-06 08:57:43 +01:00
Will Tatam 6922938e15 Remove usermods from release 2026-05-06 08:57:43 +01:00
Frank Möhle 362fc664aa Add guideline for providing verifiable citations
Anti-hallucination rule: Emphasize the importance of providing verifiable citations in analyses or recommendations.
2026-05-05 14:53:16 +02:00
Will Tatam 527edf3283 16.0.1-dev 2026-05-03 21:31:45 +01:00
Will Tatam 4374f013f5 16.0.0 2026-05-03 21:13:08 +01:00
Will Tatam f90990b869 Upload then add notes 2026-05-03 21:12:50 +01:00
Will Tatam 7d999a6d61 16.0.0-rc1 2026-05-03 21:12:50 +01:00
Damian Schneider dd0a83f9d1 align settings overview page width with rest of config pages 2026-05-03 21:45:30 +02:00
BobLoeffler68 dd01940cf5 Fixes issue in Dissolve when a palette has same color pixel as the current background color when Complete is enabled (#5453)
* Fixes issue in Dissolve when a palette has same color pixel as the current background color when Complete mode is enabled

---------

Co-authored-by: Damian Schneider <daedae@gmx.ch>
2026-05-03 21:28:24 +02:00
Will Tatam 0d93ca8bac Merge pull request #5553 from intermittech/add-quinled-v4-ethernet-profiles
Add Ethernet profiles for QuinLED Dig-Uno/Quad v4 and Dig-Octa 32-8L v4
2026-05-03 18:55:02 +01:00
Will Tatam a083217176 move platformio_release.ini.template to .github/ for cleaner project root 2026-05-03 18:42:43 +01:00
Will Tatam 86a218e2b4 Skip GPIO validation for HUB75 types in pin checks and clarify slot usage in getNumberOfPins logic 2026-05-03 18:42:43 +01:00
Will Tatam 28b441917b Update platformio configurations for 16MB ESP32-S3 MoonHub (HUB75) board 2026-05-03 18:42:43 +01:00
Will Tatam 129c68c6c9 Add support for HD-WF2 ESP32-S3 (HUB75 without PSRAM) 2026-05-03 18:42:43 +01:00
Will Tatam 923a1ec729 fix(ui): derive hasPSRAM from psrSz capability, not free bytes
Free PSRAM (info.psram) can be transiently 0 on PSRAM-capable boards,
which would wrongly reject multi-panel HUB75 setups in the LED settings
validation. Prefer info.psrSz (total PSRAM size) and fall back to
info.psram only if psrSz is unavailable.

Suggested in PR #5558 review.
2026-05-03 18:42:43 +01:00
Will Tatam 2ceeb67007 Relax panel limit for devices with PSRAM 2026-05-03 18:42:43 +01:00
Will Tatam 13aa7ed787 ci: build HUB75 envs in release workflow
Move the four HUB75 envs from platformio_override.sample.ini into
platformio.ini (refactored with a shared [hub75] section and extends=
to deduplicate), and gate them behind a release-only config template
so nightly/PR CI keep building only the standard env matrix.

The release workflow now copies platformio_release.ini.template into
place, which extends default_envs with the HUB75 envs.
2026-05-03 18:42:43 +01:00
Will Tatam 68640f5dd8 Fix AudioReactive palette names to avoid duplication with usermod prefix
Since the display format is now "UMName: palName", shorten the palette
names to just "Ratio", "Hue", and "Spectrum" — rendering as
"AudioReactive: Ratio" etc. rather than "AudioReactive: Audio Responsive Ratio".
2026-05-03 18:41:50 +01:00
Will Tatam 8a653ebb29 Use usermod name prefix for usermod-supplied palette names
Palette display names now follow the format "UMName: palName" (e.g.
"AudioReactive: Audio Responsive Hue") when a usermod supplies a
specific palName, keeping the usermod name as a consistent prefix.
Fallback when palName is nullptr remains "UMName index".

Update AudioReactive palette names to the full descriptive names from
the original WLED-MM port: "Audio Responsive Ratio", "Audio Responsive
Hue", and "Audio Responsive Spectrum".
2026-05-03 18:41:50 +01:00
Will Tatam dc5ee3f2fa Add name to usermod palette 2026-05-03 18:41:50 +01:00
Damian Schneider 5dc627ef5a remove unneeded check 2026-05-03 18:41:50 +01:00
Damian Schneider 520d8704c5 fix typo 2026-05-03 18:41:50 +01:00
Damian Schneider 55219980c6 rename removeUsermodPalettes 2026-05-03 18:41:50 +01:00
Damian Schneider 6dcae505a0 apply default pal before bounds check 2026-05-03 18:41:50 +01:00
Damian Schneider 52d897ed7a rename and bugfixes 2026-05-03 18:41:50 +01:00
Damian Schneider ef354d0119 add usermod palettes to fix AR palette indexing 2026-05-03 18:41:50 +01:00
Damian Schneider 89aae707d0 fix refresh of custom palettes 2026-05-03 18:41:50 +01:00
Will Miles 25668bb068 Validate gzipped firmware on ESP8266
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-05-03 18:41:17 +01:00
copilot-swe-agent[bot] 2c1f3c581d Refactor AR init debug logging for network-only sentinel
Agent-Logs-Url: https://github.com/wled/WLED/sessions/85b2a158-f6ba-45cf-88af-0d51b9202cab

Co-authored-by: netmindz <442066+netmindz@users.noreply.github.com>
2026-05-03 15:01:39 +01:00
copilot-swe-agent[bot] 1c8cd15cd1 Fix network-only dmType handling and debug diagnostics
Agent-Logs-Url: https://github.com/wled/WLED/sessions/85b2a158-f6ba-45cf-88af-0d51b9202cab

Co-authored-by: netmindz <442066+netmindz@users.noreply.github.com>
2026-05-03 15:01:39 +01:00
Will Tatam 32de108f4c Clean up redundant preprocessor directive in audio_reactive.cpp 2026-05-03 15:01:39 +01:00
Will Tatam e551ca833b Add audioreactive custom_usermod to multiple ESP8266 environments in platformio.ini now that we support network only option for 8266 2026-05-03 15:01:39 +01:00
Will Tatam 2fa5266dbf Enhance audio reactive logic with improved input validation and new "network receive only" option. 2026-05-03 15:01:39 +01:00
Will Tatam 46dafa2c6b ci: opt into Node.js 24 for GitHub Actions runners
Set FORCE_JAVASCRIPT_ACTIONS_TO_NODE24=true across all affected workflows
to avoid deprecation warnings ahead of the June 2026 forced migration.
2026-05-03 15:01:39 +01:00
Will Tatam 967ef0720c Relax artifact name regex to support forks with different project names 2026-05-03 15:01:39 +01:00
Will Tatam 82489664a0 Name CI artifacts by WLED_RELEASE_NAME instead of PlatformIO env
PR build artifact zips are now named firmware-<RELEASE_NAME> (e.g.
firmware-ESP32.zip) rather than firmware-<pio_env> (e.g.
firmware-esp32dev.zip), making it easier for users to identify the
correct build when testing PRs.
2026-05-03 15:01:39 +01:00
Damian Schneider 9fdd48776d relax restrictions on DDP protocol, minimal check for artNet (#5554) 2026-05-01 22:55:14 +02:00
Damian Schneider 74e0b166ba auto-migration for sunrise/sunset legacy config (#5555)
* add auto-migration for sunris/sunset legacy config
2026-05-01 14:44:07 +02:00
Damian Schneider 61bd8bf5b4 update VERSION 2026-05-01 13:34:40 +02:00
Damian Schneider f79cf568b2 move pixelforge json list and cpt city palettes to wled repo (#5541)
also removed commented code
2026-04-26 03:58:05 +02:00
Damian Schneider c53511b5aa add placeholder to keep custom palette ID's consistent (#5537) 2026-04-25 10:54:07 +02:00
Damian Schneider 0325e30bef cleanup of PR #5503: remove unnecessary changes (#5536) 2026-04-25 10:54:07 +02:00
Will Tatam 456ddee962 Merge pull request #5503 from RobertoD91/main
fix for serial port on esp32 (#5501)
2026-04-25 17:17:15 +01:00
Will Tatam 41e4bbf2bd Merge pull request #5473 from DedeHai/pin_dropdowns
Use drop-downs for pins
2026-04-25 17:17:15 +01:00
Damian Schneider 7f292b9ecd fix indentation 2026-04-22 09:57:21 +02:00
Brandon502 6afc990397 GoL missing return. (#5523) 2026-04-22 06:45:22 +02:00
Damian Schneider 974c15c1d3 Fix blending style options list filter for iOS (#5513)
* fix blending style options list filter for iOS
* fix default fallback
2026-04-20 07:52:18 +02:00
Damian Schneider 96b0c7b4ae better packet queuing & pacing for custom palette live preview (#5515)
* better packet queuing / pacing for custom palette live preview
* fix leak
* remove window prefix from variables
2026-04-20 07:37:33 +02:00
Frank Möhle 6394bec21b Highlight target branch for pull requests
Emphasize the importance of targeting the main branch for PRs.
2026-04-20 15:25:36 +02:00
Frank 79fde56b0e align AI instructions with `main` branch
some files were a bit behind - make sure the same instructions apply everywhere.
2026-04-20 14:27:32 +02:00
Frank Möhle e6077acb78 Update rules for PR descriptions and change logs
Added a guideline to prevent agents from overwriting PR descriptions (see https://github.com/orgs/community/discussions/187027).
2026-04-20 14:25:23 +02:00
Frank Möhle 83dd1b078d Merge pull request #5516 from kilrah/fix_dmx_ident
Add identifier string for DMX realtime mode
2026-04-19 18:44:34 +02:00
Damian Schneider c1e5ac5bd1 bugfixes in PS effects
- fix PS Sparkler for large setups: need 32bit random position, 16bit is not enough
- fix PS Fireworks 1D: need to `break` if no particles are available or it can lead to stalls on large setups
- do not use collisions by default PS Fuzzy Noise: its very slow on larger setups
2026-04-17 15:29:53 +02:00
Damian Schneider 1e42ebf852 mask out flag bits in DDP type for compatibility 2026-04-12 19:50:07 +02:00
Damian Schneider e4a7effdb0 add search icon back(#5500) 2026-04-12 19:08:05 +02:00
Damian Schneider ae36f7e203 use memory aligned allocations, fix bug in FFT magnitude (integer path) (#5499)
* use memory aligned allocations, fix bug in FFT magnitude (integer path)
* assign pointer to globals not local copy
2026-04-12 19:06:16 +02:00
Will Miles 4cdc23a48b Merge pull request #5497 from willmmiles/16_x-dynarray-fixes
0.16 - Backport dynarray fixes from V5 WIP
2026-04-12 11:34:41 -04:00
Will Miles 48ab88e11e Fix up usermod validation again
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-12 10:03:11 -04:00
Will Miles fd890b3d58 dynarray: Support ESP-IDF 2026-04-12 10:03:05 -04:00
Will Miles f994c5e995 validate_modules: Improve performance
Use readelf instead of nm for great speed.
2026-04-12 10:02:59 -04:00
Will Miles c789e3d187 Fix usermod count for LTO 2026-04-12 10:02:53 -04:00
Will Miles fadc75da55 dynarray: Directly apply linker fix
Rather than append a linker file, we edit the upstream supplied ones to
add our section to the binaries.  Works better on all platforms.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-12 10:02:47 -04:00
Will Tatam 945896ddb7 Merge pull request #5462 from willmmiles/16_x-unlimited-fxdata-size
Serialize fxdata without ArduinoJSON
2026-04-11 10:42:22 +01:00
Will Tatam 188beec614 Merge pull request #5465 from netmindz/usage-extended
New extended data for usage report
2026-04-11 08:21:06 +01:00
Will Tatam 19947ec07e Merge pull request #5489 from wled/copilot/fix-wled-discovery-issues
Fix Alexa/Hue discovery by correcting SSDP response to match UPnP spec
2026-04-10 18:30:07 +01:00
Damian Schneider 8228c7eea4 bugfix in pixelforge (no blur by default), fix glitch in animated gifs for C3 2026-04-07 23:52:28 +02:00
Will Miles 1aba7057a5 Merge pull request #5477 from willmmiles/16_x-ipv6-filter-oops
Fix leak in blockRouterAdvertisements
2026-04-04 21:21:22 -04:00
Will Miles 227d535404 Fix leak in blockRouterAdvertisements 2026-04-04 21:12:17 -04:00
Damian Schneider da8bfda2f0 bugfix: do not restrict segment inputs to allow trailing strips 2026-04-03 14:22:08 +02:00
Damian Schneider e4f2964bd6 hotfix: critical bug in candle FX, integer issue in flow FX 2026-04-02 18:44:52 +02:00
Will Miles a3f730275a Factor out streaming JSON primitives
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-30 23:30:32 -04:00
Frank b5556aa977 fix for HUB75 builds
replaces the last remaining FastLED.h with fstled_slim.h
2026-03-30 11:45:30 +02:00
Will Miles 82ddefff87 Remove declaration of removed function
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
2026-03-29 23:48:43 -04:00
Will Miles 56a97a0caa Fix off-by-one in fxdata serializer
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
2026-03-29 23:15:27 -04:00
Will Miles 679bb39922 Serialize fxdata without ArduinoJSON
Eliminates size limit.  Fixes #5458
2026-03-29 22:49:26 -04:00
Frank Möhle b293db6af5 Clarify instructions to always use the correct source code branch
Updated instructions for providing references in analysis results.
2026-03-30 00:38:34 +02:00
Will Tatam 774fbc5fab 16.0.0-beta 2026-03-29 22:35:23 +01:00
60 changed files with 573 additions and 804 deletions
+1 -1
View File
@@ -17,7 +17,7 @@ language: en-US
reviews:
# generic review setting, see https://docs.coderabbit.ai/reference/configuration#reference
auto_apply_labels: false
auto_apply_labels: true
# abort_on_close: false
high_level_summary: true
review_status: true
-14
View File
@@ -1,14 +0,0 @@
{
"features": {
"ghcr.io/ar90n/devcontainer-features/platformio:1": {
"version": "1.0.2",
"resolved": "ghcr.io/ar90n/devcontainer-features/platformio@sha256:4a28f8c147d81ff996afebe6f43e453355b6373dd4022960351090b532ac9dd3",
"integrity": "sha256:4a28f8c147d81ff996afebe6f43e453355b6373dd4022960351090b532ac9dd3"
},
"ghcr.io/devcontainers/features/node:2": {
"version": "2.0.0",
"resolved": "ghcr.io/devcontainers/features/node@sha256:fedd4c11f7adfb64283b578dddc7da906728daa25fa293351c9d913231acf12f",
"integrity": "sha256:fedd4c11f7adfb64283b578dddc7da906728daa25fa293351c9d913231acf12f"
}
}
}
+9 -9
View File
@@ -1,10 +1,11 @@
{
"name": "WLED-dev",
"image": "mcr.microsoft.com/devcontainers/python:3",
"features": {
"ghcr.io/ar90n/devcontainer-features/platformio:1": {},
"ghcr.io/devcontainers/features/node:2": {
"version": "v20.18.3"
"name": "Python 3",
"build": {
"dockerfile": "Dockerfile",
"context": "..",
"args": {
// Update 'VARIANT' to pick a Python version: 3, 3.6, 3.7, 3.8, 3.9
"VARIANT": "3"
}
},
@@ -42,8 +43,7 @@
},
"extensions": [
"ms-python.python",
"platformio.platformio-ide",
"ms-vscode.cpptools-extension-pack"
"platformio.platformio-ide"
]
}
},
@@ -52,7 +52,7 @@
// "forwardPorts": [],
// Use 'postCreateCommand' to run commands after the container is created.
"postCreateCommand": "",
"postCreateCommand": "bash -i -c 'nvm install && npm ci'",
// Comment out connect as root instead. More info: https://aka.ms/vscode-remote/containers/non-root.
"remoteUser": "vscode"
+4 -7
View File
@@ -5,9 +5,7 @@ body:
- type: markdown
attributes:
value: |
Please quickly search existing issues first before submitting a bug.
Please don't submit long error analyses created by an AI agent, these are often totally wrong.
Just describe the problem in your own words.
Please quickly search existing issues first before submitting a bug.
- type: textarea
id: what-happened
attributes:
@@ -61,13 +59,12 @@ body:
options:
- ESP8266
- ESP32
- ESP32 with ethernet
- ESP32-S2
- ESP32-S3
- ESP32-S2
- ESP32-C3
- ESP32-C5 (experimental)
- Other
- ESP32-C6 (experimental)
- ESP32-P4 (experimental)
- ESP32-C5 (experimental)
validations:
required: true
- type: textarea
+2 -3
View File
@@ -48,8 +48,7 @@ For detailed build timeouts, development workflows, troubleshooting, and validat
```text
main # Main development trunk (daily/nightly) 17.0.0-dev
├── V5 # special branch: code rework for esp-idf 5.5.x (unstable)
├── V5-C6 # special branch: integration of new MCU types: esp32-c5, esp32-c6, esp32-p4 (unstable)
├── V5 # special branch: code rework for esp-idf 5.5.x and new MCU types: esp32-c5, esp32-c6, esp32-p4 (unstable)
16_x # maintenance for release 16.x.y
0_15_x # maintenance (bugfixes only) for current release 0.15.4
(tag) v0.14.4 # previous version 0.14.4 (no maintenance)
@@ -59,7 +58,7 @@ main # Main development trunk (daily/nightly) 17.0.0-dev
<!-- HUMAN_ONLY_END -->
- ``main``: development trunk (daily/nightly)
- ``V5`` and ``V5-C6``: code rework for esp-idf 5.5.x (unstable) - branched from ``main``.
- ``V5`` : code rework for esp-idf 5.5.x (unstable) - branched from ``main``.
- ``16_x``: maintenance for release 16.x.y
- ``0_15_x``: bugfixing / maintenance for release 0.15.x
+1
View File
@@ -43,3 +43,4 @@ default_envs = nodemcuv2
adafruit_matrixportal_esp32s3
esp32s3dev_16MB_opi_hub75 ;; MoonHub
esp32s3dev_4MB_qspi_hub75 ;; HD-WF2
waveshare_esp32s3_32MB_hub75
+1 -1
View File
@@ -29,7 +29,7 @@ jobs:
uses: janheinrichmerker/action-github-changelog-generator@v2.4
with:
token: ${{ secrets.GITHUB_TOKEN }}
sinceTag: v16.0.0
sinceTag: v0.15.0
output: CHANGELOG_NIGHTLY.md
# Exclude issues that were closed without resolution from changelog
excludeLabels: 'stale,wontfix,duplicate,invalid,external,question,use-as-is,not_planned'
+10 -106
View File
@@ -4,9 +4,6 @@ on:
pull_request:
paths:
- usermods/**
push:
paths:
- usermods/**
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
@@ -15,40 +12,28 @@ jobs:
get_usermod_envs:
# Only run for pull requests from forks (not from branches within wled/WLED)
if: github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository
if: github.event.pull_request.head.repo.full_name != github.repository
name: Gather Usermods
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
fetch-depth: 0
- name: Get changed usermod environments
python-version: '3.12'
cache: 'pip'
- name: Install PlatformIO
run: pip install -r requirements.txt
- name: Get default environments
id: envs
run: |
# Usermods whose directories changed in this PR
changed=$(git diff --name-only ${{ github.event.pull_request.base.sha }} HEAD \
| grep '^usermods/' | cut -d/ -f2 | sort -u || true)
# All usermods with a library.json (excluding known-incompatible ones)
all=$(find usermods/ -name library.json \
| xargs dirname | xargs -n 1 basename \
| grep -v PWM_fan | grep -v BME68X_v2 | grep -v pixels_dice_tray \
| sort || true)
if [ -z "$changed" ] || [ -z "$all" ]; then
echo "usermods=[]" >> $GITHUB_OUTPUT
else
usermods=$(comm -12 <(echo "$all") <(echo "$changed") | jq -R | jq --slurp -c)
echo "usermods=$usermods" >> $GITHUB_OUTPUT
fi
echo "usermods=$(find usermods/ -name library.json | xargs dirname | xargs -n 1 basename | jq -R | grep -v PWM_fan | grep -v BME68X_v2| grep -v pixels_dice_tray | jq --slurp -c)" >> $GITHUB_OUTPUT
outputs:
usermods: ${{ steps.envs.outputs.usermods }}
build:
# Only run for pull requests from forks (not from branches within wled/WLED)
# Skip when no changed usermods were found (e.g. only non-library changes)
if: github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository && needs.get_usermod_envs.outputs.usermods != '[]'
if: github.event.pull_request.head.repo.full_name != github.repository
name: Build Enviornments
runs-on: ubuntu-latest
needs: get_usermod_envs
@@ -89,85 +74,4 @@ jobs:
cat platformio_override.ini
- name: Build firmware
run: pio run -e ${{ matrix.environment }}
get_custom_build_envs:
name: Gather Custom Build Environments
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Find usermods with custom build environments
id: custom_envs
run: |
# On PRs: only scan usermods whose directories changed.
# On push: scan all usermods (validates the full set on merge).
if [ "${{ github.event_name }}" = "pull_request" ]; then
changed=$(git diff --name-only ${{ github.event.pull_request.base.sha }} HEAD \
| grep '^usermods/' | cut -d/ -f2 | sort -u || true)
if [ -z "$changed" ]; then
echo "matrix=[]" >> $GITHUB_OUTPUT
exit 0
fi
samples=$(for mod in $changed; do
f="usermods/$mod/platformio_override.ini.sample"
[ -f "$f" ] && echo "$f"
done | sort)
else
samples=$(find usermods/ -name "platformio_override.ini.sample" | sort)
fi
result='[]'
for sample in $samples; do
usermod=$(dirname "$sample" | xargs basename)
# Skip usermods known to be incompatible (same list as get_usermod_envs)
case "$usermod" in PWM_fan|BME68X_v2|pixels_dice_tray) continue ;; esac
envs=$(grep -E '^\[env:[^]]+\]' "$sample" | sed 's/^\[env:\(.*\)\]$/\1/')
for env in $envs; do
result=$(echo "$result" | jq --arg u "$usermod" --arg e "$env" '. + [{usermod: $u, env: $e}]')
done
done
echo "matrix=$(echo "$result" | jq -c '.')" >> $GITHUB_OUTPUT
outputs:
matrix: ${{ steps.custom_envs.outputs.matrix }}
build_custom:
name: Build Custom Env (${{ matrix.usermod }} / ${{ matrix.env }})
runs-on: ubuntu-latest
needs: get_custom_build_envs
if: needs.get_custom_build_envs.outputs.matrix != '[]'
strategy:
fail-fast: false
matrix:
include: ${{ fromJSON(needs.get_custom_build_envs.outputs.matrix) }}
steps:
- uses: actions/checkout@v4
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version-file: '.nvmrc'
cache: 'npm'
- run: npm ci
- name: Cache PlatformIO
uses: actions/cache@v4
with:
path: |
~/.platformio/.cache
~/.buildcache
build_output
key: pio-${{ runner.os }}-${{ matrix.env }}-${{ hashFiles('platformio.ini', 'pio-scripts/output_bins.py') }}-${{ hashFiles('wled00/**', 'usermods/**') }}
restore-keys: pio-${{ runner.os }}-${{ matrix.env }}-${{ hashFiles('platformio.ini', 'pio-scripts/output_bins.py') }}-
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.12'
cache: 'pip'
- name: Install PlatformIO
run: pip install -r requirements.txt
- name: Apply custom build environment
run: cp -v "usermods/${{ matrix.usermod }}/platformio_override.ini.sample" platformio_override.ini
- name: Build firmware
run: pio run -e ${{ matrix.env }}
run: pio run -e ${{ matrix.environment }}
+3 -4
View File
@@ -17,8 +17,8 @@ Always reference these instructions - including coding guidelines in `docs/` - f
| `npm run build` | Build web UI into `wled00/html_*.h` / `wled00/js_*.h` | 30s |
| `npm test` | Run test suite (Node.js built-in `node --test`) | 2 min |
| `npm run dev` | Watch mode — auto-rebuilds web UI on changes | continuous |
| `pio run -e esp32dev` | Build firmware (ESP32, most common target) | 5 min |
| `pio run -e nodemcuv2` | Build firmware (ESP8266) | 5 min |
| `pio run -e esp32dev` | Build firmware (ESP32, most common target) | 30 min |
| `pio run -e nodemcuv2` | Build firmware (ESP8266) | 30 min |
**Always run `npm ci && npm run build` before `pio run`.** The web UI build generates
required C headers for firmware compilation.
@@ -68,8 +68,7 @@ docs/ # Coding convention docs
```text
main # Main development trunk (daily/nightly) 17.0.0-dev. Target branch for PRs.
├── V5 # special branch: code rework for esp-idf 5.5.x (unstable)
├── V5-C6 # special branch: integration of new MCU types: esp32-c5, esp32-c6, esp32-p4 (unstable)
├── V5 # special branch: code rework for esp-idf 5.5.x and new MCU types: esp32-c5, esp32-c6, esp32-p4 (unstable)
16_x # maintenance for release 16.0.x
0_15_x # maintenance (bugfixes only) for previous release 0.15.x
(tag) v0.14.4 # old version 0.14.4 (no maintenance)
+4 -4
View File
@@ -193,7 +193,7 @@ On ESP32-S3 modules with OPI flash (e.g. N8R8 modules where the SPI flash itself
## Migrating from ESP-IDF v4.4.x to v5.x
The jump from IDF v4.4 (arduino-esp32 v2.x) to IDF v5.x (arduino-esp32 v3.x) is the largest API break in ESP-IDF history. This section documents the critical changes and recommended migration patterns based on the upstream WLED `V5-C6` branch (`https://github.com/wled/WLED/tree/V5-C6`). Note: WLED has not yet migrated to IDF v5 — these patterns prepare for the future migration.
The jump from IDF v4.4 (arduino-esp32 v2.x) to IDF v5.x (arduino-esp32 v3.x) is the largest API break in ESP-IDF history. This section documents the critical changes and recommended migration patterns based on the upstream WLED `V5` branch (`https://github.com/wled/WLED/tree/V5`). Note: WLED has not yet migrated to IDF v5 — these patterns prepare for the future migration.
<!-- HUMAN_ONLY_START -->
### Compiler changes
@@ -295,7 +295,7 @@ The new API is channel-based:
| `rmt_item32_t` | `rmt_symbol_word_t` | Different struct layout |
<!-- HUMAN_ONLY_END -->
**WLED impact**: NeoPixelBus LED output and IR receiver both use legacy RMT. The upstream `V5-C6` branch adds `-D WLED_USE_SHARED_RMT` and disables IR until the library is ported.
**WLED impact**: NeoPixelBus LED output and IR receiver both use legacy RMT. The upstream `V5` branch adds `-D WLED_USE_SHARED_RMT` and disables IR until the library is ported.
#### I2S (Inter-IC Sound)
@@ -363,7 +363,7 @@ WLED already has a compatibility shim in `ota_update.cpp` that maps old names to
### Features disabled in IDF v5 builds
The upstream `V5-C6` branch explicitly disables features with incompatible library dependencies:
The upstream `V5` branch explicitly disables features with incompatible library dependencies:
```ini
# platformio.ini [esp32_idf_V5]
@@ -699,7 +699,7 @@ RMT drives NeoPixel LED output (via NeoPixelBus) and IR receiver input. Both use
### Migration notes
- The upstream `V5-C6` branch uses `-D WLED_USE_SHARED_RMT` to switch to the new RMT driver for NeoPixel output.
- The upstream `V5` branch uses `-D WLED_USE_SHARED_RMT` to switch to the new RMT driver for NeoPixel output.
- IR is disabled on IDF v5 until the IR library is ported.
- New chips (C6, P4) have different RMT channel counts — use `SOC_RMT_TX_CANDIDATES_PER_GROUP` to check availability.
- The new RMT API requires an "encoder" object (`rmt_encoder_t`) to translate data formats — this is more flexible but requires more setup code.
+2 -2
View File
@@ -1,12 +1,12 @@
{
"name": "wled",
"version": "17.0.0-dev",
"version": "16.0.1-dev",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "wled",
"version": "17.0.0-dev",
"version": "16.0.1-dev",
"license": "ISC",
"dependencies": {
"clean-css": "^5.3.3",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "wled",
"version": "17.0.0-dev",
"version": "16.0.1-dev",
"description": "Tools for WLED project",
"main": "tools/cdata.js",
"directories": {
+2 -8
View File
@@ -2,7 +2,6 @@
# This is implemented as a pio post-script to ensure that we can
# place our linker script at the correct point in the command arguments.
Import("env")
import shutil
from pathlib import Path
# Linker script fragment injected into the rodata output section of whichever
@@ -19,13 +18,7 @@ DYNARRAY_INJECTION = (
def inject_before_marker(path, marker):
"""Patch a linker script file in-place, inserting DYNARRAY_INJECTION before marker."""
original = path.read_text()
marker_pos = original.find(marker)
if marker_pos < 0:
raise RuntimeError(
f"DYNARRAY injection marker not found in linker script: path={path}, marker={marker!r}"
)
patched = original[:marker_pos] + DYNARRAY_INJECTION + original[marker_pos:]
path.write_text(patched)
path.write_text(original.replace(marker, DYNARRAY_INJECTION + marker, 1))
if env.get("PIOPLATFORM") == "espressif32":
@@ -45,6 +38,7 @@ if env.get("PIOPLATFORM") == "espressif32":
# leaves the ASSERTs satisfied.
build_dir = Path(env.subst("$BUILD_DIR"))
patched_path = build_dir / "dynarray_sections.ld"
import shutil
shutil.copy(sections_ld_path, patched_path)
inject_before_marker(patched_path, "_rodata_end = ABSOLUTE(.);")
+5 -12
View File
@@ -37,14 +37,14 @@ def check_elf_modules(elf_path: Path, env, module_lib_builders) -> set[str]:
Returns the set of build_dir basenames for confirmed modules.
"""
readelf_path = _get_readelf_path(env)
secho(f"INFO: Checking for usermod compilation units...")
try:
result = subprocess.run(
[readelf_path, "--debug-dump=info", "--dwarf-depth=1", str(elf_path)],
capture_output=True, text=True, errors="ignore", timeout=120,
)
output = result.stdout
if result.returncode != 0 or result.stderr.strip():
secho(f"WARNING: readelf exited {result.returncode}: {result.stderr.strip()}", fg="yellow", err=True)
except (subprocess.TimeoutExpired, FileNotFoundError, OSError) as e:
secho(f"WARNING: readelf failed ({e}); skipping per-module validation", fg="yellow", err=True)
return {Path(b.build_dir).name for b in module_lib_builders} # conservative pass
@@ -143,27 +143,20 @@ def validate_map_file(source, target, env):
Exit(1)
# Identify the WLED module builders, set by load_usermods.py
module_lib_builders = env.get('WLED_MODULES')
if module_lib_builders is None:
secho("ERROR: WLED_MODULES not set — ensure load_usermods.py is run as a pre: script", fg="red", err=True)
Exit(1)
module_lib_builders = env['WLED_MODULES']
# Extract the values we care about
modules = {Path(builder.build_dir).name: builder.name for builder in module_lib_builders}
secho(f"INFO: {len(modules)} libraries included as WLED optional/user modules")
secho(f"INFO: {len(modules)} libraries linked as WLED optional/user modules")
# Now parse the map file
map_file_contents = read_lines(map_file_path)
usermod_object_count = count_usermod_objects(map_file_contents)
secho(f"INFO: {usermod_object_count} usermod object entries found")
secho(f"INFO: {usermod_object_count} usermod object entries")
elf_path = build_dir / env.subst("${PROGNAME}.elf")
confirmed_modules = check_elf_modules(elf_path, env, module_lib_builders)
if confirmed_modules:
secho(f"INFO: Code from usermod libraries found in binary: {', '.join(confirmed_modules)}")
# else - if there's no usermods found, don't generate a message. If we're legitimately missing all entries, the error report on the
# next line will trip; and if the usermod set is expected to be empty, then there's no need for yet another null message.
missing_modules = [modname for mdir, modname in modules.items() if mdir not in confirmed_modules]
if missing_modules:
+134 -62
View File
@@ -42,6 +42,40 @@ extra_configs =
platformio_release.ini
[common]
# ------------------------------------------------------------------------------
# PLATFORM:
# !! DO NOT confuse platformio's ESP8266 development platform with Arduino core for ESP8266
#
# arduino core 2.6.3 = platformIO 2.3.2
# arduino core 2.7.0 = platformIO 2.5.0
# ------------------------------------------------------------------------------
arduino_core_2_6_3 = espressif8266@2.3.3
arduino_core_2_7_4 = espressif8266@2.6.2
arduino_core_3_0_0 = espressif8266@3.0.0
arduino_core_3_0_2 = espressif8266@3.2.0
arduino_core_3_1_0 = espressif8266@4.1.0
arduino_core_3_1_2 = espressif8266@4.2.1
# Development platforms
arduino_core_develop = https://github.com/platformio/platform-espressif8266#develop
arduino_core_git = https://github.com/platformio/platform-espressif8266#feature/stage
# Platform to use for ESP8266
platform_wled_default = ${common.arduino_core_3_1_2}
# We use 2.7.4.7 for all, includes PWM flicker fix and Wstring optimization
#platform_packages = tasmota/framework-arduinoespressif8266 @ 3.20704.7
platform_packages = platformio/toolchain-xtensa @ ~2.100300.220621 #2.40802.200502
platformio/tool-esptool #@ ~1.413.0
platformio/tool-esptoolpy #@ ~1.30000.0
## previous platform for 8266, in case of problems with the new one
## you'll need makuna/NeoPixelBus@ 2.6.9 for arduino_core_3_0_2, which does not support Ucs890x
;; platform_wled_default = ${common.arduino_core_3_0_2}
;; platform_packages = tasmota/framework-arduinoespressif8266 @ 3.20704.7
;; platformio/toolchain-xtensa @ ~2.40802.200502
;; platformio/tool-esptool @ ~1.413.0
;; platformio/tool-esptoolpy @ ~1.30000.0
# ------------------------------------------------------------------------------
# FLAGS: DEBUG
# esp8266 : see https://docs.platformio.org/en/latest/platforms/espressif8266.html#debug-level
@@ -130,7 +164,7 @@ upload_speed = 115200
lib_compat_mode = strict
lib_deps =
IRremoteESP8266 @ 2.8.2
https://github.com/Makuna/NeoPixelBus.git#a0919d1c10696614625978dd6fb750a1317a14ce
https://github.com/Makuna/NeoPixelBus.git#1d7ff38f14d04a976f9c6e365c83a232bcba04fc
https://github.com/Aircoookie/ESPAsyncWebServer.git#v2.4.2
marvinroger/AsyncMqttClient @ 0.9.0
# for I2C interface
@@ -160,41 +194,6 @@ lib_deps =
extra_scripts = ${scripts_defaults.extra_scripts}
[esp8266]
# ------------------------------------------------------------------------------
# PLATFORM:
# !! DO NOT confuse platformio's ESP8266 development platform with Arduino core for ESP8266
#
# arduino core 2.6.3 = platformIO 2.3.2
# arduino core 2.7.0 = platformIO 2.5.0
# ------------------------------------------------------------------------------
arduino_core_2_6_3 = espressif8266@2.3.3
arduino_core_2_7_4 = espressif8266@2.6.2
arduino_core_3_0_0 = espressif8266@3.0.0
arduino_core_3_0_2 = espressif8266@3.2.0
arduino_core_3_1_0 = espressif8266@4.1.0
arduino_core_3_1_2 = espressif8266@4.2.1
# Development platforms
arduino_core_develop = https://github.com/platformio/platform-espressif8266#develop
arduino_core_git = https://github.com/platformio/platform-espressif8266#feature/stage
# Platform to use for ESP8266
platform_wled_default = ${esp8266.arduino_core_3_1_2}
# We use 2.7.4.7 for all, includes PWM flicker fix and Wstring optimization
#platform_packages = tasmota/framework-arduinoespressif8266 @ 3.20704.7
platform_packages = platformio/toolchain-xtensa @ ~2.100300.220621 #2.40802.200502
platformio/tool-esptool #@ ~1.413.0
platformio/tool-esptoolpy #@ ~1.30000.0
## previous platform for 8266, in case of problems with the new one
## you'll need makuna/NeoPixelBus@ 2.6.9 for arduino_core_3_0_2, which does not support Ucs890x
;; platform_wled_default = ${esp8266.arduino_core_3_0_2}
;; platform_packages = tasmota/framework-arduinoespressif8266 @ 3.20704.7
;; platformio/toolchain-xtensa @ ~2.40802.200502
;; platformio/tool-esptool @ ~1.413.0
;; platformio/tool-esptoolpy @ ~1.30000.0
platform = ${esp8266.platform_wled_default}
build_unflags = ${common.build_unflags}
custom_usermods =
build_flags =
@@ -228,8 +227,6 @@ lib_deps =
https://github.com/tignioj/ArduinoUZlib.git#20aff95cd80c141f80bdbf66895409a0046d2c2f
${env.lib_deps}
monitor_filters = esp8266_exception_decoder
;; compatibilty flags - same as 0.14.0 which seems to work better on some 8266 boards. Not using PIO_FRAMEWORK_ARDUINO_MMU_CACHE16_IRAM48
build_flags_compat =
-DESP8266
@@ -277,7 +274,6 @@ platform_packages =
build_unflags = ${common.build_unflags}
build_flags = ${esp32_idf_V4.build_flags}
lib_deps = ${esp32_idf_V4.lib_deps}
monitor_filters = esp32_exception_decoder
tiny_partitions = tools/WLED_ESP32_2MB_noOTA.csv
default_partitions = tools/WLED_ESP32_4MB_1MB_FS.csv
@@ -340,7 +336,6 @@ build_flags = -g
lib_deps =
${esp32_idf_V4.lib_deps}
board_build.partitions = ${esp32.default_partitions} ;; default partioning for 4MB Flash - can be overridden in build envs
monitor_filters = esp32_exception_decoder
[esp32c3]
;; generic definitions for all ESP32-C3 boards
@@ -360,7 +355,6 @@ lib_deps =
${esp32_idf_V4.lib_deps}
board_build.partitions = ${esp32.default_partitions} ;; default partioning for 4MB Flash - can be overridden in build envs
board_build.flash_mode = qio
monitor_filters = esp32_exception_decoder
[esp32s3]
;; generic definitions for all ESP32-S3 boards
@@ -380,8 +374,6 @@ build_flags = -g
lib_deps =
${esp32_idf_V4.lib_deps}
board_build.partitions = ${esp32.large_partitions} ;; default partioning for 8MB flash - can be overridden in build envs
upload_speed = 921600
monitor_filters = esp32_exception_decoder
# ------------------------------------------------------------------------------
@@ -389,11 +381,15 @@ monitor_filters = esp32_exception_decoder
# ------------------------------------------------------------------------------
[env:nodemcuv2]
extends = esp8266
board = nodemcuv2
platform = ${common.platform_wled_default}
platform_packages = ${common.platform_packages}
board_build.ldscript = ${common.ldscript_4m1m}
build_unflags = ${common.build_unflags}
build_flags = ${common.build_flags} ${esp8266.build_flags} -D WLED_RELEASE_NAME=\"ESP8266\" #-DWLED_DISABLE_2D
-D WLED_DISABLE_PARTICLESYSTEM2D
lib_deps = ${esp8266.lib_deps}
monitor_filters = esp8266_exception_decoder
custom_usermods = audioreactive
[env:nodemcuv2_compat]
@@ -414,12 +410,15 @@ build_flags = ${common.build_flags} ${esp8266.build_flags} -D WLED_RELEASE_NAME=
custom_usermods = audioreactive
[env:esp8266_2m]
extends = esp8266
board = esp_wroom_02
platform = ${common.platform_wled_default}
platform_packages = ${common.platform_packages}
board_build.ldscript = ${common.ldscript_2m512k}
build_unflags = ${common.build_unflags}
build_flags = ${common.build_flags} ${esp8266.build_flags} -D WLED_RELEASE_NAME=\"ESP02\"
-D WLED_DISABLE_PARTICLESYSTEM2D
-D WLED_DISABLE_PARTICLESYSTEM1D
lib_deps = ${esp8266.lib_deps}
custom_usermods = audioreactive
[env:esp8266_2m_compat]
@@ -444,7 +443,7 @@ custom_usermods = audioreactive
;; Minimal-feature build for ESP02 (2MB flash).
;; Use this to recover from a failed OTA: flash via serial, then OTA-upload the regular esp8266_2m binary.
;; OTA is intentionally kept enabled. All other optional features are stripped to minimise binary size.
extends = esp8266
extends = env:esp8266_2m
board = esp_wroom_02
board_build.ldscript = ${common.ldscript_2m512k}
build_flags = ${common.build_flags} ${esp8266.build_flags} -D WLED_RELEASE_NAME=\"ESP02_min\"
@@ -463,14 +462,17 @@ build_flags = ${common.build_flags} ${esp8266.build_flags} -D WLED_RELEASE_NAME=
-D WLED_DISABLE_IMPROV_WIFISCAN
[env:esp01_1m_full]
extends = esp8266
board = esp01_1m
platform = ${common.platform_wled_default}
platform_packages = ${common.platform_packages}
board_build.ldscript = ${common.ldscript_1m128k}
build_unflags = ${common.build_unflags}
build_flags = ${common.build_flags} ${esp8266.build_flags} -D WLED_RELEASE_NAME=\"ESP01\" -D WLED_DISABLE_OTA
; -D WLED_USE_REAL_MATH ;; may fix wrong sunset/sunrise times, at the cost of 7064 bytes FLASH and 975 bytes RAM
-D WLED_DISABLE_PARTICLESYSTEM1D
-D WLED_DISABLE_PARTICLESYSTEM2D
-D WLED_DISABLE_PIXELFORGE
lib_deps = ${esp8266.lib_deps}
[env:esp01_1m_full_compat]
extends = env:esp01_1m_full
@@ -493,11 +495,15 @@ build_flags = ${common.build_flags} ${esp8266.build_flags} -D WLED_RELEASE_NAME=
;; custom_usermods = audioreactive ;; pushed program flash size over the limits
[env:esp32dev]
extends = esp32
board = esp32dev
platform = ${esp32_idf_V4.platform}
platform_packages = ${esp32_idf_V4.platform_packages}
build_unflags = ${common.build_unflags}
custom_usermods = audioreactive
build_flags = ${common.build_flags} ${esp32_idf_V4.build_flags} -D WLED_RELEASE_NAME=\"ESP32\" #-D WLED_DISABLE_BROWNOUT_DET
-DARDUINO_USB_CDC_ON_BOOT=0 ;; this flag is mandatory for "classic ESP32" when building with arduino-esp32 >=2.0.3
lib_deps = ${esp32_idf_V4.lib_deps}
monitor_filters = esp32_exception_decoder
board_build.partitions = ${esp32.default_partitions}
board_build.flash_mode = dio
@@ -509,33 +515,50 @@ build_flags = ${common.build_flags} ${esp32_idf_V4.build_flags}
-D WLED_RELEASE_NAME=\"ESP32_DEBUG\"
[env:esp32dev_8M]
extends = env:esp32dev
board = esp32dev
platform = ${esp32_idf_V4.platform}
platform_packages = ${esp32_idf_V4.platform_packages}
custom_usermods = audioreactive
build_unflags = ${common.build_unflags}
build_flags = ${common.build_flags} ${esp32_idf_V4.build_flags} -D WLED_RELEASE_NAME=\"ESP32_8M\" #-D WLED_DISABLE_BROWNOUT_DET
-DARDUINO_USB_CDC_ON_BOOT=0 ;; this flag is mandatory for "classic ESP32" when building with arduino-esp32 >=2.0.3
lib_deps = ${esp32_idf_V4.lib_deps}
monitor_filters = esp32_exception_decoder
board_build.partitions = ${esp32.large_partitions}
board_upload.flash_size = 8MB
board_upload.maximum_size = 8388608
; board_build.f_flash = 80000000L
board_build.flash_mode = dio
[env:esp32dev_16M]
extends = env:esp32dev
board = esp32dev
platform = ${esp32_idf_V4.platform}
platform_packages = ${esp32_idf_V4.platform_packages}
custom_usermods = audioreactive
build_unflags = ${common.build_unflags}
build_flags = ${common.build_flags} ${esp32_idf_V4.build_flags} -D WLED_RELEASE_NAME=\"ESP32_16M\" #-D WLED_DISABLE_BROWNOUT_DET
-DARDUINO_USB_CDC_ON_BOOT=0 ;; this flag is mandatory for "classic ESP32" when building with arduino-esp32 >=2.0.3
lib_deps = ${esp32_idf_V4.lib_deps}
monitor_filters = esp32_exception_decoder
board_build.partitions = ${esp32.extreme_partitions}
board_upload.flash_size = 16MB
board_upload.maximum_size = 16777216
board_build.f_flash = 80000000L
board_build.flash_mode = dio
[env:esp32_eth]
extends = esp32
board = esp32-poe
platform = ${esp32_idf_V4.platform}
platform_packages = ${esp32_idf_V4.platform_packages}
upload_speed = 921600
custom_usermods = audioreactive
build_unflags = ${common.build_unflags}
build_flags = ${common.build_flags} ${esp32.build_flags} -D WLED_RELEASE_NAME=\"ESP32_Ethernet\" -D RLYPIN=-1 -D WLED_USE_ETHERNET -D BTNPIN=-1
-D SR_DMTYPE=-1 -D AUDIOPIN=-1 -D I2S_SDPIN=-1 -D I2S_WSPIN=-1 -D I2S_CKPIN=-1 -D MCLK_PIN=-1 ;; force AR to not allocate any PINs at startup
-D DATA_PINS=4 ;; default led pin = 16 conflicts with pins used for ethernet
; -D WLED_DISABLE_ESPNOW ;; ESP-NOW requires wifi, may crash with ethernet only => uncomment if your board uses ETH_CLOCK_GPIO0_OUT, ETH_CLOCK_GPIO16_OUT, ETH_CLOCK_GPIO17_OUT
-DARDUINO_USB_CDC_ON_BOOT=0 ;; this flag is mandatory for "classic ESP32" when building with arduino-esp32 >=2.0.3
lib_deps = ${esp32.lib_deps}
board_build.partitions = ${esp32.default_partitions}
board_build.flash_mode = dio
@@ -546,14 +569,20 @@ board_build.f_flash = 80000000L
board_build.flash_mode = qio
board_build.partitions = ${esp32.extended_partitions}
custom_usermods = audioreactive
build_unflags = ${common.build_unflags}
build_flags = ${common.build_flags} ${esp32_idf_V4.build_flags} -D WLED_RELEASE_NAME=\"ESP32_WROVER\"
-DARDUINO_USB_CDC_ON_BOOT=0 ;; this flag is mandatory for "classic ESP32" when building with arduino-esp32 >=2.0.3
-DBOARD_HAS_PSRAM -mfix-esp32-psram-cache-issue ;; Older ESP32 (rev.<3) need a PSRAM fix (increases static RAM used) https://docs.espressif.com/projects/esp-idf/en/stable/esp32/api-guides/external-ram.html
-D DATA_PINS=25
lib_deps = ${esp32_idf_V4.lib_deps}
[env:esp32c3dev]
extends = esp32c3
platform = ${esp32c3.platform}
platform_packages = ${esp32c3.platform_packages}
framework = arduino
board = esp32-c3-devkitm-1
board_build.partitions = ${esp32.default_partitions}
custom_usermods = audioreactive
build_flags = ${common.build_flags} ${esp32c3.build_flags} -D WLED_RELEASE_NAME=\"ESP32-C3\"
-D WLED_WATCHDOG_TIMEOUT=0
@@ -561,6 +590,8 @@ build_flags = ${common.build_flags} ${esp32c3.build_flags} -D WLED_RELEASE_NAME=
-DARDUINO_USB_CDC_ON_BOOT=1 ;; for virtual CDC USB
;-DARDUINO_USB_CDC_ON_BOOT=0 ;; for serial-to-USB chip
upload_speed = 460800
build_unflags = ${common.build_unflags}
lib_deps = ${esp32c3.lib_deps}
board_build.flash_mode = dio ; safe default, required for OTA updates to 0.16 from older version which used dio (must match the bootloader!)
[env:esp32c3dev_qio]
@@ -570,34 +601,45 @@ board_build.flash_mode = qio ; qio is faster and works on almost all boards (som
[env:esp32s3dev_16MB_opi]
;; ESP32-S3 development board, with 16MB FLASH and >= 8MB PSRAM (memory_type: qio_opi)
extends = esp32s3
board = esp32-s3-devkitc-1 ;; generic dev board; the next line adds PSRAM support
board_build.arduino.memory_type = qio_opi ;; use with PSRAM: 8MB or 16MB
platform = ${esp32s3.platform}
platform_packages = ${esp32s3.platform_packages}
upload_speed = 921600
custom_usermods = audioreactive
build_unflags = ${common.build_unflags}
build_flags = ${common.build_flags} ${esp32s3.build_flags} -D WLED_RELEASE_NAME=\"ESP32-S3_16MB_opi\"
-D WLED_WATCHDOG_TIMEOUT=0
;-D ARDUINO_USB_CDC_ON_BOOT=0 ;; -D ARDUINO_USB_MODE=1 ;; for boards with serial-to-USB chip
-D ARDUINO_USB_CDC_ON_BOOT=1 ;; -D ARDUINO_USB_MODE=1 ;; for boards with USB-OTG connector only (USBCDC or "TinyUSB")
-DBOARD_HAS_PSRAM
lib_deps = ${esp32s3.lib_deps}
board_build.partitions = ${esp32.extreme_partitions}
board_upload.flash_size = 16MB
board_upload.maximum_size = 16777216
board_build.f_flash = 80000000L
board_build.flash_mode = qio
monitor_filters = esp32_exception_decoder
[env:esp32s3dev_8MB_opi]
;; ESP32-S3 development board, with 8MB FLASH and >= 8MB PSRAM (memory_type: qio_opi)
extends = esp32s3
board = esp32-s3-devkitc-1 ;; generic dev board; the next line adds PSRAM support
board_build.arduino.memory_type = qio_opi ;; use with PSRAM: 8MB or 16MB
platform = ${esp32s3.platform}
platform_packages = ${esp32s3.platform_packages}
upload_speed = 921600
custom_usermods = audioreactive
build_unflags = ${common.build_unflags}
build_flags = ${common.build_flags} ${esp32s3.build_flags} -D WLED_RELEASE_NAME=\"ESP32-S3_8MB_opi\"
-D WLED_WATCHDOG_TIMEOUT=0
;-D ARDUINO_USB_CDC_ON_BOOT=0 ;; -D ARDUINO_USB_MODE=1 ;; for boards with serial-to-USB chip
-D ARDUINO_USB_CDC_ON_BOOT=1 ;; -D ARDUINO_USB_MODE=1 ;; for boards with USB-OTG connector only (USBCDC or "TinyUSB")
-DBOARD_HAS_PSRAM
lib_deps = ${esp32s3.lib_deps}
board_build.partitions = ${esp32.large_partitions}
board_build.f_flash = 80000000L
board_build.flash_mode = qio
monitor_filters = esp32_exception_decoder
[env:esp32s3dev_8MB_qspi]
;; generic ESP32-S3 board with 8MB FLASH and PSRAM (memory_type: qio_qspi). Try this one if esp32s3dev_8MB_opi does not work on your board
@@ -610,6 +652,7 @@ build_flags = ${common.build_flags} ${esp32s3.build_flags} -D WLED_RELEASE_NAME=
-D ARDUINO_USB_CDC_ON_BOOT=1 ;; -D ARDUINO_USB_MODE=1 ;; for boards with USB-OTG connector only (USBCDC or "TinyUSB")
-DBOARD_HAS_PSRAM
;; -DLOLIN_WIFI_FIX ;; uncomment if you have WiFi connectivity problems
monitor_filters = esp32_exception_decoder
[env:esp32s3dev_8MB_none]
;; ESP32-S3 development board, 8MB FLASH, no PSRAM
@@ -627,10 +670,13 @@ board_build.flash_mode = qio
[env:esp32S3_wroom2]
;; For ESP32-S3 WROOM-2, a.k.a. ESP32-S3 DevKitC-1 v1.1
;; with >= 16MB FLASH and >= 8MB PSRAM (memory_type: opi_opi)
extends = esp32s3
platform = ${esp32s3.platform}
platform_packages = ${esp32s3.platform_packages}
board = esp32s3camlcd ;; this is the only standard board with "opi_opi"
board_build.arduino.memory_type = opi_opi
upload_speed = 921600
custom_usermods = audioreactive
build_unflags = ${common.build_unflags}
build_flags = ${common.build_flags} ${esp32s3.build_flags} -D WLED_RELEASE_NAME=\"ESP32-S3_WROOM-2\"
-D WLED_WATCHDOG_TIMEOUT=0
-D ARDUINO_USB_CDC_ON_BOOT=0 ;; -D ARDUINO_USB_MODE=1 ;; for boards with serial-to-USB chip
@@ -640,9 +686,12 @@ build_flags = ${common.build_flags} ${esp32s3.build_flags} -D WLED_RELEASE_NAME=
-D BTNPIN=0 -D RLYPIN=16 -D IRPIN=17 -D AUDIOPIN=-1
;;-D WLED_DEBUG
-D SR_DMTYPE=1 -D I2S_SDPIN=13 -D I2S_CKPIN=14 -D I2S_WSPIN=15 -D MCLK_PIN=4 ;; I2S mic
lib_deps = ${esp32s3.lib_deps}
board_build.partitions = ${esp32.extreme_partitions}
board_upload.flash_size = 16MB
board_upload.maximum_size = 16777216
monitor_filters = esp32_exception_decoder
[env:esp32S3_wroom2_32MB]
;; For ESP32-S3 WROOM-2 with 32MB Flash, and >= 8MB PSRAM (memory_type: opi_opi)
@@ -659,20 +708,26 @@ build_flags = ${common.build_flags} ${esp32s3.build_flags} -D WLED_RELEASE_NAME=
board_build.partitions = tools/WLED_ESP32_32MB.csv
board_upload.flash_size = 32MB
board_upload.maximum_size = 33554432
monitor_filters = esp32_exception_decoder
[env:esp32s3_4M_qspi]
;; ESP32-S3, with 4MB FLASH and <= 4MB PSRAM (memory_type: qio_qspi)
extends = esp32s3
board = lolin_s3_mini ;; -S3 mini, 4MB flash 2MB PSRAM
board = lolin_s3_mini ;; -S3 mini, 4MB flash 2MB PSRAM
platform = ${esp32s3.platform}
platform_packages = ${esp32s3.platform_packages}
upload_speed = 921600
custom_usermods = audioreactive
build_unflags = ${common.build_unflags}
build_flags = ${common.build_flags} ${esp32s3.build_flags} -D WLED_RELEASE_NAME=\"ESP32-S3_4M_qspi\"
-DARDUINO_USB_CDC_ON_BOOT=1 ;; -DARDUINO_USB_MODE=1 ;; for boards with USB-OTG connector only (USBCDC or "TinyUSB")
-DBOARD_HAS_PSRAM
-DLOLIN_WIFI_FIX ; seems to work much better with this
-D WLED_WATCHDOG_TIMEOUT=0
lib_deps = ${esp32s3.lib_deps}
board_build.partitions = ${esp32.default_partitions}
board_build.f_flash = 80000000L
board_build.flash_mode = qio
monitor_filters = esp32_exception_decoder
[env:esp32s3_4M_none]
;; ESP32-S3 with 4MB FLASH, no PSRAM
@@ -690,11 +745,14 @@ board_build.flash_mode = qio
[env:lolin_s2_mini]
extends = esp32s2
platform = ${esp32s2.platform}
platform_packages = ${esp32s2.platform_packages}
board = lolin_s2_mini
board_build.partitions = ${esp32.default_partitions}
board_build.flash_mode = qio
board_build.f_flash = 80000000L
custom_usermods = audioreactive
build_unflags = ${common.build_unflags}
build_flags = ${common.build_flags} ${esp32s2.build_flags} -D WLED_RELEASE_NAME=\"ESP32-S2\"
-DARDUINO_USB_CDC_ON_BOOT=1
-DARDUINO_USB_MSC_ON_BOOT=0
@@ -709,12 +767,19 @@ build_flags = ${common.build_flags} ${esp32s2.build_flags} -D WLED_RELEASE_NAME=
-D HW_PIN_DATASPI=11
-D HW_PIN_MISOSPI=9
; -D STATUSLED=15
lib_deps = ${esp32s2.lib_deps}
[env:usermods]
extends = env:esp32dev
board = esp32dev
platform = ${esp32_idf_V4.platform}
platform_packages = ${esp32_idf_V4.platform_packages}
build_unflags = ${common.build_unflags}
build_flags = ${common.build_flags} ${esp32_idf_V4.build_flags} -D WLED_RELEASE_NAME=\"ESP32_USERMODS\"
-DTOUCH_CS=9
lib_deps = ${esp32_idf_V4.lib_deps}
monitor_filters = esp32_exception_decoder
board_build.flash_mode = dio
custom_usermods = * ; Expands to all usermods in usermods folder
board_build.partitions = ${esp32.extreme_partitions} ; We're gonna need a bigger boat
@@ -797,11 +862,18 @@ extends = env:esp32S3_wroom2_32MB
monitor_filters = esp32_exception_decoder
build_unflags = ${env:esp32S3_wroom2_32MB.build_unflags}
-D WLED_RELEASE_NAME=\"ESP32-S3_WROOM-2_32MB\" ;; need to un-set the relese name before setting a new one
build_flags = ${common.build_flags} ${esp32s3.build_flags} ${hub75.build_flags} ${hub75.s3_build_flags} ${hub75.i2s_disable_flags}
custom_usermods =
Internal_Temperature
audioreactive = https://github.com/MoonModules/WLED-AudioReactive-Usermod#171c0bbc2bc47e2c11ae203dd00beed82865df2b ;; broadcast
build_flags = ${common.build_flags} ${esp32s3.build_flags} ${hub75.build_flags} ${hub75.s3_build_flags}
-D WLED_RELEASE_NAME=\"ESP32-S3_Waveshare_HUB75\"
-D WAVESHARE_S3_PINOUT
; -D WLED_USE_SD_SPI
; -D SD_PRINT_HOME_DIR
-D BTNPIN=0
-D I2CSDAPIN=47 -D I2CSCLPIN=48
-D SR_DMTYPE=9 -D I2S_SDPIN=39 -D I2S_CKPIN=43 -D I2S_WSPIN=38 -D MCLK_PIN=12 ; Waveshare ES8311 Codec pins
-D UM_SD_SELECT=14 -D UM_SD_CLOCK=1 -D UM_SD_POCI=17 -D UM_SD_PICO=44 ; Waveshare SD Card pins ** Requires updated sd_card from this PR https://github.com/wled/WLED/pull/5679 **
-D WLED_USE_SD_SPI
-D SD_PRINT_HOME_DIR
; -D WLED_DEBUG
lib_deps = ${esp32s3.lib_deps}
${hub75.lib_deps}
+84 -59
View File
@@ -13,8 +13,8 @@ default_envs = WLED_generic8266_1M, esp32dev_dio80 # put the name(s) of your ow
[env:WLED_generic8266_1M]
extends = env:esp01_1m_full # when you want to extend the existing environment (define only updated options)
; board = esp01_1m # uncomment when ou need different board
; platform = ${esp8266.platform_wled_default} # uncomment and change when you want particular platform
; platform_packages = ${esp8266.platform_packages}
; platform = ${common.platform_wled_default} # uncomment and change when you want particular platform
; platform_packages = ${common.platform_packages}
; board_build.ldscript = ${common.ldscript_1m128k}
; upload_speed = 921600 # fast upload speed (remove ';' if your board supports fast upload speed)
# Sample libraries used for various usermods. Uncomment when using particular usermod.
@@ -36,12 +36,7 @@ build_flags = ${common.build_flags} ${esp8266.build_flags} -D WLED_RELEASE_NAME=
-D WLED_DISABLE_OTA -D WLED_DISABLE_2D
;
; *** To use the below defines/overrides, copy and paste each onto its own line just below build_flags in the section above.
; *** Note: on adding custom usermods
; custom_usermods entries are a separate key in the env section (not inside build_flags). Place them on their own line in the env.
; Multiple usermods are separated by a space, the names can be found in the library.json file of the usermod.
; Example: use the default usermods from the esp32dev env and add the Temperature and four_line_display_ALT usermods
; custom_usermods = ${env:esp32dev.custom_usermods} Temperature four_line_display_ALT
;
;
; Set a release name that may be used to distinguish required binary for flashing
; -D WLED_RELEASE_NAME=\"ESP32_MULTI_USREMODS\"
;
@@ -106,17 +101,17 @@ build_flags = ${common.build_flags} ${esp8266.build_flags} -D WLED_RELEASE_NAME=
; -D WLED_DEBUG_PORT=7868
;
; Use Autosave usermod and set it to do save after 90s
; custom_usermods = ${env:esp32dev.custom_usermods} auto_save
; -D USERMOD_AUTO_SAVE
; -D AUTOSAVE_AFTER_SEC=90
;
; Use AHT10/AHT15/AHT20 usermod
; custom_usermods = ${env:esp32dev.custom_usermods} AHT10_v2
; -D USERMOD_AHT10
;
; Use INA226 usermod
; custom_usermods = ${env:esp32dev.custom_usermods} INA226_v2
; -D USERMOD_INA226
;
; Use 4 Line Display usermod with SPI display
; custom_usermods = ${env:esp32dev.custom_usermods} four_line_display_ALT
; -D USERMOD_FOUR_LINE_DISPLAY
; -DFLD_SPI_DEFAULT
; -D FLD_TYPE=SSD1306_SPI64
; -D FLD_PIN_CLOCKSPI=14
@@ -126,22 +121,22 @@ build_flags = ${common.build_flags} ${esp8266.build_flags} -D WLED_RELEASE_NAME=
; -D FLD_PIN_RESET=27
;
; Use Rotary encoder usermod (in conjunction with 4LD)
; custom_usermods = ${env:esp32dev.custom_usermods} rotary_encoder_ui_ALT
; -D USERMOD_ROTARY_ENCODER_UI
; -D ENCODER_DT_PIN=5
; -D ENCODER_CLK_PIN=18
; -D ENCODER_SW_PIN=19
;
; Use Dallas DS18B20 temperature sensor usermod and configure it to use GPIO13
; custom_usermods = ${env:esp32dev.custom_usermods} Temperature
; -D USERMOD_DALLASTEMPERATURE
; -D TEMPERATURE_PIN=13
;
; Use Multi Relay usermod and configure it to use 6 relays and appropriate GPIO
; custom_usermods = ${env:esp32dev.custom_usermods} multi_relay
; -D USERMOD_MULTI_RELAY
; -D MULTI_RELAY_MAX_RELAYS=6
; -D MULTI_RELAY_PINS=12,23,22,21,24,25
;
; Use PIR sensor usermod and configure it to use GPIO4 and timer of 60s
; custom_usermods = ${env:esp32dev.custom_usermods} PIR_sensor_switch
; -D USERMOD_PIRSWITCH
; -D PIR_SENSOR_PIN=4 # use -1 to disable usermod
; -D PIR_SENSOR_OFF_SEC=60
; -D PIR_SENSOR_MAX_SENSORS=2 # max allowable sensors (uses OR logic for triggering)
@@ -154,12 +149,12 @@ build_flags = ${common.build_flags} ${esp8266.build_flags} -D WLED_RELEASE_NAME=
; -D I2S_CKPIN=19
;
; Use PWM fan usermod
; custom_usermods = ${env:esp32dev.custom_usermods} PWM_fan
; -D USERMOD_PWM_FAN
; -D TACHO_PIN=33
; -D PWM_PIN=32
;
; Use POV Display usermod
; custom_usermods = ${env:esp32dev.custom_usermods} pov_display
; -D USERMOD_POV_DISPLAY
; Use built-in or custom LED as a status indicator (assumes LED is connected to GPIO16)
; -D STATUSLED=16
;
@@ -224,8 +219,8 @@ build_flags =
[env:esp07]
board = esp07
platform = ${esp8266.platform_wled_default}
platform_packages = ${esp8266.platform_packages}
platform = ${common.platform_wled_default}
platform_packages = ${common.platform_packages}
board_build.ldscript = ${common.ldscript_4m1m}
build_unflags = ${common.build_unflags}
build_flags = ${common.build_flags} ${esp8266.build_flags} -D WLED_RELEASE_NAME=\"ESP8266_ESP07\" #-DWLED_DISABLE_2D
@@ -234,8 +229,8 @@ lib_deps = ${esp8266.lib_deps}
[env:d1_mini]
board = d1_mini
platform = ${esp8266.platform_wled_default}
platform_packages = ${esp8266.platform_packages}
platform = ${common.platform_wled_default}
platform_packages = ${common.platform_packages}
upload_speed = 921600
board_build.ldscript = ${common.ldscript_4m1m}
build_unflags = ${common.build_unflags}
@@ -246,8 +241,8 @@ monitor_filters = esp8266_exception_decoder
[env:heltec_wifi_kit_8]
board = d1_mini
platform = ${esp8266.platform_wled_default}
platform_packages = ${esp8266.platform_packages}
platform = ${common.platform_wled_default}
platform_packages = ${common.platform_packages}
board_build.ldscript = ${common.ldscript_4m1m}
build_unflags = ${common.build_unflags}
build_flags = ${common.build_flags} ${esp8266.build_flags} -D WLED_RELEASE_NAME=\"ESP8266_HT_D1MINI\" #-DWLED_DISABLE_2D
@@ -256,8 +251,8 @@ lib_deps = ${esp8266.lib_deps}
[env:h803wf]
board = d1_mini
platform = ${esp8266.platform_wled_default}
platform_packages = ${esp8266.platform_packages}
platform = ${common.platform_wled_default}
platform_packages = ${common.platform_packages}
board_build.ldscript = ${common.ldscript_4m1m}
build_unflags = ${common.build_unflags}
build_flags = ${common.build_flags} ${esp8266.build_flags} -D DATA_PINS=1 -D WLED_DISABLE_INFRARED -D WLED_RELEASE_NAME=\"ESP8266_HT803WF\" #-DWLED_DISABLE_2D
@@ -294,8 +289,8 @@ lib_deps = ${esp32s2.lib_deps}
[env:esp8285_4CH_MagicHome]
board = esp8285
platform = ${esp8266.platform_wled_default}
platform_packages = ${esp8266.platform_packages}
platform = ${common.platform_wled_default}
platform_packages = ${common.platform_packages}
board_build.ldscript = ${common.ldscript_1m128k}
build_unflags = ${common.build_unflags}
build_flags = ${common.build_flags} ${esp8266.build_flags} -D WLED_DISABLE_OTA -D WLED_RELEASE_NAME=\"ESP8285_4CH_MagicHome\" #-DWLED_DISABLE_2D
@@ -304,8 +299,8 @@ lib_deps = ${esp8266.lib_deps}
[env:esp8285_H801]
board = esp8285
platform = ${esp8266.platform_wled_default}
platform_packages = ${esp8266.platform_packages}
platform = ${common.platform_wled_default}
platform_packages = ${common.platform_packages}
board_build.ldscript = ${common.ldscript_1m128k}
build_unflags = ${common.build_unflags}
build_flags = ${common.build_flags} ${esp8266.build_flags} -D WLED_DISABLE_OTA -D WLED_RELEASE_NAME=\"ESP8285_H801\" #-DWLED_DISABLE_2D
@@ -314,8 +309,8 @@ lib_deps = ${esp8266.lib_deps}
[env:d1_mini_5CH_Shojo_PCB]
board = d1_mini
platform = ${esp8266.platform_wled_default}
platform_packages = ${esp8266.platform_packages}
platform = ${common.platform_wled_default}
platform_packages = ${common.platform_packages}
board_build.ldscript = ${common.ldscript_4m1m}
build_unflags = ${common.build_unflags}
build_flags = ${common.build_flags} ${esp8266.build_flags} -D WLED_USE_SHOJO_PCB ;; NB: WLED_USE_SHOJO_PCB is not used anywhere in the source code. Not sure why its needed.
@@ -326,8 +321,8 @@ lib_deps = ${esp8266.lib_deps}
[env:d1_mini_debug]
board = d1_mini
build_type = debug
platform = ${esp8266.platform_wled_default}
platform_packages = ${esp8266.platform_packages}
platform = ${common.platform_wled_default}
platform_packages = ${common.platform_packages}
board_build.ldscript = ${common.ldscript_4m1m}
build_unflags = ${common.build_unflags}
build_flags = ${common.build_flags} ${esp8266.build_flags} ${common.debug_flags} -D WLED_RELEASE_NAME=\"ESP8266_D1MINI_DEBUG\" #-DWLED_DISABLE_2D
@@ -339,8 +334,8 @@ board = d1_mini
upload_protocol = espota
# exchange for your WLED IP
upload_port = "10.10.1.27"
platform = ${esp8266.platform_wled_default}
platform_packages = ${esp8266.platform_packages}
platform = ${common.platform_wled_default}
platform_packages = ${common.platform_packages}
board_build.ldscript = ${common.ldscript_4m1m}
build_unflags = ${common.build_unflags}
build_flags = ${common.build_flags} ${esp8266.build_flags} -D WLED_RELEASE_NAME=\"ESP8266_D1MINI_OTA\" #-DWLED_DISABLE_2D
@@ -349,8 +344,8 @@ lib_deps = ${esp8266.lib_deps}
[env:anavi_miracle_controller]
board = d1_mini
platform = ${esp8266.platform_wled_default}
platform_packages = ${esp8266.platform_packages}
platform = ${common.platform_wled_default}
platform_packages = ${common.platform_packages}
board_build.ldscript = ${common.ldscript_4m1m}
build_unflags = ${common.build_unflags}
build_flags = ${common.build_flags} ${esp8266.build_flags} -D DATA_PINS=12 -D IRPIN=-1 -D RLYPIN=2
@@ -383,7 +378,6 @@ board_upload.maximum_size = 2097152
extends = esp32 ;; use default esp32 platform
board = esp32dev
upload_speed = 460800
custom_usermods = ${env:esp32dev.custom_usermods} Temperature four_line_display_ALT
build_flags = ${common.build_flags} ${esp32.build_flags}
-D WLED_RELEASE_NAME=\"ESP32_wemos_shield\"
-D DATA_PINS=16
@@ -391,8 +385,12 @@ build_flags = ${common.build_flags} ${esp32.build_flags}
-D BTNPIN=17
-D IRPIN=18
-UWLED_USE_MY_CONFIG
-D USERMOD_DALLASTEMPERATURE
-D USERMOD_FOUR_LINE_DISPLAY
-D TEMPERATURE_PIN=23
lib_deps = ${esp32.lib_deps}
OneWire@~2.3.5 ;; needed for USERMOD_DALLASTEMPERATURE
olikraus/U8g2 @ ^2.28.8 ;; needed for USERMOD_FOUR_LINE_DISPLAY
board_build.partitions = ${esp32.default_partitions}
[env:esp32_pico-D4]
@@ -419,7 +417,7 @@ build_flags = ${common.build_flags} ${esp32.build_flags} -D DATA_PINS=27 -D BTNP
[env:sp501e]
board = esp_wroom_02
platform = ${esp8266.platform_wled_default}
platform = ${common.platform_wled_default}
board_build.ldscript = ${common.ldscript_2m512k}
build_flags = ${common.build_flags} ${esp8266.build_flags} -D DATA_PINS=3 -D BTNPIN=1
-D WLED_RELEASE_NAME=\"ESP8266_sp501e\" -D WLED_DISABLE_PARTICLESYSTEM2D
@@ -427,7 +425,7 @@ lib_deps = ${esp8266.lib_deps}
[env:sp511e]
board = esp_wroom_02
platform = ${esp8266.platform_wled_default}
platform = ${common.platform_wled_default}
board_build.ldscript = ${common.ldscript_2m512k}
build_flags = ${common.build_flags} ${esp8266.build_flags} -D DATA_PINS=3 -D BTNPIN=2 -D IRPIN=5 -D WLED_MAX_BUTTONS=3
-D WLED_RELEASE_NAME=\"ESP8266_sp511e\" -D WLED_DISABLE_PARTICLESYSTEM2D
@@ -435,8 +433,8 @@ lib_deps = ${esp8266.lib_deps}
[env:Athom_RGBCW] ;7w and 5w(GU10) bulbs
board = esp8285
platform = ${esp8266.platform_wled_default}
platform_packages = ${esp8266.platform_packages}
platform = ${common.platform_wled_default}
platform_packages = ${common.platform_packages}
board_build.ldscript = ${common.ldscript_2m512k}
build_unflags = ${common.build_unflags}
build_flags = ${common.build_flags} ${esp8266.build_flags} -D BTNPIN=-1 -D RLYPIN=-1 -D DATA_PINS=4,12,14,13,5
@@ -446,8 +444,8 @@ lib_deps = ${esp8266.lib_deps}
[env:Athom_15w_RGBCW] ;15w bulb
board = esp8285
platform = ${esp8266.platform_wled_default}
platform_packages = ${esp8266.platform_packages}
platform = ${common.platform_wled_default}
platform_packages = ${common.platform_packages}
board_build.ldscript = ${common.ldscript_2m512k}
build_unflags = ${common.build_unflags}
build_flags = ${common.build_flags} ${esp8266.build_flags} -D BTNPIN=-1 -D RLYPIN=-1 -D DATA_PINS=4,12,14,5,13
@@ -457,8 +455,8 @@ lib_deps = ${esp8266.lib_deps}
[env:Athom_3Pin_Controller] ;small controller with only data
board = esp8285
platform = ${esp8266.platform_wled_default}
platform_packages = ${esp8266.platform_packages}
platform = ${common.platform_wled_default}
platform_packages = ${common.platform_packages}
board_build.ldscript = ${common.ldscript_2m512k}
build_unflags = ${common.build_unflags}
build_flags = ${common.build_flags} ${esp8266.build_flags} -D BTNPIN=0 -D RLYPIN=-1 -D DATA_PINS=1 -D WLED_DISABLE_INFRARED
@@ -467,8 +465,8 @@ lib_deps = ${esp8266.lib_deps}
[env:Athom_4Pin_Controller] ; With clock and data interface
board = esp8285
platform = ${esp8266.platform_wled_default}
platform_packages = ${esp8266.platform_packages}
platform = ${common.platform_wled_default}
platform_packages = ${common.platform_packages}
board_build.ldscript = ${common.ldscript_2m512k}
build_unflags = ${common.build_unflags}
build_flags = ${common.build_flags} ${esp8266.build_flags} -D BTNPIN=0 -D RLYPIN=12 -D DATA_PINS=1 -D WLED_DISABLE_INFRARED
@@ -477,8 +475,8 @@ lib_deps = ${esp8266.lib_deps}
[env:Athom_5Pin_Controller] ;Analog light strip controller
board = esp8285
platform = ${esp8266.platform_wled_default}
platform_packages = ${esp8266.platform_packages}
platform = ${common.platform_wled_default}
platform_packages = ${common.platform_packages}
board_build.ldscript = ${common.ldscript_2m512k}
build_unflags = ${common.build_unflags}
build_flags = ${common.build_flags} ${esp8266.build_flags} -D BTNPIN=0 -D RLYPIN=-1 DATA_PINS=4,12,14,13 -D WLED_DISABLE_INFRARED
@@ -487,8 +485,8 @@ lib_deps = ${esp8266.lib_deps}
[env:MY9291]
board = esp01_1m
platform = ${esp8266.platform_wled_default}
platform_packages = ${esp8266.platform_packages}
platform = ${common.platform_wled_default}
platform_packages = ${common.platform_packages}
board_build.ldscript = ${common.ldscript_1m128k}
build_unflags = ${common.build_unflags}
custom_usermods = ${env:esp01_1m_full.custom_usermods} MY9291
@@ -502,8 +500,8 @@ lib_deps = ${esp8266.lib_deps}
[env:codm-controller-0_6]
board = esp_wroom_02
platform = ${esp8266.platform_wled_default}
platform_packages = ${esp8266.platform_packages}
platform = ${common.platform_wled_default}
platform_packages = ${common.platform_packages}
board_build.ldscript = ${common.ldscript_2m512k}
build_unflags = ${common.build_unflags}
build_flags = ${common.build_flags} ${esp8266.build_flags} -D WLED_RELEASE_NAME=\"ESP8266_CODM06_2MB\" -D WLED_DISABLE_PARTICLESYSTEM2D
@@ -511,8 +509,8 @@ lib_deps = ${esp8266.lib_deps}
[env:codm-controller-0_6-rev2]
board = esp_wroom_02
platform = ${esp8266.platform_wled_default}
platform_packages = ${esp8266.platform_packages}
platform = ${common.platform_wled_default}
platform_packages = ${common.platform_packages}
board_build.ldscript = ${common.ldscript_4m1m}
build_unflags = ${common.build_unflags}
build_flags = ${common.build_flags} ${esp8266.build_flags} -D WLED_RELEASE_NAME=\"ESP8266_CODM06R2_4MB\" -D WLED_DISABLE_PARTICLESYSTEM2D
@@ -520,15 +518,42 @@ lib_deps = ${esp8266.lib_deps}
# ------------------------------------------------------------------------------
# EleksTube-IPS
# See usermods/EleksTube_IPS/platformio_override.ini.sample
# ------------------------------------------------------------------------------
[env:elekstube_ips]
extends = esp32 ;; use default esp32 platform
board = esp32dev
upload_speed = 921600
custom_usermods = ${env:esp32dev.custom_usermods} RTC EleksTube_IPS
build_flags = ${common.build_flags} ${esp32.build_flags} -D WLED_DISABLE_BROWNOUT_DET -D WLED_DISABLE_INFRARED
-D DATA_PINS=12
-D RLYPIN=27
-D BTNPIN=34
-D PIXEL_COUNTS=6
# Display config
-D ST7789_DRIVER
-D TFT_WIDTH=135
-D TFT_HEIGHT=240
-D CGRAM_OFFSET
-D TFT_SDA_READ
-D TFT_MOSI=23
-D TFT_SCLK=18
-D TFT_DC=25
-D TFT_RST=26
-D SPI_FREQUENCY=40000000
-D USER_SETUP_LOADED
monitor_filters = esp32_exception_decoder
# ------------------------------------------------------------------------------
# Usermod examples
# ------------------------------------------------------------------------------
# 433MHz RF remote example: see usermods/usermod_v2_RF433/platformio_override.ini.sample
# 433MHz RF remote example for esp32dev
[env:esp32dev_usermod_RF433]
extends = env:esp32dev
custom_usermods =
${env:esp32dev.custom_usermods}
RF433
# External usermod from a git repository.
# The library's `library.json` must include `"build": {"libArchive": false}`.
+6 -12
View File
@@ -119,7 +119,7 @@ describe('Script', () => {
async function checkIfFileWasNewlyCreated(file) {
const modifiedTime = fs.statSync(file).mtimeMs;
assert(Date.now() - modifiedTime < 850, file + ' was not modified');
assert(Date.now() - modifiedTime < 500, file + ' was not modified');
}
async function testFileModification(sourceFilePath, resultFile) {
@@ -129,7 +129,7 @@ describe('Script', () => {
// modify file
fs.appendFileSync(sourceFilePath, ' ');
// delay for 1 second to ensure the modified time is different
await new Promise(resolve => setTimeout(resolve, 1400));
await new Promise(resolve => setTimeout(resolve, 1000));
// run script cdata.js again and wait for it to finish
await execPromise('node tools/cdata.js');
@@ -175,19 +175,13 @@ describe('Script', () => {
});
it('a settings file changes', async () => {
await testFileModification(path.join(dataPath, 'settings_leds.htm'), 'html_settings.h');
await testFileModification(path.join(dataPath, 'settings_leds.htm'), 'html_ui.h');
});
it('common.js changes', async () => {
await testFileModification(path.join(dataPath, 'common.js'), 'html_settings.h');
it('the favicon changes', async () => {
await testFileModification(path.join(dataPath, 'favicon.ico'), 'html_ui.h');
});
// this testcase currently fails - might be due to npm updates (maybe "faking" a favicon.ico change is harder now), or a real regression
// see https://github.com/wled/WLED/issues/5581
// it('the favicon changes', async () => {
// await testFileModification(path.join(dataPath, 'favicon.ico'), 'html_other.h');
// });
it('cdata.js changes', async () => {
await testFileModification('tools/cdata.js', 'html_ui.h');
});
@@ -215,4 +209,4 @@ describe('Script', () => {
assert(secondRunTime < firstRunTime / 2, 'html_*.h files were rebuilt');
});
});
});
});
+2 -10
View File
@@ -141,16 +141,8 @@ discover_devices() {
exit 1
fi
# Map avahi responses to strings separated by 0x1F (unit separator), deduplicated
mapfile -t raw_devices < <(
avahi-browse _wled._tcp --terminate -r -p |
awk -F';' '
/^=/ {
key = $7 "\x1F" $8 "\x1F" $9
if (!seen[key]++) print key
}
'
)
# Map avahi responses to strings seperated by 0x1F (unit separator)
mapfile -t raw_devices < <(avahi-browse _wled._tcp --terminate -r -p | awk -F';' '/^=/ {print $7"\x1F"$8"\x1F"$9}')
local devices_array=()
for device in "${raw_devices[@]}"; do
+11 -12
View File
@@ -28,19 +28,18 @@ class ADS1115Usermod : public Usermod {
}
void loop() {
if (!isEnabled || strip.isUpdating() || millis() - lastTime <= loopInterval)
return;
if (isEnabled && millis() - lastTime > loopInterval) {
lastTime = millis();
lastTime = millis();
// If we don't have new data, skip this iteration.
if (!ads.conversionComplete()) {
return;
}
// If we don't have new data, skip this iteration.
if (!ads.conversionComplete()) {
return;
updateResult();
moveToNextChannel();
startReading();
}
updateResult();
moveToNextChannel();
startReading();
}
void addToJsonInfo(JsonObject& root)
@@ -70,8 +69,6 @@ class ADS1115Usermod : public Usermod {
{
JsonObject top = root.createNestedObject(F("ADC ADS1115"));
top[F("Loop Interval")] = loopInterval;
for (uint8_t i = 0; i < channelsCount; i++) {
ChannelSettings* settingsPtr = &(channelSettings[i]);
JsonObject channel = top.createNestedObject(settingsPtr->settingName);
@@ -82,6 +79,8 @@ class ADS1115Usermod : public Usermod {
channel[F("Offset")] = settingsPtr->offset;
channel[F("Decimals")] = settingsPtr->decimals;
}
top[F("Loop Interval")] = loopInterval;
}
bool readFromConfig(JsonObject& root)
+2 -2
View File
@@ -2,7 +2,7 @@
"name": "ADS1115_v2",
"build": { "libArchive": false },
"dependencies": {
"Adafruit BusIO": "https://github.com/adafruit/Adafruit_BusIO#1.17.4",
"Adafruit ADS1X15": "https://github.com/adafruit/Adafruit_ADS1X15#2.6.2"
"Adafruit BusIO": "https://github.com/adafruit/Adafruit_BusIO#1.13.2",
"Adafruit ADS1X15": "https://github.com/adafruit/Adafruit_ADS1X15#2.4.0"
}
}
+5 -24
View File
@@ -1,29 +1,10 @@
# ADS1115 Usermod
# ADS1115 16-Bit ADC with four inputs
Reads values from an ADS1115 16-bit ADC and exposes them in the `Info` tab.
This usermod will read from an ADS1115 ADC. The voltages are displayed in the Info section of the web UI.
## Features
- Reads values from an ADS1115 over I2C.
- Supports 8 ADS1115 input modes:
- 4 single-ended inputs (`AIN0` to `AIN3`)
- 4 differential pairs (`AIN0-AIN1`, `AIN0-AIN3`, `AIN1-AIN3`, `AIN2-AIN3`)
- Per-channel configuration in the Usermod settings:
- Enable/disable
- Display name
- Units
- Multiplier and offset
- Decimal precision
- Configurable measurement loop interval.
- Publishes configured channel values to the `Info` tab.
Configuration is performed via the Usermod menu. There are no parameters to set in code!
## Compatibility
- Requires an ADS1115 module connected via I2C.
- Works on targets with I2C support.
- Default ADC gain is `1x` (input range `+/-4.096V`).
## Installation
## Installation
- Add `ADS1115` to `custom_usermods` in your `platformio.ini` (or `platformio_override.ini`).
## Author
- Dima Zhemkov [@dima-zhemkov](https://github.com/dima-zhemkov)
Add 'ADS1115' to `custom_usermods` in your platformio environment.
@@ -0,0 +1,5 @@
[env:aht10_example]
extends = env:esp32dev
build_flags =
${common.build_flags} ${esp32.build_flags}
; -D USERMOD_AHT10_DEBUG ; -- add a debug status to the info modal
@@ -25,8 +25,6 @@ class Animated_Staircase : public Usermod {
unsigned int topMaxDist = 50; // default maximum measured distance in cm, top
unsigned int bottomMaxDist = 50; // default maximum measured distance in cm, bottom
bool togglePower = false; // toggle power on/off with staircase on/off
bool topAPinInvert = false; // invert output of top sensor
bool bottomAPinInvert = false; // invert output of bottom sensor
/* runtime variables */
bool initDone = false;
@@ -93,8 +91,6 @@ class Animated_Staircase : public Usermod {
static const char _topEchoCm[];
static const char _bottomEchoCm[];
static const char _togglePower[];
static const char _topPIRorTrigger_pin_invert[];
static const char _bottomPIRorTrigger_pin_invert[];
void publishMqtt(bool bottom, const char* state) {
#ifndef WLED_DISABLE_MQTT
@@ -160,12 +156,6 @@ class Animated_Staircase : public Usermod {
return pulseIn(echoPin, HIGH, maxTimeUs) > 0;
}
bool readPIRPin(int8_t pin, bool invert) {
if (pin < 0) return false;
bool v = digitalRead(pin);
return invert ? !v : v;
}
bool checkSensors() {
bool sensorChanged = false;
@@ -174,15 +164,15 @@ class Animated_Staircase : public Usermod {
bottomSensorRead = bottomSensorWrite ||
(!useUSSensorBottom ?
(bottomPIRorTriggerPin<0 ? false : readPIRPin(bottomPIRorTriggerPin, bottomAPinInvert)) :
(bottomPIRorTriggerPin<0 ? false : digitalRead(bottomPIRorTriggerPin)) :
ultrasoundRead(bottomPIRorTriggerPin, bottomEchoPin, bottomMaxDist*59) // cm to us
);
topSensorRead = topSensorWrite ||
(!useUSSensorTop ?
(topPIRorTriggerPin<0 ? false : readPIRPin(topPIRorTriggerPin, topAPinInvert)) :
(topPIRorTriggerPin<0 ? false : digitalRead(topPIRorTriggerPin)) :
ultrasoundRead(topPIRorTriggerPin, topEchoPin, topMaxDist*59) // cm to us
);
if (bottomSensorRead != bottomSensorState) {
bottomSensorState = bottomSensorRead; // change previous state
sensorChanged = true;
@@ -449,20 +439,18 @@ class Animated_Staircase : public Usermod {
if (staircase.isNull()) {
staircase = root.createNestedObject(FPSTR(_name));
}
staircase[FPSTR(_enabled)] = enabled;
staircase[FPSTR(_segmentDelay)] = segment_delay_ms;
staircase[FPSTR(_onTime)] = on_time_ms / 1000;
staircase[FPSTR(_useTopUltrasoundSensor)] = useUSSensorTop;
staircase[FPSTR(_topPIRorTrigger_pin)] = topPIRorTriggerPin;
staircase[FPSTR(_topEcho_pin)] = useUSSensorTop ? topEchoPin : -1;
staircase[FPSTR(_useBottomUltrasoundSensor)] = useUSSensorBottom;
staircase[FPSTR(_bottomPIRorTrigger_pin)] = bottomPIRorTriggerPin;
staircase[FPSTR(_bottomEcho_pin)] = useUSSensorBottom ? bottomEchoPin : -1;
staircase[FPSTR(_topEchoCm)] = topMaxDist;
staircase[FPSTR(_bottomEchoCm)] = bottomMaxDist;
staircase[FPSTR(_togglePower)] = togglePower;
staircase[FPSTR(_topPIRorTrigger_pin_invert)] = topAPinInvert;
staircase[FPSTR(_bottomPIRorTrigger_pin_invert)] = bottomAPinInvert;
staircase[FPSTR(_enabled)] = enabled;
staircase[FPSTR(_segmentDelay)] = segment_delay_ms;
staircase[FPSTR(_onTime)] = on_time_ms / 1000;
staircase[FPSTR(_useTopUltrasoundSensor)] = useUSSensorTop;
staircase[FPSTR(_topPIRorTrigger_pin)] = topPIRorTriggerPin;
staircase[FPSTR(_topEcho_pin)] = useUSSensorTop ? topEchoPin : -1;
staircase[FPSTR(_useBottomUltrasoundSensor)] = useUSSensorBottom;
staircase[FPSTR(_bottomPIRorTrigger_pin)] = bottomPIRorTriggerPin;
staircase[FPSTR(_bottomEcho_pin)] = useUSSensorBottom ? bottomEchoPin : -1;
staircase[FPSTR(_topEchoCm)] = topMaxDist;
staircase[FPSTR(_bottomEchoCm)] = bottomMaxDist;
staircase[FPSTR(_togglePower)] = togglePower;
DEBUG_PRINTLN(F("Staircase config saved."));
}
@@ -474,13 +462,11 @@ class Animated_Staircase : public Usermod {
bool readFromConfig(JsonObject& root) {
bool oldUseUSSensorTop = useUSSensorTop;
bool oldUseUSSensorBottom = useUSSensorBottom;
bool oldTopAPinInvert = topAPinInvert;
bool oldBottomAPinInvert = bottomAPinInvert;
int8_t oldTopAPin = topPIRorTriggerPin;
int8_t oldTopBPin = topEchoPin;
int8_t oldBottomAPin = bottomPIRorTriggerPin;
int8_t oldBottomBPin = bottomEchoPin;
JsonObject top = root[FPSTR(_name)];
if (top.isNull()) {
DEBUG_PRINT(FPSTR(_name));
@@ -499,12 +485,10 @@ class Animated_Staircase : public Usermod {
useUSSensorTop = top[FPSTR(_useTopUltrasoundSensor)] | useUSSensorTop;
topPIRorTriggerPin = top[FPSTR(_topPIRorTrigger_pin)] | topPIRorTriggerPin;
topEchoPin = top[FPSTR(_topEcho_pin)] | topEchoPin;
topAPinInvert = top[FPSTR(_topPIRorTrigger_pin_invert)] | topAPinInvert;
useUSSensorBottom = top[FPSTR(_useBottomUltrasoundSensor)] | useUSSensorBottom;
bottomPIRorTriggerPin = top[FPSTR(_bottomPIRorTrigger_pin)] | bottomPIRorTriggerPin;
bottomEchoPin = top[FPSTR(_bottomEcho_pin)] | bottomEchoPin;
bottomAPinInvert = top[FPSTR(_bottomPIRorTrigger_pin_invert)] | bottomAPinInvert;
topMaxDist = top[FPSTR(_topEchoCm)] | topMaxDist;
topMaxDist = min(150,max(30,(int)topMaxDist)); // max distance ~1.5m (a lag of 9ms may be expected)
@@ -570,15 +554,14 @@ const char Animated_Staircase::_segmentDelay[] PROGMEM = "segment-d
const char Animated_Staircase::_onTime[] PROGMEM = "on-time-s";
const char Animated_Staircase::_useTopUltrasoundSensor[] PROGMEM = "useTopUltrasoundSensor";
const char Animated_Staircase::_topPIRorTrigger_pin[] PROGMEM = "topPIRorTrigger_pin";
const char Animated_Staircase::_topPIRorTrigger_pin_invert[] PROGMEM = "topPIRorTrigger_pin_invert";
const char Animated_Staircase::_topEcho_pin[] PROGMEM = "topEcho_pin";
const char Animated_Staircase::_useBottomUltrasoundSensor[] PROGMEM = "useBottomUltrasoundSensor";
const char Animated_Staircase::_bottomPIRorTrigger_pin[] PROGMEM = "bottomPIRorTrigger_pin";
const char Animated_Staircase::_bottomPIRorTrigger_pin_invert[] PROGMEM = "bottomPIRorTrigger_pin_invert";
const char Animated_Staircase::_bottomEcho_pin[] PROGMEM = "bottomEcho_pin";
const char Animated_Staircase::_topEchoCm[] PROGMEM = "top-dist-cm";
const char Animated_Staircase::_bottomEchoCm[] PROGMEM = "bottom-dist-cm";
const char Animated_Staircase::_togglePower[] PROGMEM = "toggle-on-off";
static Animated_Staircase animated_staircase;
REGISTER_USERMOD(animated_staircase);
+2 -2
View File
@@ -1,5 +1,5 @@
#include "wled.h"
#ifdef WLED_DISABLE_MQTT
#if defined(USERMOD_DHT_MQTT) && defined(WLED_DISABLE_MQTT)
#error "This user mod requires MQTT to be enabled."
#endif
@@ -246,4 +246,4 @@ class UsermodDHT : public Usermod {
static UsermodDHT dht;
REGISTER_USERMOD(dht);
REGISTER_USERMOD(dht);
@@ -8,13 +8,13 @@
; USERMOD_DHT_MQTT - publish measurements to the MQTT broker
; USERMOD_DHT_STATS - For debug, report delay stats
[env:esp8266_2m_usermod_dht_C]
extends = env:esp8266_2m
custom_usermods = ${env:esp8266_2m.custom_usermods} DHT
build_flags = ${env:esp8266_2m.build_flags} -D USERMOD_DHT_CELSIUS
[env:d1_mini_usermod_dht_C]
extends = env:d1_mini
custom_usermods = ${env:d1_mini.custom_usermods} DHT
build_flags = ${env:d1_mini.build_flags} -D USERMOD_DHT_CELSIUS
[env:esp32dev_LEDPIN_16_usermod_dht_C]
extends = env:esp32dev
custom_usermods = ${env:esp32dev.custom_usermods} DHT
build_flags = ${env:esp32dev.build_flags} -D LEDPIN=16 -D USERMOD_DHT_CELSIUS -D USERMOD_DHT_STATS
[env:custom32_LEDPIN_16_usermod_dht_C]
extends = env:custom32_LEDPIN_16
custom_usermods = ${env:custom32_LEDPIN_16.custom_usermods} DHT
build_flags = ${env:custom32_LEDPIN_16.build_flags} -D USERMOD_DHT_CELSIUS -D USERMOD_DHT_STATS
+1 -1
View File
@@ -1,5 +1,5 @@
{
"name": "EleksTube_IPS",
"name:": "EleksTube_IPS",
"build": { "libArchive": false },
"dependencies": {
"TFT_eSPI" : "2.5.33"
+35 -114
View File
@@ -1,38 +1,14 @@
#include "wled.h"
#include <INA226_WE.h>
#ifndef INA226_ADDRESS
#define INA226_ADDRESS 0x40 // Default I2C address for INA226
#endif
#ifndef INA226_CHECK_INTERVAL_MS
#define INA226_CHECK_INTERVAL_MS 60000 // Default check interval in milliseconds
#endif
#define DEFAULT_CHECKINTERVAL INA226_CHECK_INTERVAL_MS
#define DEFAULT_CHECKINTERVAL 60000
#define DEFAULT_INASAMPLES 128
#define DEFAULT_INASAMPLESENUM AVERAGE_128
#define DEFAULT_INACONVERSIONTIME 1100
#define DEFAULT_INACONVERSIONTIMEENUM CONV_TIME_1100
// Compile-time defaults for shunt resistor (micro-ohms), current range (mA), and current offset (mA)
// These can be overridden via -D flags in platformio.ini / platformio_override.ini
#ifndef INA226_SHUNT_MICRO_OHMS
#define INA226_SHUNT_MICRO_OHMS 1000000 // 1 Ohm = 1,000,000 μΩ
#endif
#ifndef INA226_DEFAULT_CURRENT_RANGE
#define INA226_DEFAULT_CURRENT_RANGE 1000 // 1000 mA = 1 A
#endif
#ifndef INA226_CURRENT_OFFSET_MA
#define INA226_CURRENT_OFFSET_MA 0 // No offset by default
#endif
#ifndef INA226_ENABLED_DEFAULT
#define INA226_ENABLED_DEFAULT false
#endif
// A packed version of all INA settings enums and their human friendly counterparts packed into a 32 bit structure
// Some values are shifted and need to be preprocessed before usage
struct InaSettingLookup
@@ -105,11 +81,10 @@ private:
uint16_t _settingInaSamples : 11; // Number of samples for averaging, max 1024
uint8_t _i2cAddress;
uint32_t _checkIntervalMs; // milliseconds, user settings is in seconds
float _decimalFactor; // a power of 10 factor. 1 would be no change, 10 is one decimal, 100 is two etc. User sees a power of 10 (0, 1, 2, ..)
uint32_t _shuntResistorUOhm; // Shunt resistor value in micro-ohms (μΩ)
uint16_t _currentRangeMa; // Expected maximum current in milliamps
int16_t _currentOffsetMa; // Current offset in milliamps, subtracted from readings
uint16_t _checkInterval; // milliseconds, user settings is in seconds
float _decimalFactor; // a power of 10 factor. 1 would be no change, 10 is one decimal, 100 is two etc. User sees a power of 10 (0, 1, 2, ..)
uint16_t _shuntResistor; // Shunt resistor value in milliohms
uint16_t _currentRange; // Expected maximum current in milliamps
uint8_t _lastStatus = 0;
float _lastCurrent = 0;
@@ -118,7 +93,7 @@ private:
float _lastShuntVoltage = 0;
bool _lastOverflow = false;
#ifndef WLED_DISABLE_MQTT
#ifndef WLED_MQTT_DISABLE
float _lastCurrentSent = 0;
float _lastVoltageSent = 0;
float _lastPowerSent = 0;
@@ -143,11 +118,9 @@ private:
_ina226 = new INA226_WE(_i2cAddress);
if (!_ina226->init())
{
DEBUG_PRINTLN(F("INA226: init failed!"));
DEBUG_PRINTLN(F("INA226 initialization failed!"));
return;
}
DEBUG_PRINTF_P(PSTR("INA226: addr=0x%02X shunt=%luμΩ range=%umA offset=%dmA\n"),
_i2cAddress, _shuntResistorUOhm, _currentRangeMa, _currentOffsetMa);
_ina226->setCorrectionFactor(1.0);
uint16_t tmpShort = _settingInaSamples;
@@ -156,7 +129,7 @@ private:
tmpShort = _settingInaConversionTimeUs << 2;
_ina226->setConversionTime(getConversionTimeEnum(tmpShort));
if (_checkIntervalMs >= 20000)
if (_checkInterval >= 20000)
{
_isTriggeredOperationMode = true;
_ina226->setMeasureMode(TRIGGERED);
@@ -167,11 +140,7 @@ private:
_ina226->setMeasureMode(CONTINUOUS);
}
_ina226->setResistorRange(static_cast<float>(_shuntResistorUOhm) / 1000000.0f, static_cast<float>(_currentRangeMa) / 1000.0f);
DEBUG_PRINTF_P(PSTR("INA226: mode=%s interval=%lums samples=%u convTime=%uμs\n"),
_isTriggeredOperationMode ? "triggered" : "continuous",
_checkIntervalMs, _settingInaSamples, _settingInaConversionTimeUs << 2);
_ina226->setResistorRange(static_cast<float>(_shuntResistor) / 1000.0, static_cast<float>(_currentRange) / 1000.0);
}
void fetchAndPushValues()
@@ -181,19 +150,17 @@ private:
if (_lastStatus != 0)
return;
float current = truncateDecimals((_ina226->getCurrent_mA() - _currentOffsetMa) / 1000.0f);
float current = truncateDecimals(_ina226->getCurrent_mA() / 1000.0);
float voltage = truncateDecimals(_ina226->getBusVoltage_V());
float power = truncateDecimals(_ina226->getBusPower() / 1000.0f);
float shuntVoltage = truncateDecimals(_ina226->getShuntVoltage_mV());
float power = truncateDecimals(_ina226->getBusPower() / 1000.0);
float shuntVoltage = truncateDecimals(_ina226->getShuntVoltage_V());
bool overflow = _ina226->overflow;
#ifndef WLED_DISABLE_MQTT
mqttPublishIfChanged(F("current"), _lastCurrentSent, current, 0.01f);
mqttPublishIfChanged(F("voltage"), _lastVoltageSent, voltage, 0.01f);
mqttPublishIfChanged(F("power"), _lastPowerSent, power, 0.1f);
// Publish in V for backward compatibility
float shuntVoltageV = shuntVoltage / 1000.0f;
mqttPublishIfChanged(F("shunt_voltage"), _lastShuntVoltageSent, shuntVoltageV, 0.01f);
mqttPublishIfChanged(F("shunt_voltage"), _lastShuntVoltageSent, shuntVoltage, 0.01f);
mqttPublishIfChanged(F("overflow"), _lastOverflowSent, overflow);
#endif
@@ -202,9 +169,6 @@ private:
_lastPower = power;
_lastShuntVoltage = shuntVoltage;
_lastOverflow = overflow;
DEBUG_PRINTF_P(PSTR("INA226: %.3fA %.2fV %.2fW shunt=%.2fmV%s\n"),
current, voltage, power, shuntVoltage, overflow ? " OVF" : "");
}
void handleTriggeredMode(unsigned long currentTime)
@@ -224,7 +188,7 @@ private:
}
else
{
if (currentTime - _lastLoopCheck >= _checkIntervalMs)
if (currentTime - _lastLoopCheck >= _checkInterval)
{
// Start a measurement and use isBusy() later to determine when it is done
_ina226->startSingleMeasurementNoWait();
@@ -237,7 +201,7 @@ private:
void handleContinuousMode(unsigned long currentTime)
{
if (currentTime - _lastLoopCheck >= _checkIntervalMs)
if (currentTime - _lastLoopCheck >= _checkInterval)
{
_lastLoopCheck = currentTime;
fetchAndPushValues();
@@ -251,23 +215,19 @@ private:
return;
char topic[128];
auto buildTopic = [&](const char *suffix) {
snprintf_P(topic, sizeof(topic), PSTR("%s/%s"), mqttDeviceTopic, suffix);
};
buildTopic("current");
snprintf_P(topic, 127, "%s/current", mqttDeviceTopic);
mqttCreateHassSensor(F("Current"), topic, F("current"), F("A"));
buildTopic("voltage");
snprintf_P(topic, 127, "%s/voltage", mqttDeviceTopic);
mqttCreateHassSensor(F("Voltage"), topic, F("voltage"), F("V"));
buildTopic("power");
snprintf_P(topic, 127, "%s/power", mqttDeviceTopic);
mqttCreateHassSensor(F("Power"), topic, F("power"), F("W"));
buildTopic("shunt_voltage");
snprintf_P(topic, 127, "%s/shunt_voltage", mqttDeviceTopic);
mqttCreateHassSensor(F("Shunt Voltage"), topic, F("voltage"), F("V"));
buildTopic("overflow");
snprintf_P(topic, 127, "%s/overflow", mqttDeviceTopic);
mqttCreateHassBinarySensor(F("Overflow"), topic);
}
@@ -355,23 +315,14 @@ public:
UsermodINA226()
{
// Default values
_settingEnabled = INA226_ENABLED_DEFAULT;
_settingInaSamples = DEFAULT_INASAMPLES;
_settingInaConversionTimeUs = DEFAULT_INACONVERSIONTIME >> 2; // stored shifted to fit 12-bit field
_settingInaConversionTimeUs = DEFAULT_INACONVERSIONTIME;
_i2cAddress = INA226_ADDRESS;
_checkIntervalMs = DEFAULT_CHECKINTERVAL;
_checkInterval = DEFAULT_CHECKINTERVAL;
_decimalFactor = 100;
_shuntResistorUOhm = INA226_SHUNT_MICRO_OHMS;
_currentRangeMa = INA226_DEFAULT_CURRENT_RANGE;
_currentOffsetMa = INA226_CURRENT_OFFSET_MA;
_mqttPublish = false;
_mqttPublishAlways = false;
_mqttHomeAssistant = false;
_initDone = false;
_isTriggeredOperationMode = false;
_measurementTriggered = false;
_shuntResistor = 1000;
_currentRange = 1000;
}
void setup()
@@ -448,7 +399,7 @@ public:
JsonArray jsonCurrent = user.createNestedArray(F("Current"));
JsonArray jsonVoltage = user.createNestedArray(F("Voltage"));
JsonArray jsonPower = user.createNestedArray(F("Power"));
JsonArray jsonShuntVoltage = user.createNestedArray(F("Shunt Voltage Drop"));
JsonArray jsonShuntVoltage = user.createNestedArray(F("Shunt Voltage"));
JsonArray jsonOverflow = user.createNestedArray(F("Overflow"));
if (_lastLoopCheck == 0)
@@ -481,7 +432,7 @@ public:
jsonPower.add(F("W"));
jsonShuntVoltage.add(_lastShuntVoltage);
jsonShuntVoltage.add(F("mV"));
jsonShuntVoltage.add(F("V"));
jsonOverflow.add(_lastOverflow ? F("true") : F("false"));
}
@@ -491,13 +442,12 @@ public:
JsonObject top = root.createNestedObject(FPSTR(_name));
top[F("Enabled")] = _settingEnabled;
top[F("I2CAddress")] = static_cast<uint8_t>(_i2cAddress);
top[F("CheckInterval")] = _checkIntervalMs / 1000;
top[F("CheckInterval")] = _checkInterval / 1000;
top[F("INASamples")] = _settingInaSamples;
top[F("INAConversionTime")] = _settingInaConversionTimeUs << 2;
top[F("Decimals")] = log10f(_decimalFactor);
top[F("ShuntResistor")] = static_cast<float>(_shuntResistorUOhm) / 1000.0f;
top[F("CurrentRange")] = _currentRangeMa;
top[F("CurrentOffset")] = _currentOffsetMa;
top[F("ShuntResistor")] = _shuntResistor;
top[F("CurrentRange")] = _currentRange;
#ifndef WLED_DISABLE_MQTT
top[F("MqttPublish")] = _mqttPublish;
top[F("MqttPublishAlways")] = _mqttPublishAlways;
@@ -507,17 +457,6 @@ public:
DEBUG_PRINTLN(F("INA226 config saved."));
}
void appendConfigData() override
{
oappend(F("addInfo('INA226:CheckInterval',1,'seconds');"));
oappend(F("addInfo('INA226:INASamples',1,'samples (1-1024)');"));
oappend(F("addInfo('INA226:INAConversionTime',1,'&micro;s');"));
oappend(F("addInfo('INA226:Decimals',1,'(0-5)');"));
oappend(F("addInfo('INA226:ShuntResistor',1,'m&Omega;');"));
oappend(F("addInfo('INA226:CurrentRange',1,'mA');"));
oappend(F("addInfo('INA226:CurrentOffset',1,'mA');"));
}
bool readFromConfig(JsonObject &root) override
{
JsonObject top = root[FPSTR(_name)];
@@ -533,12 +472,12 @@ public:
configComplete = false;
configComplete &= getJsonValue(top[F("I2CAddress")], _i2cAddress);
if (getJsonValue(top[F("CheckInterval")], _checkIntervalMs))
if (getJsonValue(top[F("CheckInterval")], _checkInterval))
{
if (1 <= _checkIntervalMs && _checkIntervalMs <= 600)
_checkIntervalMs *= 1000;
if (1 <= _checkInterval && _checkInterval <= 600)
_checkInterval *= 1000;
else
_checkIntervalMs = DEFAULT_CHECKINTERVAL;
_checkInterval = DEFAULT_CHECKINTERVAL;
}
else
configComplete = false;
@@ -572,26 +511,8 @@ public:
else
configComplete = false;
float shuntMilliOhms;
if (getJsonValue(top[F("ShuntResistor")], shuntMilliOhms))
{
if (shuntMilliOhms > 0)
_shuntResistorUOhm = static_cast<uint32_t>(shuntMilliOhms * 1000.0f + 0.5f);
else
_shuntResistorUOhm = INA226_SHUNT_MICRO_OHMS;
}
else
configComplete = false;
if (getJsonValue(top[F("CurrentRange")], _currentRangeMa))
{
if (_currentRangeMa == 0 || _currentRangeMa > 20000)
_currentRangeMa = INA226_DEFAULT_CURRENT_RANGE;
}
else
configComplete = false;
if (!getJsonValue(top[F("CurrentOffset")], _currentOffsetMa))
_currentOffsetMa = INA226_CURRENT_OFFSET_MA; // Use compile-time default if missing from config
configComplete &= getJsonValue(top[F("ShuntResistor")], _shuntResistor);
configComplete &= getJsonValue(top[F("CurrentRange")], _currentRange);
#ifndef WLED_DISABLE_MQTT
if (getJsonValue(top[F("MqttPublish")], tmpBool))
+1 -31
View File
@@ -18,7 +18,6 @@ The following settings can be configured in the Usermod Menu:
- **Decimals**: Number of decimals in the output.
- **ShuntResistor**: Shunt resistor value in milliohms. An R100 shunt resistor should be written as "100", while R010 should be "10".
- **CurrentRange**: Expected maximum current in milliamps (e.g., 5 A = 5000 mA).
- **CurrentOffset**: Current offset in milliamps, subtracted from raw readings. Useful for compensating a consistent bias in the sensor. Default is 0.
- **MqttPublish**: Enable or disable MQTT publishing.
- **MqttPublishAlways**: Publish always, regardless if there is a change.
- **MqttHomeAssistantDiscovery**: Enable Home Assistant discovery.
@@ -64,33 +63,4 @@ extends = env:esp32dev
custom_usermods = ${env:esp32dev.custom_usermods} INA226
build_flags = ${env:esp32dev.build_flags}
; -D USERMOD_INA226_DEBUG ; -- add a debug status to the info modal
```
### Compile-time Defaults
Several parameters can be overridden at compile time via `-D` build flags. This is useful for setting board-specific defaults so the device works correctly on first boot without manual configuration.
| Build Flag | Default | Unit | Description |
|---|---|---|---|
| `INA226_ADDRESS` | `0x40` | — | I2C address of the INA226 |
| `INA226_SHUNT_MICRO_OHMS` | `1000000` | μΩ | Shunt resistor value (1 000 000 μΩ = 1 Ω) |
| `INA226_DEFAULT_CURRENT_RANGE` | `1000` | mA | Expected maximum current (1000 mA = 1 A) |
| `INA226_CURRENT_OFFSET_MA` | `0` | mA | Current offset subtracted from readings |
| `INA226_CHECK_INTERVAL_MS` | `60000` | ms | Default interval between readings on first boot |
| `INA226_ENABLED_DEFAULT` | `false` | — | Enable the usermod on first boot |
Example for a board with a 2.888 mΩ effective shunt, 10 A range, -118 mA offset, 1 second polling, and enabled by default:
```ini
[env:my_board]
extends = env:esp32dev
custom_usermods = ${env:esp32dev.custom_usermods} INA226
build_flags = ${env:esp32dev.build_flags}
-D INA226_ENABLED_DEFAULT=true
-D INA226_SHUNT_MICRO_OHMS=2888
-D INA226_DEFAULT_CURRENT_RANGE=10000
-D INA226_CURRENT_OFFSET_MA=-118
-D INA226_CHECK_INTERVAL_MS=1000
```
All compile-time defaults can still be changed at runtime through the Usermod settings page.
```
@@ -0,0 +1,6 @@
[env:ina226_example]
extends = env:esp32dev
custom_usermods = ${env:esp32dev.custom_usermods} INA226_v2
build_flags =
${env:esp32dev.build_flags}
; -D USERMOD_INA226_DEBUG ; -- add a debug status to the info modal
@@ -1,5 +1,6 @@
; Options
; -------
; USERMOD_SN_PHOTORESISTOR - define this to have this user mod included wled00\usermods_list.cpp
; USERMOD_SN_PHOTORESISTOR_MEASUREMENT_INTERVAL - the number of milliseconds between measurements, defaults to 60 seconds
; USERMOD_SN_PHOTORESISTOR_FIRST_MEASUREMENT_AT - the number of milliseconds after boot to take first measurement, defaults to 20 seconds
; USERMOD_SN_PHOTORESISTOR_REFERENCE_VOLTAGE - the voltage supplied to the sensor, defaults to 5v
@@ -7,10 +8,9 @@
; USERMOD_SN_PHOTORESISTOR_RESISTOR_VALUE - the resistor size, defaults to 10000.0 (10K hms)
; USERMOD_SN_PHOTORESISTOR_OFFSET_VALUE - the offset value to report on, defaults to 25
;
[env:usermod_sn_photoresistor_esp8266_2m]
extends = env:esp8266_2m
custom_usermods = ${env:esp8266_2m.custom_usermods} SN_Photoresistor
[env:usermod_sn_photoresistor_d1_mini]
extends = env:d1_mini
build_flags =
${env:esp8266_2m.build_flags}
-D USERMOD_SN_PHOTORESISTOR_MEASUREMENT_INTERVAL=60
lib_deps = ${env:esp8266_2m.lib_deps}
${common.build_flags_esp8266}
-D USERMOD_SN_PHOTORESISTOR
lib_deps = ${env.lib_deps}
@@ -1,4 +1,4 @@
{
"name": "ST7789_display",
"name:": "ST7789_display",
"build": { "libArchive": false }
}
@@ -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 IRPIN=4
; -D RLYPIN=12
; -D RLYMDE=1
@@ -0,0 +1,5 @@
; Options
; -------
; USERMOD_DALLASTEMPERATURE_MEASUREMENT_INTERVAL - the number of milliseconds between measurements, defaults to 60 seconds
;
+36 -17
View File
@@ -296,17 +296,17 @@ void FFTcode(void * parameter)
ArduinoFFT<float> FFT = ArduinoFFT<float>(valFFT, vImag, samplesFFT, SAMPLE_RATE, true);
#elif !defined(UM_AUDIOREACTIVE_USE_INTEGER_FFT)
// allocate and initialize FFT buffers on first call
// note: free() is never used on these pointers. If it ever is implemented, this implementation can cause memory leaks (need to free raw pointers)
if (valFFT == nullptr) {
float* raw_buffer = (float*)heap_caps_malloc((2 * samplesFFT * sizeof(float)) + 16, MALLOC_CAP_8BIT);
if ((raw_buffer == nullptr)) return; // something went wrong
valFFT = (float*)(((uintptr_t)raw_buffer + 15) & ~15); // SIMD requires aligned memory to 16-byte boundary. note in IDF5 there is MALLOC_CAP_SIMD available
valFFT = (float*)heap_caps_aligned_calloc(16, 2 * samplesFFT, sizeof(float), MALLOC_CAP_8BIT); // SIMD requires aligned memory to 16-byte boundary. note in IDF5 there is MALLOC_CAP_SIMD available
if ((valFFT == nullptr)) return; // something went wrong
}
// create window
if (windowFFT == nullptr) {
float* raw_buffer = (float*)heap_caps_malloc((samplesFFT * sizeof(float)) + 16, MALLOC_CAP_8BIT);
if ((raw_buffer == nullptr)) return; // something went wrong
windowFFT = (float*)(((uintptr_t)raw_buffer + 15) & ~15); // SIMD requires aligned memory to 16-byte boundary
windowFFT = (float*)heap_caps_aligned_calloc(16, samplesFFT, sizeof(float), MALLOC_CAP_8BIT); // SIMD requires aligned memory to 16-byte boundary. note in IDF5 there is MALLOC_CAP_SIMD available
if ((windowFFT == nullptr)) {
heap_caps_free(valFFT); valFFT = nullptr;
return; // something went wrong
}
}
if (dsps_fft2r_init_fc32(NULL, samplesFFT) != ESP_OK) return; // initialize FFT tables
// create window function for FFT
@@ -316,16 +316,20 @@ void FFTcode(void * parameter)
dsps_wind_flat_top_f32(windowFFT, samplesFFT);
#endif
#else
// allocate and initialize integer FFT buffers on first call
if (valFFT == nullptr) valFFT = (int16_t*) calloc(sizeof(int16_t), samplesFFT * 2);
if ((valFFT == nullptr)) return; // something went wrong
// use integer FFT - allocate and initialize integer FFT buffers on first call, 4 bytes aligned (just in case, even if not strictly needed for int16_t)
if (valFFT == nullptr) valFFT = (int16_t*) heap_caps_aligned_calloc(4, samplesFFT * 2, sizeof(int16_t), MALLOC_CAP_8BIT);
// create window
if (windowFFT == nullptr) windowFFT = (int16_t*) calloc(sizeof(int16_t), samplesFFT);
if ((windowFFT == nullptr)) return; // something went wrong
if (dsps_fft2r_init_sc16(NULL, samplesFFT) != ESP_OK) return; // initialize FFT tables
if (windowFFT == nullptr) windowFFT = (int16_t*) heap_caps_aligned_calloc(4, samplesFFT, sizeof(int16_t), MALLOC_CAP_8BIT);
// create window function for FFT
float *windowFloat = (float*) calloc(sizeof(float), samplesFFT); // temporary buffer for window function
if ((windowFloat == nullptr)) return; // something went wrong
float *windowFloat = (float*) heap_caps_aligned_calloc(4, samplesFFT, sizeof(float), MALLOC_CAP_8BIT); // temporary buffer for window function
if (windowFloat == nullptr || windowFFT == nullptr || valFFT == nullptr) { // something went wrong
if (windowFloat) heap_caps_free(windowFloat);
if (windowFFT) heap_caps_free(windowFFT); windowFFT = nullptr;
if (valFFT) heap_caps_free(valFFT); valFFT = nullptr;
return;
}
if (dsps_fft2r_init_sc16(NULL, samplesFFT) != ESP_OK) return; // initialize FFT tables
#ifdef FFT_PREFER_EXACT_PEAKS
dsps_wind_blackman_harris_f32(windowFloat, samplesFFT);
#else
@@ -335,7 +339,7 @@ void FFTcode(void * parameter)
for (int i = 0; i < samplesFFT; i++) {
windowFFT[i] = (int16_t)(windowFloat[i] * 32767.0f);
}
free(windowFloat); // free temporary buffer
heap_caps_free(windowFloat); // free temporary buffer
#endif
// see https://www.freertos.org/vtaskdelayuntil.html
@@ -468,7 +472,6 @@ void FFTcode(void * parameter)
}
FFT_Magnitude = FFT_Magnitude_int * 512; // scale to match raw float value
FFT_MajorPeak = FFT_MajorPeak_int;
FFT_Magnitude = FFT_Magnitude_int;
#endif
#endif
FFT_MajorPeak = constrain(FFT_MajorPeak, 1.0f, 11025.0f); // restrict value to range expected by effects
@@ -2071,6 +2074,13 @@ class AudioReactive : public Usermod {
bool configComplete = !top.isNull();
bool oldEnabled = enabled;
bool oldAddPalettes = addPalettes;
#ifdef ARDUINO_ARCH_ESP32
auto oldDMType = dmType;
auto oldI2SsdPin = i2ssdPin;
auto oldI2swsPin = i2swsPin;
auto oldI2SckPin = i2sckPin;
auto oldI2SmclkPin = mclkPin;
#endif
configComplete &= getJsonValue(top[FPSTR(_enabled)], enabled);
configComplete &= getJsonValue(top[FPSTR(_addPalettes)], addPalettes);
@@ -2112,6 +2122,15 @@ class AudioReactive : public Usermod {
// add/remove custom/audioreactive palettes
if ((oldAddPalettes && !addPalettes) || (oldAddPalettes && !enabled)) removeAudioPalettes();
if ((addPalettes && !oldAddPalettes && enabled) || (addPalettes && !oldEnabled && enabled)) createAudioPalettes();
#ifdef ARDUINO_ARCH_ESP32
// notify user when a reboot is necessary
if ((audioSource != nullptr) && (oldDMType != dmType)) errorFlag = ERR_REBOOT_NEEDED; // changing mic type requires reboot
if ( (audioSource != nullptr) && (enabled==true)
&& ((oldI2SsdPin != i2ssdPin) || (oldI2swsPin != i2swsPin) || (oldI2SckPin != i2sckPin)) ) errorFlag = ERR_REBOOT_NEEDED; // changing mic pins requires reboot
if ((audioSource != nullptr) && (oldI2SmclkPin != mclkPin)) errorFlag = ERR_REBOOT_NEEDED; // changing MCLK pin requires reboot
if ((oldDMType != dmType) && (oldDMType == 0)) errorFlag = ERR_POWEROFF_NEEDED; // changing from analog mic requires power cycle
if ((oldDMType != dmType) && (dmType == 0)) errorFlag = ERR_POWEROFF_NEEDED; // changing to analog mic requires power cycle
#endif
} // else setup() will create palettes
return configComplete;
}
@@ -13,7 +13,7 @@ board_build.partitions = ${esp32.large_partitions}
board_build.f_flash = 80000000L
board_build.flash_mode = qio
monitor_filters = esp32_exception_decoder
build_flags = ${common.build_flags} ${esp32s3.build_flags} -D WLED_RELEASE_NAME=\"T-QT-PRO-8MB_dice\"
build_flags = ${common.build_flags} ${esp32s3.build_flags} -D WLED_RELEASE_NAME=T-QT-PRO-8MB
-D CONFIG_LITTLEFS_FOR_IDF_3_2 -D WLED_WATCHDOG_TIMEOUT=0
-D ARDUINO_USB_CDC_ON_BOOT=1 -D ARDUINO_USB_MODE=1 ;; for boards with USB-OTG connector only (USBCDC or "TinyUSB")
@@ -75,7 +75,7 @@ board_build.partitions = ${esp32.large_partitions}
board_build.f_flash = 80000000L
board_build.flash_mode = qio
monitor_filters = esp32_exception_decoder
build_flags = ${common.build_flags} ${esp32s3.build_flags} -D WLED_RELEASE_NAME=\"ESP32-S3_8MB_qspi_dice\"
build_flags = ${common.build_flags} ${esp32s3.build_flags} -D WLED_RELEASE_NAME=ESP32-S3_8MB_qspi
-D CONFIG_LITTLEFS_FOR_IDF_3_2 -D WLED_WATCHDOG_TIMEOUT=0
-D ARDUINO_USB_CDC_ON_BOOT=1 -D ARDUINO_USB_MODE=1 ;; for boards with USB-OTG connector only (USBCDC or "TinyUSB")
@@ -105,7 +105,7 @@ lib_deps = ${esp32s3.lib_deps}
# https://github.com/wled-dev/WLED/issues/1382
; [env:esp32dev_dice]
; extends = env:esp32dev
; build_flags = ${common.build_flags} ${esp32.build_flags} -D WLED_RELEASE_NAME=\"ESP32_dice\"
; build_flags = ${common.build_flags} ${esp32.build_flags} -D WLED_RELEASE_NAME=ESP32
; ; Enable Pixels dice mod
; -D USERMOD_PIXELS_DICE_TRAY
; lib_deps = ${esp32.lib_deps}
+1 -1
View File
@@ -1,5 +1,5 @@
{
"name": "pov_display",
"name:": "pov_display",
"build": { "libArchive": false},
"platforms": ["espressif32"]
}
-6
View File
@@ -143,13 +143,7 @@ void ShtUsermod::appendDeviceToMqttDiscoveryMessage(JsonDocument& root) {
device[F("ids")] = escapedMac.c_str();
device[F("name")] = serverDescription;
device[F("sw")] = versionString;
// AI: below section was generated by an AI
#ifdef ARDUINO_ARCH_ESP32
device[F("mdl")] = ESP.getChipModel();
#else
device[F("mdl")] = F("ESP8266");
#endif
// AI: end
device[F("mf")] = F("espressif");
}
@@ -2,10 +2,10 @@
default_envs = esp32dev_fld
[env:esp32dev_fld]
extends = env:esp32dev
custom_usermods = ${env:esp32dev.custom_usermods} four_line_display_ALT
extends = env:esp32dev_V4
custom_usermods = ${env:esp32dev_V4.custom_usermods} four_line_display_ALT
build_flags =
${env:esp32dev.build_flags}
${env:esp32dev_V4.build_flags}
-D FLD_TYPE=SH1106
-D I2CSCLPIN=27
-D I2CSDAPIN=26
@@ -2,10 +2,10 @@
default_envs = esp32dev_re
[env:esp32dev_re]
extends = env:esp32dev
custom_usermods = ${env:esp32dev.custom_usermods} rotary_encoder_ui_ALT
extends = env:esp32dev_V4
custom_usermods = ${env:esp32dev_V4.custom_usermods} rotary_encoder_ui_ALT
build_flags =
${env:esp32dev.build_flags}
${env:esp32dev_V4.build_flags}
-D USERMOD_ROTARY_ENCODER_GPIO=INPUT
-D ENCODER_DT_PIN=21
-D ENCODER_CLK_PIN=23
+3 -12
View File
@@ -42,7 +42,7 @@
#define DEFAULT_MODE (uint8_t)0
#define DEFAULT_SPEED (uint8_t)128
#define DEFAULT_INTENSITY (uint8_t)128
#define DEFAULT_COLOR (uint32_t)0xFFAA00
#define DEFAULT_COLOR (uint32_t)0xFFA000
#define DEFAULT_C1 (uint8_t)128
#define DEFAULT_C2 (uint8_t)128
#define DEFAULT_C3 (uint8_t)16
@@ -562,7 +562,7 @@ class Segment {
public:
Segment(uint16_t sStart=0, uint16_t sStop=30, uint16_t sStartY = 0, uint16_t sStopY = 1)
: colors{DEFAULT_COLOR,BLACK,BLACK}
: colors{BLACK,BLACK,BLACK} // set colors to black, will be updated to orange if segment is created as "auto segment" or from UI
, start(sStart)
, stop(sStop > sStart ? sStop : sStart+1) // minimum length is 1
, startY(sStartY)
@@ -810,11 +810,6 @@ class Segment {
friend class ParticleSystem1D;
};
// max wait times when waiting until !strip.isUpdating() - use with waitForLEDs(...)
constexpr unsigned STRIP_WAIT_VERYSHORT = 25; // 25 ms - when risk of flickering is low but delays should be avoided
constexpr unsigned STRIP_WAIT_SHORT = 50; // 50 ms - for cases where fluent animations are most important, and risk of flickering is low
constexpr unsigned STRIP_WAIT_MEDIUM = 150; // 150 ms - good balance to avoid flickering on -C3 (good up to 4000 ws2812b LEDs per pin)
// main "strip" class (108 bytes)
class WS2812FX {
typedef void (*mode_ptr)(); // pointer to mode function
@@ -915,11 +910,6 @@ class WS2812FX {
{ if (_segments.size() < getMaxSegments()) _segments.emplace_back(sStart,sStop,sStartY,sStopY); }
inline void suspend() { _suspend = true; } // will suspend (and canacel) strip.service() execution
inline void resume() { _suspend = false; } // will resume strip.service() execution
inline bool isSuspended() const { return _suspend; } // true if strip.service() execution is suspended
// be nice, but not too nice - wait until LEDs are idle, or maxWaitMS have passed
// on 8266 this call will _not_ wait outside of the main loop context
// returns isUpdating() status after waiting
bool waitForLEDs(unsigned maxWaitMS, bool always = false) const;
void restartRuntime();
void setTransitionMode(bool t);
@@ -933,6 +923,7 @@ class WS2812FX {
inline bool isServicing() const { return _isServicing; } // returns true if strip.service() is executing
inline bool hasWhiteChannel() const { return _hasWhiteChannel; } // returns true if strip contains separate white chanel
inline bool isOffRefreshRequired() const { return _isOffRefreshRequired; } // returns true if strip requires regular updates (i.e. TM1814 chipset)
inline bool isSuspended() const { return _suspend; } // returns true if strip.service() execution is suspended
inline bool needsUpdate() const { return _triggered; } // returns true if strip received a trigger() request
// uint8_t paletteBlend; // obsolete - use global paletteBlend instead of strip.paletteBlend
+12 -92
View File
@@ -1148,10 +1148,10 @@ void Segment::blur(uint8_t blur_amount, bool smear) const {
*/
uint32_t Segment::color_wheel(uint8_t pos) const {
if (palette) return color_from_palette(pos, false, true, 0); // color_wheel is a continuous (moving) wheel, so wrap end->start (restores pre-0.16 behaviour)
uint8_t w = W(getCurrentColor(0));
CRGBW rgb;
rgb = CHSV32(static_cast<uint16_t>(pos << 8), 255, 255);
return rgb.color32 | (w << 24); // add white channel
rgb.w = W(getCurrentColor(0)); // add white channel
return rgb.color32;
}
/*
@@ -1418,7 +1418,6 @@ static uint8_t _dummy (uint8_t a, uint8_t b) { return a; } // dummy (same as
void WS2812FX::blendSegment(const Segment &topSegment) const {
typedef uint8_t(*FuncType)(uint8_t, uint8_t);
// function pointer array: fill with _dummy if using special case: avoid OOB access and always provide a valid path
// note: making the function array static const uses more ram and comes at no significant speed gain
FuncType funcs[] = {
_dummy, _dummy, _dummy, _subtract,
_difference, _average, _dummy, _divide,
@@ -1450,71 +1449,14 @@ void WS2812FX::blendSegment(const Segment &topSegment) const {
const size_t matrixSize = Segment::maxWidth * Segment::maxHeight;
const size_t startIndx = XY(topSegment.start, topSegment.startY);
const size_t stopIndx = startIndx + length;
const unsigned progress = topSegment.progress();
const unsigned progInv = 0xFFFFU - progress;
uint8_t opacity = topSegment.currentBri(); // returns transitioned opacity for style FADE
uint8_t cct = topSegment.currentCCT();
if (gammaCorrectCol) opacity = gamma8inv(opacity); // use inverse gamma on brightness for correct color scaling after gamma correction (see #5343 for details)
const Segment *segO = topSegment.getOldSegment();
const bool hasGrouping = topSegment.groupLength() != 1;
Segment::setClippingRect(0, 0); // disable clipping by default
// fast path: handle the default case - no transitions, no grouping/spacing, no mirroring, no CCT
if (!segO && blendingStyle == TRANSITION_FADE && !hasGrouping && !topSegment.mirror && !topSegment.mirror_y) {
if (isMatrix && stopIndx <= matrixSize && !_pixelCCT) {
#ifndef WLED_DISABLE_2D
// Calculate pointer steps to avoid 'if' and 'XY()' inside loops
int x_inc = 1;
int y_inc = Segment::maxWidth;
int start_offset = XY(topSegment.start, topSegment.startY);
// adjust starting position and steps based on Reverse/Transpose
// note: transpose is handled in separate loop so it is still fast and no branching is needed in default path
if (!topSegment.transpose) {
if (topSegment.reverse) { start_offset += (width - 1); x_inc = -1; }
if (topSegment.reverse_y) { start_offset += (height - 1) * Segment::maxWidth; y_inc = -Segment::maxWidth; }
for (int y = 0; y < height; y++) {
uint32_t* pRow = &_pixels[start_offset + y * y_inc];
const int y_width = y * width;
for (int x = 0; x < width; x++) {
uint32_t* p = pRow + x * x_inc;
uint32_t c_a = topSegment.getPixelColorRaw(x + y_width);
*p = color_blend(*p, segblend(c_a, *p), opacity);
}
}
} else { // transposed
for (int y = 0; y < height; y++) {
const int px = topSegment.reverse ? (height - y - 1) : y; // source pixel: swap y into x, reverse if needed
for (int x = 0; x < width; x++) {
const int py = topSegment.reverse_y ? (width - x - 1) : x; // source pixel: swap x into y, reverse if needed
const uint32_t c_a = topSegment.getPixelColorRaw(px + py * height); // height = virtual width
const size_t idx = XY(topSegment.start + x, topSegment.startY + y); // write logical (non swapped) pixel coordinate
_pixels[idx] = color_blend(_pixels[idx], segblend(c_a, _pixels[idx]), opacity);
}
}
}
return;
#endif
} else if (!isMatrix) {
// 1D fast path, include CCT as it is more common on 1D setups
uint32_t* strip = _pixels;
int start = topSegment.start;
int off = topSegment.offset;
for (int i = 0; i < length; i++) {
uint32_t c_a = topSegment.getPixelColorRaw(i);
int p = topSegment.reverse ? (length - i - 1) : i;
int idx = start + p + off;
if (idx >= topSegment.stop) idx -= length;
strip[idx] = color_blend(strip[idx], segblend(c_a, strip[idx]), opacity);
if (_pixelCCT) _pixelCCT[idx] = cct;
}
return;
}
}
// slow path: handle transitions, grouping/spacing, segments with clipping and CCT pixels
Segment::setClippingRect(0, 0); // disable clipping by default
const unsigned progress = topSegment.progress();
const unsigned progInv = 0xFFFFU - progress;
const unsigned dw = (blendingStyle==TRANSITION_OUTSIDE_IN ? progInv : progress) * width / 0xFFFFU + 1;
const unsigned dh = (blendingStyle==TRANSITION_OUTSIDE_IN ? progInv : progress) * height / 0xFFFFU + 1;
const unsigned orgBS = blendingStyle;
@@ -1575,6 +1517,7 @@ void WS2812FX::blendSegment(const Segment &topSegment) const {
#ifndef WLED_DISABLE_2D
const int nCols = topSegment.virtualWidth();
const int nRows = topSegment.virtualHeight();
const Segment *segO = topSegment.getOldSegment();
const int oCols = segO ? segO->virtualWidth() : nCols;
const int oRows = segO ? segO->virtualHeight() : nRows;
@@ -1670,8 +1613,8 @@ void WS2812FX::blendSegment(const Segment &topSegment) const {
}
#endif
} else {
// 1D Slow Path
const int nLen = topSegment.virtualLength();
const Segment *segO = topSegment.getOldSegment();
const int oLen = segO ? segO->virtualLength() : nLen;
const auto setMirroredPixel = [&](int i, uint32_t c, uint8_t o) {
@@ -1751,7 +1694,7 @@ void WS2812FX::show() {
if (realtimeMode == REALTIME_MODE_INACTIVE || useMainSegmentOnly || realtimeOverride > REALTIME_OVERRIDE_NONE) {
// clear frame buffer
memset(_pixels, 0, sizeof(uint32_t) * totalLen);
for (size_t i = 0; i < totalLen; i++) _pixels[i] = BLACK; // memset(_pixels, 0, sizeof(uint32_t) * getLengthTotal());
// blend all segments into (cleared) buffer
for (Segment &seg : _segments) if (seg.isActive() && (seg.on || seg.isInTransition())) {
blendSegment(seg); // blend segment's buffer into frame buffer
@@ -1837,33 +1780,6 @@ void WS2812FX::waitForIt() {
#endif
};
/**
* Be nice, but not too nice - wait until LEDs are idle, or maxWaitMS milliseconds have passed.
* always=true enforces waiting even when using the RMTHI driver.
* On 8266 this call will _not_ wait outside the main loop context.
* Function returns isUpdating() status after waiting.
**/
bool WS2812FX::waitForLEDs(unsigned maxWaitMS, bool always) const {
#ifdef ARDUINO_ARCH_ESP32
#if !defined(WLED_USE_SHARED_RMT) && !defined(__riscv)
// shortcut: don't wait if we have the RMTHI driver, unless requested with "always = true"
if (!always) return isUpdating();
#endif
unsigned long waitStart = millis();
while (isUpdating() && (millis() - waitStart < maxWaitMS)) delay(1);
#else
if (can_yield()) {
// If we are in a yieldable context (main loop), wait until the LEDs output finishes
yield();
unsigned long waitStart = millis();
while (isUpdating() && (millis() - waitStart < maxWaitMS)) delay(1);
yield();
}
#endif
return isUpdating();
}
void WS2812FX::setTargetFps(unsigned fps) {
if (fps <= 250) _targetFps = fps;
if (_targetFps > 0) _frametime = 1000 / _targetFps;
@@ -2051,6 +1967,9 @@ void WS2812FX::makeAutoSegments(bool forceReset) {
for (size_t i = 1; i < s; i++) {
_segments.emplace_back(segStarts[i], segStops[i]);
}
for (size_t i = 0; i < _segments.size(); i++) {
_segments[i].colors[0] = DEFAULT_COLOR; // set color to default orange on all segments
}
DEBUGFX_PRINTF_P(PSTR("%d auto segments created.\n"), _segments.size());
} else {
@@ -2200,6 +2119,7 @@ bool WS2812FX::deserializeMap(unsigned n) {
int index = atoi(number);
if (index < 0 || index > 65535) index = 0xFFFF; // prevent integer wrap around
customMappingTable[customMappingSize++] = index;
if (end != nullptr) break; // array closing ']' was in this chunk; stop before atoi() coerces trailing JSON keys into bogus entries
if (customMappingSize >= getLengthTotal()) break;
} else break; // there was nothing to read, stop
}
+2
View File
@@ -1134,6 +1134,8 @@ void BusHub75Matrix::cleanup() {
if (display != nullptr) delete display;
display = nullptr;
virtualDisp = nullptr; // note: when not using "NO_GFX" this causes a memory leak
#else // runtime reconfiguration is not working on -S3, request reboot from user instead
errorFlag = ERR_REBOOT_NEEDED;
#endif
if (_ledBuffer != nullptr) d_free(_ledBuffer); _ledBuffer = nullptr;
if (_ledsDirty != nullptr) d_free(_ledsDirty); _ledsDirty = nullptr;
+11 -2
View File
@@ -472,8 +472,17 @@ static_assert(WLED_MAX_BUSSES <= 32, "WLED_MAX_BUSSES exceeds hard limit");
#define ERR_OVERTEMP 30 // An attached temperature sensor has measured above threshold temperature (not implemented)
#define ERR_OVERCURRENT 31 // An attached current sensor has measured a current above the threshold (not implemented)
#define ERR_UNDERVOLT 32 // An attached voltmeter has measured a voltage below the threshold (not implemented)
#define ERR_REBOOT_NEEDED 98 // reboot needed after changing hardware setting
#define ERR_POWEROFF_NEEDED 99 // power-cycle needed after changing hardware setting
#define ERR_LOW_MEM 33 // low memory (RAM)
#define ERR_LOW_SEG_MEM 34 // low memory (effect data RAM)
#define ERR_LOW_WS_MEM 35 // low memory (ws)
//#define ERR_LOW_AJAX_MEM 36 // (not used any more) low memory (oappend)
#define ERR_LOW_BUF 37 // low memory (LED pixels buffer)
#define ERR_SYS_REBOOT 90 // reboot after error, trying to roll back
#define ERR_SYS_BROWNOUT 91 // reboot after brownout alert
#define ERR_PERSISTENT_THRESHOLD 100 // ToDO: errors below this value are non-persistent; persistent errors stay in the UI until restart
// ERR_PERSISTENT_THRESHOLD is a threshold value only - never assign directly to errorFlag
#define ERR_REBOOT_NEEDED 100 // reboot needed after changing hardware setting
#define ERR_POWEROFF_NEEDED 101 // power-cycle needed after changing hardware setting
// JSON buffer lock owners
#define JSON_LOCK_UNKNOWN 255
+31 -10
View File
@@ -1567,8 +1567,36 @@ function readState(s,command=false)
case 19:
errstr = "A filesystem error has occured.";
break;
// error code from WLEDMM - not supported yet
// case 33:
// errstr = "Low Memory (generic RAM).";
// break;
// case 34:
// errstr = "Low Memory (effect data).";
// break;
// case 35:
// errstr = "Low Memory (WS data).";
// break;
// case 36:
// errstr = "Low Memory (oappend buffer).";
// break;
// case 37:
// errstr = "no memory for LEDs buffer.";
// break;
case 90:
errstr = "Unexpected Restart.";
break;
case 91:
errstr = "Brownout Restart.";
break;
case 100:
errstr = "Please reboot WLED to activate changed settings.";
break;
case 101:
errstr = "Please switch your device off and back on.";
break;
}
showToast('Error ' + s.error + ": " + errstr, true);
showToast((s.error<100) ? 'Error ': 'Note ' + s.error + ": " + errstr, true); // show "please restart" as a note, all others as errors
}
selectedPal = i.pal;
@@ -2818,14 +2846,7 @@ function rSegs()
cnfrS = false;
bt.style.color = "var(--c-f)";
bt.innerHTML = "Reset segments";
var obj = {"seg":[{"start":0,"stop":ledCount,"sel":true}]};
if (isM) {
obj.seg[0].stop = mw;
obj.seg[0].startX = 0;
obj.seg[0].stopY = mh;
}
for (let i=1; i<=lSeg; i++) obj.seg.push({"stop":0});
requestJson(obj);
requestJson({"rSeg": true}); // send reset segment request, calls makeAutoSegments() in firmware
}
function loadPalettesData() {
@@ -3597,4 +3618,4 @@ _C.addEventListener('touchstart', lock, false);
_C.addEventListener('mouseout', move, false);
_C.addEventListener('mouseup', move, false);
_C.addEventListener('touchend', move, false);
_C.addEventListener('touchend', move, false);
+1 -2
View File
@@ -1126,8 +1126,7 @@ Swap: <select id="xw${s}" name="XW${s}">
<div class="sec">
<h3>Power up</h3>
Turn LEDs on after power up/reset: <input type="checkbox" name="BO"><br>
with brightness: <input name="CA" type="number" class="m" min="1" max="255" required> (1-255)<br>
<i>(disable if using boot preset to turn LEDs on)</i><br><br>
Bootup brightness: <input name="CA" type="number" class="m" min="1" max="255" required> (1-255)<br><br>
Apply preset <input name="BP" type="number" class="m" min="0" max="250" required> at boot (0 = none)<br><br>
</div>
<div class="sec">
+1 -11
View File
@@ -106,17 +106,12 @@ void handleE131Packet(e131_packet_t* p, IPAddress clientIP, byte protocol, size_
handleArtnetPollReply(clientIP);
return;
}
if (packetLen < 18) return; // need art_length (offset 16, 2 bytes) for DMX data
uni = p->art_universe;
dmxChannels = htons(p->art_length);
const int artNetMaxData = (packetLen >= 18) ? (int)(packetLen - 18) : 0; // art_data at offset 18; clamp so e131_data[dmxChannels] stays in bounds
if (dmxChannels > artNetMaxData) dmxChannels = artNetMaxData;
if (dmxChannels > MAX_CHANNELS_PER_UNIVERSE) dmxChannels = MAX_CHANNELS_PER_UNIVERSE;
e131_data = p->art_data;
seq = p->art_sequence_number;
mde = REALTIME_MODE_ARTNET;
} else if (protocol == P_E131) {
if (packetLen < 126) return; // need up to property_values[0] (offset 125) and property_value_count (offset 123)
// Ignore PREVIEW data (E1.31: 6.2.6)
if ((p->options & 0x80) != 0) return;
dmxChannels = htons(p->property_value_count) - 1; // on malformed packets, this can become negative, checked below
@@ -125,9 +120,6 @@ void handleE131Packet(e131_packet_t* p, IPAddress clientIP, byte protocol, size_
uni = htons(p->universe);
e131_data = p->property_values;
seq = p->sequence_number;
const int e131MaxData = (packetLen > 126) ? (int)(packetLen - 126) : 0; // property_values at offset 125; clamp so e131_data[dmxChannels] stays in bounds
if (dmxChannels > e131MaxData) dmxChannels = e131MaxData;
if (dmxChannels > MAX_CHANNELS_PER_UNIVERSE) dmxChannels = MAX_CHANNELS_PER_UNIVERSE;
if (e131Priority != 0) {
if (p->priority < e131Priority ) return;
// track highest priority & skip all lower priorities
@@ -143,10 +135,8 @@ void handleE131Packet(e131_packet_t* p, IPAddress clientIP, byte protocol, size_
#ifdef WLED_ENABLE_DMX
// does not act on out-of-order packets yet
if (e131ProxyUniverse > 0 && uni == e131ProxyUniverse) {
// Art-Net: art_data is 0-indexed (channel 1 at index 0)
// E1.31: property_values[0] is start code, (channel 1 at index 1)
for (uint16_t i = 1; i <= dmxChannels; i++)
dmx.write(i, mde == REALTIME_MODE_ARTNET ? e131_data[i-1] : e131_data[i]);
dmx.write(i, e131_data[i]);
dmx.update();
}
#endif
+1 -17
View File
@@ -34,24 +34,13 @@ static File f; // don't export to other cpp files
//wrapper to find out how long closing takes
void closeFile() {
if (!doCloseFile || !f) { doCloseFile = false; return; } // file not open, or no request to close -> nothing to do, nothing to wait
#ifdef WLED_DEBUG_FS
DEBUGFS_PRINT(F("Close -> "));
uint32_t s = millis();
#endif
doCloseFile = false; // consume flag early, to reduce the time window for concurrent closing attempts from several tasks.
// f.close() may enter flash critical sections (interrupts/cache paused), so we wait for LED transmission to finish first to avoid WS281x glitches
// This is most relevant on ESP32-C3/C5/C6, where the RMT driver is very sensitive to interrupt timing.
bool haveSuspended = false;
#if defined(WLED_USE_SHARED_RMT) || defined(__riscv) || !defined(ARDUINO_ARCH_ESP32)
if (!strip.isSuspended()) { strip.suspend(); haveSuspended = true; } // prevent that a new strip.show() starts after waiting
strip.waitForLEDs(STRIP_WAIT_MEDIUM); // be nice, but not too nice. Waits up to 150ms
#endif
f.close(); // "if (f)" check is aleady done inside f.close(), and f cannot be nullptr -> no need for double checking before closing the file handle.
if (haveSuspended) strip.resume(); // end of critical section - new LEDs updates are allowed again
DEBUGFS_PRINTF("took %lu ms\n", millis() - s);
doCloseFile = false;
}
//find() that reads and buffers data from file stream in 256-byte blocks.
@@ -199,7 +188,6 @@ static bool appendObjectToFile(const char* key, const JsonDocument* content, uin
if (f.size() < 3) {
char init[10];
strcpy_P(init, PSTR("{\"0\":{}}"));
f.seek(0, SeekSet); // rewind to ensure we overwrite from the start, instead of appending
f.print(init);
}
@@ -448,7 +436,6 @@ bool handleFileRead(AsyncWebServerRequest* request, String path){
}
}
#endif
strip.waitForLEDs(STRIP_WAIT_SHORT); // wait for LEDs before file access (not using strip.suspend(), to avoid effect stuttering)
if(WLED_FS.exists(path) || WLED_FS.exists(path + ".gz")) {
request->send(request->beginResponse(WLED_FS, path, {}, request->hasArg(F("download")), {}));
return true;
@@ -459,7 +446,6 @@ bool handleFileRead(AsyncWebServerRequest* request, String path){
// copy a file, delete destination file if incomplete to prevent corrupted files
bool copyFile(const char* src_path, const char* dst_path) {
DEBUG_PRINTF("copyFile from %s to %s\n", src_path, dst_path);
strip.waitForLEDs(STRIP_WAIT_MEDIUM, true); // wait for LEDs before file access (not using strip.suspend(), to avoid effect stuttering)
if(!WLED_FS.exists(src_path)) {
DEBUG_PRINTLN(F("file not found"));
return false;
@@ -498,7 +484,6 @@ bool copyFile(const char* src_path, const char* dst_path) {
// compare two files, return true if identical
bool compareFiles(const char* path1, const char* path2) {
DEBUG_PRINTF("compareFile %s and %s\n", path1, path2);
strip.waitForLEDs(STRIP_WAIT_SHORT); // wait for LEDs before file access (not using strip.suspend(), to avoid effect stuttering)
if (!WLED_FS.exists(path1) || !WLED_FS.exists(path2)) {
DEBUG_PRINTLN(F("file not found"));
return false;
@@ -557,7 +542,6 @@ bool restoreFile(const char* filename) {
char backupname[32];
snprintf_P(backupname, sizeof(backupname), s_backup_fmt, filename + 1); // skip leading '/' in filename
strip.waitForLEDs(STRIP_WAIT_MEDIUM); // wait for LEDs before file existence checking
if (!WLED_FS.exists(backupname)) {
DEBUG_PRINTLN(F("no backup found"));
return false;
+4 -2
View File
@@ -28,7 +28,10 @@ int fileReadCallback(void) {
}
int fileReadBlockCallback(void * buffer, int numberOfBytes) {
strip.waitForLEDs(STRIP_WAIT_MEDIUM);
#ifdef CONFIG_IDF_TARGET_ESP32C3
unsigned t0 = millis();
while (strip.isUpdating() && (millis() - t0 < 150)) yield(); // be nice, but not too nice. Waits up to 150ms to avoid glitches
#endif
return file.read((uint8_t*)buffer, numberOfBytes);
}
@@ -134,7 +137,6 @@ byte renderImageToSegment(Segment &seg) {
DEBUG_PRINTF_P(PSTR("GIF decoder unsupported file: %s\n"), lastFilename);
return IMAGE_ERROR_UNSUPPORTED_FORMAT;
}
strip.waitForLEDs(STRIP_WAIT_MEDIUM);
if (file) file.close();
if (!openGif(lastFilename)) {
gifDecodeFailed = true;
+12 -5
View File
@@ -85,6 +85,9 @@ static bool deserializeSegment(JsonObject elem, byte it, byte presetId = 0)
//DEBUG_PRINTLN(F("-- JSON deserialize segment."));
Segment& seg = strip.getSegment(id);
if (newSeg && presetId == 0) {
seg.colors[0] = DEFAULT_COLOR; // set color of newly created segment to warm orange as an indicator to the user
}
// we do not want to make segment copy as it may use a lot of RAM (effect data and pixel buffer)
// so we will create a copy of segment options and compare it with original segment when done processing
SegmentCopy prev = {
@@ -485,6 +488,14 @@ bool deserializeState(JsonObject root, byte callMode, byte presetId)
}
strip.resume();
}
// reset segment request
if (root[F("rSeg")] | false) {
strip.suspend();
strip.waitForIt();
strip.makeAutoSegments(true); // respects autoSegments flag
strip.resume();
stateChanged = true;
}
UsermodManager::readFromJsonState(root);
@@ -520,9 +531,7 @@ bool deserializeState(JsonObject root, byte callMode, byte presetId)
if (root["win"].isNull() && getVal(root["ps"], presetCycCurr, 1, 250) && presetCycCurr > 0 && presetCycCurr < 251 && presetCycCurr != currentPreset) {
DEBUG_PRINTF_P(PSTR("Preset select: %d\n"), presetCycCurr);
// b) preset ID only or preset that does not change state (use embedded cycling limits if they exist in getVal())
// async load from file system (only preset ID was specified)
// avoid propogating CALL_MODE_INIT, which may cause accidental recursion
applyPreset(presetCycCurr, callMode == CALL_MODE_INIT ? CALL_MODE_DIRECT_CHANGE : callMode);
applyPreset(presetCycCurr, callMode); // async load from file system (only preset ID was specified)
return stateResponse;
} else presetCycCurr = currentPreset; // restore presetCycCurr
}
@@ -849,8 +858,6 @@ void serializeInfo(JsonObject root)
root[F("lwip")] = LWIP_VERSION_MAJOR;
#endif
// calling ESP.getFreeHeap() during led update causes glitches on C3 and possibly on 8266, too
strip.waitForLEDs(STRIP_WAIT_SHORT); // be nice, but not too nice. Waits up to 50ms. No need to suspend effects - ESP.getFreeHeap() will not need much time
root[F("freeheap")] = getFreeHeapSize();
#if defined(ARDUINO_ARCH_ESP32) && defined(BOARD_HAS_PSRAM)
// Report PSRAM information
+3 -1
View File
@@ -126,7 +126,6 @@ void stateUpdated(byte callMode) {
jsonTransitionOnce = false;
transitionActive = false;
applyFinalBri();
strip.trigger();
} else {
if (transitionActive) {
briOld = briT;
@@ -232,7 +231,10 @@ void handleNightlight() {
{
for (unsigned i=0; i<4; i++) colPri[i] = colNlT[i]+ ((colSec[i] - colNlT[i])*nper); // fading from actual color to secondary color
}
uint16_t transitionduration = strip.getTransition();
strip.setTransition(0); // temporary disable transition and set color & brightness directly, (hacky fix for #5620)
colorUpdated(CALL_MODE_NO_NOTIFY);
strip.setTransition(transitionduration); // restore transition time to previous value. Note: this needs proper fixing by disabling transitions completely in nightlight mode, reference implementation https://github.com/blazoncek/WLED/commit/c01a6b774969b652c30e383073958302042fd1f9
}
if (nper >= 1) //nightlight duration over
{
-2
View File
@@ -239,7 +239,6 @@ static bool beginOTA(AsyncWebServerRequest *request, UpdateContext* context)
UsermodManager::onUpdateBegin(true); // notify usermods that update is about to begin (some may require task de-init)
strip.suspend();
strip.waitForLEDs(STRIP_WAIT_MEDIUM, true); // always wait for LED transmissions to finish
backupConfig(); // backup current config in case the update ends badly
strip.resetSegments(); // free as much memory as you can
context->needsRestart = true;
@@ -760,7 +759,6 @@ bool initBootloaderOTA(AsyncWebServerRequest *request) {
#endif
lastEditTime = millis(); // make sure PIN does not lock during update
strip.suspend();
strip.waitForLEDs(STRIP_WAIT_SHORT, true); // be sure that LED transmissions have finished
strip.resetSegments();
// Check available heap before attempting allocation
+2 -2
View File
@@ -194,8 +194,8 @@ void handlePresets()
changePreset = true;
} else {
if (!fdo["seg"].isNull() || !fdo["on"].isNull() || !fdo["bri"].isNull() || !fdo["nl"].isNull() || !fdo["ps"].isNull() || !fdo[F("playlist")].isNull()) changePreset = true;
if (!(tmpMode == CALL_MODE_INIT || (tmpMode == CALL_MODE_BUTTON_PRESET && fdo["ps"].is<const char *>() && strchr(fdo["ps"].as<const char *>(),'~') != strrchr(fdo["ps"].as<const char *>(),'~'))))
fdo.remove("ps"); // remove load request for presets to prevent recursive crash (if not called by boot preset or button which contains preset cycling string "1~5~")
if (!(tmpMode == CALL_MODE_BUTTON_PRESET && fdo["ps"].is<const char *>() && strchr(fdo["ps"].as<const char *>(),'~') != strrchr(fdo["ps"].as<const char *>(),'~')))
fdo.remove("ps"); // remove load request for presets to prevent recursive crash (if not called by button and contains preset cycling string "1~5~")
deserializeState(fdo, CALL_MODE_NO_NOTIFY, tmpPreset); // may change presetToApply by calling applyPreset()
}
if (!errorFlag && tmpPreset < 255 && changePreset) currentPreset = tmpPreset;
+16 -16
View File
@@ -110,24 +110,24 @@ void ESPAsyncE131::parsePacket(AsyncUDPPacket _packet) {
protocol = P_E131;
}
if (protocol == P_ARTNET) {
if (memcmp(sbuff->art_id, ESPAsyncE131::ART_ID, sizeof(sbuff->art_id)))
error = true; //not ART_ID = "Art-Net"
if (sbuff->art_opcode != ARTNET_OPCODE_OPDMX && sbuff->art_opcode != ARTNET_OPCODE_OPPOLL)
error = true; //not a DMX or poll packet
} else { //E1.31 error handling
if (pktLen < 126) { // need up to property_values[0] at offset 125
error = true;
if (protocol == P_ARTNET) {
if (pktLen < 10) {
error = true; // Need at least Art-Net ID (8) + opcode (2)
} else {
if (htonl(sbuff->root_vector) != ESPAsyncE131::VECTOR_ROOT)
error = true;
if (htonl(sbuff->frame_vector) != ESPAsyncE131::VECTOR_FRAME)
error = true;
if (sbuff->dmp_vector != ESPAsyncE131::VECTOR_DMP)
error = true;
if (sbuff->property_values[0] != 0)
error = true;
if (memcmp(sbuff->art_id, ESPAsyncE131::ART_ID, sizeof(sbuff->art_id)))
error = true; //not "Art-Net"
if (sbuff->art_opcode != ARTNET_OPCODE_OPDMX && sbuff->art_opcode != ARTNET_OPCODE_OPPOLL)
error = true; //not a DMX or poll packet
}
} else { //E1.31 error handling
if (htonl(sbuff->root_vector) != ESPAsyncE131::VECTOR_ROOT)
error = true;
if (htonl(sbuff->frame_vector) != ESPAsyncE131::VECTOR_FRAME)
error = true;
if (sbuff->dmp_vector != ESPAsyncE131::VECTOR_DMP)
error = true;
if (sbuff->property_values[0] != 0)
error = true;
}
if (error && _packet.localPort() == DDP_DEFAULT_PORT) { //DDP packet
+1 -1
View File
@@ -272,4 +272,4 @@ class E131Priority {
}
};
#endif // ESPASYNCE131_H_
#endif // ESPASYNCE131_H_
+3 -6
View File
@@ -6,7 +6,7 @@
#define UDP_SEG_SIZE 36
#define SEG_OFFSET (41)
static constexpr size_t WLEDPACKETSIZE = 41+(WS2812FX::getMaxSegments()*UDP_SEG_SIZE); // make sure this is known at compile-time
#define WLEDPACKETSIZE (41+(WS2812FX::getMaxSegments()*UDP_SEG_SIZE)+0)
#define UDP_IN_MAXSIZE 1472
#define PRESUMED_NETWORK_DELAY 3 //how many ms could it take on avg to reach the receiver? This will be added to transmitted times
@@ -268,7 +268,6 @@ static void parseNotifyPacket(const uint8_t *udpIn) {
size_t inactiveSegs = 0;
for (size_t i = 0; i < numSrcSegs && i < WS2812FX::getMaxSegments(); i++) {
unsigned ofs = 41 + i*udpIn[40]; //start of segment offset byte
if (ofs + 36 > UDP_IN_MAXSIZE) break; // avoid reading outside of array
unsigned id = udpIn[0 +ofs];
DEBUG_PRINTF_P(PSTR("UDP segment received: %u\n"), id);
if (id > strip.getSegmentsNum()) break;
@@ -500,7 +499,7 @@ void handleNotifications()
packetSize = rgbUdp.parsePacket();
if (packetSize) {
if (!receiveDirect) return;
if (packetSize > UDP_IN_MAXSIZE || packetSize < 3) return; // packetSize must not exceed buffersize (UDP_IN_MAXSIZE)
if (packetSize > UDP_IN_MAXSIZE || packetSize < 3) return;
realtimeIP = rgbUdp.remoteIP();
DEBUG_PRINTLN(rgbUdp.remoteIP());
uint8_t lbuf[packetSize];
@@ -588,9 +587,7 @@ void handleNotifications()
unsigned id = (tpmPayloadFrameSize/3)*(packetNum-1); //start LED
unsigned totalLen = strip.getLengthTotal();
// Clamp to prevent buffer overread: loop accesses up to udpIn[tpmPayloadFrameSize + 5]
size_t currentPayloadFrameSize = (packetSize >= 5) ? min(tpmPayloadFrameSize, uint16_t(packetSize - 5)) : 0;
for (size_t i = 6; i < currentPayloadFrameSize + 4U && id < totalLen; i += 3, id++) {
for (size_t i = 6; i < tpmPayloadFrameSize + 4U && id < totalLen; i += 3, id++) {
setRealtimePixel(id, udpIn[i], udpIn[i+1], udpIn[i+2], 0);
}
if (tpmPacketCount == numPackets) { //reset packet count and show if all packets were received
+8
View File
@@ -8,6 +8,7 @@
#else
#include <Update.h>
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 4, 0)
#include "rom/rtc.h" // for rtc_get_reset_reason()
#include "esp32/rtc.h" // for bootloop detection
#elif ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(3, 3, 0)
#include "soc/rtc.h"
@@ -998,6 +999,11 @@ RTC_NOINIT_ATTR static uint32_t bl_crashcounter;
RTC_NOINIT_ATTR static uint32_t bl_actiontracker;
static inline ResetReason rebootReason() {
// check RTC restart reason first - brownout is not reliably reported by esp_reset_reason()
if (rtc_get_reset_reason(0) == RTCWDT_BROWN_OUT_RESET) return ResetReason::Brownout; // core0 brownout
#if SOC_CPU_CORES_NUM > 1
if (rtc_get_reset_reason(1) == RTCWDT_BROWN_OUT_RESET) return ResetReason::Brownout; // core1 brownout
#endif
esp_reset_reason_t reason = esp_reset_reason();
if (reason == ESP_RST_BROWNOUT) return ResetReason::Brownout;
if (reason == ESP_RST_SW) return ResetReason::Software;
@@ -1032,6 +1038,7 @@ static bool detectBootLoop() {
case ResetReason::Crash:
{
DEBUG_PRINTLN(F("crash detected!"));
errorFlag = ERR_SYS_REBOOT;
uint32_t rebootinterval = rtctime - bl_last_boottime;
if (rebootinterval < BOOTLOOP_INTERVAL_MILLIS) {
bl_crashcounter++;
@@ -1052,6 +1059,7 @@ static bool detectBootLoop() {
case ResetReason::Brownout:
// crash due to brownout can't be detected unless using flash memory to store bootloop variables
DEBUG_PRINTLN(F("brownout detected"));
errorFlag = ERR_SYS_BROWNOUT;
//restoreConfig(); // TODO: blindly restoring config if brownout detected is a bad idea, need a better way (if at all)
break;
}
+27 -27
View File
@@ -174,9 +174,12 @@ void WLED::loop()
#ifdef ESP8266
uint32_t heap = getFreeHeapSize(); // ESP8266 needs ~8k of free heap for UI to work properly
#else
#ifdef CONFIG_IDF_TARGET_ESP32C3
// calling getContiguousFreeHeap() during led update causes glitches on C3
// this can (probably) be removed once RMT driver for C3 is fixed
strip.waitForLEDs(STRIP_WAIT_MEDIUM); // be nice, but not too nice. Waits up to 150ms - we are in the main loop, so a new strip.show() cannot start while waiting
unsigned t0 = millis();
while (strip.isUpdating() && (millis() - t0 < 150)) delay(1); // be nice, but not too nice. Waits up to 150ms
#endif
uint32_t heap = getContiguousFreeHeap(); // ESP32 family needs ~10k of contiguous free heap for UI to work properly
#endif
if (heap < MIN_HEAP_SIZE - 1024) heapDanger+=5; // allow 1k of "wiggle room" for things that do not respect min heap limits
@@ -491,7 +494,6 @@ void WLED::setup()
DEBUG_PRINTLN(F("Initializing strip"));
beginStrip();
strip.waitForLEDs(STRIP_WAIT_MEDIUM); // prevent flickering - beginStrip() calls strip.show()
DEBUG_PRINTF_P(PSTR("heap %u\n"), getFreeHeapSize());
DEBUG_PRINTLN(F("Usermods setup"));
@@ -501,12 +503,6 @@ void WLED::setup()
if (needsCfgSave) serializeConfigToFS(); // usermods required new parameters; need to wait for strip to be initialised #4752
if (bootPreset > 0) {
handlePresets(); // handle boot preset
handlePlaylist(); // handle playlist if preset queued one
handlePresets(); // handle presets again to give a chance for anything queued by the boot preset or playlist
}
if (strcmp(multiWiFi[0].clientSSID, DEFAULT_CLIENT_SSID) == 0 && !configBackupExists())
showWelcomePage = true;
@@ -596,7 +592,7 @@ void WLED::setup()
#endif
#if defined(ARDUINO_ARCH_ESP32) && defined(WLED_DISABLE_BROWNOUT_DET)
WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 1); //re-enable brownout detector
WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 1); //enable brownout detector
#endif
markOTAvalid();
}
@@ -614,31 +610,35 @@ void WLED::beginStrip()
// init offMode and relay
offMode = false; // init to on state to allow proper relay init
handleOnOff(true); // init relay and force off
if (rlyPin < 0) strip.show(); // ensure LEDs are off if no relay is used
// Note on how bootup behaviour works:
// if turnOnAtBoot is false: strip is set to black. It will fade in to startup brightness and orange when turned on
// if a bootup preset is set, it will fade to that preset if it has "on:true" set (to default brightness) or to that preset's brightness if set
// if turnOnAtBoot is true: the LEDs will fade in to orange and default brightness
// if a bootup preset is set, it will start at the default brightness except if "fade" transition is used, then it will still fade from black
// there is no way to have LEDs off at boot and upon turn-on have them immediatel jump to a target brightness but users can use a playlist to do that
bri = 0; // start off black by default (on a fresh install this is overruled by briS as turnOnAtBoot is true)
if (turnOnAtBoot) {
if (briS > 0) bri = briS;
else if (bri == 0) bri = 128;
} else {
// fix for #3196
if (bootPreset > 0) {
// set all segments black (no transition)
for (unsigned i = 0; i < strip.getSegmentsNum(); i++) {
Segment &seg = strip.getSegment(i);
if (seg.isActive()) seg.colors[0] = BLACK;
}
colPri[0] = colPri[1] = colPri[2] = colPri[3] = 0; // needed for colorUpdated()
}
briLast = briS; bri = 0;
strip.fill(BLACK);
if (rlyPin < 0)
strip.show(); // ensure LEDs are off if no relay is used
bri = briS; // load startup brightness (set in UI), 0 is not allowed in UI
}
colorUpdated(CALL_MODE_INIT); // will not send notification but will initiate transition
else briLast = briS; // go to startup brightness (set in UI) when turning on (can be overruled by a preset)
colorUpdated(CALL_MODE_INIT); // set bootup brightness immediately, do not send notification (brightness is also set for preset if used, useful for swipe etc.)
if (bootPreset > 0) {
applyPreset(bootPreset, CALL_MODE_INIT);
}
else {
// set color to warm welcoming orange (aka DEFAULT_COLOR) if no preset loaded (will fade to this color once turned on)
colPri[0] = R(DEFAULT_COLOR);
colPri[1] = G(DEFAULT_COLOR);
colPri[2] = B(DEFAULT_COLOR);
colPri[3] = W(DEFAULT_COLOR);
}
strip.setTransition(transitionDelayDefault); // restore transitions
strip.setTransition(transitionDelayDefault); // restore default transition time
colorUpdated(CALL_MODE_INIT); // apply color & initiate transition, do not send notification
}
void WLED::initAP(bool resetAP)
+4 -4
View File
@@ -7,7 +7,7 @@
*/
// version code in format yymmddb (b = daily build)
#define VERSION 2605011
#define VERSION 2605010
//uncomment this if you have a "my_config.h" file you'd like to use
//#define WLED_USE_MY_CONFIG
@@ -274,7 +274,7 @@ using PSRAMDynamicJsonDocument = BasicJsonDocument<PSRAM_Allocator>;
#define STRINGIFY(X) #X
#define TOSTRING(X) STRINGIFY(X)
#define WLED_CODENAME "Kagayaki"
#define WLED_CODENAME "Niji"
// AP and OTA default passwords (for maximum security change them!)
WLED_GLOBAL char apPass[65] _INIT(WLED_AP_PASS);
@@ -413,8 +413,8 @@ WLED_GLOBAL bool gammaCorrectCol _INIT(true); // use gamma correction on col
WLED_GLOBAL bool gammaCorrectBri _INIT(false); // use gamma correction on brightness
WLED_GLOBAL float gammaCorrectVal _INIT(2.2f); // gamma correction value
WLED_GLOBAL byte colPri[] _INIT_N(({ 255, 160, 0, 0 })); // current RGB(W) primary color. colPri[] should be updated if you want to change the color.
WLED_GLOBAL byte colSec[] _INIT_N(({ 0, 0, 0, 0 })); // current RGB(W) secondary color
WLED_GLOBAL byte colPri[] _INIT_N(({ 0, 0, 0, 0 })); // current RGB(W) primary color. colPri[] should be updated if you want to change the color.
WLED_GLOBAL byte colSec[] _INIT_N(({ 0, 0, 0, 0 })); // current RGB(W) secondary color
WLED_GLOBAL byte nightlightTargetBri _INIT(0); // brightness after nightlight is over
WLED_GLOBAL byte nightlightDelayMins _INIT(60);
-7
View File
@@ -212,14 +212,7 @@ static void handleUpload(AsyncWebServerRequest *request, const String& filename,
request->_tempFile.write(data,len);
}
if (isFinal) {
bool haveSuspended = false;
#if defined(WLED_USE_SHARED_RMT) || defined(__riscv) || !defined(ARDUINO_ARCH_ESP32)
if (!strip.isSuspended()) { strip.suspend(); haveSuspended = true; } // prevent that a new strip.show() starts after waiting
strip.waitForLEDs(STRIP_WAIT_SHORT, true); // calling file.close() during LEDs sendout can cause glitches on C3 and on 8266
#endif
request->_tempFile.close();
if (haveSuspended) strip.resume();
if (filename.indexOf(F("cfg.json")) >= 0) { // check for filename with or without slash
doReboot = true;
request->send(200, FPSTR(CONTENT_TYPE_PLAIN), F("Config restore ok.\nRebooting..."));
-1
View File
@@ -153,7 +153,6 @@ void sendDataWs(AsyncWebSocketClient * client)
DEBUG_PRINTF_P(PSTR("JSON buffer size: %u for WS request (%u).\n"), pDoc->memoryUsage(), len);
// the following may no longer be necessary as heap management has been fixed by @willmmiles in AWS
strip.waitForLEDs(STRIP_WAIT_VERYSHORT); // wait for LEDs ouptut to finish - prevents glitches on -C3
size_t heap1 = getFreeHeapSize();
DEBUG_PRINTF_P(PSTR("heap %u\n"), getFreeHeapSize());
AsyncWebSocketBuffer buffer(len);