Conversation
pio.ini: Latest FastLED Backend ======= - IO: add pin_PIR and use in board_LuxceoMood1XiaoMod (pin 4) - LightsControl: support PIR
WalkthroughAdds PIR (motion) sensor support and centralizes periodic module loops: new Changes
Sequence Diagram(s)sequenceDiagram
autonumber
participant Main as "main.cpp"
participant Module as "Module (e.g. Lights)"
participant Router as "Shared Routers\n(HTTP/WebSocket/Event/FS)"
participant HW as "Hardware GPIO / PIR"
Main->>Module: create & configure (readPins)
Main->>Router: create shared routers
Main->>Module: registerWithRouters(Router)
Main->>Module: init()
loop every 20ms
Main->>Module: loop20ms()
Module->>HW: read PIR pin
HW-->>Module: PIR level (HIGH/LOW)
Module->>Module: debounce & update lightsOn
Module->>Router: emit events if state changed
end
loop every 1s
Main->>Module: loop1s()
Module->>Router: update shared status (fps, clients, connection)
end
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Suggested labels
Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 2❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Fix all issues with AI agents
In `@src/MoonBase/Modules/ModuleIO.h`:
- Around line 72-73: The enum now includes pin_PIR but setupDefinition() never
registers a matching UI entry, so update setupDefinition() to call
addControlValue(control, "PIR") (or "PIR ♨️") for the usage select after the
existing "Reserved" entry; locate the usage select registration in
setupDefinition and add addControlValue(control, "PIR") for the pin_PIR enum
value so pins mapped to pin_PIR show correctly in the web UI.
In `@src/MoonLight/Modules/ModuleLightsControl.h`:
- Around line 406-408: The debounce state is shared across independent inputs
(lastDebounceTime, lastButtonPinState), causing interference between the push
button, toggle button and PIR handlers; add per-input debounce variables (for
example lastDebounceTimePush, lastDebounceTimeToggle, lastDebounceTimePIR and
lastButtonPinStatePush, lastButtonPinStateToggle, lastButtonPinStatePIR) and
keep debounceDelay as-is or make a per-input constant if needed, then update
each handler (push button handler, toggle button handler, PIR handler) to
reference its corresponding lastDebounceTime* and lastButtonPinState* variables
instead of the shared ones so each input debounces independently.
- Around line 488-500: The PIR handler in ModuleLightsControl.h currently forces
_state.data["lightsOn"] to match pinPIR on every debounce interval, preventing
manual overrides; change the logic in the block that reads pinPIR to act on edge
transitions or respect a PIR-enable/timeout mode instead of absolute level:
introduce and maintain a persistent previous PIR state (e.g., lastPirState) and
only call update(...) when the PIR input transitions (rising edge -> optionally
set lightsOn true; falling edge -> start/complete a configurable auto-off
timeout before setting lightsOn false), or add a boolean state flag (pirEnabled)
that the UI can toggle and guard the PIR handling with it; keep use of millis(),
lastDebounceTime, debounceDelay and still call update(newState,
ModuleState::update, _moduleName) only when you actually want to change
lightsOn.
backend ======= main: use loopxx() virtual functions - modules: use loop20ms instead of loopms, add loop1s and loop10s - Module effects: loop1s: set sharedData - Lights control: PIR ffixes
There was a problem hiding this comment.
🧹 Nitpick comments (2)
src/MoonBase/Modules/ModuleDevices.h (1)
119-125: Note:Module::loop20ms()is not called here.Unlike
ModuleIOandModuleLightsControlwhich callModule::loop20ms(), this override skips it. This meansrequestUIUpdateflag processing is bypassed. This appears intentional sinceModuleDevicesusesupdate()directly, but it diverges from the documented contract on Line 113 ofModule.h: "any Module that overrides loop20ms() must continue to call Module::loop20ms()".If
requestUIUpdateis never set on this module, there's no functional issue — just a consistency concern.src/main.cpp (1)
389-423: Consider removing commented-out sizeof diagnostics instead of keeping them as dead code.This block of commented-out
sizeof(...)expressions adds visual clutter without providing runtime value. If these are useful for future debugging, consider moving them to a separate header/doc or behind a#if 0/ dedicated build flag so the intent is explicit.
|
@coderabbitai, I am using the updated firmware manager (see d5a1806) but firmware installs are not working. See logging below. Can you explain what is happening? Look at E (200994) boot_comm: Image requires efuse blk rev >= v16.0, but chip is v1.3 especially. Logging: [133358][I][DownloadFirmwareService.cpp:220] downloadUpdate(): [🐼] Starting OTA from: https://github.com/MoonModules/MoonLight/releases/download/v0.8.0/MoonLight_esp32-s3-n16r8v_0-8-0_webflash.bin [134426][D][NetworkManager.cpp:83] hostByName(): Clearing DNS cache [135407][D][HTTPClient.cpp:390] disconnect(): tcp is closed [135414][D][HTTPClient.cpp:290] beginInternal(): protocol: https, host: release-assets.githubusercontent.com port: 443 url: /github-production-release-asset/944519235/aed33b2b-6f64-4d40-90aa-f540e83fc79c?sp=r&sv=2018-11-09&sr=b&spr=https&se=2026-02-16T14%3A30%3A33Z&rscd=attachment%3B+filename%3DMoonLight_esp32-s3-n16r8v_0-8-0_webflash.bin&rsct=application%2Foctet-stream&skoid=96c2d410-5711-43a1-aedd-ab1947aa7ab0&sktid=398a6654-997b-47e9-b12b-9515b896b4de&skt=2026-02-16T13%3A29%3A42Z&ske=2026-02-16T14%3A30%3A33Z&sks=b&skv=2018-11-09&sig=%2BG1bdJR5VmeppVTKv7tsMplb5SvvjUpeARV56RR%2FWFs%3D&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmVsZWFzZS1hc3NldHMuZ2l0aHVidXNlcmNvbnRlbnQuY29tIiwia2V5Ijoia2V5MSIsImV4cCI6MTc3MTI0OTMzNiwibmJmIjoxNzcxMjQ5MDM2LCJwYXRoIjoicmVsZWFzZWFzc2V0cHJvZHVjdGlvbi5ibG9iLmNvcmUud2luZG93cy5uZXQifQ.KiOWJig_81pbOs6TZf_oEthlb5ptraAbWjOK7SWfJ2I&response-content-disposition=attachment%3B%20filename%3DMoonLight_esp32-s3-n16r8v_0-8-0_webflash.bin&response-content-type=application%2Foctet-stream [135530][D][NetworkManager.cpp:127] hostByName(): DNS found IPv4 185.199.110.133 [135973][D][HTTPUpdate.cpp:265] handleUpdate(): Header read fin. [135980][D][HTTPUpdate.cpp:266] handleUpdate(): Server header: [135986][D][HTTPUpdate.cpp:267] handleUpdate(): - code: 200 [135993][D][HTTPUpdate.cpp:268] handleUpdate(): - len: 2663872 [136000][D][HTTPUpdate.cpp:280] handleUpdate(): ESP32 info: [136007][D][HTTPUpdate.cpp:281] handleUpdate(): - free Space: 3145728 [136014][D][HTTPUpdate.cpp:282] handleUpdate(): - current Sketch Size: 2899392 [136253][I][DownloadFirmwareService.cpp:72] update_started(): [🐼] HTTP Update started [136376][D][Updater.cpp:239] begin(): OTA Partition: app1 [201137][E][HTTPUpdate.cpp:402] handleUpdate(): Update failed [201145][D][HTTPClient.cpp:390] disconnect(): tcp is closed [201160][E][DownloadFirmwareService.cpp:156] updateTask(): [🐼] HTTP Update failed with error (9): Update error: Could Not Activate The Firmware |
|
Tip For best results, initiate chat on the files or code changes. 🧩 Analysis chain🏁 Script executed: Length of output: 2109 🏁 Script executed: Length of output: 6403 🏁 Script executed: Length of output: 1548 🌐 Web query: 💡 Result: That message usually means ESP-IDF’s image compatibility check is rejecting the new OTA image because the chip’s eFuse block revision is higher than what the image says it supports. What “eFuse blk rev v16.0 vs v1.3” is
So if your chip reports eFuse block rev = v16.0, but the OTA image was built with a max supported eFuse block revision of v1.3, the update will fail. Why it happensMost commonly: you built the firmware (or the OTA binary) with an older ESP-IDF / older project config whose What to do (recommended order)
Key point: don’t try to “fix” the chip from Sources: 🏁 Script executed: Length of output: 5749
What's HappeningThe error
The firmware downloads successfully and writes to flash, but activation is blocked by the bootloader's hardware compatibility check. Why This HappenedThe v0.8.0 release binaries were likely built with the newer ESP-IDF 5.5.x platform (you're currently using SolutionsOption 1: Build firmware locally (Recommended for your device) # Your local build will automatically match your chip revision
pio run -e esp32-s3-n16r8vThe locally built firmware will be compatible with your v1.3 chip revision. Option 2: Adjust release build configuration [esp32-s3-base]
build_flags =
${env.build_flags}
${moonlight.build_flags}
${livescripts.build_flags}
${HP_ALL_DRIVERS.build_flags}
-D CONFIG_IDF_TARGET_ESP32S3=1
-D CONFIG_ESP32S3_REV_MIN_0=y
; Add this to support older chip revisions in releases:
-D CONFIG_ESP_EFUSE_BLOCK_REV_MAX_FULL=199This would make release binaries compatible with a wider range of ESP32-S3 hardware revisions, though it may disable some newer hardware features. The commit d5a1806 you mentioned didn't cause this issue - the firmware manager is functioning properly. This is purely a hardware compatibility issue with the pre-built binary. 🧠 Learnings used |
|
@coderabbitai, regarding
When compiling I get: Users/ewoud/.platformio/packages/framework-arduinoespressif32-libs/esp32s3/qio_opi/include/sdkconfig.h:1010:9: warning: "CONFIG_ESP32S3_REV_MIN_0" redefined |
|
Tip For best results, initiate chat on the files or code changes.
The Real IssueThe problem isn't about chip revision settings - it's about max_efuse_blk_rev_full, which is determined by CONFIG_ESP_EFUSE_BLOCK_REV_MAX_FULL and reflects whether the current IDF version supports this efuse block format or not, and should not be changed by the user. Important distinction:
These are two separate versioning systems. Why You Can't Fix This with Build FlagsCONFIG_ESP_EFUSE_BLOCK_REV_MAX_FULL cannot be changed by user - only Espressif can change it when a new version will be supported in ESP-IDF. This value is baked into the precompiled Arduino framework libraries you're using. SolutionsOption 1: Build Locally ✅ (Already works for you) Option 2: Fix Release Binaries Option 3: Document Hardware Requirements The root cause is that ESP-IDF 5.5.x (used in Recommendation: Stick with local builds for your hardware, or consider providing multiple release variants built with different ESP-IDF versions if you need to support a wide range of ESP32-S3 chip ages. 🧠 Learnings used |
|
@coderabbitai, are the DebounceTime's for the buttons/pir still needed in ModuleLightsControl now the loop runs every 20ms instead of always? Would save a few bytes if not |
|
Tip For best results, initiate chat on the files or code changes. 🧩 Analysis chain🏁 Script executed: Length of output: 22713
Why 20ms loop interval doesn't eliminate debounce needsMechanical switch bounce physics haven't changed:
What would happen without debounce: With your current 50ms debounce, at a single button press: Without debounce (reading every 20ms during bounce): Result: Lights flicker 5 times for a single button press! 🎇 Current implementationYour current 50ms debounce acts as rate-limiting - it samples the button every ~50-60ms instead of every 20ms. This gives mechanical contacts time to settle between samples, drastically reducing false triggers. Memory considerationThe debounce variables use:
Total: 24 bytes - negligible for ESP32 with hundreds of KB of RAM. VerdictKeep the debounce! It's preventing a significant user experience bug. Those 24 bytes are buying you reliable button behavior. 👍 🧠 Learnings used |
Summary by CodeRabbit