Virridy Home | Lume — Water Quality Sensing Water for Carbon

Turbidity Calibration — ToF → NTU

Formazin bench cal (50031, 2025-12-15), wastewater dilution series (50056, 2026-05-20), a 36-unit barrel ladder (2026-09-01), Chicago field grabs (July to September 2026) and Suez lab runs (unit 50043, July to September 2026)

Overview

Five independent data sets characterizing the Lume’s Time-of-Flight (ToF) photon-backscatter signal (signal_per_spad_kcps) against known turbidity, all using the standard production SiPM sweep configuration (led_power = 512, sipm_bias ∈ [2980, 3020]).

Live Field Stream — Fleet Turbidity

The calibration below is a bench result. This section is the same channel running in the field: every deployed Lume reporting turbidity over the trailing 48 hours, pulled live from /api/site-series. It exists to answer one question — does the ToF→NTU relationship hold up outside a beaker, and is the number fit to show a partner?

What this number is, and is not. Served turbidity is max(0, 1.25 × (sps − that sensor’s clean-water floor)), the fleet conversion below (in service since 2026-09-24; before that the slope was 2.0488). The zero is each sensor’s own 10th-percentile in-water baseline, not turbidity-free water. So this is NTU above baseline: comparable over time for one sensor, not comparable between sensors, and a reading of 0 means “at this sensor’s clean floor”, not 0 NTU. Absolute NTU would need a per-sensor co-deployment against a turbidimeter, which we have on two units and not on the fleet. Note also that sps is an integer, so the output is quantised to ~2.05 NTU steps — visible as banding in the chart.
Loading fleet turbidity…

Per-site summary, trailing 48 h

Site Lume n latest median p95 max distinct
Loading…

All values NTU above that sensor’s own clean-water baseline. distinct counts how many different values the sensor produced in the window: a low count on many points means the channel is sitting on its quantisation floor rather than tracking anything.

Regression Fits

Sensor 50031 (bench, formazin): SPS₀ ≈ 71 kcps/SPAD  ·  individual R² = 0.990  ·  RMSE = … NTU
Sensor 50056 (wastewater dilution): SPS₀ ≈ 30 kcps/SPAD  ·  individual R² = 0.993  ·  RMSE = … NTU
Pooled regression (excess SPS vs NTU):
NTU = k × (SPS − SPS₀)  ·  k = … NTU per kcps/SPAD  ·  R² = …  ·  RMSE = … NTU

Subtracting each sensor’s clean-water baseline (SPS₀) removes the unit-to-unit offset. Multiplying the excess by the pooled slope k converts the signal directly to NTU, giving a sensor-predicted NTU that can be compared against the reference on a 1:1 plot. The chart below shows this: reference NTU on x, sensor-predicted NTU on y, with the ideal 1:1 line.

The two datasets overlap well on the 1:1 line, validating the pooled model across both sensors and matrices. Any remaining scatter could reflect sensor-to-sensor variation in optical chamber geometry, or a matrix effect: formazin turbidity standards are purely scattering particles, while real wastewater both scatters and absorbs photons. With only two sensors across two different matrices, these contributions cannot be separated from these data alone.

Dataset 1: Bench Calibration (Sensor 50031, 2025-12-15)

Formazin turbidity standards, bench protocol. ToF sensor reads once per SiPM sweep cycle independent of LED/bias combo; production combo (led=512, sipm_bias~3000) timestamps used to select the 140 ToF readings below.

Step start (MST) Step end NTU n (ToF) distance_mm signal_rate_kcps signal_per_spad_kcps
13:3313:480.0015239,63270
13:4914:040.2015239,67271
14:0614:211.8915239,73671
14:2414:396.70152410,05674
14:4214:5713.2015259,86480
15:0315:1858.6015299,832103
15:2215:35109.0013319,688122

Dataset 2: Wastewater Dilution Test (Sensor 50056, 2026-05-20)

Eight concentration steps of real wastewater diluted into tap water (0–100%). NTU measured by lab turbidimeter; median ToF SPS per window at the same production combo (led=512, sipm_bias~3000).

Concentration NTU (lab turbidimeter) n (ToF) distance_mm signal_rate_kcps signal_per_spad_kcps
0%0.00012266,55630
1%0.47410266,67630
5%2.7507267,14432
10%8.5409267,71235
25%17.7309269,71244
50%39.97082610,02864
75%72.47092610,06480
100%91.1008279,30495.5

Dataset 3: Fleet Barrel Ladder (36 Units, 2026-09-01)

Three turbidity standards were dosed into a 167.7 L barrel holding the spike-test fleet (details on the spike test page): StablCal formazin to 2.31 NTU nominal, then AMCO Clear to 5.02 and 7.23 NTU. Each rung ran 20 minutes, and the table uses the last 10 minutes of each, after settling. The window before the ladder is the preceding tryptophan rung, with no turbidity standard in the water. Two AquaTroll sondes in the same barrel measured turbidity directly; a third (Marina) did not track the ladder and is left out. ToF is signal_per_spad_kcps, the median per unit per window. Times are local (MDT).

Window (MDT) Standard added Nominal NTU Sonde NTU (Jamison / Lakeview East) Units Fleet median ToF Median rise over baseline
18:45–18:55none (baseline)00.55 / 0.0036440
19:05–19:15485 mL StablCal 800 NTU2.311.03 / 0.123546+2
19:25–19:35460 mL AMCO Clear 1000 NTU5.022.32 / 1.293548+4
19:45–19:55375 mL AMCO Clear 1000 NTU7.233.64 / 3.483650+6

The fleet median ToF rose 2, 4 and 6 counts across the three rungs. 31 of the 36 units rose at every rung; four held flat on one rung, which integer counts produce at this size of step, and one (500218) moved up and down. Per unit the rise is close to linear: median R² 0.98 against nominal NTU and 0.92 against the sondes, over the 35 units with enough rungs to fit.

The slope depends on the reference. Against the nominal dose the fleet median is 1.24 NTU per count (middle half of units 1.19–1.56), below the bench pooled k in the fits above. Against the sonde-measured turbidity it is 0.49 NTU per count (0.44–0.62), because both sondes read well under the nominal dose: a third of it or less on the first two rungs, and under half on the third. The two references differ by a factor of about 2.5, and this ladder does not say which is right. It spans only 0–7 NTU, the bottom of the bench range, where one count covers roughly half an NTU to one and a half NTU depending on the reference.

StablCal also raised specific conductivity from 8.9 to 44.6 µS/cm, so the first rung changed the ionic matrix as well as the scattering. The barrel held 148.6 ppb quinine, 103.5 ppb rhodamine and 50 ppb tryptophan from earlier rungs; those change fluorescence, and the ToF channel responded to none of the earlier blocks by more than a few counts.

Dataset 4: Chicago Field Grabs (Portable Turbidimeter, 2026-07-29 to 09-21)

Current’s H2NOW program read turbidity on 37 grab samples at the six Chicago sites with an Apera portable turbidimeter. Each is paired to the Lume at that site: the median ToF within ±20 minutes of the grab, inside the unit’s install window. These units foul, and a fouled cap raises the ToF floor by hundreds of counts between cleanings (North Branch sat at 466–508 counts before its 14 August cleaning and 41–57 after), so each reading is taken as a rise over that unit’s own floor: the 10th percentile of its ToF over the preceding seven days. 28 of the 37 grabs pair; the rest fall where a unit was offline or had under a week of prior data. Grab times are Chicago local (CDT).

In the field the ToF rises well above anything the bench predicts, and not in proportion to turbidity. Across all 28 pairs the rank correlation between turbidity and the rise over the floor is 0.32 (p 0.09); the linear correlation of 0.63 comes from a handful of high events. Leaving out the 21 September storm, the rank correlation is 0.00 over 23 grabs. The two Calumet sites track turbidity (Cal-Sag 0.68, Little Calumet 0.60); North Branch (−0.09) and South Branch (0.02) do not. Measured as counts per NTU, the field reads a median of 2.1 on ordinary days, 4.9 above 20 NTU and 7.5 on the storm day, against 0.8 on the bench at low turbidity. On 21 September North Branch rose 282 counts at 19.9 NTU and South Branch 352 counts at 13.1 NTU, readings that no bench slope connects to those turbidities.

Above 20 NTU this data set shows a strong ToF response to high-turbidity events, and no stable conversion to NTU. Something in storm water raises the ToF signal beyond what the portable meter reads as turbidity, and the floor under each reading moves with fouling by more than the whole bench range. The comparison also mixes a grab bucket read once against a 40-minute median of the river at the sensor.

DateTime (CDT)SitePortable NTULume ToF7-day floorRise over floor
07-2907:00North Branch12.149146625
07-2907:45Wild Mile6.992812729
07-2908:30Main Stem3.36———no ToF within 20 min (unit offline)
07-2909:00South Branch13.17478480-2
07-2909:45Cal-Sag Channel25.31379641
07-2910:15Little Calumet45.7—88—no ToF within 20 min (unit offline)
08-0507:15North Branch8.4150847731
08-0507:45Wild Mile9.74—283—no ToF within 20 min (unit offline)
08-0508:45Main Stem1.17508——less than a week of prior data
08-0509:30South Branch7.1548247012
08-0510:30Little Calumet26.2123——less than a week of prior data
08-0511:00Cal-Sag Channel19.2561556
08-1207:00North Branch8.6354450836
08-1207:30Wild Mile8.16———no ToF within 20 min (unit offline)
08-1208:15Main Stem3.78———no ToF within 20 min (unit offline)
08-1208:45South Branch7.3648347112
08-1209:30Cal-Sag Channel55.634674272
08-1209:45Little Calumet90.6602306296
08-1907:15North Branch10.8645414
08-1908:00Main Stem1.63———no ToF within 20 min (unit offline)
08-1908:30South Branch12.832795232
08-1909:15Cal-Sag Channel12.2450144259
08-1909:30Little Calumet27.66316274
08-2607:15North Branch17.0347443
08-2608:00Main Stem2.01———no ToF within 20 min (unit offline)
08-2608:30South Branch8.7930828720
08-2609:15Cal-Sag Channel9.7952949732
08-2609:30Little Calumet14.01482495-13
09-0208:15South Branch4.5435327182
09-0209:30North Branch9.8352484
09-0210:30Cal-Sag Channel10.4954251428
09-0210:45Little Calumet9.381216952
09-2107:15North Branch19.9133957282
09-2107:45Wild Mile23.725581174
09-2108:30South Branch13.1341664352
09-2109:00Cal-Sag Channel27.7325121204
09-2109:15Little Calumet51.3574187386

Dataset 5: Suez Lab Runs (Unit 50043, Hach Reference)

Suez ran one Lume (50043) through several lab sessions and read each sample on a Hach turbidimeter. Each run is fitted on its own, NTU against ToF, and the chart shows the ToF rise over that run’s first (blank) sample. Source: the Suez campaign page.

RunWhat was addednHach range (NTU)ToF rangeNTU per countR²
2026-07-23Seine samples50.2–2324–451.100.989
2026-08-06Seine water into blank60.21–9.037–780.250.910
2026-08-25E. coli culture, Seine sample80.15–5.239–44no usable range0.14
2026-09-01E. coli culture into MilliQ110.14–2837–651.040.892

Two of the three runs with a usable range sit on the fleet scale: 1.10 NTU per count on the July Seine samples and 1.04 on the September culture additions. The 6 August run, Seine water added to a blank, reads four times steeper per NTU (0.25), on the same unit. The clean-water ToF also moved between sessions, from 24 counts in July to 37–41 in August and September, so the zero has to be taken from each session’s blank.

Fleet Conversion

One equation over the whole range, served on the dashboards and the customer API since 2026-09-24. The zero is each unit’s own clean-water floor, because floors differ by unit from 29 to 125 counts.

NTU = 1.25 × (ToF − that unit’s clean floor)

The slope is the value the controlled experiments agree on up to 20 NTU: 1.36 on 50031, 1.26 on 50056, 1.24 on the barrel ladder (fleet median, nominal dose), and 1.10 and 1.04 on Suez’s 50043 (Dataset 5). Up to 20 NTU it fits the bench points with an RMSE of 1.3 NTU on 50056 and 1.9 on 50031. Above 20 NTU it reads low: 8.2 NTU RMSE on 50056, which is 10.5% under at its 91 NTU step, and 35 NTU on 50031, whose response flattens, 42% under at 109 NTU.

Unit-to-unit slope variation in the barrel ladder was about 28% beyond counting noise, so a single unit can read roughly ±28% off. Natural river water can read far steeper than this scale: Suez’s 6 August Seine run gave 0.25 NTU per count, and in the Chicago field data (Dataset 4) the ToF rise does not follow turbidity on ordinary days. This conversion describes controlled water, not fouled river deployments.

Comparison to Published Turbidimeter Accuracy

The pooled RMSE (computed dynamically above) can be compared against manufacturer-specified accuracy for commercial lab and field turbidimeters in the 0–100 NTU range:

Instrument Type Accuracy spec (0–100 NTU) Typical error at 10 NTU Typical error at 50 NTU
Hach 2100N / 2100ANLab bench±2% rdg + 0.01 NTU±0.21 NTU±1.01 NTU
Hach TU5200 (EPA laser)Lab bench±2% or ±0.01 NTU (<40 NTU); ±10% (40–100 NTU)±0.20 NTU±5.0 NTU
Hach Solitax sc (w/ site cal)Field inline<1% rdg + 0.01 NTU±0.11 NTU±0.51 NTU
YSI EXO sondeField sonde±2% or ±0.3 FNU, whichever greater±0.30 NTU±1.0 NTU
Campbell OBS-3+ / OBS300Field backscatter±2% or ±0.5 NTU, whichever greater±0.50 NTU±1.0 NTU
In-Situ Aqua TROLLField sonde±2% or ±0.1 NTU (0–200 NTU)±0.20 NTU±1.0 NTU
Lume ToF — per-sensor cal Integrated sensor Individual OLS fit per sensor … / … NTU (50031 / 50056) … / … NTU (50031 / 50056)
Lume ToF — pooled model Integrated sensor Single k, per-sensor SPS₀ … NTU (all points ≤20 NTU) … NTU (all 15 points)

A few important caveats on this comparison. First, manufacturer accuracy specs are measured under controlled laboratory conditions using formazin or AMCO Clear standards — the same conditions as Dataset 1. Published USGS field comparisons between approved commercial sensors document real-world inter-sensor disagreement of 10–40% at moderate turbidities (USGS OFR 2021-1009; SIR 2023-5077), far exceeding the manufacturer specs. Second, our RMSE is computed across only 15 points spanning two sensors and two matrices — it is an early-stage estimate, not a validated deployment accuracy. Third, the Lume sensor’s ToF photon-backscatter signal uses a fundamentally different optical geometry (time-gated single-photon counting) than the nephelometric or backscatter designs above; sensitivity to particle size, shape, and absorption will differ.

Two Lume performance figures are shown. Per-sensor cal is the RMSE when each sensor uses its own OLS fit (m, b) — the best-case accuracy assuming a bench calibration has been run for that unit. Pooled model is the RMSE when a single shared slope k is applied to both sensors using only their clean-water baselines (SPS₀) — representing a factory-calibration scenario where only the offset is sensor-specific.

The per-sensor RMSE (computed below from the individual fits) is competitive with commercial field sondes: at the low end of the range (<20 NTU) errors are sub-1 NTU for both sensors, comparable to the YSI EXO floor of ±0.3 FNU and the Campbell OBS floor of ±0.5 NTU. At higher turbidities the absolute error grows but remains within the ±2% of reading band that defines field-grade accuracy. The pooled RMSE is larger because the shared slope k ≈ 1.59 is a compromise between the two sensors’ individual slopes (2.05 and 1.38); sensor 50031 is systematically underpredicted above ~50 NTU by the pooled model, pulling the pooled RMSE up. This is visible in the chart as the 50031 points (circles) sitting above the 1:1 line at high NTU.

These results are encouraging for a sensor not designed as a dedicated turbidimeter, but this is a two-sensor, two-matrix dataset. A deployment-grade accuracy specification will require calibration across more units, more matrices (including turbid river water and stormwater), and validation against a traceable ISO 7027 reference.

Why signal_per_spad_kcps, not the other metrics