06 · YAML cookbook
This chapter is a complete set of working YAML configurations for the rbAmp ESPHome component. Every example is self-contained: copy it, fill in your board name and Wi-Fi credentials, compile, flash. Where an example deviates from the minimal template, the deviation is explained.
Cross-references:
- Component schema:
09_api_reference.md - Period metering protocol: SPEC.md §7
- Multi-module topology: SPEC.md §8
- Broadcast LATCH: SPEC.md §9
- NACK loose-sanity rule: SPEC.md §B.5
1 · UI1 — single channel (minimal)
Source: example/ui1.yaml
The simplest useful configuration: one voltage channel, one current channel, six derived quantities. Use this as the starting point for any new deployment and add fields as needed.
esphome:
name: rbamp-ui1
esp32:
board: esp32dev
framework:
type: arduino
logger:
level: DEBUG
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
ap:
ssid: "rbAmp UI1 Fallback"
password: !secret ap_password
captive_portal:
api:
ota:
- platform: esphome
i2c:
sda: GPIO21
scl: GPIO22
frequency: 50kHz # 100 kHz causes periodic NACKs from the module;
# 50 kHz reduces them by ~5-10x (see SPEC §B.5).
scan: true
external_components:
- source:
type: local
path: ../components
components: [rbamp]
rbamp:
id: meter1
address: 0x50
update_interval: 60s
ct_model: SCT_013_030 # CT clamp model — change to match yours
sensor:
- platform: rbamp
rbamp_id: meter1
voltage:
name: "Mains Voltage"
current:
name: "Mains Current"
power:
name: "Mains Power"
energy:
name: "Mains Energy"
frequency:
name: "Mains Frequency"
power_factor:
name: "Mains Power Factor"What this demonstrates: a minimum viable configuration. Six sensors cover the basic case — whole-house metering or a single load. The energy sensor already has device_class: energy + state_class: total_increasing set, so it lands in the HA Energy dashboard out of the box without extra configuration. For details on the period-metering protocol, see SPEC §7.
1.1 · UI1 with customization — all standard ESPHome knobs
rbAmp is a "good citizen" of ESPHome. Every slot (voltage, current, power, ...) is a regular ESPHome sensor: object. The full standard set of properties and filters works on it. No lambda:, no custom templates — everything you do with pzemac / atm90e32 / cse7766 works here in exactly the same way. The example below shows the most common customizations in a single block:
esphome:
name: rbamp-ui1-tuned
esp32:
board: esp32dev
framework:
type: arduino
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
api:
ota:
- platform: esphome
i2c:
sda: GPIO21
scl: GPIO22
frequency: 50kHz
scan: true
external_components:
- source:
type: local
path: ../components
components: [rbamp]
rbamp:
id: meter1
address: 0x50
update_interval: 10s # ↑ Poll once per 10 s instead of the default 60 s —
# denser graph, ~6x I²C traffic.
ct_model: SCT_013_030
sensor:
- platform: rbamp
rbamp_id: meter1
# ──────────── Customizing names + precision + filters ────────────
voltage:
name: "Mains Voltage" # Any name — becomes the HA entity_id
accuracy_decimals: 1 # 226.7 instead of the default 226.70
filters:
# Linear calibration against a reference multimeter:
- calibrate_linear:
- 0.0 -> 0.0
- 230.0 -> 230.5
# Smoothing of sharp spikes (standard ESPHome):
- exponential_moving_average:
alpha: 0.3
send_every: 1
current:
name: "Load Current"
accuracy_decimals: 3 # 0.755 instead of 0.75
filters:
# Mask noise floor — drop values below 50 mA (50 mW at 230 V).
# Equivalent of the `noise_floor` option in pzemac / cse7766.
- lambda: 'return x < 0.05 ? 0.0f : x;'
power:
name: "Power"
accuracy_decimals: 1
filters:
# Throttle publishes: at most once per 30 s, even if update_interval is 10 s.
- throttle: 30s
energy:
name: "Energy (Wh)"
# The standard device_class: energy + state_class: total_increasing
# are already set by the component — the Energy dashboard works.
filters:
# Convert Wh → kWh for a more familiar scale in Lovelace.
# (The HA Energy dashboard itself expects Wh, but if you want a kWh
# graph — declare a second template sensor with division rather
# than changing units here.)
- multiply: 0.001
unit_of_measurement: "kWh" # ← overrides the default "Wh"
accuracy_decimals: 3
frequency:
name: "Mains Frequency"
accuracy_decimals: 2
power_factor:
name: "Power Factor"
accuracy_decimals: 3
# Optional: filter to hide PF at zero load (P ~ 0)
filters:
- lambda: 'return isnan(x) ? 0.0f : x;'What this demonstrates:
- Custom names (
name:) become HAentity_ids —sensor.rbamp_ui1_tuned_mains_voltage. Names in any language, including Cyrillic, work. - Output precision (
accuracy_decimals:) — independent of the module; the module returns float32 at maximum precision and ESPHome truncates for the UI. update_interval:does not need to be changed per sensor — it is a property of the component (PollingComponent), set once in therbamp:block. If you want rare publishes from individual sensors, addfilters: - throttle: <interval>.filters:— the full ESPHome set:calibrate_linear— point calibration against your reference (multimeter, reference ammeter).exponential_moving_average/sliding_window_moving_average— smoothing.lambda— arbitrary transformation (noise-floor mask, conditional zero).multiply/offset— arithmetic (for example, Wh → kWh).throttle/delta— reducing publish frequency.unit_of_measurement:can be overridden (for example, tokWhwithmultiply: 0.001). HA picks up the new unit automatically.- No
lambda:for basic operation — all RMS, power, frequency, and PF computations are done by the module. The ESP32 only renames, formats, and filters.
⚠ Do not override
device_class:forenergy— the HA Energy dashboard strictly expectsdevice_class: energy+state_class: total_increasing. Unit conversion viamultiply+unit_of_measurement:preserves compatibility, but changingdevice_classwill break the dashboard.
The full list of standard sensor properties and filters is in the official ESPHome Sensor Component documentation. That documentation applies in full to rbAmp slots — no deviations from the standard.
2 · UI3 — three channels with mixed clamps
Source: example/ui3.yaml
The UI3 SKU has one voltage input and three independent current channels. The canonical scenario is to use different clamp models on different channels: a small clamp for low-current loads (for maximum resolution), and a large one on the main feed (for headroom on peaks).
esphome:
name: rbamp-ui3
esp32:
board: esp32dev
framework:
type: arduino
logger:
level: DEBUG
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
api:
ota:
- platform: esphome
i2c:
sda: GPIO21
scl: GPIO22
frequency: 50kHz
scan: true
external_components:
- source:
type: local
path: ../components
components: [rbamp]
rbamp:
id: meter1
address: 0x50
update_interval: 60s
# drdy_pin: GPIO15
ct_models: [SCT_013_005, SCT_013_030, SCT_013_100]
# CH0=5A for standby loads and LED lighting,
# CH1=30A for the main household loads,
# CH2=100A for the main feed or EV charging
sensor:
- platform: rbamp
rbamp_id: meter1
# Shared (topology-independent)
voltage:
name: "Mains Voltage"
frequency:
name: "Mains Frequency"
apparent_power:
name: "CH0 Apparent Power"
# Channel 0 — primary current input (small loads, 5A)
current:
name: "CH0 Current"
power:
name: "CH0 Power"
energy:
name: "CH0 Energy"
power_factor:
name: "CH0 Power Factor"
reactive_power:
name: "CH0 Reactive Power"
# Channel 1 — main loads (30A)
current_1:
name: "CH1 Current"
power_1:
name: "CH1 Power"
energy_1:
name: "CH1 Energy"
power_factor_1:
name: "CH1 Power Factor"
reactive_power_1:
name: "CH1 Reactive Power"
# Channel 2 — main feed / EV (100A)
current_2:
name: "CH2 Current"
power_2:
name: "CH2 Power"
energy_2:
name: "CH2 Energy"
power_factor_2:
name: "CH2 Power Factor"
reactive_power_2:
name: "CH2 Reactive Power"What this demonstrates: all three UI3 SKU channels plus mixed clamp models via ct_models:. The schema validator checks that power_N requires current_N and voltage — if you declare power_1 without current_1, compilation fails with a clear message. Each channel has its own independent NVS-persisted energy_* accumulator. If all channels use the same clamp model, use the global ct_model: instead of ct_models:.
3 · Multi-module bus (three rbAmp on 0x50 / 0x51 / 0x52)
Source: example/multi_module.yaml
Three modules on a single I²C bus — the house main feed, the solar generation output, the EV charger. Each gets its own rbamp: block (the component schema sets MULTI_CONF = True).
esphome:
name: rbamp-multi
esp32:
board: esp32dev
framework:
type: arduino
logger:
level: INFO
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
api:
ota:
- platform: esphome
i2c:
sda: GPIO21
scl: GPIO22
frequency: 50kHz # mandatory: at 100 kHz with three modules, periodic
# NACKs are almost inevitable in every cycle
scan: true
external_components:
- source:
type: local
path: ../components
components: [rbamp]
# Three independent rbamp: blocks — MULTI_CONF = True in the schema.
# broadcast_latch: true is declared here for forward compatibility: on
# current firmware the component logs a warning at load (the broadcast
# address is disabled) and falls back to sequential latch for each
# module. The warning will disappear automatically once firmware adds
# broadcast support — the YAML will not need to change. See SPEC §9.
rbamp:
- id: meter_house
address: 0x50
update_interval: 60s
broadcast_latch: true
- id: meter_solar
address: 0x51
update_interval: 60s
broadcast_latch: true
bidirectional: true # STANDARD / PRO tiers; energy_exported_*
# publishes 0 until the export accumulator
# appears in firmware
- id: meter_evcharger
address: 0x52
update_interval: 60s
broadcast_latch: true
sensor:
- platform: rbamp
rbamp_id: meter_house
voltage:
name: "House Voltage"
current:
name: "House Current"
power:
name: "House Power"
energy:
name: "House Energy"
frequency:
name: "Mains Frequency"
- platform: rbamp
rbamp_id: meter_solar
voltage:
name: "Solar Voltage"
internal: true # hidden from HA — same mains as House Voltage
current:
name: "Solar Current"
power:
name: "Solar Power"
energy:
name: "Solar Energy"
energy_exported:
name: "Solar Energy Exported"
- platform: rbamp
rbamp_id: meter_evcharger
voltage:
name: "EV Charger Voltage"
internal: true
current:
name: "EV Charger Current"
power:
name: "EV Charger Power"
energy:
name: "EV Charger Energy"What this demonstrates: the MULTI_CONF = True pattern — declare as many rbamp: blocks as you have modules on the bus. Each maintains its own NVS accumulator, the key of which is derived from the I²C address, so the three counters remain independent across reboots. The internal: true flag on duplicate voltage sensors hides three nearly identical mains-voltage entities from HA when all modules measure the same phase. For the address provisioning procedure, see Example 4 below.
Semantics of
internal: true. The flag does not disable reading the register from the module — the component still reads voltage from every module everyupdate_interval(this is required to compute power). The flag only hides the sensor from the Home Assistant API: the entity is not created, does not appear in Lovelace, and is not counted in the Energy dashboard. If you want to reduce I²C traffic, do not declare thevoltage:slot undersensor.platform: rbampat all — the component then stops requesting the register. Once declared, theinternal:flag is cosmetic only.
The second constraint concerns address uniqueness on the bus:
⚠ Unique addresses are the configuration's responsibility. The component schema (
MULTI_CONF = True) does not validateaddress:collisions acrossrbamp:blocks. If two blocks specify the sameaddress: 0x50, both declarations are accepted, and on the bus both targets will respond simultaneously — expect I²C conflicts, garbled responses, or symptoms resembling a missing module. Before committing YAML, verify that alladdress:values are unique (and do not clash with other I²C devices on the bus). After everynew_address:provisioning, update therbamp:block to the new address — the old entry is not invalidated automatically.
Pull-ups on a multi-module bus
All three modules ship from the factory with 4.7 kΩ pull-ups. On a three-module bus the parallel combination drops to ~1.6 kΩ — increased current draw and marginal signal integrity at 50 kHz. Cut the pull-up solder jumpers on modules #2 and #3 (leave only #1, or install a single external 4.7 kΩ pair near the ESP32). For details, see Wiring, the multi-module bus section.
4 · One-time I²C address change (0x50 → 0x51)
Source: example/address_change.yaml
All rbAmp modules ship from the factory at address 0x50. To put several modules on the same bus, each must be reflashed to its own unique address before they are connected in parallel.
esphome:
name: rbamp-addr-change
esp32:
board: esp32dev
framework:
type: arduino
logger:
level: DEBUG # DEBUG shows the address-change log lines
api:
ota:
- platform: esphome
i2c:
sda: GPIO21
scl: GPIO22
frequency: 50kHz
scan: true
external_components:
- source:
type: local
path: ../components
components: [rbamp]
rbamp:
id: meter1
address: 0x50 # current address — before the change
new_address: 0x51 # one-shot target — REMOVE this line after success
sensor:
- platform: rbamp
rbamp_id: meter1
voltage:
name: "rbAmp Voltage (post-relocate)"
current:
name: "rbAmp Current (post-relocate)"What this demonstrates: the one-shot address-change flow. Flashing this YAML makes the component run the following procedure once at boot:
- Probe
0x50. If0x50is silent and0x51is already responding — the change was applied in a previous boot, the component adapts and logs a warning asking you to clean up the YAML. - Verify the module is ready to accept a provisioning operation.
- Write the new address to flash (~700 ms), perform a soft reset (~300 ms), re-lock onto the AC cycle.
- Confirm on the new address. On success — log lines
Address change confirmed at 0x51andIMPORTANT: update YAML to address: 0x51 and remove new_address:.
Requirement: the module must be in factory-provisioning mode — a mode for one-shot provisioning operations. Standard production modules ship with provisioning mode disabled; to change the address in the field, consult the module documentation or supplier for the procedure to enable it temporarily.
After success: edit the YAML to address: 0x51 and remove the new_address: 0x51 line. Flash again. From the next boot, the component will use 0x51 normally and the change procedure will not run again.
Revert checklist after successful provisioning
To avoid leaving a "dangling" provisioning variant in the repository:
# BEFORE (provisioning):
rbamp:
id: meter1
address: 0x50 # current module address
new_address: 0x51 # provisioning target
update_interval: 60s
# AFTER (production — applied next flash):
rbamp:
id: meter1
address: 0x51 # ← replaced with the new address
# new_address: 0x51 # ← REMOVE the line (do not comment it out)
update_interval: 60sExactly three edits:
- Change the value of
address:from the old to the new one. - Remove (do not comment out) the
new_address:line. - Reflash via OTA or USB.
After step 3, the log should show a normal dump_config line without the warning address change requested but current address matches new_address — that means the revert went through correctly. See also 10_troubleshooting §4 "OTA right after new_address: provisioning does not load" if the first OTA after the revert refuses to start.
5 · Bench configuration with secrets
Source: example/bench-ui1.yaml
The bench-*.yaml pattern is for development machines where Wi-Fi credentials need to be present in the config but must not be committed. example/.gitignore excludes bench-*.yaml and secrets.yaml from version control.
esphome:
name: rbamp-ui1
esp32:
board: esp32dev
framework:
type: arduino
logger:
level: DEBUG
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
ap:
ssid: "rbAmp UI1 Fallback"
password: !secret ap_password
captive_portal:
api:
ota:
- platform: esphome
web_server:
port: 80
version: 3 # optional: local HTTP UI — handy for bench testing
i2c:
sda: GPIO21
scl: GPIO22
frequency: 50kHz
scan: true
external_components:
- source:
type: local
path: ../components
components: [rbamp]
rbamp:
id: meter1
address: 0x50
update_interval: 60s
ct_model: SCT_013_030
sensor:
- platform: rbamp
rbamp_id: meter1
voltage:
name: "Mains Voltage"
current:
name: "Mains Current"
power:
name: "Mains Power"
energy:
name: "Mains Energy"
frequency:
name: "Mains Frequency"
power_factor:
name: "Mains Power Factor"The matching secrets.yaml (in example/, not tracked):
wifi_ssid: "YourNetworkName"
wifi_password: "YourPassword"
ap_password: "rbamprbamp"What this demonstrates: separating compile-time credentials from version-controlled YAML using ESPHome's !secret. Listing bench-*.yaml in .gitignore lets you keep as many bench variants as you want without risking leaks. Use esphome run --device 192.168.0.173 example/bench-ui1.yaml for OTA after the first network attach, or esphome run --device COM6 example/bench-ui1.yaml for the initial USB flash.
6 · Brownout and loss of mains
When mains power is cut, the module's isolated analog front-end stops receiving signal. The voltage register drops to 0.0 V — a valid IEEE 754 finite float that passes the component's isfinite() sanity filter. From SPEC §B.5:
NO physical lower bounds — brownout (U=0 V on mains disconnect), voltage sag, off-grid / UPS test, and breaker-trip MUST pass through to HA so the user can see the real state.
No special YAML is required to detect a mains loss — the voltage sensor itself will read 0.0 V.
sensor:
- platform: rbamp
rbamp_id: meter1
voltage:
name: "Mains Voltage" # reads 0.0 V when mains is disconnected
current:
name: "Mains Current"
power:
name: "Mains Power"
energy:
name: "Mains Energy"HA automation: mains loss alert
# configuration.yaml or Automations UI
automation:
- alias: "rbAmp mains loss alert"
trigger:
- platform: numeric_state
entity_id: sensor.rbamp_ui1_mains_voltage
below: 10 # U < 10 V = mains disconnected or severe brownout
for:
seconds: 5 # debounce: sustained, not transient
action:
- service: notify.mobile_app_your_phone
data:
title: "Mains power lost"
message: >
Voltage dropped to {{ states('sensor.rbamp_ui1_mains_voltage') }} V
at {{ now().strftime('%H:%M:%S') }}.What this demonstrates: using the 0 V passthrough behavior (SPEC §B.5) as a "mains loss" event source. Because the component publishes 0.0 V instead of suppressing the publish, HA automations and the Energy dashboard see the brownout event in real time. The for: 5 seconds condition blocks false positives during the ~250 ms boot warm-up (when registers read 0 before the first valid measurement).
7 · HA Energy dashboard
The energy sensor (and energy_1, energy_2, energy_exported, etc.) is automatically configured with device_class: energy and state_class: total_increasing — exactly what the HA Energy dashboard expects for cumulative consumption sensors. No extra YAML is needed.
After discovery:
- Settings → Dashboards → Energy.
- Add Consumption → pick "Mains Energy" (or the entity tracking your import).
- If you have solar — Add Production → pick Solar Energy (from
meter_solarin the multi-module example).
Energy values are in Wh. HA converts to kWh for display itself. The component's NVS persistence guarantees that the accumulator survives ESP32 reboots without a spurious "counter reset" in HA statistics.
# Example: consumption + solar export for the HA Energy dashboard
sensor:
- platform: rbamp
rbamp_id: meter_house
energy:
name: "House Grid Import" # → HA Energy: grid consumption
- platform: rbamp
rbamp_id: meter_solar
energy:
name: "Solar Production" # → HA Energy: solar production
energy_exported:
name: "Solar Grid Export" # → HA Energy: return to grid
# reads 0 until the export accumulator
# in STANDARD/PRO firmware ships8 · HA automations on rbAmp sensors
Load shedding: relay opens when threshold is exceeded
automation:
- alias: "Load shedding — drop non-critical loads at 3 kW"
trigger:
- platform: numeric_state
entity_id: sensor.rbamp_multi_house_power
above: 3000 # 3 kW threshold
for:
seconds: 10
action:
- service: switch.turn_off
target:
entity_id: switch.ev_charger_relay # non-critical load relay
- alias: "Load shedding — restore when below 2 kW"
trigger:
- platform: numeric_state
entity_id: sensor.rbamp_multi_house_power
below: 2000
for:
seconds: 30
action:
- service: switch.turn_on
target:
entity_id: switch.ev_charger_relayPower-factor correction reminder
automation:
- alias: "Poor power factor notification"
trigger:
- platform: numeric_state
entity_id: sensor.rbamp_ui1_mains_power_factor
below: 0.7
for:
minutes: 5
action:
- service: persistent_notification.create
data:
title: "Low power factor"
message: >
Power factor is {{ states('sensor.rbamp_ui1_mains_power_factor') }}.
Check for large inductive loads (motors, old lighting ballasts).Daily budget exceeded alert
automation:
- alias: "Daily energy budget — warning at 10 kWh"
trigger:
- platform: template
value_template: >
{{ states('sensor.energy_daily') | float(0) > 10000 }}
action:
- service: notify.mobile_app_your_phone
data:
message: "Daily energy usage exceeded 10 kWh."9 · Lovelace cards
Gauge — live power
type: gauge
entity: sensor.rbamp_ui1_mains_power
min: 0
max: 3600
name: "Live Power"
segments:
- from: 0
color: green
- from: 1500
color: orange
- from: 2500
color: redApex Charts — power over time
type: custom:apexcharts-card
header:
title: "Power (W)"
show: true
graph_span: 4h
series:
- entity: sensor.rbamp_ui1_mains_power
name: Power
stroke_width: 2
curve: smoothApex Charts — energy comparison across three channels
type: custom:apexcharts-card
header:
title: "Channel Energy (Wh)"
show: true
graph_span: 24h
series:
- entity: sensor.rbamp_ui3_ch0_energy
name: CH0
- entity: sensor.rbamp_ui3_ch1_energy
name: CH1
- entity: sensor.rbamp_ui3_ch2_energy
name: CH2Mini graph — voltage
type: custom:mini-graph-card
entities:
- sensor.rbamp_ui1_mains_voltage
name: "Mains Voltage"
hours_to_show: 12
points_per_hour: 4
line_width: 210 · Utility meter — aggregation by day / week / month
ESPHome publishes cumulative totals in Wh. The HA utility_meter integration resets the counter at configurable intervals and publishes the delta as a separate sensor — useful for daily or monthly billing cuts.
# configuration.yaml
utility_meter:
energy_daily:
source: sensor.rbamp_ui1_mains_energy
cycle: daily
name: "Daily Energy"
energy_monthly:
source: sensor.rbamp_ui1_mains_energy
cycle: monthly
name: "Monthly Energy"
energy_weekly:
source: sensor.rbamp_ui1_mains_energy
cycle: weekly
name: "Weekly Energy"HA creates three entities: sensor.energy_daily, sensor.energy_monthly, sensor.energy_weekly. Each resets to 0 at the start of the corresponding period and accumulates the delta from the source total_increasing sensor.
Derived kWh/day sensor
utility_meter outputs Wh by default. To display in kWh, add a template sensor:
template:
- sensor:
- name: "Daily Energy kWh"
unit_of_measurement: "kWh"
state_class: total_increasing
device_class: energy
state: >
{{ (states('sensor.energy_daily') | float(0) / 1000) | round(3) }}Daily cost sensor
template:
- sensor:
- name: "Daily Energy Cost"
unit_of_measurement: "EUR"
icon: mdi:currency-eur
state: >
{% set kwh = states('sensor.energy_daily') | float(0) / 1000 %}
{% set rate = 0.28 %} # EUR/kWh — set your own tariff
{{ (kwh * rate) | round(2) }}11 · Per-load sub-metering (3 modules on 0x50 / 0x51 / 0x52)
Installing three rbAmp modules in a distribution panel enables per-circuit energy metering without a smart panel or extra hardware.
# Extending the multi-module example with per-circuit utility meters
utility_meter:
kitchen_daily:
source: sensor.rbamp_multi_house_energy
cycle: daily
name: "Kitchen Circuit Daily"
solar_monthly:
source: sensor.rbamp_multi_solar_energy
cycle: monthly
name: "Solar Production Monthly"
ev_daily:
source: sensor.rbamp_multi_ev_charger_energy
cycle: daily
name: "EV Charging Daily"Combined with the HA Energy dashboard, you get per-circuit monthly statements without extra kWh × tariff calculations.
12 · rbAmp + relay — closed-loop control
Water heater with relay control
# ESPHome YAML on the same ESP32 as rbAmp
switch:
- platform: gpio
pin: GPIO5
id: heater_relay
name: "Water Heater"With rbAmp and the relay on the same ESP32, you can build a closed loop directly in ESPHome (through Lambda or on_value) without round-tripping through HA:
sensor:
- platform: rbamp
rbamp_id: meter1
power:
name: "House Power"
on_value:
then:
- if:
condition:
lambda: 'return x > 3000.0f;'
then:
- switch.turn_off: heater_relay
else:
- switch.turn_on: heater_relayWhat this demonstrates: using the rbAmp sensor's on_value callback to drive a relay without HA involvement. The callback fires on the ESP32 every update_interval (60 s) and updates the relay state from the latest power reading. For tighter control (< 60 s loop), drop update_interval to 10s — this proportionally increases I²C bus load. A more complete closed-loop example for a water heater is in DIY Integrations.
13 · DRDY integration
The module's open-drain DRDY pin produces a ~10 µs LOW pulse every ~200 ms after the instantaneous registers update. You can wire it to an ESP32 GPIO and use it as an interrupt hint instead of polling on a fixed timer.
rbamp:
id: meter1
address: 0x50
update_interval: 60s # energy integration still runs every 60 s
drdy_pin:
number: GPIO15
mode:
input: true
pullup: true # DRDY is open-drain; a pull-up is required
inverted: true # DRDY pulses LOW; inverted=true yields a rising edgeNote: in current firmware the component logs
drdy_pinindump_configbut does not yet implement interrupt-driven RT reads —update_intervalstill drives the poll rate. The pin can be wired up now in anticipation of future firmware revisions without code changes.
14 · Preparing for future split-phase / three-phase SKUs
The component schema already accepts phased sensor fields (voltage_a/b/c, current_a/b/c, power_a/b/c, energy_a/b/c, power_factor_a/b/c, reactive_power_a/b/c, power_total). They are reserved for the upcoming rbAmp-U2I2 (split-phase US) and rbAmp-U3I3 (three-phase Europe) SKUs.
If you are preparing YAML for a future three-phase deployment today, you can describe the full phased block and validate it now. On current firmware it compiles cleanly (there are just no real registers to read). The schema validator checks that single and phased groups are not mixed in the same sensor: block.
# Forward-compat three-phase config — compiles today, sensor data will
# become available when rbAmp-U3I3 firmware ships. DO NOT USE on
# current single-channel UI* SKUs — readings will be 0.
sensor:
- platform: rbamp
rbamp_id: meter1
voltage_a:
name: "Phase A Voltage"
voltage_b:
name: "Phase B Voltage"
voltage_c:
name: "Phase C Voltage"
current_a:
name: "Phase A Current"
current_b:
name: "Phase B Current"
current_c:
name: "Phase C Current"
power_a:
name: "Phase A Power"
power_b:
name: "Phase B Power"
power_c:
name: "Phase C Power"
power_total:
name: "Total Power"
energy_a:
name: "Phase A Energy"
energy_b:
name: "Phase B Energy"
energy_c:
name: "Phase C Energy"
frequency:
name: "Grid Frequency"What this demonstrates: the phased field group. Mixing single and phased fields in the same sensor: block produces a compile-time error — pick the group that matches your hardware SKU. The topology definition is in SPEC §8.
15 · Migrating from other ESPHome metering components
From pzem004t
The pzem004t platform exports the same field names as rbamp for the common AC quantities. The replacement is block-level with identical sensor names:
# Before (pzem004t, UART)
uart:
rx_pin: GPIO16
tx_pin: GPIO17
baud_rate: 9600
sensor:
- platform: pzem004t
voltage:
name: "Mains Voltage"
current:
name: "Mains Current"
power:
name: "Mains Power"
energy:
name: "Mains Energy"
frequency:
name: "Mains Frequency"
power_factor:
name: "Mains Power Factor"
# After (rbamp, I²C) — same sensor names → same entity IDs in HA
i2c:
sda: GPIO21
scl: GPIO22
frequency: 50kHz
rbamp:
id: meter1
address: 0x50
ct_model: SCT_013_030
sensor:
- platform: rbamp
rbamp_id: meter1
voltage:
name: "Mains Voltage"
current:
name: "Mains Current"
power:
name: "Mains Power"
energy:
name: "Mains Energy"
frequency:
name: "Mains Frequency"
power_factor:
name: "Mains Power Factor"Identical name: fields yield identical entity IDs in HA. Energy dashboard history survives the swap: the total_increasing sensor picks up where it left off. Remove the uart: block if it is not shared with another component.
From cse7766 (Sonoff POW R2)
Same pattern. cse7766 provides voltage, current, power, energy, power_factor, apparent_power — all of which exist in rbamp. Replace platform: cse7766 with platform: rbamp, add rbamp_id: meter1, remove uart:, and add an i2c: and rbamp: block.
YAML validation rules summary
| Rule | Where enforced |
|---|---|
power / energy / power_factor / reactive_power require current |
Schema validator (_SINGLE_SLOT_DEPS) |
P/Q/PF/E for any channel require voltage |
Schema validator |
Single and phased groups cannot be mixed in one sensor: |
_validate_topology_consistency |
new_address ≠ address |
_validate_new_address |
address within 0x08..0x77 |
cv.i2c_address |
update_interval minimum: not enforced; practical — 10s |
cv.polling_component_schema |
ct_model: and ct_models: are mutually exclusive |
Schema validator |
Validation errors are reported at esphome compile time with a human-readable message pointing at the offending key. You do not need to flash hardware to find a configuration mistake.
Source & issues: rb-amp/rbamp-esphome · this page in the repo: docs/06_examples.md