feat(vl53l1x): Implement Arduino driver. #9#191
Conversation
There was a problem hiding this comment.
Pull request overview
Adds a new Arduino/C++ driver for the ST VL53L1X Time-of-Flight sensor to the STeaMi driver collection, along with native (mocked I2C) and on-device hardware validation tests plus updated documentation.
Changes:
- Introduces a new
VL53L1Xdriver (register constants, I2C helpers, begin/reset/ranging/data-ready/distance read API). - Adds native mock tests and hardware integration tests for device detection and plausible distance reads.
- Replaces the placeholder
vl53l1xREADME with usage/API/testing documentation.
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 8 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/native/test_vl53l1x/test_main.cpp | Adds native MockWire unit tests for the new VL53L1X driver API. |
| tests/native/helpers/Wire.h | Extends the MockWire helper to support VL53L1X-style 16-bit register addressing. |
| tests/hardware/test_vl53l1x/test_main.cpp | Adds on-hardware Unity tests for begin/device ID/plausible distance reads. |
| lib/vl53l1x/src/VL53L1X.h | Declares the public VL53L1X driver API. |
| lib/vl53l1x/src/VL53L1X.cpp | Implements the VL53L1X driver, including default-config upload and distance reads. |
| lib/vl53l1x/src/VL53L1X_const.h | Defines VL53L1X register addresses, bit masks, and offsets used by the driver/tests. |
| lib/vl53l1x/README.md | Documents setup, API surface, behavior, and testing for the driver. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| void test_device_id_returns_who_am_i() { | ||
| preloadWhoAmI(true); | ||
| VL53L1X testSensor; // ← Créé ici | ||
| testSensor.begin(); | ||
| check_who_am_i(sensor, VL53L1X_DEVICE_ID); | ||
| } |
| void test_reset_writes_assert_then_release(void) { | ||
| preloadDataReady(false); | ||
| TEST_ASSERT_FALSE(sensor.dataReady()); | ||
| } |
| bool is16bit = | ||
| (txBuffer_.size() >= 2) && (txBuffer_[0] <= 0x03) && (currentAddress_ == 0x29); | ||
|
|
||
| if (is16bit && txBuffer_.size() == 2) { | ||
| uint16_t regAddr = (static_cast<uint16_t>(txBuffer_[0]) << 8) | txBuffer_[1]; | ||
| currentRegisterByAddr_[currentAddress_] = regAddr; | ||
| } else if (is16bit) { | ||
| uint16_t regAddr = (static_cast<uint16_t>(txBuffer_[0]) << 8) | txBuffer_[1]; | ||
| for (size_t i = 2; i < txBuffer_.size(); ++i) { | ||
| uint8_t targetReg = static_cast<uint8_t>(regAddr + (i - 2)); | ||
| uint8_t val = txBuffer_[i]; | ||
| registers_[makeKey(currentAddress_, targetReg)] = val; | ||
| writes_.push_back({currentAddress_, targetReg, val}); | ||
| } | ||
| currentRegisterByAddr_[currentAddress_] = regAddr; | ||
| } else { | ||
| for (size_t i = 1; i < txBuffer_.size(); ++i) { | ||
| uint8_t targetReg = static_cast<uint8_t>(reg + (i - 1)); | ||
| uint8_t val = txBuffer_[i]; | ||
| registers_[makeKey(currentAddress_, targetReg)] = val; | ||
| writes_.push_back({currentAddress_, targetReg, val}); | ||
| } | ||
| currentRegisterByAddr_[currentAddress_] = reg; | ||
| } |
| void setRegister(uint8_t address, uint16_t reg, uint8_t value) { | ||
| registers_[makeKey(address, reg)] = value; | ||
| } | ||
|
|
||
| uint8_t getRegister(uint8_t address, uint8_t reg) const { | ||
| uint8_t getRegister(uint8_t address, uint16_t reg) const { | ||
| auto it = registers_.find(makeKey(address, reg)); | ||
| return (it != registers_.end()) ? it->second : 0x00; | ||
| } |
| void VL53L1X::writeRegBytes(uint16_t reg, const uint8_t* data, size_t len) { | ||
| _wire->beginTransmission(_address); | ||
| _wire->write((reg >> 8) & 0xFF); | ||
| _wire->write(reg & 0xFF); | ||
| for (size_t i = 0; i < len; i++) { | ||
| _wire->write(data[i]); | ||
| } | ||
| _wire->endTransmission(); | ||
| } |
| uint16_t VL53L1X::distanceMm() { | ||
| ensureData(); | ||
| uint8_t data[RESULT_BLOCK_SIZE] = {}; | ||
| _wire->beginTransmission(_address); | ||
| _wire->write((REG_RESULT_RANGE_STATUS >> 8) & 0xFF); | ||
| _wire->write(REG_RESULT_RANGE_STATUS & 0xFF); | ||
| _wire->endTransmission(false); | ||
| _wire->requestFrom(_address, static_cast<uint8_t>(RESULT_BLOCK_SIZE)); | ||
| for (uint8_t i = 0; i < RESULT_BLOCK_SIZE && _wire->available(); i++) { | ||
| data[i] = static_cast<uint8_t>(_wire->read()); | ||
| } | ||
| uint16_t distance = static_cast<uint16_t>(data[RESULT_DISTANCE_MSB_OFFSET] << 8) + | ||
| data[RESULT_DISTANCE_LSB_OFFSET]; | ||
| clearInterrupt(); | ||
| return distance; | ||
| } |
| See [examples/read_distance/](examples/read_distance/) for the complete | ||
| example sketch. | ||
|
|
||
| ## Examples | ||
|
|
||
| | Example | What it does | | ||
| |---------|--------------| | ||
| | [`read_distance`](examples/read_distance/) | Continuously reads and prints the measured distance in millimeters. | | ||
| | [`distance_alarm`](examples/distance_alarm/) | Triggers an alert when an object comes closer than a configurable threshold. | | ||
| | [`power_cycle`](examples/power_cycle/) | Demonstrates sensor power control using `powerOff()` and `powerOn()`. | | ||
| | [`continuous_ranging`](examples/continuous_ranging/) | Runs continuous ranging and prints measurements as soon as data becomes available. | | ||
|
|
| void test_power_off_writes_assert(void) { | ||
| sensor.powerOff(); | ||
| preloadDataReady(false); | ||
| TEST_ASSERT_FALSE(sensor.dataReady()); | ||
| } |
|
Thanks for the update and for addressing the Copilot comments. I checked the fixes and the major issues reported by Copilot seem resolved. I only have a few remaining points before merge:
Also, when replying to review comments, please indicate which Copilot comment each change addresses so the review history is easier to follow. Apart from these points, the implementation looks good. |
|
🎉 This PR is included in version 0.21.0 🎉 The release is available on GitHub release Your semantic-release bot 📦🚀 |
Summary
Adds a full driver for the ST VL53L1X Time-of-Flight distance sensor, including native mock tests, hardware validation tests, and complete documentation.
Close #9
Close #41
close #29
Changes
VL53L1X.h,VL53L1X.cpp, andVL53L1X_const.himplementing the full driver API0xEACC)distanceMm,read)startRanging,stopRanging)reset,powerOn,powerOff)begin()README.mdwith setup, API, examples, and testing documentationChecklist
make lintpasses (clang-format)make buildpasses (PlatformIO)make test-nativepasses (if native tests exist)make test-hardwarepasses on a connected STeaMi (if hardware tests exist)