Zum Inhalt springen

Three-Phase Energy Monitoring in Home Assistant: 3× rbAmp UI on One ESP32

Coherent per-phase real power from three UI modules on one I²C bus — the full build
29. Juli 2026 durch
Three-Phase Energy Monitoring in Home Assistant: 3× rbAmp UI on One ESP32
Administrator

If you've read why three single-phase meters can't measure your 3-phase power, you know the trap: three independent meters sample at different instants, so their numbers don't add up. This is the build that does it right — three rbAmp UI modules on one ESP32, one per phase, each measuring its own phase's real power and all three latched on the same instant. The result lands in Home Assistant as honest per-phase data plus a coherent three-phase total that reconciles with your utility meter.

What you'll build

  • Real per-phase voltage, current, active power, energy (kWh) and power factor for L1 / L2 / L3.
  • A coherent three-phase total active power (the three phases summed on one synchronized latch).
  • Everything on one ESP32 over a single I²C bus — no second microcontroller, no round-robin ADC.
  • All of it in the Home Assistant Energy Dashboard.

Bill of materials

Item Qty Notes
rbAmp Basic Wattmeter (UI1) 3 one per phase — voltage + current + on-chip real power · product
SCT-013 current transformer 3 one per phase, rating to match each phase's service capacity · product
ESP32 dev board 1 any esp32dev-class board
Jumper wires the shared I²C bus (SDA/SCL/3V3/GND)

Each UI1 module needs its own phase voltage as well as its CT. Wire each module's voltage input to the phase it's metering (L1→module A, L2→module B, L3→module C) — that per-phase voltage pairing is exactly what makes the measurement coherent. Read the safety section below before you wire anything — the voltage taps are live-conductor connections, not clip-on clamps.

Safety first — the voltage taps are live-conductor work

⚠️ This is not a clip-on-clamp build. Unlike a non-invasive CT that clamps around an insulated wire, each module here needs a voltage tap — a galvanic connection to a live phase conductor. That is mains-voltage work and qualified-electrician territory. If you're not certain you're competent inside a live panel, stop and have an electrician make the in-panel connections.

Before you touch anything: kill the main breaker and verify the conductors are dead with a meter — never assume. Then:

  • Fuse or breaker every voltage tap. Each phase-voltage lead to a module comes off its own suitably rated fuse or protected branch — never an unfused tap straight off a busbar.
  • Use correctly rated wire and insulation for the tap leads (mains-rated conductor, adequate gauge, full insulation up to the module terminal). Keep the low-voltage I²C side (SDA / SCL / 3V3 / GND) physically clear of the mains-side wiring.
  • The CT side stays non-invasive — the SCT-013 still just clamps around its phase conductor; you never cut or strip a live wire for the current side.
  • Label every tap and CT to its phase and breaker before you close the panel.

Three-phase mains voltage is lethal. When in doubt, bring only the low-voltage module leads out of the panel and have a qualified electrician do the live connections.

Wire the bus

All three modules share one I²C bus off the ESP32:

plaintext
ESP32 GPIO21 (SDA) ─┬── UI1 phase-A  (CT on L1, voltage tap on L1)
                    ├── UI1 phase-B  (CT on L2, voltage tap on L2)
                    └── UI1 phase-C  (CT on L3, voltage tap on L3)
ESP32 GPIO22 (SCL) ─┘   + shared 3V3 and GND to all three
  • Clamp each module's CT around one phase conductor, arrow toward the load.
  • On-board pull-ups: keep them active on the first module in physical wire order and disable them on the other two — one pull-up pair per bus, never external. (See the module hardware doc.)

Give each module its own address

All modules ship at I²C address 0x50. Three on one bus need three addresses — 0x50, 0x51, 0x52. Assign the second and third once each, one module at a time with the others disconnected so there's no clash. On current firmware this is a production-mode operation — no factory mode, no extra tools:

  1. Connect only the module you're re-addressing.
  2. Flash a scratch config with address: 0x50 and new_address: 0x51 (then 0x52 for the third).
  3. Watch the ESPHome boot log confirm the change, then set address: 0x51, delete the new_address: line, and move on to the next module.

(Full mechanics: ESPHome API reference → new_address.)

The ESPHome config

Three UI1 modules at 0x50 / 0x51 / 0x52, one synchronized fleet, live per-phase data plus the coherent total. Set your CT sizes and Wi-Fi secrets, flash:

yaml
# Three-phase energy monitoring: 3× rbAmp UI1 on one ESP32, one I²C bus.
#   GPIO21 SDA ─┬─ UI1 @0x50  (phase A: V+I on L1)
#              ├─ UI1 @0x51  (phase B: V+I on L2)
#              └─ UI1 @0x52  (phase C: V+I on L3)
# Each module computes its phase's real power on-chip; fleet_gc_enable + group_id
# latch all three on one broadcast instant (<10 µs skew).
# Compile-verified: ESPHome 2026.5.3, github://rb-amp/[email protected].
esphome:
  name: rbamp-3phase
esp32:
  board: esp32dev
  framework:
    type: arduino
wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password
api:
ota:
  - platform: esphome
logger:
i2c:
  sda: GPIO21
  scl: GPIO22
  frequency: 50kHz   # ESP-IDF i2c_master driver + the module's I²C recovery window interact at
                     # 100 kHz → intermittent read NACKs on ESP32. 50 kHz is the robust setting.
                     # STM32 / RP2040 / Linux-SBC masters run this module at 100 kHz fine.
  scan: true
external_components:
  - source: github://rb-amp/[email protected]
    components: [rbamp]
# ─── Three UI1 modules in the same GC-LATCH fleet ────────────────────────────
rbamp:
  - id: phase_a
    address: 0x50
    update_interval: 10s
    latch_interval: 60s
    ct_model: SCT_013_050         # mains phase — pick to match your service capacity
    fleet_gc_enable: true
    group_id: 1
  - id: phase_b
    address: 0x51
    update_interval: 10s
    latch_interval: 60s
    ct_model: SCT_013_050
    fleet_gc_enable: true
    group_id: 1
  - id: phase_c
    address: 0x52
    update_interval: 10s
    latch_interval: 60s
    ct_model: SCT_013_050
    fleet_gc_enable: true
    group_id: 1
# ─── HA entities — per-phase real V/I/P/Wh/PF + 3-phase total ────────────────
sensor:
  # ══ Phase A (L1) ═════════════════════════════════════════════════════════
  - platform: rbamp
    rbamp_id: phase_a
    voltage:
      name: "Phase A Voltage"
    current:
      name: "Phase A Current"
    power:
      name: "Phase A Power"
      id: p_phase_a
    energy:
      name: "Phase A Energy"                  # ← per-phase kWh accumulator
    power_factor:
      name: "Phase A Power Factor"
    frequency:
      name: "Phase A Frequency"               # publish freq from phase A only
  # ══ Phase B (L2) ═════════════════════════════════════════════════════════
  - platform: rbamp
    rbamp_id: phase_b
    voltage:
      name: "Phase B Voltage"
    current:
      name: "Phase B Current"
    power:
      name: "Phase B Power"
      id: p_phase_b
    energy:
      name: "Phase B Energy"
    power_factor:
      name: "Phase B Power Factor"
  # ══ Phase C (L3) ═════════════════════════════════════════════════════════
  - platform: rbamp
    rbamp_id: phase_c
    voltage:
      name: "Phase C Voltage"
    current:
      name: "Phase C Current"
    power:
      name: "Phase C Power"
      id: p_phase_c
    energy:
      name: "Phase C Energy"
    power_factor:
      name: "Phase C Power Factor"
  # ── 3-phase total active power (Σ per-phase real P) ───────────────────────
  # All three modules latch on the same broadcast instant (fleet_gc_enable),
  # so the summed instantaneous P values are coherent. Reads happen
  # sequentially after the latch, but the frozen P values reflect the same
  # wire moment. Skew: <10 µs chip-side; negligible for any real load.
  - platform: template
    name: "Total 3-Phase Active Power"
    device_class: power
    state_class: measurement
    unit_of_measurement: W
    accuracy_decimals: 1
    update_interval: 10s
    lambda: |-
      float total = 0;
      if (id(p_phase_a).has_state()) total += id(p_phase_a).state;
      if (id(p_phase_b).has_state()) total += id(p_phase_b).state;
      if (id(p_phase_c).has_state()) total += id(p_phase_c).state;
      return total;

Two knobs worth understanding:

  • fleet_gc_enable: true + group_id: 1 put all three modules in one synchronized fleet. Once a minute the ESP32 sends a single General-Call "latch now" frame and every module freezes its period accumulator on the same instant (sub-10-µs skew) — that's what makes the three-phase total coherent instead of three independently-sampled numbers.
  • latch_interval: 60s (rbAmp ESPHome v1.4) decouples the synchronized LATCH from the live read cadence: the dashboard refreshes voltage / current / power every update_interval (10 s), while the coherent energy-latch burst runs just once a minute. kWh stays exact either way — the master integrates over real wall-clock time. Drop the line for single-cadence v1.3 behaviour.

Add it to Home Assistant

  1. Flash and let the node come up — Home Assistant auto-discovers it via the ESPHome API. You'll see the per-phase entities plus Total 3-Phase Active Power.
  2. rbamp-3phase entity list in Home Assistant — 17 sensors: per-phase voltage, current, power, energy, power factor, frequency, and total 3-phase active power

    The rbamp-3phase node in Home Assistant: all 17 entities reporting — per-phase V/I/P/Wh/PF, frequency, and the coherent total.

  3. Settings → Devices & Services → Energy. Add each phase's Energy sensor (Phase A/B/C Energy) as a grid-consumption source — the dashboard sums them for whole-home consumption.
  4. Home Assistant Energy Dashboard with three-phase per-phase energy breakdown — Phase A, B, C as individual grid consumption sources

    The HA Energy Dashboard with per-phase grid consumption: each phase is an individual source, stacked bars show the unbalance.

  5. Build a quick Lovelace view with the three per-phase powers and the total for a live per-circuit picture.
  6. Three-phase power glance card in Home Assistant — Phase A 1987 W, Phase B 3198 W, Phase C 1204 W, Total 6389 W

    A glance card showing per-phase active power and the coherent three-phase total — the imbalance is visible at a glance.

Verify it's wired right

  • The boot log's I²C scan should list all three addresses:
plaintext
[i2c] Found i2c device at address 0x50
[i2c] Found i2c device at address 0x51
[i2c] Found i2c device at address 0x52
  • Under a known single-phase load on one phase, only that phase's power should move.
  • The three per-phase powers should sum to Total 3-Phase Active Power at every update.
  • If a phase reads a suspiciously round fraction of what you expect, check that its voltage tap is on the same phase as its CT — the coherent pairing is the whole point (see the physics).

Why this is accurate

Each module measures its phase's voltage and current together and computes real active power on-chip; the synchronized latch freezes all three on one instant. That's coherent per-phase integration — the sub-1% tier, versus the 15–50% error of measuring one phase and tripling it. The full reasoning is in the companion article: why three single-phase meters can't measure your 3-phase power.

Prefer one board? A dedicated single-board three-phase module (U3I3 — one board, three phases, one address) is in development. It's on the roadmap, not shipping yet; subscribe below and we'll say when it lands. Until then, this three-module fleet is the honest-numbers path you can build today.

[newsletter / early-adopter subscribe block — deploy session inserts the site's standard subscribe snippet]


Documentation & source code
📖 rbAmp ESPHome component reference · 💻 rb-amp/rbamp-esphome on GitHub — issues, examples, ⭐
Real-Time Load Control with rbAmp — Current Limits, Alerts & Load Shedding in Home Assistant
Meter branch current, cap it, shed by priority — before the breaker trips