metrology_insight 0.1.0

Embedded-first electrical metrology DSP library in Rust. Pre-compliance implementation of measurement algorithms derived from IEC 61000-4-30:2021 Class S and IEC 62053-21, fully no_std + alloc compatible.
Documentation
# metrology_insight — Documentation

> **Standards support (pre-compliance):** This library implements measurement algorithms derived from several IEC standards. It is intended for development, evaluation, and pre-compliance testing. It has not been certified or validated as fully compliant with the referenced standards. See [COMPLIANCE_STATUS.md]./COMPLIANCE_STATUS.md for the per-clause status.

## Files

| Document | Description |
|-----------|-------------|
| [API_REFERENCE.md]./API_REFERENCE.md | Complete reference of all modules, types, functions and constants (English) |
| [API_REFERENCE_ES.md]./API_REFERENCE_ES.md | Complete reference of all modules, types, functions and constants (Spanish) |
| [COMPLIANCE_STATUS.md]./COMPLIANCE_STATUS.md | Per-clause standards compliance status (pre-compliance) |

## Quick Start

```rust
use metrology_insight::{MetrologyInsight, MetrologyInsightConfig, SystemMode};

// Minimum setup — all other fields use IEC defaults
let mut config = MetrologyInsightConfig::default();
config.adc_samples_seconds = 8000.0;
config.adc_samples_per_cycle = 160.0;
config.avg_sec = 160.0 / 8000.0; // 1 cycle averaging

let mut insight = MetrologyInsight::new(config);
// Optional: syncs nominal_voltage across event_config + flicker simultaneously
insight.set_nominal_voltage(230.0);

let active = SystemMode::ThreePhase4Wire.active_phases(); // 4

// Deposit ADC samples into socket.phases[i].{voltage,current}
insight.process_and_update_metrics(active);

let v_rms  = insight.socket.phases[0].voltage.rms;
let freq   = insight.socket.phases[0].voltage.pll_state.freq_10s; // 10s avg EN 61000-4-30
let p_kw   = insight.socket.power_metrics_total.real_power / 1000.0;
let u2_pct = insight.socket.unbalance_metrics.u2_neg_ratio_pct;   // Negative unbalance
```

## Integration Strategy for Embedded Systems

> **`no_std` + `alloc` contract**: `no_std` builds require a target with an
> `alloc` allocator (ARM Cortex-M, ESP32/Xtensa, RISC-V with a heap). The core
> heap-allocates via `Box` on initialization; allocator-less targets are not
> supported. The `alloc` feature only adds optional test/simulation helpers.

To avoid data loss (missed ADC samples) during intensive mathematical processing (FFT, THD, RMS), an asynchronous or multi-core architecture is recommended:

1. **Acquisition (Core 0 or High Priority Task)**:
   - Use asynchronous polling or interrupts for the ADC `DRDY` pin.
   - Read SPI data and accumulate into a buffer (e.g., 160 samples at 50 Hz / 8 kSPS).
   - Send the full buffer via an inter-thread channel without blocking acquisition.

2. **DSP Processing (Core 1 or Medium Priority Task)**:
   - Receive buffers from the channel and transfer them to `insight.socket.phases[i]`.
   - Call `insight.process_and_update_metrics()`.
   - Publish metrics (MQTT, REST). Decoupling acquisition from DSP guarantees sample continuity.

## Standards Compliance

Pre-compliance status — not certified. See [COMPLIANCE_STATUS.md](./COMPLIANCE_STATUS.md) for the per-clause breakdown.

| Standard | Status | Application |
|----------|--------|-----------|
| IEC 61000-4-30:2021 Class S | Partial implementation | Quality flags, synchronous resampling, 10-cycle RMS, 10 s frequency, Fortescue unbalance, Dips/Swells/RVC |
| IEC 62053-21 (2nd Ed.) | Algorithm / pre-compliance | Static meters for AC active energy (Classes 1/2 limits), 4-Quadrant energy metering — simulation only |
| IEC 61000-4-15 | Algorithm implementation | Flickermeter Blocks 1–4 ($P_{\text{inst}}$ realtime; $P_{\text{st}}$ / $P_{\text{lt}}$ library helpers) — incorporated by reference via IEC 61000-4-30 §5.3 |
| IEC 62053-23 | Algorithm implementation | Static meters for AC reactive energy (Q1–Q4 quadrant decomposition) |
| EN 50160 | Partial implementation | Quality events: Dip, Swell, Interruption, RVC threshold limits |

## Runtime Configuration

After building `MetrologyInsight::new(config)`, all configuration values can be
hot-modified and propagated to sub-components:

```rust
// Change nominal voltage (syncs event_config + flicker automatically)
insight.set_nominal_voltage(120.0); // American market

// Modify any parameter and propagate manually
insight.config.pll.kp = 0.003;
insight.config.flicker.rms_tc_seconds = 30.0;
insight.apply_config(); // Propagates to FlickerMeter and other sub-components
```

## Changelog

| Commit | Change |
|--------|--------|
| `6b603ef` | 10 s frequency integration (IEC 61000-4-30 §5.1), fixed initial flicker transient, Fortescue unbalance protection with PLL lock |
| `fcbdd00` | Critical fix capacitive/inductive detection: rising zero-crossing + signed angle (φ = θI − θV). Unit test added. |
| `2f481c2` | Full refactor: 27 named constants, new structs `FlickerConfig`, `PhaseConfig`, `SignalConfig`; extended `PllConfig` and `RvcConfig`; `apply_config()` and `set_nominal_voltage()` methods |
| `77165df` | `GridFrequency` propagation → `nominal_freq` + PLL bounds from firmware `Measurements::apply_config()` |