You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Adds espp::Vl53l5cx, a driver for the VL53L5CX 4x4 / 8x8 multizone time-of-flight sensor, to the vl53l component next to the existing VL53L4CD/CX driver (both talk I2C with 16-bit register addresses and share BasePeripheral plus the component scaffolding).
The sensor has no firmware in ROM: initialize() (run by the constructor by default) reboots it and uploads ST's ~84 KB firmware, then configures it through the DCI command interface. About two seconds at 400 kHz; the sensor supports 1 MHz.
The logic is a port of ST's Ultra Lite Driver 1.1.2 (BSD-3-Clause, as redistributed by stm32duino/VL53L5CX); the firmware / default configuration / crosstalk blobs are generated from its vl53l5cx_buffers.h and keep the license in their file headers. The component README has a license note.
API: resolution, ranging frequency (validated against the resolution), integration time, sharpener, target order, ranging mode, power mode, I2C address change; start_ranging() / stop_ranging(), is_data_ready() polling, get_ranging_data() into a RangingData (distance, sigma, signal / ambient rates, SPAD count, reflectance, target count and target status per zone, row-major); the motion indicator plugin.
One target per zone (the ULD default). The crosstalk calibration and detection threshold plugins are documented follow-ups.
components/vl53l/vl53l5cx_example (Kconfig: pins, I2C clock, resolution, frequency) prints the distance grid; docs pages, Doxyfile and the CI build matrix are updated.
Notes for review: BasePeripheral::write_many_to_register stages each write on the stack, so the driver chunks writes to 512 bytes; the I2C device timeout has to cover those and the ~1.4 KB frame reads (the example uses 100 ms).
WebUSB console (second commit)
A separate example next to the first one, so the sensor can be watched and driven from a browser over the dispatcher / stream_frame protocol:
Protocolvl53l5cx_protocol.hpp (module id 10, protocol espp.vl53l5cx v1, standard-library only, host test components/vl53l/test/vl53l5cx_protocol_host_test.cpp): every setting (resolution, frequency, integration time, sharpener, target order, ranging mode, power mode, motion indicator window, I2C address), start / stop / initialize, a per-transport frame stream (every Nth frame), GET_FRAME, and a STATUS snapshot (settings read back from the sensor when idle, cached while ranging).
Serviceespp::Vl53l5cxService (vl53l5cx_service.hpp): the application owns the one poll loop and hands each frame to every instance through on_frame(), so the vendor (WebUSB) and CDC (Web Serial) transports share one sensor and one mutex.
Examplecomponents/vl53l/vl53l5cx_webapp_example (ESP32-S3 / ESP32-P4; Kconfig: pins, part, boot resolution / frequency, ranging at boot, P4 USB port): the sensor service plus the standard System / Monitor / OTA / CoreDump services on both transports, OTA + coredump partition layout, like the MCP266 webapp example.
Web appcomponents/vl53l/web/vl53l5cx_console.html: live 3D view (zones at their measured position in the field of view as a surface, or a bar height field), coloured by distance / signal / ambient / sigma / reflectance / status, numeric grid, per-zone details, motion indicator, all settings, start / stop / initialize, CSV export. Shares the byte-identical discovery / connection / navigation / hand-back blocks with the other consoles (the node test list is extended). New apps-index category sensors.
Docs: web apps page, module id table, distance sensor pages; Doxyfile; READMEs; CI entry (esp32s3, manager off).
espp::UsbDevice fix (third commit): on the ESP32-P4 the full-speed port (Config::port 0) enumerated on GPIO 26 / 27, because IDF leaves USB-OTG 1.1 on the second internal FS PHY while the dev kits' USB-C (and the USB-Serial-JTAG console) is on GPIO 24 / 25. New Config::fs_phy (default 0) selects the PHY pads; the example defaults the P4 dev kits to the full-speed port.
Test plan
components/vl53l/vl53l5cx_example builds for esp32s3 (IDF 6.1), no warnings
components/vl53l/example (VL53L4) still builds
cppcheck with the CI flags is clean on the new sources
Hardware: VL53L5CX breakout on an ESP32-P4-WIFI6 dev kit (init 2.1 s, 8x8 @ 15 Hz, 4x4 @ ~56 Hz, motion indicator, recovery after a host reset mid-frame)
vl53l5cx_webapp_example builds for esp32s3 and esp32p4 (IDF 6.1, manager off), boots on the P4 kit (sensor ranging, TinyUSB on the high-speed port)
node components/dispatcher/web/test/resolve_module_id_test.js and vl53l5cx_protocol_host_test pass; doc/generate_apps_index.py accepts the new page
Web app rendered in Chrome with a synthetic 8x8 frame (surface + bars views, grid, zone details, motion panel)
Protocol against the device over its CDC (Web Serial) interface on the P4 kit: discovery, every request incl. error paths, 4x4 @ 30 Hz streaming with no sequence gaps, 8x8 @ 15 Hz with divider 3 + motion indicator, snapshot, re-initialize, live STATUS while ranging
Web app connected through the browser chooser (WebUSB and Web Serial) on the P4 kit; screenshots / recording in the comment below
VL53L7CX firmware image (Config::variant): bundled from the same ULD source, not tested on hardware (no part available)
Adds a driver for the VL53L5CX 4x4 / 8x8 multizone time-of-flight sensor to
the vl53l component, next to the VL53L4CD/CX driver (both use 16-bit register
addresses over I2C; they share BasePeripheral and the component scaffolding).
The sensor has no firmware in ROM, so the driver reboots it and uploads ST's
~84 KB firmware at initialize(), then talks to it through the DCI command
interface. The logic is a port of ST's Ultra Lite Driver 1.1.2 (BSD-3-Clause,
as redistributed by stm32duino/VL53L5CX; the firmware / default configuration
blobs are generated from its vl53l5cx_buffers.h, license kept in the file
headers) to espp conventions: error codes, bool returns, a recursive mutex
around the multi-step transactions, chunked writes (BasePeripheral stages a
write on the stack).
- resolution, ranging frequency (validated against the resolution),
integration time, sharpener, target order, ranging mode, power mode, I2C
address change; start / stop ranging, is_data_ready() polling and
get_ranging_data() into a RangingData (distance, sigma, signal / ambient
rates, SPAD count, reflectance, target count, target status per zone)
- motion indicator plugin ported (with the ULD's set_resolution write bug
fixed); one target per zone; xtalk calibration and detection thresholds are
documented follow-ups
- vl53l5cx_example (Kconfig: pins, I2C clock, resolution, frequency) prints
the distance grid; docs page + example page, Doxyfile, CI build entry,
component README / manifest updated
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DFjjnq3XCTRAXENSxsCxJU
The reason will be displayed to describe this comment to others. Learn more.
Warning
Copilot couldn't run its full agentic review because it didn't start before the timeout. Make sure your repository has a runner available, or add a copilot-code-review.yml file specifying one with the runs-on attribute. See the docs for more details.
Adds a new espp::Vl53l5cx multizone ToF driver (VL53L5CX) alongside the existing VL53L4 driver, including an ESP-IDF example and documentation/CI wiring.
- initialize() refuses a device that does not answer with the VL53L5CX ids
(no_such_device) instead of uploading the firmware into it
- send_offset_data: the NVM header is dropped with a bounded memmove of the
480 payload bytes (the ULD shifted 4 bytes past the offset buffer)
- poll_for_answer validates size / pos
- comments on the two ULD conventions kept on purpose (output list length
13, stream count 255 excluded)
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DFjjnq3XCTRAXENSxsCxJU
If either ID read fails after selecting page 0, short-circuit evaluation skips the page-2 restore. Calling this health check on an initialized sensor can leave subsequent frame reads and DCI commands accessing the wrong register page after the bus recovers. Always attempt to restore page 2, preserving the original error if the probe failed.
Restore register page after failed power-register read
components/vl53l/src/vl53l5cx.cpp:490
If selecting page 0 succeeds but reading the power register fails, this return skips the page-2 restoration below. Subsequent DCI commands and frame reads then access the wrong register page even after the I2C fault clears. Attempt the restore on this error path with a separate error code so the original failure is preserved.
Restore register page after xshut-bypass failure
components/vl53l/src/vl53l5cx.cpp:893
If selecting page 0 succeeds but the xshut-bypass write fails, this error path does not restore page 2. Retrying start_ranging() then begins with a DCI resolution read against the wrong page, so a transient I2C failure can prevent recovery. Attempt the page-2 restore before returning, preserving the original error.
Preserve ranging state when stop or cleanup fails
components/vl53l/src/vl53l5cx.cpp:931
If a stop-command write fails or the MCU-stop poll times out, stopping has not been confirmed, but this still clears ranging_. Subsequent frame reads are rejected and configuration setters bypass their while-ranging guard even though the sensor may still be active. Preserve the ranging state on failure; only clear it after a successful stop and cleanup.
- initialized_ / ranging_ are atomics (is_initialized() / is_ranging() read
them without the mutex)
- is_alive(), get_power_mode() and start_ranging() restore the firmware's
register page (0x7fff = 0x02) on their failure paths too, keeping the
original error, so a transient I2C fault never leaves later DCI / frame
reads on page 0
- stop_ranging() clears ranging_ only after a confirmed stop and cleanup
- Vl53l5cx::MAX_TRANSFER_BYTES + i2c_timeout_ms(clock_hz): the example sets
the bus and device timeouts from the clock (the legacy I2C API uses the bus
timeout; 100 ms did not cover an 8x8 frame at 100 kHz)
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DFjjnq3XCTRAXENSxsCxJU
The four "previously missed" items are fixed in f646e5d as well: is_alive(), get_power_mode() and start_ranging() restore register page 2 on their failure paths (original error preserved), and stop_ranging() keeps ranging_ set unless the stop and cleanup were confirmed.
Incoming error prevents recovery after successful retry
components/vl53l/src/vl53l5cx.cpp:107
Clear the incoming error before this read. The separate-write/read fallback selected by this driver's Config leaves ec unchanged on success (components/base_peripheral/include/base_peripheral.hpp:333–344). After a transient read failure, retrying is_data_ready() or get_ranging_data() with the same error-code variable therefore still returns false even when both I2C callbacks succeed. Clearing it here allows recovery while retaining any new transfer error.
Page restoration skipped when cleanup write fails
components/vl53l/src/vl53l5cx.cpp:950
If a cleanup write to 0x14, 0x15 or 0x09 fails after selecting page 0, this short-circuit chain skips restoring page 2. Subsequent frame reads or a stop retry then access the wrong register page, even after a transient I2C failure clears. Attempt the final page restore independently and preserve the first cleanup error.
Address-aware callbacks ignored for configurable I2C addresses
These adapters ignore the callback address and stay bound to 0x29 (components/i2c/include/i2c.hpp:872–892). If a caller uses this setup with set_i2c_address(), the sensor changes address, but the final page-restoration write and later transfers still target 0x29 and fail. Use address-aware bus callbacks here; the bus already has the required timeout. Also document the callback requirement on set_i2c_address() so callers do not use fixed-device adapters for address changes.
- write_multi / read_multi clear the incoming error code first: the base
class's separate write / read path only sets it, so a stale error from an
earlier failure made a successful retry of is_data_ready() /
get_ranging_data() look failed
- stop_ranging() restores the firmware's register page even when the cleanup
writes failed, reporting the first error
- the example uses address-aware bus callbacks (lambdas over I2c::write /
I2c::read) so set_i2c_address() keeps working; the Config / set_i2c_address
docs state that requirement
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DFjjnq3XCTRAXENSxsCxJU
Round 3's three "previously missed" items are fixed in 2c22f41: write_multi / read_multi clear the incoming error code (the base class's separate write / read path only sets it); stop_ranging() restores register page 2 independently of the cleanup writes and reports the first error; the example uses address-aware bus callbacks (lambdas over I2c::write / I2c::read) and the Config / set_i2c_address() docs state that the callbacks must honour their address argument.
The reason will be displayed to describe this comment to others. Learn more.
🔵 Needs a closer look
The firmware-driven hardware port still needs device validation and human review, with power-mode reporting and address-change recovery issues unresolved.
0 open findings
Previously missed (2)
In code that hasn't changed since last review
Restore page 2 when address write fails
components/vl53l/src/vl53l5cx.cpp:492
If selecting page 0 succeeds but the address write fails before changing the address, this return leaves the sensor on page 0. Later DCI and frame operations assume page 2, so they access the wrong registers even after the bus recovers. Attempt to restore page 2 on this failure path, using a separate error code to preserve the original failure.
Accept 0x05 as a valid wakeup power mode
components/vl53l/src/vl53l5cx.cpp:514
start_ranging() writes 0x05 to register 0x09 to enable xshut bypass, but this switch accepts only 0x04 and 0x02. Reading back the awake-with-bypass value therefore sets an I/O error in get_power_mode() during normal ranging. Accept 0x05 as WAKEUP too.
- set_i2c_address() restores the firmware's register page on the old address
when the address write failed (the address did not change)
- get_power_mode() accepts 0x05 (awake with the xshut bypass that
start_ranging() sets) as WAKEUP instead of reporting an I/O error while
ranging
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DFjjnq3XCTRAXENSxsCxJU
Round 4's two "previously missed" items are fixed in 1951aad: set_i2c_address() restores register page 2 on the old address when the address write fails, and get_power_mode() accepts 0x05 (awake + xshut bypass during ranging) as WAKEUP.
The reason will be displayed to describe this comment to others. Learn more.
🔵 Needs a closer look
Firmware initialization, ranging and motion-indicator behavior still need hardware validation and final human review.
0 open findings
Previously missed (1)
In code that hasn't changed since last review
Correct default DCI_INT_TIME from 10 ms to 5 ms
components/vl53l/include/vl53l5cx.hpp:183
The bundled configuration sets DCI_INT_TIME (0x545C) to 10,000 microseconds, and initialize() does not override it. The default integration time is therefore 10 ms, not 5 ms. Please correct this value so callers do not underestimate the integration budget, particularly with four integrations per 8x8 frame.
Round 5's item is fixed in a0d9c38: the bundled default configuration sets DCI_INT_TIME to 10 000 µs, so the initialize() doc now says 10 ms (verified against the blob bytes at 0x545C).
…irmware-error details
The VL53L7CX (90 deg field of view) is the VL53L5CX's silicon, ids, command
interface, default configuration and crosstalk shape with a different
firmware image - the parts cannot be told apart over I2C, and the wrong image
fails at the first firmware command after boot (the NVM read, firmware error
0x9f on the bench). Both images are bundled (BSD-3-Clause, ST's ULD via
stm32duino/VL53L7CX 1.2.3) and Config::variant selects one; the example has
a Kconfig choice. The MCU boot wait is the newer ULD's (0x06 bit 7, then the
boot error code in 0x07, reported), and a firmware error log now carries the
four status bytes and what was expected.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DFjjnq3XCTRAXENSxsCxJU
…based example
- the first transaction after a host reset failed when the sensor was still
clocking out the frame the previous firmware was reading (SDA held low):
the identity probe retries a few times, so a reset while ranging now logs
one failed write and initializes (verified on an ESP32-P4-WIFI6 dev kit)
- example: Kconfig hardware choice for the ESP32-P4 dev kits (SDA 7 / SCL 8;
the empty P4 defaults left the pins unset), a plain polling task instead
of a 5 ms timer (a 1.4 KB frame read takes ~40 ms at 400 kHz and tripped
the timer's period warning every frame), and a per-frame summary of why
zones are invalid (target status counts)
Bench, VL53L5CX on an ESP32-P4-WIFI6 dev kit: initialize 2.1 s at 400 kHz,
8x8 at 15 Hz, 96 frames in 6.4 s, scene distances 0.43 .. 2.8 m.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DFjjnq3XCTRAXENSxsCxJU
Hardware-tested on an ESP32-P4-WIFI6 dev kit with a VL53L5CX breakout (I2C 400 kHz, SDA 7 / SCL 8): initialize in 2.1 s, 8x8 at 15 Hz (96 frames in 6.4 s), plausible scene distances 0.43 .. 2.8 m; a reset while ranging recovers through the new identity-probe retry. Two fixes came out of it (f9a72f7, and this push): the MCU boot wait is the newer ULD's (the old 0x06 == 0 check could pass before the MCU was up and the first firmware command then failed with error 0x9f), and the first transaction after a host reset is retried. VL53L7CX support (same ids, different firmware) is selected by Config::variant; untested on an L7CX. Remaining test-plan items: 4x4 @ 60 Hz and the motion indicator.
…per frame
Bench on the ESP32-P4-WIFI6 dev kit: 4x4 @ 60 Hz ran 416 frames in 7.4 s
(~56 Hz with the console printing in the loop); 8x8 @ 15 Hz with the motion
indicator on (400..1500 mm window) reported 16 aggregates with low motion
values on a static scene.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DFjjnq3XCTRAXENSxsCxJU
Remaining test-plan items done on the same P4 kit: 4x4 @ 60 Hz (416 frames in 7.4 s, ~56 Hz with console printing in the loop) and the motion indicator (new Kconfig option in the example; 16 aggregates, low values on a static scene). Everything in the test plan is now hardware-verified on a VL53L5CX; the VL53L7CX path is untested.
…ple, web app)
Add a dispatcher-module front-end for the multizone ToF driver so a browser
can watch the 4x4 / 8x8 zone distances live in 3D and exercise the sensor API:
- `vl53l5cx_protocol.hpp`: wire protocol (module 10, `espp.vl53l5cx` v1):
every setting, start / stop / initialize, a per-transport frame stream
(every Nth frame) and a STATUS snapshot; standard-library only, with a
host test (`test/vl53l5cx_protocol_host_test.cpp`).
- `vl53l5cx_service.hpp`: `espp::Vl53l5cxService`; the application owns the
one poll loop and hands each frame to every instance via `on_frame()`, so
the vendor (WebUSB) and CDC (Web Serial) transports share one sensor.
Settings are cached while ranging (the firmware cannot be queried then).
- `vl53l5cx_webapp_example`: ESP32-S3 / ESP32-P4 (Kconfig USB port choice),
with the standard system / monitor / OTA / core-dump services, OTA +
coredump partition layout, 24 KB main task stack (the driver's buffers and
the services' frame copies live on it).
- `web/vl53l5cx_console.html`: single-file app with a hand-rolled Canvas 3D
view (surface at the measured positions in the field of view, or bars),
numeric grid, zone details, motion indicator, settings panel, CSV export;
shares the byte-identical discovery / connection / navigation blocks with
the other consoles (test list extended). New apps-index category "sensors".
- Driver: `variant()` / `is_motion_indicator_enabled()` getters.
- Docs (web_apps, module id table, distance_sensors), Doxyfile, READMEs,
component manifest / CMake deps, CI build entry.
Verified: builds for esp32s3 and esp32p4 (IDF 6.1); runs on an
ESP32-P4-WIFI6 dev kit (init, 8x8 @ 15 Hz, TinyUSB on the HS port); page
rendered in Chrome with a synthetic frame; node web-app test + host test pass.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DFjjnq3XCTRAXENSxsCxJU
… VL53L5CX status
The ESP32-P4 has two internal full-speed PHYs. At power-on the USB-Serial-JTAG
owns PHY 0 (GPIO 24 / 25, the dev kits' USB-C) and USB-OTG 1.1 is wired to
PHY 1 (GPIO 26 / 27); IDF never swaps them, so a full-speed TinyUSB device on
`Config::port` 0 enumerated on pads no dev kit routes. `UsbDevice::Config::fs_phy`
(default 0) now maps the OTG 1.1 controller onto the USB-C pads before the
driver is installed (`usb_wrap_ll_phy_select`); -1 keeps IDF's mapping.
usb_device PRIV_REQUIRES esp_hal_usb on IDF 6.
The VL53L5CX webapp example defaults to the full-speed port on the P4 dev
kits (their USB-C), and `Vl53l5cxService` reads the settings back from the
sensor on every STATUS, also while ranging (the firmware only refuses writes),
so the boot-time settings are reported correctly.
Verified on an ESP32-P4-WIFI6 dev kit over the CDC interface: discovery,
every request (OK / ERROR paths), 4x4 @ 30 Hz streaming with no gaps, 8x8 @
15 Hz with divider 3 + motion indicator, snapshot, re-initialize; esp32s3
still builds.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DFjjnq3XCTRAXENSxsCxJU
…lot low-confidence zones
A zone whose target status is 255 (no target detected) still carries the
zone's last distance in the frame, so the console showed e.g. "3600 mm" in the
zone panel while (correctly) plotting nothing. Tier the statuses the way
UM2884 describes them: 5 / 9 valid, 6 / 10 / 12 a range with lower confidence
(now plotted as hollow / faded points and dashed cells; a "Show" selector
restricts to valid only or widens to any target), 255 "no target" (cell reads
"none", the panel says "no target (last N mm)"), anything else a failed
measurement (value in brackets, not plotted). The frame line counts each
class and a hint under the grid explains that no-target zones mean the return
signal was too weak at that distance, with the settings that extend the reach.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DFjjnq3XCTRAXENSxsCxJU
The auto range followed each frame's min / max, so a few millimetres of
noise re-coloured every zone. The range is now a mode: "sensor scale" (the
default; the metric's full scale, 0-4000 mm for the distance, 0-100 % for the
reflectance, 0-32 mm for the sigma) so a value always has the same colour;
"auto", which widens at once but narrows only 5 % per frame and rounds its
ends to a tidy step; and "manual". The 3D scene's framing distance is
tracked the same way, so the view no longer zooms with every frame.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DFjjnq3XCTRAXENSxsCxJU
…ster the "sensors" app category everywhere
A "Trail" control (seconds, default 2, 0 = off) keeps the zone positions of
the previous frames in the 3D view and fades them out with age: in the
surface view as small markers behind the current frame (not pickable), in
the bars view as a zone's last seen height while it currently reports no
target. Intermittent far zones stay visible between detections and a moving
target leaves a trail; a timer keeps the fade going between frames.
The new "sensors" category was missing from the apps-registry host test's
category list (the CI web lint) and from one list in the custom-modules
guide; both now match doc/generate_apps_index.py.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DFjjnq3XCTRAXENSxsCxJU
…e READMEs and docs
Surface view, bars view and a short recording (orbit, bars, colour by
signal) of the hosted console showing live data from a VL53L5CX on an
ESP32-P4-WIFI6 dev kit (8x8 at 15 Hz), hosted as PR #846 attachments and
linked from the component and example READMEs, the distance-sensor page
and the web-apps page.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DFjjnq3XCTRAXENSxsCxJU
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds
espp::Vl53l5cx, a driver for the VL53L5CX 4x4 / 8x8 multizone time-of-flight sensor, to thevl53lcomponent next to the existing VL53L4CD/CX driver (both talk I2C with 16-bit register addresses and shareBasePeripheralplus the component scaffolding).initialize()(run by the constructor by default) reboots it and uploads ST's ~84 KB firmware, then configures it through the DCI command interface. About two seconds at 400 kHz; the sensor supports 1 MHz.vl53l5cx_buffers.hand keep the license in their file headers. The component README has a license note.start_ranging()/stop_ranging(),is_data_ready()polling,get_ranging_data()into aRangingData(distance, sigma, signal / ambient rates, SPAD count, reflectance, target count and target status per zone, row-major); the motion indicator plugin.components/vl53l/vl53l5cx_example(Kconfig: pins, I2C clock, resolution, frequency) prints the distance grid; docs pages, Doxyfile and the CI build matrix are updated.Notes for review:
BasePeripheral::write_many_to_registerstages each write on the stack, so the driver chunks writes to 512 bytes; the I2C device timeout has to cover those and the ~1.4 KB frame reads (the example uses 100 ms).WebUSB console (second commit)
A separate example next to the first one, so the sensor can be watched and driven from a browser over the dispatcher /
stream_frameprotocol:vl53l5cx_protocol.hpp(module id 10, protocolespp.vl53l5cxv1, standard-library only, host testcomponents/vl53l/test/vl53l5cx_protocol_host_test.cpp): every setting (resolution, frequency, integration time, sharpener, target order, ranging mode, power mode, motion indicator window, I2C address), start / stop / initialize, a per-transport frame stream (every Nth frame),GET_FRAME, and aSTATUSsnapshot (settings read back from the sensor when idle, cached while ranging).espp::Vl53l5cxService(vl53l5cx_service.hpp): the application owns the one poll loop and hands each frame to every instance throughon_frame(), so the vendor (WebUSB) and CDC (Web Serial) transports share one sensor and one mutex.components/vl53l/vl53l5cx_webapp_example(ESP32-S3 / ESP32-P4; Kconfig: pins, part, boot resolution / frequency, ranging at boot, P4 USB port): the sensor service plus the standardSystem/Monitor/OTA/CoreDumpservices on both transports, OTA + coredump partition layout, like the MCP266 webapp example.components/vl53l/web/vl53l5cx_console.html: live 3D view (zones at their measured position in the field of view as a surface, or a bar height field), coloured by distance / signal / ambient / sigma / reflectance / status, numeric grid, per-zone details, motion indicator, all settings, start / stop / initialize, CSV export. Shares the byte-identical discovery / connection / navigation / hand-back blocks with the other consoles (the node test list is extended). New apps-index categorysensors.espp::UsbDevicefix (third commit): on the ESP32-P4 the full-speed port (Config::port0) enumerated on GPIO 26 / 27, because IDF leaves USB-OTG 1.1 on the second internal FS PHY while the dev kits' USB-C (and the USB-Serial-JTAG console) is on GPIO 24 / 25. NewConfig::fs_phy(default 0) selects the PHY pads; the example defaults the P4 dev kits to the full-speed port.Test plan
components/vl53l/vl53l5cx_examplebuilds for esp32s3 (IDF 6.1), no warningscomponents/vl53l/example(VL53L4) still buildsvl53l5cx_webapp_examplebuilds for esp32s3 and esp32p4 (IDF 6.1, manager off), boots on the P4 kit (sensor ranging, TinyUSB on the high-speed port)node components/dispatcher/web/test/resolve_module_id_test.jsandvl53l5cx_protocol_host_testpass;doc/generate_apps_index.pyaccepts the new pageConfig::variant): bundled from the same ULD source, not tested on hardware (no part available)🤖 Generated with Claude Code
https://claude.ai/code/session_01DFjjnq3XCTRAXENSxsCxJU