mirror of
https://github.com/alexhopeoconnor/firmware.git
synced 2026-10-13 15:11:20 +10:00
* Remove proprietary Bosch BSEC blob; open in-tree IAQ estimator for BME680 BSEC2 cost ~37-39 KB flash and ~4-5 KB static RAM on ~190 of ~240 build targets, linked whether or not a BME680 was attached, and was a no-source proprietary archive inside GPLv3 release binaries. The firmware consumed exactly one BSEC-exclusive output: the IAQ value. - New BME680IaqEstimator: clean-room log-domain baseline tracker (humidity-compensated gas resistance vs a rise-fast/decay-slow ceiling, 0-500 scale matching the existing UI bands), pure math, unit-tested on native (test_bme680_iaq, 15 tests incl. a deep-sleep reboot simulation). Warm-up/burn-in progress persists to /prefs/bme680.dat via SafeFile so one-sample-per-wake SENSOR nodes converge across reboots; stale /prefs/bsec.dat is removed once. - BME680Sensor: single-path rewrite on Adafruit_BME680 with async once-per-minute sampling (~20x lower heater duty than BSEC LP mode), a hard 2-minute publish-freshness bound (a dead sensor stops reporting instead of freezing its last reading on the wire), and suppression of bogus gas_resistance=0 points from heater-unstable cycles. - platformio.ini: environmental_extra_common/_extra/_no_bsec collapsed into one section; Bosch BSEC2 + BME68x deps deleted; per-variant BSEC link-path hacks and the TEMPORARY promicro lib_ignore removed. nrf52_promicro_diy_tcxo regains BME680 support at 36 KB clear of the warm-store cap; rak4631 lands at 75 KB clear. - EnvironmentTelemetry: iaq rendering gates on has_iaq (a genuine IAQ of 0 now displays); stale BSEC comments rewritten. - rak4631 size budgets tightened (113000->108000 RAM, 786000->746000 flash) to lock in the reclaimed headroom. - bin/bme680_iaq_replay.cpp: host-side replay harness for tuning the estimator against captured BSEC traces (mean abs error + band agreement), no reflashing needed. Measured (develop -> this branch): rak4631 -38.8 KB flash / -4.9 KB RAM; heltec-v3 -36.4 KB / -4.0 KB; tlora-v2-1-1_6 +1.3 KB (its IAQ approximation had been dead code since #9663 due to an inverted isfinite check and now actually runs). Note: gas_resistance stays kOhm on the wire for fleet compatibility; the proto comment claiming MOhm gets a separate meshtastic/protobufs docs PR. * Address CodeRabbit review feedback - Use Throttle::isWithinTimespanMs for all elapsed-time predicates in BME680Sensor per coding guidelines (deadline math for the async reading completion stays raw, as it targets an absolute timestamp) - Make the state file name members static constexpr - Replay tool: cast uint16_t before %u (default argument promotion), report malformed input lines instead of silently skipping, and fail non-zero on stream read errors * Address CodeRabbit nitpicks - Replace the local clampf helper with std::clamp (meshUtils.h's clamp drags in Arduino.h, which would break the estimator's standalone host build that the replay harness depends on) - Trim the replay tool's file header to a two-line summary; the full build, capture, and tuning workflow moves to docs/bme680_iaq_replay.md
55 lines
1.8 KiB
Markdown
55 lines
1.8 KiB
Markdown
# BME680 IAQ replay harness
|
|
|
|
`bin/bme680_iaq_replay.cpp` replays a captured sensor trace through the in-tree
|
|
`BME680IaqEstimator` on a dev machine, for tuning the estimator's constants
|
|
against recorded Bosch BSEC output. The estimator is pure math with no platform
|
|
dependencies, so a trace replays in milliseconds - edit the constants in
|
|
`src/modules/Telemetry/Sensor/BME680IaqEstimator.h`, recompile, rerun.
|
|
|
|
## Build
|
|
|
|
From the repo root:
|
|
|
|
```bash
|
|
c++ -std=c++17 -O2 -I src -o /tmp/iaq_replay \
|
|
bin/bme680_iaq_replay.cpp src/modules/Telemetry/Sensor/BME680IaqEstimator.cpp
|
|
```
|
|
|
|
## Input
|
|
|
|
CSV on stdin or as a file argument, one sample per line:
|
|
|
|
```text
|
|
gas_ohms,relative_humidity[,bsec_iaq]
|
|
```
|
|
|
|
Lines starting with `#` are ignored; a single non-numeric header row is
|
|
tolerated; any other malformed line is reported on stderr and skipped.
|
|
|
|
## Capturing a trace
|
|
|
|
On a firmware build that still links BSEC (any release tag before the BSEC
|
|
removal), add one log line to `BME680Sensor::getMetrics` in the BSEC branch:
|
|
|
|
```cpp
|
|
LOG_INFO("IAQCSV,%.0f,%.2f,%.0f", bme680.getData(BSEC_OUTPUT_RAW_GAS).signal,
|
|
bme680.getData(BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_HUMIDITY).signal,
|
|
bme680.getData(BSEC_OUTPUT_IAQ).signal);
|
|
```
|
|
|
|
then extract the columns from the serial log:
|
|
|
|
```bash
|
|
grep -o 'IAQCSV,.*' serial.log | cut -d, -f2- > trace.csv
|
|
```
|
|
|
|
BSEC's `RAW_GAS` and heat-compensated humidity are exactly the estimator's
|
|
inputs, so one physical sensor feeds both algorithms identically.
|
|
|
|
## Output
|
|
|
|
Per-sample CSV `n,gas_ohms,rh,est_iaq,bsec_iaq` on stdout (empty `est_iaq`
|
|
during the estimator's warm-up/burn-in window), plus a stderr summary with the
|
|
mean absolute error and UI-band agreement against the `bsec_iaq` column, using
|
|
the same 0-500 band thresholds the device screen applies.
|