# GoodWe RS485 Controller Drives a GoodWe ES/BP battery inverter over its RS485 meter bus: holds net grid exchange at zero, and runs a monthly battery maintenance cycle so the BMS can balance cells and recalibrate its coulomb counter. Installers: read `FIELD-GUIDE.md` in the repository. It is not optional reading — it contains the commissioning gates and the failure modes. ## Before you start You need: - A GoodWe **ES / BP family** inverter (AA55 / RS485 meter-bus generation) - The vendor's meter-emulating controller **disconnected** from the bus - A T-CAN485 (ESP32) flashed with `firmware/goodwe-master.yaml` - A grid-power sensor already working in Home Assistant, updating every ~5–10 s ## The safety model, in short The inverter **holds its last command forever** — it has no meter-timeout. So: - The ESP32 commands 0 W if this add-on stops refreshing for ~30 s, and keeps commanding it. - This add-on commands 0 W when its inputs go missing, when you stop control, and when it shuts down. - The **optional RS485 e-stop** is the only thing that covers this machine dying. Without it, a failed host leaves the battery latched at its last command until someone intervenes. **If anything looks wrong: stop the add-on.** That commands 0 W and the hardware holds it there. ## Configuration ### Sources | option | required | meaning | |---|---|---| | `meter_entity` | yes | Net grid power. **Positive must mean importing** | | `meter_invert` | | Flip the sign if the meter reports the other way | | `soc_entity` | yes | Battery state of charge — use the **ESP32's own read** | | `batt_entity` | yes | Battery power — again the ESP32's read, `+` = discharging | | `batt_invert` | | Flip if needed | | `setpoint_entity` | yes | The ESPHome `number.*_goodwe_setpoint_w` | Use the ESP32's readings rather than the inverter's cloud or dongle sensors: those serve cached values, and a stale reading here ends the maintenance charge phase having charged nothing. ### Control | option | default | meaning | |---|---|---| | `max_w` | 2000 | Hard limit on what may be commanded. Start low, raise after commissioning | | `gain` | 0.6 | Correction per cycle. **At the limit — do not raise** | | `slew_w` | 1000 | Maximum change per cycle | | `deadband_w` | 15 | Ignore errors smaller than this | | `step_w` | 10 | Quantisation | | `saturation_w` | 500 | Divergence that counts as "the inverter is at a limit" | | `saturation_cycles` | 3 | How many consecutive cycles before freezing. **Do not set to 1** | | `heartbeat_s` | 10 | Refresh interval; must stay well under the firmware watchdog | | `stale_input_s` | 15 | How long inputs may be missing before commanding 0 W | | `auto_start` | false | Start controlling on boot (only after commissioning) | ### Maintenance | option | default | meaning | |---|---|---| | `maintenance_enabled` | false | Enable the monthly cycle | | `maintenance_interval_days` | 28 | Minimum gap between cycles | | `maintenance_start_hour` | 10 | Hour of day a due cycle begins | | `maintenance_discharge_w` | 2500 | Drain rate (exports the surplus) | | `maintenance_charge_w` | 2500 | Charge ceiling, capped again by peak headroom | | `maintenance_soc_floor` | 11 | Drain target — stay just above the inverter's own floor | | `maintenance_soc_target` | 99 | Charge target | | `maintenance_hold_min` | 120 | Hold at full so the BMS can balance | ### Tariff (all optional) | option | meaning | |---|---| | `peak_forecast_entity` | Quarter-hour demand forecast, for capacity-tariff markets. Empty = no cap | | `peak_cap_w` | The site's capacity-tariff target | | `price_now_entity`, `price_avg_entity` | Dynamic tariff. Empty = never force a paid grid top-up | On a capacity-tariff site the maintenance charge is capped by the headroom left under `peak_cap_w`, and if the forecast goes over the cap the charge-only clamp is dropped so the battery can shave the peak instead. Money outranks the maintenance schedule. ### Site | option | meaning | |---|---| | `estop_fitted` | Whether the RS485 e-stop is installed. Drives the warning banner | | `log_level` | `trace`/`debug`/`info`/`warning`/`error` | ## The Web UI The ingress panel shows live values, why the controller is commanding what it is, and a **Commissioning** checklist that names any problem in words. It also carries the three buttons: start/stop control, force a maintenance cycle, and abort one. ## Status entities If an MQTT broker is available the add-on publishes setpoint, grid power, battery power, state of charge, maintenance phase and controller status by MQTT discovery. This is observability only — the controller works fine without a broker, and MQTT problems can never affect control.