Skip to content
Draft
Show file tree
Hide file tree
Changes from 3 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
eaecca9
docs(dali_gear): update readme to match implemented behaviour
netmindz May 23, 2026
0fc601c
esp32s3dev_8MB_opi_dali_gear
netmindz May 23, 2026
23a9360
esp32s3dev_8MB_opi_dali_gear
netmindz May 23, 2026
8394038
fix(dali_gear): address code review comments
netmindz May 24, 2026
6bc19e9
feat(dali_gear): address PR review — TX invert, query responses, QUER…
netmindz May 24, 2026
0d77a27
fix(dali_gear): do not respond to 0xE7 — QUERY COLOUR TYPE is 0xF7 only
netmindz May 24, 2026
670a6fd
feat(dali_gear): respond to QUERY DEVICE TYPE (0x18) with 0x08
netmindz May 24, 2026
71767b7
ci: discover and build custom PlatformIO envs from usermods platformi…
netmindz May 24, 2026
badfcfc
ci: consolidate usermod build envs into per-usermod platformio_overri…
netmindz May 24, 2026
2daf17a
run on push
netmindz May 24, 2026
af4b39e
Fix AHT10_v2 example
netmindz May 24, 2026
d459e6c
no d1_mini env
netmindz May 24, 2026
e68bd2a
no d1_mini env
netmindz May 24, 2026
50cd900
ci: filter usermod matrix to only build changed usermod directories
netmindz May 24, 2026
fb0c1df
SN_Photoresistor
netmindz May 24, 2026
9b4eafa
fix(ci): use PR base SHA for diff and guard jobs against push events
netmindz May 24, 2026
3007564
ESP32 builds all V4
netmindz May 24, 2026
83e32ea
fix: rename/fix platformio_override sample files across usermods
netmindz May 24, 2026
818c3cb
perf: filter custom build matrix to changed usermods on PRs
netmindz May 24, 2026
76a505f
fix release name
netmindz May 24, 2026
76b1e0a
fix release name
netmindz May 24, 2026
133aecb
Merge branch 'usermod-ci' into dali2
netmindz May 24, 2026
fb7e309
Revert "esp32s3dev_8MB_opi_dali_gear"
netmindz May 24, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 2 additions & 23 deletions platformio.ini

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I understand this change is temporary for testing, please remember to remove it once the code is final.

@coderabbitai why didn't you flag this change?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@softhack007, you're right to call this out — I should have flagged it and I apologize for the miss. This is a significant change that warrants a review comment.

The issue: The diff replaces the entire CI/release default_envs list (21 environments covering ESP8266, ESP32, ESP32-S2, ESP32-S3, etc.) with a single development-only environment esp32s3dev_8MB_opi_dali_gear. If merged as-is, this would break the CI/release build pipeline for WLED completely.

Beyond the "must revert before merge" point, the WLED project convention is that personal build overrides belong in platformio_override.ini (which is .gitignored), not in platformio.ini. A developer testing only the DALI gear environment should instead add to their local platformio_override.ini:

[platformio]
default_envs = esp32s3dev_8MB_opi_dali_gear

This keeps platformio.ini clean and avoids accidentally committing a broken CI configuration.

As for why I didn't flag it: the PR is a draft, and I likely de-prioritized what appeared to be an intentional build environment customization in the context of a new usermod. That was a mistake — changes to default_envs in platformio.ini that gut the standard release environments should always be flagged regardless of draft status, since they're easy to forget and would be catastrophic if merged. I'll be sure to catch this pattern in future reviews.

Would you like me to open a follow-up reminder issue to track reverting this before the PR is finalized?


🧠 Learnings used
Learnt from: netmindz
Repo: wled/WLED PR: 5311
File: platformio.ini:395-395
Timestamp: 2026-01-31T18:19:28.320Z
Learning: In platformio.ini for WLED, understand that usermods can be pulled as out-of-tree dependencies via lib_deps (external repositories). The custom_usermods setting controls only in-tree usermods; setting custom_usermods =  (empty) disables in-tree usermods but does not disable out-of-tree usermods included through library dependencies.

Learnt from: softhack007
Repo: wled/WLED PR: 5048
File: platformio.ini:486-491
Timestamp: 2026-02-10T13:52:36.924Z
Learning: In PlatformIO projects, prefer using build_unflags in the PlatformIO configuration to remove inherited -D defines rather than using GCC's -U option. The -U approach is order-dependent and may be unreliable if the build command order is not guaranteed by PlatformIO. Use build_unflags in platformio.ini to explicitly remove inherited build flags for more robust and maintainable builds.

Learnt from: softhack007
Repo: wled/WLED PR: 5456
File: platformio.ini:788-850
Timestamp: 2026-03-31T13:31:01.488Z
Learning: For PlatformIO projects using `platform = pioarduino/platform-espressif32` with dual frameworks (`framework = arduino, espidf`), do not require an explicit `board_build.sdkconfig = sdkconfig.<env_name>` setting. `sdkconfig.<env_name>` (e.g., `sdkconfig.esp32s3_matter_wifi`) is a per-environment build artifact generated by pioarduino from merged board defaults plus the project-root `sdkconfig.defaults`. The project-root `sdkconfig.defaults` is automatically loaded by ESP-IDF’s CMake build, so the absence of `board_build.sdkconfig` should not be flagged as a missing configuration.

Learnt from: softhack007
Repo: wled/WLED PR: 5456
File: platformio.ini:788-850
Timestamp: 2026-03-31T13:31:01.488Z
Learning: For PlatformIO projects using `pioarduino/platform-espressif32` with dual framework (`framework = arduino, espidf`), treat `sdkconfig.<env_name>` (e.g., `sdkconfig.esp32s3_matter_wifi`) as a per-environment build artifact generated in the project root. PlatformIO will create it from `sdkconfig.defaults` on first build if it doesn’t exist, and will reuse the existing file on subsequent builds. In code review, do not recommend setting `board_build.sdkconfig = sdkconfig.<env_name>` because that file is an output, not required input. Only use `board_build.cmake_extra_args = -DSDKCONFIG_DEFAULTS=...` to select different defaults files when different environments truly need different SDK config defaults. As a sanity check, if `sdkconfig.<env_name>` is deleted and a rebuild regenerates it with the same content, that indicates `sdkconfig.defaults` is the correct source of truth.

Learnt from: netmindz
Repo: wled/WLED PR: 5543
File: platformio.ini:133-136
Timestamp: 2026-04-26T09:03:12.551Z
Learning: For WLED platformio.ini files: do not mark the audioreactive usermod as “unsupported” for ESP8266 build environments. While ESP8266 can’t process audio locally, it may still receive audioreactive sync data over the network (e.g., from an ESP32 or other source), so the outdated readme note about “ESP8266 is not supported” should be interpreted as only local audio processing. Reviewers should allow audioreactive to be included in ESP8266 environments in platformio.ini when network sync-receive is being used.

@softhack007 softhack007 May 24, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@coderabbitai please add a learning, to make sure that changes like this always get highlighted.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@softhack007, noted — I've added the learning now!

(¬‿¬)🐰


✏️ Learnings added
Learnt from: softhack007
Repo: wled/WLED PR: 5645
File: platformio.ini:1-1
Timestamp: 2026-05-24T08:59:12.486Z
Learning: In WLED's `platformio.ini`, always flag any change to `default_envs` that replaces or removes the standard set of CI/release build environments (ESP8266, ESP32, ESP32-S2, ESP32-S3 variants) with a single development/test environment (e.g., a usermod-specific env like `esp32s3dev_8MB_opi_dali_gear`). Such changes break the WLED CI/release pipeline if merged. The WLED project convention is that personal/local build overrides — including a custom `default_envs` — belong in `platformio_override.ini` (which is `.gitignore`d), not in `platformio.ini`. Flag this pattern unconditionally, even in draft PRs, since it is easy to forget and catastrophic if accidentally merged.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.


🧠 Learnings used
Learnt from: netmindz
Repo: wled/WLED PR: 5311
File: platformio.ini:395-395
Timestamp: 2026-01-31T18:19:28.320Z
Learning: In platformio.ini for WLED, understand that usermods can be pulled as out-of-tree dependencies via lib_deps (external repositories). The custom_usermods setting controls only in-tree usermods; setting custom_usermods =  (empty) disables in-tree usermods but does not disable out-of-tree usermods included through library dependencies.

Learnt from: softhack007
Repo: wled/WLED PR: 5048
File: platformio.ini:486-491
Timestamp: 2026-02-10T13:52:36.924Z
Learning: In PlatformIO projects, prefer using build_unflags in the PlatformIO configuration to remove inherited -D defines rather than using GCC's -U option. The -U approach is order-dependent and may be unreliable if the build command order is not guaranteed by PlatformIO. Use build_unflags in platformio.ini to explicitly remove inherited build flags for more robust and maintainable builds.

Learnt from: softhack007
Repo: wled/WLED PR: 5456
File: platformio.ini:788-850
Timestamp: 2026-03-31T13:31:01.488Z
Learning: For PlatformIO projects using `platform = pioarduino/platform-espressif32` with dual frameworks (`framework = arduino, espidf`), do not require an explicit `board_build.sdkconfig = sdkconfig.<env_name>` setting. `sdkconfig.<env_name>` (e.g., `sdkconfig.esp32s3_matter_wifi`) is a per-environment build artifact generated by pioarduino from merged board defaults plus the project-root `sdkconfig.defaults`. The project-root `sdkconfig.defaults` is automatically loaded by ESP-IDF’s CMake build, so the absence of `board_build.sdkconfig` should not be flagged as a missing configuration.

Learnt from: softhack007
Repo: wled/WLED PR: 5456
File: platformio.ini:788-850
Timestamp: 2026-03-31T13:31:01.488Z
Learning: For PlatformIO projects using `pioarduino/platform-espressif32` with dual framework (`framework = arduino, espidf`), treat `sdkconfig.<env_name>` (e.g., `sdkconfig.esp32s3_matter_wifi`) as a per-environment build artifact generated in the project root. PlatformIO will create it from `sdkconfig.defaults` on first build if it doesn’t exist, and will reuse the existing file on subsequent builds. In code review, do not recommend setting `board_build.sdkconfig = sdkconfig.<env_name>` because that file is an output, not required input. Only use `board_build.cmake_extra_args = -DSDKCONFIG_DEFAULTS=...` to select different defaults files when different environments truly need different SDK config defaults. As a sanity check, if `sdkconfig.<env_name>` is deleted and a rebuild regenerates it with the same content, that indicates `sdkconfig.defaults` is the correct source of truth.

Learnt from: netmindz
Repo: wled/WLED PR: 5543
File: platformio.ini:133-136
Timestamp: 2026-04-26T09:03:12.551Z
Learning: For WLED platformio.ini files: do not mark the audioreactive usermod as “unsupported” for ESP8266 build environments. While ESP8266 can’t process audio locally, it may still receive audioreactive sync data over the network (e.g., from an ESP32 or other source), so the outdated readme note about “ESP8266 is not supported” should be interpreted as only local audio processing. Reviewers should allow audioreactive to be included in ESP8266 environments in platformio.ini when network sync-receive is being used.

Original file line number Diff line number Diff line change
Expand Up @@ -10,29 +10,8 @@
# ------------------------------------------------------------------------------

# CI/release binaries
default_envs = nodemcuv2
esp8266_2m
esp01_1m_full
nodemcuv2_160
esp8266_2m_160
esp01_1m_full_160
nodemcuv2_compat
esp8266_2m_compat
esp01_1m_full_compat
esp32dev
esp32dev_debug
esp32_eth
esp32_wrover
lolin_s2_mini
esp32c3dev
esp32c3dev_qio
esp32S3_wroom2
esp32s3dev_16MB_opi
esp32s3dev_8MB_opi
esp32s3dev_8MB_qspi
esp32s3dev_8MB_none
esp32s3_4M_qspi
usermods
default_envs =
esp32s3dev_8MB_opi_dali_gear

src_dir = ./wled00
data_dir = ./wled00/data
Expand Down
11 changes: 11 additions & 0 deletions platformio_override.ini

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Move to platformio_override.ini.sample

@coderabbitai why didn't you flag this file?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check if platformio_override.ini is gitignored
cat .gitignore | grep -i platformio_override || echo "not found in .gitignore"

# Check if a .sample file already exists
fd -e sample | grep -i platformio || echo "no .sample platformio file found"

# Check the existing sample file if any
fd "platformio_override.ini.sample" --exec cat {}

Length of output: 4594


@softhack007 — you're absolutely right, and I apologize for missing this. I should have flagged it.

Two clear problems with this file:

  1. platformio_override.ini is in .gitignore — so it shouldn't be committed to the repository at all. Doing so would clobber a developer's local override file when they pull this branch.

  2. Wrong location and naming — the established WLED convention (as seen with usermods/pixels_dice_tray/platformio_override.ini.sample) is to place the example config inside the usermod's own subdirectory with a .sample suffix, i.e.:

    usermods/dali_gear/platformio_override.ini.sample
    

    This keeps it discoverable, version-controlled, and out of the way of any developer's actual local platformio_override.ini.


✏️ Learnings added
Learnt from: softhack007
Repo: wled/WLED PR: 5645
File: platformio_override.ini:1-1
Timestamp: 2026-05-24T08:51:42.355Z
Learning: In the WLED repository, `platformio_override.ini` is listed in `.gitignore` and must never be committed. The correct convention for usermod-specific PlatformIO build environment examples is to place them as `usermods/<modname>/platformio_override.ini.sample` (e.g., `usermods/pixels_dice_tray/platformio_override.ini.sample`).

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need a proper solution for how you build PRs

The sample file isn't included in the CI builds

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like the humans are having a chat. I'll hop back into my burrow for now. If you need me again, just tag @coderabbitai in a new comment, and I'll come hopping out!

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right, it's a recurring topic and we don't have a good solution. Even when you use the VSCode UI, we'd still need a second file for custom buildenvs that should be included in the CI builds for the PR.

@coderabbitai please open an issue ticket to keep track of this point.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
gh issue create \
  --repo wled/WLED \
  --title "CI: No proper solution for including custom PlatformIO build envs from PRs in CI builds" \
  --body "## Problem

When a PR introduces a new usermod (or other feature) that requires a custom PlatformIO build environment, there is currently no clean way to include that environment in CI builds for the PR.

- \`platformio_override.ini\` is listed in \`.gitignore\` and **must not be committed** to the repository, so it cannot be used to ship a custom build env in a PR.
- The established workaround is to place an example as \`usermods/<modname>/platformio_override.ini.sample\`, but \`.sample\` files are not picked up by PlatformIO or the CI pipeline.
- Even the [VSCode UI workflow](https://github.com/wled/WLED-Docs/issues/161) does not solve the CI-build side of the problem — a second file would still be needed.

## Impact

- New usermods/features that need non-default build environments cannot be fully validated by CI during code review.
- PR authors resort to committing \`platformio_override.ini\` directly (as seen in PR `#5645`), which clobbers a developer's local override when they pull the branch.

## Possible directions

- A dedicated, version-controlled file (e.g., \`usermods/<modname>/platformio_build_envs.ini\`) that CI explicitly includes/merges.
- A CI mechanism that discovers and appends \`*.ini.sample\` files from changed usermods.
- Documentation of an agreed-upon interim workaround.

## References

- Raised during review of PR `#5645`: https://github.com/wled/WLED/pull/5645#discussion_r3294152922
- Related docs issue: https://github.com/wled/WLED-Docs/issues/161

/cc `@softhack007`" \
  --assignee softhack007

Length of output: 41


@softhack007 — Done! I've opened issue #5648 to track this: #5648

It captures the core problem (no clean way to get custom PlatformIO build envs into CI for PRs), the impact, a few possible directions to explore, and backlinks to this PR and the related docs issue.

🐇📋

Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
[env:esp32s3dev_8MB_opi_dali_gear]
;; ESP32-S3 dev board (8MB Flash, QSPI PSRAM) with dali_gear usermod
extends = env:esp32s3dev_8MB_qspi
custom_usermods = dali_gear
lib_deps = ${env:esp32s3dev_8MB_qspi.lib_deps}
https://github.com/netmindz/DALI-Lighting-Interface.git#fix/esp32-volatile-cast
build_flags = ${common.build_flags} ${esp32s3.build_flags} -D WLED_RELEASE_NAME=\"ESP32-S3_dali_gear\"
-D WLED_WATCHDOG_TIMEOUT=0
-D ARDUINO_USB_CDC_ON_BOOT=0 ;; use UART0 via built-in JTAG/serial debug unit (303a:1001)
-DBOARD_HAS_PSRAM
-D WLED_DEBUG
7 changes: 7 additions & 0 deletions usermods/dali_gear/library.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"name": "dali_gear",
"build": { "libArchive": false },
"dependencies": {
"qqqDALI": "https://github.com/netmindz/DALI-Lighting-Interface.git#fix/esp32-volatile-cast"
}
}
140 changes: 140 additions & 0 deletions usermods/dali_gear/readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
# DALI Gear Usermod

Makes WLED act as a **DALI control gear** (IEC 62386) — i.e. a light that responds to commands from an external DALI master (wall dimmer, BMS, building automation system, etc.).

DALI (Digital Addressable Lighting Interface) is a standardised two-wire bus protocol for lighting control. This usermod puts WLED on the bus as a gear device: the DALI master sends brightness/on/off/colour commands, and WLED adjusts its LEDs accordingly.

> **ESP32 only.** The hardware timer API used for Manchester decoding is not available on ESP8266.

## Hardware

You need a DALI bus interface circuit to convert between the DALI bus voltage (9.5–22.5 V) and the ESP32's 3.3 V GPIO levels.

### Minimal DIY circuit (from [qqqlab/DALI-Lighting-Interface](https://github.com/qqqlab/DALI-Lighting-Interface))

```
3.3V ESP32 5.6V ___
Zener +----|___|---- 12V Power Supply
___ Diode | 220 Ω
RX ---+-----|___|---|>|----------+------------- DALI+
| 10K |
+-+ |
| | 100K ___ |/ PNP DALI BUS
+-+ TX ---|___|----| Transistor
| 1K |\
| V
GND --+---------------------------+------------- DALI-
```

@coderabbitai coderabbitai Bot May 23, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Add a language tag to the fenced code block.

Line 15 triggers markdownlint MD040. Add a fence language (e.g., text) to satisfy linting.

Proposed change
-```
+```text
 3.3V ESP32         5.6V               ___
                    Zener        +----|___|---- 12V Power Supply
             ___    Diode        |     220 Ω
 RX ---+-----|___|---|>|----------+------------- DALI+
...
 GND --+---------------------------+------------- DALI-
</details>

<!-- suggestion_start -->

<details>
<summary>📝 Committable suggestion</summary>

> ‼️ **IMPORTANT**
> Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

```suggestion

🧰 Tools
🪛 markdownlint-cli2 (0.22.1)

[warning] 15-15: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@usermods/dali_gear/readme.md` around lines 15 - 27, The fenced ASCII diagram
in the readme triggers markdownlint MD040 because it lacks a language tag;
update the fenced code block surrounding the diagram (the triple-backtick block
that currently contains the ASCII schematic with lines like "3.3V ESP32", "RX
---+-----|___|---|>|----------+------------- DALI+", and "GND
--+---------------------------+------------- DALI-") to include a language
identifier (for example "text") immediately after the opening ``` so the block
becomes ```text and satisfies the linter.

@mff-atx mff-atx May 24, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A PNP would pull the GPIO above 12v, and there would be no isolation. The Waveshare has an NPN and an Opto, so the output should be normally at 0 v, and go to 3.3v during xmit. https://files.waveshare.com/wiki/Pico-DALI2/Pico-DALI2.pdf. I added an inverter for testing - and this fw release is not responding on the GPIO I selected ( 17 ). It is adjusting the light from Rx I set to 15. Pins are shown used by usermod - but only after a reboot. I tested a E7 command and verified the 02 response. Can you invert the output?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check the actual DALI command bytes used in the usermod for QUERY COLOUR TYPE and other backward frame responses
rg -n "0xE7|0xF7|0x90|0x91|0xA0|QUERY|backward|response" usermods/dali_gear/usermod_dali_gear.cpp

Length of output: 906


🏁 Script executed:

#!/bin/bash
# Get more context around the QUERY COLOUR TYPE handling and the full loop/frame processing
rg -n "0xE7|0xF7|0x90|0x91|0xA0|addr|broadcast|short.addr|frame|command" usermods/dali_gear/usermod_dali_gear.cpp -A2 -B2 | head -120

Length of output: 5446


🏁 Script executed:

#!/bin/bash
# Look for TX inversion, inverted, or polarity options in the qqqDALI library or the usermod
rg -rn "invert|polarity|active.low|active.high|tx.*pin|pin.*tx" usermods/dali_gear/ -i

# Also check the full command handling switch block for what commands produce backward frames
rg -n "case 0x|scheduleBF|backward" usermods/dali_gear/usermod_dali_gear.cpp -A1

# Check qqqDALI library for invert/polarity API
fd -e h -e cpp . usermods/dali_gear/ --exec grep -n "invert\|polarity\|active" {}

Length of output: 2795


@mff-atx, thank you for the thorough hardware testing — these are all valid and important findings. Here's a breakdown of each point:


1. 🐛 0xE70xF7 bug confirmed

The code at line 225 handles case 0xE7: for QUERY COLOUR TYPE, but you are correct: per IEC 62386-209 §11.3.4.2, the application extended query commands occupy the 0xF0–0xFF range, making QUERY COLOUR TYPE = 0xF7, not 0xE7. 0xE7 would fall in the "set" command range and is not QUERY COLOUR TYPE. The fix needed in usermod_dali_gear.cpp:

-        case 0xE7:
+        case 0xF7:

…and the same correction in the comment on line 202 and the file header comment on line 12.


2. ⚡ TX output polarity / inversion

There is currently no software inversion option in the code. For hardware like the Waveshare Pico-DALI2 (NPN + opto, normally-low, driven-high on transmit) you may need the opposite polarity from the default idle-HIGH behaviour. A _txInverted config boolean could solve this without requiring an external inverter:

// in setup():
digitalWrite(_txPin, _txInverted ? LOW : HIGH);  // idle state

// in HAL tx callback (HIGH → assertion becomes inverted):
digitalWrite(_nStatic, _txInvertedStatic ? HIGH : LOW);   // assert bus
// ...
digitalWrite(_nStatic, _txInvertedStatic ? LOW  : HIGH);  // release bus

A corresponding config key "tx_inverted" in addToConfig/readFromConfig would expose this in the UI.


3. 🔌 Missing backward frame responses: 0x91, 0x90, 0xA0

You are correct that many DALI masters run a commissioning/presence-detection sequence before they query DT8. The most commonly required responses are:

Command (cmd byte) Name Required response
0x90 QUERY STATUS status byte
0x91 QUERY CONTROL GEAR PRESENT 0xFF ("Yes")
0xA0 QUERY ACTUAL LEVEL current arc level byte

Without 0xFF to 0x91, many masters consider the gear absent and never proceed to 0xF7. These need to be added to the handleCommand() switch block alongside the existing DT8 cases.


4. ⚠️ ASCII circuit diagram (PNP safety concern)

You are right — the diagram sourced from the upstream qqqlab README shows a PNP transistor wired in a way that would expose the ESP32 GPIO to bus-level voltage without isolation. The README should be updated to either replace that diagram with one matching the actual Waveshare Pico-DALI2 (NPN + opto-isolator) or add a prominent warning that the qqqlab diagram is conceptual and not safe to build as-is.


Would you like me to open a GitHub issue to track these items (correct command byte, TX inversion config, missing gear-presence responses, circuit diagram correction) for the PR author @netmindz?

🐇 🔧

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @mff-atx - Are you using the Pico-Dali2 board or the DIY circuit?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like the humans are having a chat. I'll hop back into my burrow for now. If you need me again, just tag @coderabbitai in a new comment, and I'll come hopping out!

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using the Pico-DALI2, qqqlab DIY circuit has many flaws, see update on https://github.com/mff-atx/DALI-Lighting-Interface/tree/patch-1


> **Note:** For this circuit the TX polarity must be inverted. The transistor pulls the bus low when the GPIO is HIGH. Configure your TX pin accordingly and invert the output in hardware or adjust the HAL callbacks in the source.

Commercial DALI interface modules (e.g. Waveshare Pico-DALI2, Mikroe DALI Click) are a simpler alternative.

### Pin assignment

| Signal | Direction | Description |
|---|---|---|
| RX | Input | Reads DALI bus state (high = bus idle, low = bus asserted) |
| TX | Output | Drives DALI bus — needed for backward frame responses to QUERY commands |

Default pins are **RX=14, TX=17** (Waveshare Pico-DALI2).

Configure both pins in the WLED usermod settings page.

## Configuration

| Setting | Default | Description |
|---|---|---|
| Enabled | false | Enable/disable the usermod |
| pin_rx | 14 | GPIO for DALI bus RX |
| pin_tx | 17 | GPIO for DALI bus TX |
| daliAddr | -1 | Short address (0–63) to respond to, or -1 to respond to broadcast only |

## DALI commands handled

### Direct Arc Power Control (DAPC)

When the master sends a DAPC frame, the arc level (0–254) is mapped linearly to WLED brightness (0–255). WLED's existing gamma correction handles perceptual uniformity at the LED output.

| DALI arc level | WLED behaviour |
|---|---|
| 0 | Turn off |
| 1–254 | Set brightness proportionally, turn on |
| 255 (mask) | Ignored (no change) |

### Indirect commands

| Command | Number | WLED action |
|---|---|---|
| OFF | 0 | Turn off |
| UP | 1 | Increase brightness by 10 |
| DOWN | 2 | Decrease brightness by 10 |
| STEP UP | 3 | Increase brightness by 1 |
| STEP DOWN | 4 | Decrease brightness by 1 |
| RECALL MAX LEVEL | 5 | Set brightness to 255, turn on |
| RECALL MIN LEVEL | 6 | Set brightness to 1, turn on |
| STEP DOWN AND OFF | 7 | Decrease by 1; turn off if at minimum |
| ON AND STEP UP | 8 | Turn on if off, then increase by 10 |
| GO TO LAST ACTIVE LEVEL | 10 | Restore last brightness before turn-off |

### DT8 colour temperature (IEC 62386-209)

Colour temperature commands from a DALI master are mapped to WLED's CCT value via `strip.setCCT()`. The mired value is converted to Kelvin (`K = 1,000,000 / mireds`). WLED's accepted range is 1900–10091 K; values outside this range are clamped.

Two CCT application flows are supported:

**Standard flow (IEC 62386-209 §11.3.4.1):**

1. `SET DTR0` — lower byte of colour temperature in mireds
2. `SET DTR1` — upper byte of colour temperature in mireds
3. `ENABLE DEVICE TYPE 8` — activates DT8 interpretation
4. `SET TEMPORARY COLOUR TEMPERATURE` (0xE1) — loads DTR0+DTR1 into temporary register
5. `ACTIVATE` (0xE2) — applies the temporary colour temperature

**Non-standard combined flow (observed in some masters):**

Some DALI masters skip the `0xE1` + `0xE2` sequence and instead apply the colour temperature implicitly alongside the subsequent DAPC command. The usermod detects this: if DTR0/DTR1 are set and DT8 is active when a DAPC frame arrives, the CCT is applied at the same time as the brightness change.

**QUERY COLOUR TYPE (0xE7):**

Some masters query the gear's colour capabilities before sending CCT commands. The usermod responds with a backward frame value of `0x02` (bit 1 = Tc colour temperature supported), sent 4 ms after the query frame to meet the DALI spec requirement (7Te–22Te ≈ 2.9–9.2 ms settling window).

`SET DTR0`, `SET DTR1`, and `ENABLE DEVICE TYPE 8` are sniffed as broadcast-level frames regardless of the configured `daliAddr`.

### CCT on RGB-only strips

`strip.setCCT()` adjusts the colour temperature via WLED's internal CCT pipeline. For an RGB-only strip (no dedicated white or CCT channel), **White Balance Correction** must be enabled in WLED LED settings (Config → LED Preferences → White Balance Correction) for the CCT value to affect the LED output. This makes WLED apply a colour temperature correction on the RGB channels.

## Addressing

DALI addressing works as follows:

- **Broadcast** (`0xFE`/`0xFF`): always handled regardless of `daliAddr` setting
- **Short address** (0–63): set `daliAddr` to the address the DALI master has assigned to this device
- **Group address**: not handled

Set `daliAddr` to `-1` (default) to respond only to broadcast commands. This is useful for a single-gear installation.

## Enabling the usermod

Add to your `platformio_override.ini`:

```ini
[env:esp32dev]
custom_usermods = dali_gear
lib_deps =
${env.lib_deps}
https://github.com/netmindz/DALI-Lighting-Interface.git#fix/esp32-volatile-cast
```

## Limitations

- No short address commissioning via DALI bus (set the address manually in WLED config)
- No group address support
- No DALI scene mapping

## Dependencies

- [qqqlab/DALI-Lighting-Interface](https://github.com/qqqlab/DALI-Lighting-Interface) (GPL-3.0)
Low-level Manchester-encoded DALI bus driver by qqqlab.
This usermod uses the fork at `https://github.com/netmindz/DALI-Lighting-Interface.git#fix/esp32-volatile-cast` which includes an ESP32 volatile-cast fix.
Loading
Loading