Перейти к содержимому

Changelog

Per-release notes for the RbAmp Arduino library. Library SemVer is independent of the rbAmp protocol version — see the rbAmp protocol spec CHANGELOG_PROTOCOL.md (see API Reference) for the wire-protocol history (the protocol bumped from 1.0 to 1.1 on 2026-05-24 — additive, fully backward-compatible).


v1.5.0 — Per-channel CT models + sensor-model registry

Adds per-channel CT-model assignment for every channel (including senior-SKU channels 3+) via the channel window (field 15), and moves the CT-model list off a hand-maintained enum onto the generated registry. Firmware: v1.4.18 (fw ver 0x0A), where window field 15 is signed on silicon.

Added

  • Per-channel CT models on channels 3+setCTModel(channel, code) and configureChannels() now bind any channel 0..channels()-1. Channels 0-2 use the flat CMD_SET_CT_MODEL_CHn path; channels 3+ bind through the window (field 15), which the firmware applies immediately (NF+GAIN preset). Every window write is confirmed by a read-back; a model the module does not accept is surfaced as RB_ERR_PARAM and the channel keeps its previous model.
  • readCTModelCh() covers all channels — channels 3+ read the applied model from the window; the flat mirrors 0x51-0x53 still serve ch0-2.
  • Generated sensor-model registryRbAmpSensorModels.h (generated from libs/spec/sensor_models.yaml): RBAMP_CT_* code defines for both classes (SCT-013 + WIRED_CT 1..13), human descriptors, per-model status, and rbamp_sensor_model_lookup(). Use the RBAMP_CT_* defines to name a model.
  • 10_PerChannelModels example.

Changed

  • CT-model validation is registry-driven — the client no longer keeps a per-class accept-list (it had drifted: WIRED_CT was absent entirely, and the new clamp models 6-9 plus reserved 10-13 would have been rejected). The client now only fast-fails codes absent from the registry; acceptance is runtime truth — the module returns RB_ERR_PARAM for a code without a preset row.
  • RbAmpCTModel enum is now a frozen backward-compat alias for the seven SCT-013 codes; its values are sourced from the generated RBAMP_CT_SCT013_* defines so they cannot drift. New code (and all WIRED_CT models) uses the generated defines directly.
  • The code > 7 hard caps in setCTModel() / configureChannels() are gone — the valid range is whatever the registry defines.
  • Internal: the ch<3 / ch3+ routing for the RT metrics (I_RMS / I_PEAK / P_REAL / PF) is consolidated into a single readChannelMetric() decision point.

Fixed

  • CT model / sensor class now persist in production. setCTModel(), configureChannels() and setSensorClass() persisted via CMD_SAVE_GAINS, which is factory-gated — on a production module the save was a silent no-op, so the binding applied to RAM but was lost on the next reboot. These registers are user_config, so they now persist via CMD_SAVE_USER_CONFIG (ungated). No API change; same ~700 ms settle.

v1.4.0 — Senior SKUs (UI5 / UI7)

Adds support for the 5- and 7-channel senior SKUs (UI5, UI7). Hardware-verified on silicon (UI7 board, bench, 4/4 PASS). Cross-platform-aligned with the STM32 HAL / ESP-IDF / Python bundle.

Added

  • Senior SKU detectionbegin() now reads the channel count from REG_TOPOLOGY (0x24, values 1/2/3/5/7) and the SKU + voltage presence from REG_HW_VARIANT (0x55): UI5 and UI7 added to RbAmpVariant; Five / Seven added to RbAmpTopology.
  • Channel access windowreadCurrent() / readCurrentPeak() / readPower() / readPowerFactor() now accept ch = 0..channels()-1. Channels 0-2 use the flat block; channels 3+ are read transparently through the device's channel window (re-selected on every read). No new public read methods — the existing per-channel calls just extend.
  • readCommitSeq() — reads the digest commit sequence byte; increments once per RT commit (~20 ms), for detecting that the device advanced a sample between two reads. Change flag only (there is no CRC in the digest).
  • Period energy now covers all channels: readPeriodSnapshot() fills avg_p[] for every channel (ch3+ via the window's latched period field) and energy().wh(ch) accumulates per channel.
  • 09_SeniorSku example.

Changed

  • RBAMP_MAX_CHANNELS (=7) now sizes the per-channel arrays in RbAmpSnapshot (current / current_peak / power / power_factor), RbAmpPeriodSnapshot.avg_p, and the Wh accumulator (was hardcoded 3). Warning: Source-recompile note: the snapshot structs grew — recompile any code that includes this library against the new headers. Wire protocol and the method surface for junior SKUs are unchanged.

v1.3.0 — Fleet + v1.3 protocol

Aligns the Arduino library with the v1.3 rbAmp wire contract and the cross-platform reference (STM32 HAL / ESP-IDF / Python). Hardware-validated on a heterogeneous fleet (UI1 + I2 + I3) through the public API with raw-register ground-truth (38/38 full-coverage suite, plus an extended app-WDT soak).

Added

  • RbAmpFleet multi-module manager: bus scan() (with collision detection), batched pollAll(), fleet-wide totalPower() / totalEnergyWh() / pollErrors(), General-Call sync (enableGcAll() / gcLatch() / checkSync()), assignAddress(), checkConflict(), and provision() for bringing a factory-fresh module onto the bus.
  • Identity / capability: readVariant(), readCapability(), readProductId(), readUid().
  • Event channel: readEventFlags(), clearEventFlags(), hasError(), clearError(), readLastError().
  • Per-channel CT configuration: configureChannels() (batched, one flash save) and readCTModelCh() (applied-model mirror read).
  • Fleet primitives on the device: enableGc(), setGroupId(), readGroupId(), readGcTick(), readFleetConfig(), readLabel(), writeLabel(), saveUserConfig(), static broadcastLatchGroup().
  • 08_FleetSync example (scan -> GC sync -> aggregate).
  • RbAmpSnapshot.implausible per-field mask: a field that fails the physical sanity filter is set NaN and flagged, leaving the rest of the snapshot usable (only a transport failure fails the whole read).

Changed

  • Energy integrates over the master's wall-clock, never the module's diagnostic latch_ms (the module timer under-counts ~25-30%). On a stale period the integration anchor is held so the next valid window is not under-counted.
  • CT model codes follow the v1.3 per-class accepted set — Sct013 accepts {005, 010, 030, 050, 020}; SCT-013-100 and -060 are recognised SKUs but uncharacterised and rejected client-side. REG_CT_MODEL is pure staging: binding is via the per-channel command, so multi-channel binds are order-independent and never clobber channel 0.
  • Address change is a production-OK two-phase magic commit — no factory mode required.
  • Variant detection reads REG_HW_VARIANT; the constructor topology hint is now a fallback for pre-v1.3 firmware. The default hint is Single (safe — no spurious polls of absent channels).
  • I2C writes now share the same NACK-retry discipline as reads (a silently dropped config write on a contended bus is otherwise invisible).
  • setSensorClass() rejects out-of-enum classes client-side (the firmware silently accepts a bad class, so the client guard is the only defense).

Notes

  • AVR: double is 32-bit (== float) on the classic AVR toolchain, so the Wh accumulator loses precision on long soak logging — reset periodically or prefer a 32/64-bit-double core (ESP32, SAMD, STM32, RP2040).
  • Marginal bus / ESP32: Arduino-ESP32's Wire wraps a driver that can spin on a held bus below the library. Use proper external ~4.7 k pull-ups, avoid a debugger/NRST in production, and arm an app-level task watchdog on the polling task as the recovery path.

v1.0.0 — 2026-05-25 (initial release)

First public release of the RbAmp Arduino library. Implements the canonical API surface from the rbAmp protocol spec §12 for protocol v1.0.

Features

  • RbAmp class — one instance per slave device, public methods for every metering operation:
  • Lifecycle: begin(), probe(), waitReady(), firmwareVersion(), topology(), channels(), hasVoltageHw(), address(), rawTopology()
  • Real-time reads (200 ms refresh): readVoltage(), readVoltagePeak(), readCurrent(ch), readCurrentPeak(ch), readPower(ch), readPowerFactor(ch), readFrequency(), readAll(&snapshot)
  • Period metering: latchPeriod(), isPeriodValid(), readPeriodAvgPower(ch), readPeriodMaxPower(), readPeriodLatchMs(), readPeriodSnapshot(&snap, settle_ms, skip_latch)
  • Configuration: setCTModel(code), saveGains(), prepareAddressChange(addr), commitAddressChange(), factoryReset(), reset()
  • Multi-module: RbAmp::broadcastLatch(bus) (returns false on v1 firmware per SPEC §9 — General-Call disabled)
  • Diagnostics: lastError(), errorString(code), setLogStream(&Serial), retryExhaustionCount(), sanityRejectCount(), resetCounters()

  • RbAmpEnergy per-channel Wh accumulator — owned by each RbAmp instance, exposed via dev.energy(). Updated automatically by readPeriodSnapshot(). Signed (negative = net export). Opt-out via dev.energy().disable().

  • RbAmpSnapshot / RbAmpPeriodSnapshot POD structs — readAll() and period snapshot result containers.

  • RbAmpTopology enumSingle / SplitPhase / ThreePhase for the variant hint.

  • SPEC §B.5 retry+sanity discipline built in:

  • Per-byte retry on ESP32 targets (default 3 attempts × 5 ms gap)
  • Configurable via #define RBAMP_NACK_RETRY_ATTEMPTS / _GAP_MS before #include <RbAmp.h>
  • Loose sanity filter on float reads (!isfinite(x) || fabsf(x) > 10000)
  • Diagnostic counters (retryExhaustionCount() / sanityRejectCount())
  • Auto-disabled on non-ESP32 platforms (single attempt default)

  • v1.1 forward-readiness:

  • dev.rawTopology() reads REG_TOPOLOGY (0x24) directly. Returns 1/2/3 on v1.1 firmware, 0x00 on v1.0 (unmapped), 0xFF on I2C failure.
  • dev.setCTModel(code) automatically benefits from v1.1 firmware's preset NF + GAIN auto-load — no API change needed.

  • Two-step address-change protocol (SPEC §10) — prepareAddressChange() arms, commitAddressChange() must follow within 5 s. Library validates REG_MODE == factory and the 5 s window. Internal handle address updates automatically on successful commit.

Supported platforms

  • Arduino AVR (Uno / Mega / Nano) — 32-bit float energy accumulator
  • arduino-esp32 v3.x (ESP32 / S2 / S3 / C3) — RBAMP_NACK_RETRY_ATTEMPTS=3 default
  • arduino-esp8266 — single attempt default, no NACK pattern
  • STM32duino (F1 / F4 / G4) — single attempt default
  • SAMD / RP2040 (arduino-pico) — lightly tested, expected to work

Examples (7 bundled sketches)

  • 01_QuickRead — smoke test: U/I/P/PF per second
  • 02_PeriodEnergyOLED — 60-second Wh meter on SSD1306 OLED
  • 03_MultiModuleBroadcast — 3 modules, per-device sequential LATCH
  • 04_UI3PerChannelMQTT — UI3 + MQTT per-channel publish
  • 05_AddressChange — two-step I2C address reassignment
  • 06_BidirectionalEnergy — master-side consume / export split
  • 07_DeepSleepLogger — ESP32 deep-sleep with RTC-memory Wh

Plus ../examples/SoakMonitor (12-hour autonomous bench monitor for v1.1 firmware validation).

Documentation

11 reference documents under docs/ covering installation, hardware, tiers, sensor selection, examples, DIY + cloud integrations, API reference, troubleshooting, and changelog.

Known limitations

These are deliberate omissions from v1.0 — tracked for v1.x or v2:

  • broadcastLatch() always returns false (v1 firmware has General-Call disabled — SPEC §9). v2 firmware will enable it; this library will return true automatically once the wire transaction succeeds.
  • No explicit setNoiseFloor() / setGain() helpers — these registers fall under the calibration namespace (out of scope for v1 client libraries). For bench tuning use raw Wire writes per Sensor Selection.
  • No reactive-power read — RESERVED for v2 (STANDARD / PRO tier feature, not exposed in protocol v1).
  • No dimmer control (REG_DIM0_* 0x10..0x18 untouched). Out of scope for v1 — see future RbAmpDimmer companion library.

Wire-protocol compatibility matrix

Library v Firmware v Behaviour
1.0 1.0 Library uses constructor topology hint. Fully functional.
1.0 1.1+ Library uses constructor hint; REG_TOPOLOGY ignored. CT_MODEL preset auto-load works via existing setCTModel() call.
1.3 1.0 Library reads REG_TOPOLOGY = 0x00, falls back to constructor hint. Identical to 1.0/1.0.
1.3 1.3+ Library reads REG_TOPOLOGY as authoritative. Fleet, events, per-channel CT config, GC sync all available.
1.4 1.3+ Senior SKU detection (UI5/UI7); channel window extends per-channel reads to ch 3+.
1.5 1.4.18+ Per-channel CT models on all channels via window field 15; sensor-model registry; CT/class persist fix.

Bench validation

Phase 1 closed 2026-05-24 (root commit 4b16cbb) — reference master for the v1.0 firmware validation. Calibration baseline: NF=6, GAIN=2.1094 on the reference SCT-013-5A bench. Final acceptance #4 (100-paired-sample capture via CalibSampler @ 4 Hz):

Quantity DUT METER Ratio Spec Status
U (V) 225.30 225.24 1.0003 ±2%
I (A) 0.793 0.786 1.0090 ±2%
P (W) 111.05 114.17 0.9727 ±2% ⚠ borderline -2.7%
PF 0.620 0.643 0.964 ±2% ⚠ -3.6%

P/PF marginally outside ±2% due to SMPS load flicker (mean-of-100 converges to ~1 %; a stable resistive reference would close the gap). See the rbAmp protocol spec PHASE1_LESSONS_LEARNED (see API Reference) §2.5.

Additional 12-hour SoakMonitor validation (ard-amp-log.csv, 145 cycles): 100 % period_valid, 1 retry exhaust, 0 sanity reject.


Roadmap

v2.0.0 (planned — firmware v2)

  • Broadcast LATCH via I2C General-Call.
  • Reactive-power register exposed: readReactivePower(ch).
  • Dimmer control exposed: setDimmer(level), getDimmer().

Reporting issues + contributing

Open issues at github.com/rbamp/rbamp-arduino/issues with the diagnostic info checklist from Troubleshooting.

Pull requests welcome — the library is in pure standard-Arduino C++, no platform-specific dependencies. Run the conformance test in extras/conformance/ against a real DUT before submitting (PR template will guide).


License

MIT — see LICENSE.



Source & issues: rb-amp/rbamp-arduino · this page in the repo: docs/11_changelog.md