Virridy Home | Lume — Water Quality Sensing Water for Carbon

ToF Ranging Firmware Test

Loading…

This experiment is closed and this page is static. Final pull 2026-08-22 15:18:07Z — 7,309 readings, 10 logged events, 36 within-unit paired contrasts. scripts/build_tof_ranging.js refuses to re-pull without --thaw, so no number here can move.

What it established. Ranging works: valid range_status went 0.56 % → 100 % on v0.1.20, and the 70 mm “reading” was a sentinel emitted on failure, never a measurement. The cap dominates — removing it in water moved distance +27.5 / +27.4 / +28.1 mm across three units, agreeing to under a millimetre. The medium does not: tested in both directions with the cap undisturbed, air→water gave −0.52 mm (t = −0.44) and water→air −1.87 mm (t = −1.39) — the same sign under opposite treatments, so the medium is not the cause. Amplitude is the mirror image, moving 2.8× with the medium and not at all with the cap in air.

The two channels are therefore not redundant, which is exactly what a fouling-vs-turbidity discriminator needs. That work continues at /fouling-turbidity.

Distance by test condition

Mean and SD of distance_mm per condition, pooled across sensors. Valid ranging only — a sentinel is a failure code, not a distance, and averaging it in would drag every cell toward 70 mm.

ToF amplitude by condition — signal_per_spad_kcps

The same 2 × 2 for the amplitude channel. Every reading counts here, not just valid-ranging ones: the amplitude does not depend on range_status, so filtering it the same way would discard sound measurements.

Each unit against itself — one variable at a time

The pooled table above cannot separate the treatment from the sensor mix: different units sit in different cells. This finds every boundary where a single variable changed on one unit with everything else held, and compares that unit to itself either side. Adjacent intervals only, so nothing unrelated intervenes.

unitchangedtransition beforeafterdelta

Interventions

The three signals

A mix of three optics, not one instrument.   Absolute levels are not comparable between them. Compare shape only. Colours follow the house convention (green = Chl‑a, gold = FDOM, blue = TLF); four test conditions are encoded in the line style: ——— air, cap on  ·  ···· air, cap off  ·  – – – water, cap on  ·  –·–· water, cap off. Every unit starts in air with its cap on.

ToF distance — distance_mm

One line per sensor. Every reading in this window carries range_status = 0 — 278 of 278 — so there is no failure sentinel to join across and a plain line is honest here. The line style follows that unit’s test condition over time (key above), so every change of state is visible on the trace itself rather than only in the legend.

ToF amplitude — signal_per_spad_kcps

The working half, shown as the control: if the new build disturbed the sensor generally, it would show here as well as in the ranging.

Fluorescence — full-sweep STLF slope at bias 3000

Refitted from each stored sweep: quadratic in bias across the whole screened sweep, derivative at a fixed reference bias so different LED drives stay poolable.

An uncapped unit admits room light, and on the Chl-a units that is the whole “signal”. mon2_dark is the ambient channel, so it settles this directly. Measured in this window:
unitwindow (UTC)conditionmedian darkmedian valnet
On 500185 the dark channel equals the value channel once the cap is off — net signal is zero and the trace is room light, not fluorescence. Its 46 slope fits appear only after 22:13 and are an artifact of uncapping. The TLF unit is different: ambient rose too, but its net signal survives (825 → 784), so it is still measuring. Do not read the uncapped Chl-a trace as a measurement.