feat(VL53L4CD): 增加偏移校准支持并固化44mm安装偏移

- 新增 vl53l4cd_set_offset/get_offset/calibrate_offset
- main 支持开机自动校准或启动时写回固定偏移
- 当前44mm哑光目标校准结果 offset=-9mm
- 同步更新 README 与 CHANGES
This commit is contained in:
2026-08-07 00:16:50 +08:00
parent 782fe2b2b0
commit ef37553b18
6 changed files with 210 additions and 2 deletions
+109
View File
@@ -94,6 +94,26 @@ bool vl53l4cd_clear_interrupt(void)
return vl53l4cd_write_reg8(VL53L4CD_REG_SYSTEM_INTERRUPT_CLEAR, 0x01U);
}
/**
* @brief 等待新的测距结果就绪
* @param[in] timeout_ms: 超时时间,单位 ms
* @retval true: 结果就绪; false: 超时或读取失败
*/
static bool vl53l4cd_wait_for_data_ready(uint32_t timeout_ms)
{
uint32_t elapsed_ms = 0U;
while (elapsed_ms < timeout_ms) {
if (vl53l4cd_data_ready()) {
return true;
}
delay_ms(1);
elapsed_ms++;
}
return false;
}
bool vl53l4cd_get_result(vl53l4cd_result_t *result)
{
static const uint8_t status_rtn[24] = {
@@ -191,6 +211,95 @@ bool vl53l4cd_set_range_timing(uint8_t timing_budget_ms, uint32_t inter_measurem
(uint16_t)((uint16_t)ms_byte << 8 | ls_byte));
}
bool vl53l4cd_set_offset(int16_t offset_mm)
{
uint16_t reg_value;
reg_value = (uint16_t)((int16_t)offset_mm * 4);
return vl53l4cd_write_reg16(VL53L4CD_REG_RANGE_OFFSET_MM, reg_value) &&
vl53l4cd_write_reg16(VL53L4CD_REG_INNER_OFFSET_MM, 0U) &&
vl53l4cd_write_reg16(VL53L4CD_REG_OUTER_OFFSET_MM, 0U);
}
bool vl53l4cd_get_offset(int16_t *offset_mm)
{
uint16_t reg_value;
int16_t raw;
if (offset_mm == NULL) {
return false;
}
if (!vl53l4cd_read_reg16(VL53L4CD_REG_RANGE_OFFSET_MM, &reg_value)) {
return false;
}
raw = (int16_t)reg_value;
*offset_mm = (int16_t)(raw / 4);
return true;
}
bool vl53l4cd_calibrate_offset(uint16_t target_distance_mm, uint16_t num_samples,
int16_t *measured_offset_mm)
{
vl53l4cd_result_t result;
int32_t distance_sum = 0;
uint16_t valid_samples = 0;
uint16_t i;
int16_t average_distance;
int16_t offset;
if (measured_offset_mm == NULL ||
target_distance_mm < 10U || target_distance_mm > 1000U ||
num_samples < 5U || num_samples > 255U) {
return false;
}
if (!vl53l4cd_stop_ranging() ||
!vl53l4cd_set_offset(0) ||
!vl53l4cd_start_ranging()) {
return false;
}
/* 热机 10 帧,丢弃 */
for (i = 0U; i < 10U; i++) {
if (!vl53l4cd_wait_for_data_ready(VL53L4CD_DATA_TIMEOUT_MS)) {
return false;
}
(void)vl53l4cd_clear_interrupt();
(void)vl53l4cd_get_result(&result);
}
/* 统计有效测距样本 */
for (i = 0U; i < num_samples; i++) {
if (!vl53l4cd_wait_for_data_ready(VL53L4CD_DATA_TIMEOUT_MS)) {
return false;
}
(void)vl53l4cd_clear_interrupt();
if (vl53l4cd_get_result(&result) &&
result.range_status == VL53L4CD_STATUS_RANGE_VALID) {
distance_sum += (int32_t)result.distance_mm;
valid_samples++;
}
}
(void)vl53l4cd_stop_ranging();
if (valid_samples == 0U) {
return false;
}
average_distance = (int16_t)(distance_sum / (int32_t)valid_samples);
offset = (int16_t)((int16_t)target_distance_mm - average_distance);
if (!vl53l4cd_set_offset(offset)) {
return false;
}
*measured_offset_mm = offset;
return true;
}
bool vl53l4cd_init(void)
{
uint16_t model_id = 0U;
+13
View File
@@ -78,6 +78,19 @@ int main(void)
#endif
if (vl53l4cd_init()) {
#if VL53L4CD_AUTO_CALIB == CFG_ENABLE
int16_t cal_offset = 0;
if (vl53l4cd_calibrate_offset(VL53L4CD_CALIB_TARGET_MM,
VL53L4CD_CALIB_SAMPLES,
&cal_offset)) {
printf("VL53L4CD offset calibrated: %d mm\r\n", cal_offset);
} else {
printf("VL53L4CD offset calibration failed\r\n");
}
#else
(void)vl53l4cd_set_offset(VL53L4CD_CALIB_OFFSET_MM);
#endif
vl53l4cd_start_ranging();
printf("VL53L4CD ready\r\n");
} else {