VL53L5CX: is it normal for each sensor to run at random deviated frame rate?
Hello,
We asked multiple VL53L5CX sensors for the same ranging frequency for different frequencies and measured what each one actually delivered. No two ran at the same rate, and none ran at the rate we asked for for higher frequencies.
Commanded 10 Hz, result read every frame — the parts delivered 10.06, 10.14, 10.21, 10.26, 10.06 and 10.28 Hz. Commanded 30 Hz, same parts — 29.38, 29.62, 29.80, 29.94, 29.44 and 30.00 Hz. The deviation is different for every part, it changes sign between 10 and 30 Hz, and we see no pattern that predicts it.
Is this normal? Is there a specified tolerance on the achieved ranging frequency? That is our main question.
Two things we can add:
It is not jitter. Each part's deviation is reproducible. Repeat a run and it returns to within tens of parts per million (ppm); power the part down for two minutes and re-initialise it, and it still comes back to the same value. The spread between parts is ≈ 2 percentage points, i.e. ≈ 20 000 ppm; the scatter within one part is 9–189 ppm. Each sensor appears to have its own fixed offset.
Reading the result widens the spread about tenfold. If we never fetch the result and only poll the data-ready flag, the same parts sit within about 1 % of the commanded rate. Fetch the result every frame and they spread over about 2.2 percentage points. That surprised us, and we cannot explain it:
- It is not I²C bus time. We cut the read from 688 to 220 bytes per frame — 8.2 ms down to 2.6 ms on the bus — by compiling out the result arrays we do not use. That 3.1× change in bus occupancy changed the behaviour by 2 parts in 10 000. Going from no fetch to the smallest useful fetch changed everything. The step is at zero, not along the axis.
- It is not the sensor's clock. Fitting
T_actual = alpha * T_commanded + betaper part, reading adds ≈ 1.5 ms tobeta. No change of oscillator frequency adds a fixed time to a frame. - It is not a fixed hand-off delay either, because
alphamoves too (by ≈ 0.031), so part of the effect scales with the frame length.
Setup: VL53L5CX-SATEL on RP2040, ULD VL53L5CX_1.1.2, I²C at 1 MHz, 4×4, AUTONOMOUS, 5 ms integration, 2 targets, CLOSEST. Frame periods timed from the falling edge of each sensor's INT pin in hardware, not from the host's data-ready poll — a read can delay our poll by up to 100 ms on a three-sensor bus, which would have measured our scheduler instead of the sensor. Zero dropped edges, zero doubles, edge count matching the stream counter.
Questions
- Is a per-part spread of this size expected, and is there a tolerance specified for the achieved ranging frequency?
- In AUTONOMOUS mode, is the frame schedule supposed to be independent of whether the host reads the result? The closest statement I found here is for the VL53L4CX, saying the sensor starts the next range while you read the current one.
- Is there a mechanism that would couple the two — the result buffer being held or copied during the read, or the next start deferred until the host releases it? That would explain why the step is at "any read at all" rather than at "a big read".
- Is there a way to get a schedule independent of host reads, or to predict a part's offset so a commanded rate can be corrected for it?
Full method, which fields we read and which we disabled, per-part numbers and the checks above are in the attached note. Per-run CSVs available on request.
Thanks,
