|
STAR
Cal STAR — firmware, DAQ server, and engine design
|
The ADC a calibration capture records: a bounded, recent, checked mean. More...
#include <cstddef>#include <cstdint>#include <deque>#include <unordered_map>#include <vector>Go to the source code of this file.
Classes | |
| struct | fsw::calibration::AdcSample |
| struct | fsw::calibration::CaptureResult |
| class | fsw::calibration::CaptureWindow |
| Per-sensor ring of recent samples, and the capture decision over it. More... | |
Namespaces | |
| namespace | fsw |
| Motorized ball valve position: raw ADC counts -> % open. | |
| namespace | fsw::calibration |
| Output smoothing for calibrated PT pressure, per sensor uid (ESP32 and LabJack T7 alike). | |
Variables | |
| constexpr uint64_t | fsw::calibration::kCaptureWindowMs = 1000 |
| How far back a capture averages. | |
| constexpr uint64_t | fsw::calibration::kMaxSampleAgeMs = 1500 |
| Newest sample older than this (in OUR clock) means the sensor is not live. | |
| constexpr size_t | fsw::calibration::kMinCaptureSamples = 3 |
| Below this a "mean" is not one, and the settle check has nothing to say. | |
| constexpr uint64_t | fsw::calibration::kStaleSamplePeriods = 2 |
| Liveness allowance for a slow sensor, in its own sample periods: one late sample is jitter, two missing in a row is a sensor that stopped. | |
| constexpr uint64_t | fsw::calibration::kMaxCaptureWindowMs = 5000 |
| Upper bound on the adaptive window and staleness allowance. | |
| constexpr uint64_t | fsw::calibration::kRingSpanMs = 8000 |
| Ring eviction: by span so it self-sizes across 1-250 Hz, by count so memory is bounded if a board ever runs fast. | |
| constexpr size_t | fsw::calibration::kRingMax = 1024 |
| constexpr double | fsw::calibration::kSettleZ = 6.0 |
| Half-mean difference, in standard errors, above which the window is not settled. | |
| constexpr const char * | fsw::calibration::kReasonOk = "" |
| Why a capture was refused. | |
| constexpr const char * | fsw::calibration::kReasonNoSamples = "no_samples" |
| constexpr const char * | fsw::calibration::kReasonStale = "stale" |
| constexpr const char * | fsw::calibration::kReasonTooFew = "too_few" |
The ADC a calibration capture records: a bounded, recent, checked mean.
A capture must answer "what is this sensor reading RIGHT NOW", and the answer has to mean the same thing on a 250 Hz pressure transducer and on a 13 Hz load cell.
It did not. The calibration service kept a plain deque<int32_t> of the last 128 samples per sensor and averaged the whole thing, with this comment:
constexpr size_t kPtAdcRingMax = 128; // ~0.5 s of samples at ~250 Hz
No board on the rig runs at 250 Hz. Measured pre-downsample ingest: PT 61-68 Hz, RTD 26 Hz, actuators 10 Hz, and a load cell 13.7 Hz. So the same 128 samples is 2 s on a PT and 9.3 s on a load cell, and every capture averaged the last nine seconds of the scale. On 2026-09-13 an operator added weight and captured 13 s later; roughly a quarter of the window still held the previous load, and the point landed 26% short of the line (steps of 52241, 53737, then 39238 counts per equal 2.268 kg). Three separate ZERO-load captures spanned 29,087 counts while the live signal's sigma was 798 — 36 sigma, impossible as noise, ordinary as a moving average over nine seconds.
So the window is bounded in TIME, not in samples, and two different clocks answer two different questions:
SETTLING. A window can be recent and still wrong, if the load changed inside it. The check compares the mean of the window's first half against its second half, normalised by the window's own noise, so a ramp or step reads as drift while plain noise does not. Normalising is what lets one threshold serve a 4-20 mA PT (codes ~1e6) and a load cell (~5e4) with nothing to tune per sensor. An unsettled capture is reported, never silently dropped: the caller records the point and flags it.
Pure and deterministic: no clock is read here — times are inputs, so the tests drive every edge case (see lib/test/test_capture_window.cpp).
NOTE on [time_sync] mode = "arrival" (BoardClockSync.hpp): that revert switch flattens a whole packet onto one stamp, which coarsens ts_ns to per-packet resolution. The newest-sample anchoring keeps membership from failing closed, and kMinCaptureSamples plus the drift check still catch the pathological case — but expect fewer, chunkier samples per window in that mode.
Definition in file CaptureWindow.hpp.