Passa al contenuto

← Compilation | Contents | Next: Application Structure →

1.2 Commissioning

Your modules are wired (Hardware Guide) and the firmware is flashed (Compilation). This guide binds the modules to roles and starts regulation.

A v2.0 system is a host MCU plus external smart modules — rbAmp (sensing) and DimmerLink (dimmers) — on the I2C bus. The UI is external (the device serves GET / → 302), so you drive commissioning either through the external web app pointed at the device's IP, or with the REST API directly.

Profile note. The REST commissioning flow below is available on the ESP32 and C2-HTTP builds. C2-MQTT is headless — it has no REST API; commission it over MQTT (MQTT-bootstrap, see the MQTT Guide).

Steps 1–7 are done through the web app or REST, so bring the device onto the network first — connect WiFi, then open the app at the device's IP. (Step 0 is the exception: I2C bus pins can also be set over the serial console before WiFi.)


Key Principles

  • Roles are per-channel, not per-module. A module is a device (an address); a role is attached to an (address, channel) pair. The registry (GET /api/modules) is the source of truth.
  • The grid role must be on a module that also measures voltage. Only a channel with a voltage reference produces signed power (import vs. export). A current-only (CT-only) channel cannot tell direction. You can tell which modules are voltage-capable from has_voltage: true in GET /api/modules (also in GET /api/rbamp/modules). Minimum viable config = one voltage-capable rbAmp assigned as grid.
  • role = dimmer auto-binds a DimmerLink to dimmer output id 4 — you work with roles and addresses, never raw output ids.

Step 0 — I2C Bus (only if not on default pins)

Default pins per target: ESP32 SDA 21 / SCL 22, ESP32-C2 SDA 5 / SCL 6. To change them:

plaintext
POST /api/hardware/config
{"i2c":{"bus0":{"sda":N,"scl":M}}}

This is saved to NVS and requires a reboot — the bus reads its pins at boot. After the reboot the bus can see the modules.


Step 1 — Discover (rescan)

plaintext
POST /api/modules/rescan        → 202 {"scanning":true}

The ~2.5 s scan runs in the background (a second rescan while busy → 409 {"error":"busy"}). Poll GET /api/modules until "scanning": false — the list is then fresh. Each module reports its family (rbAmp / DimmerLink / …), addr, channels, current roles[], and valid_roles[] (the only roles allowed for that family — a UI offers exactly these).


Step 2 — Assign Roles (per channel)

plaintext
POST /api/modules/role
{ "addr": "0x51", "channel": 0, "role": "grid" }
  • rolegrid | solar | load | voltage | dimmer | relay | none
  • 200 {"success":true,"message":"Role saved"} · no module → 404 · bad channel → 400
  • This is the recommended way to bind a module — the registry is the source of truth, and role = dimmer auto-binds the DimmerLink to dimmer id 4.

Start with the mandatory grid channel (on a voltage-capable rbAmp), then add solar / load as wired, and dimmer for the DimmerLink.

🔁 The first DimmerLink needs one reboot. The DimmerLink poll task is created at boot only when at least one dimmer is enabled. When you enable your first dimmer, the role persists immediately, but reboot once so the poll task starts and the dimmer begins driving the load. Subsequent dimmers and level changes apply live (no reboot).


Step 3 — Set the CT Model (per rbAmp channel)

Fetch the catalog with GET /api/rbamp/ct-models, then set the model that matches your physical CT:

plaintext
POST /api/rbamp/modules/ct-model
{ "addr": "0x51", "ct_model": "sct013-030" }        → 202 {"pending":true, …}
  • ct_model is a catalog id (e.g. sct013-030 = a 30 A clamp).
  • ⚠️ Changing the CT model overwrites the module's per-unit factory gain calibration with the model's preset gain. Set it once for the correct clamp; re-selecting the same model is a no-op.

Step 4 — Resolve Address Conflicts (re-address)

If two modules share the same default address, give each a unique one:

plaintext
POST /api/rbamp/modules/address
{ "addr": "0x51", "new_addr": "0x52" }              → 202 {"pending":true, …}

Two-phase commit; the role mapping migrates and persists. The module re-appears at the new address.


Step 5 — Name the Channels (optional)

POST /api/modules/name sets a human-readable per-channel name that shows up in GET /api/metrics (e.g. dimmers[].name) and the UI.


Step 6 — Verify Sensing

Read GET /api/sensors (per-source live V/I/P/PF/frequency + role) or GET /api/metrics (merged power_grid / power_solar / power_load).

🔴 Check the grid sign under a known load. power_grid must read + when importing and when exporting. If the sign or direction is wrong, the grid channel isn't voltage-capable, or the CT model / clamp polarity is off.


Step 7 — Start a Mode

plaintext
POST /api/mode
{ "mode": "auto" }

Modes: off · auto · eco · offgrid · manual · boost · grid_limit. For grid_limit, set the current cap: POST /api/config {"grid_current_limit": <A>} (default 16.0 A). See Router Modes for what each mode does.

Your system is now regulating — in AUTO it will raise the dimmer whenever you'd otherwise export, so the surplus heats your load instead of feeding the grid.


Not in v2.0

If you followed a v1.x commissioning guide, these steps are gone (sensing moved to smart modules):

  • ADC channel setup (adc_channels) — ignored; sensing is external.
  • Sensor-driver selection/api/hardware/sensor-profiles, /sensor-types, /voltage-drivers, /current-drivers are removed (smart modules self-calibrate).
  • Per-GPIO dimmer config (/api/dimmers/{0-3}/…) — removed; the dimmer is driven by the router mode, not per channel.

ESP-NOW nodes. Wireless measurement nodes appear with source: espnow, are keyed by MAC, and their dimmer outputs start at id 12+. Assign their roles the same way (by MAC).


← Compilation | Contents | Next: Application Structure →