ESP32-C3-Super-Mini-Firmware, die einen Deye SUN-xK-SG04LP3 Hybrid-Wechselrichter per Modbus RTU (RS485) ausliest und die Werte als JSON-State auf einen MQTT-Broker publisht. Inklusive Home-Assistant-MQTT-Auto-Discovery, Web-UI fuer Konfiguration und OTA-Update.
Die vollstaendige Register-Referenz (Skalierungen, Enums, Bitmasken, MQTT-Mapping) steht im Wiki: Modbus-Register.
ESP32-C3 Super Mini + MAX485-Modul.
Pinbelegung (im Web-UI aenderbar, mit interaktiver Pinout-Visualisierung in der Sektion "Deye RTU Konfiguration" - aenderbare GPIO-Felder heben das jeweils zugeordnete Pad live hervor):
| MAX485 | Funktion | ESP32-C3 |
|---|---|---|
| RO | Receiver-Out -> ESP RX | GPIO 0 |
| DI | Driver-In <- ESP TX | GPIO 1 |
| DE | Driver Enable (HIGH=TX) | GPIO 3 |
| RE | Receiver Enable (LOW=RX) | GPIO 4 |
| A / B | RS485-Bus | Deye COM-Port |
| VCC | 3.3 V oder 5 V | ESP |
| GND | gemeinsam mit Deye-GND | GND |
Onboard-LED: GPIO 8 (active LOW). Strapping-Pins (GPIO 2, 8, 9) werden bewusst nicht fuer RS485 verwendet.
- NVS laden (
settings::begin) - WLAN starten - bei leerem NVS oder Fehlschlag -> AP
DeyeBridge-Setup(PWdeye12345) - Webserver starten (immer, auch im AP-Mode)
- Deye-RTU-Master starten (laeuft auch ohne WLAN, RS485 ist lokal)
- Im STA-Mode zusaetzlich: NTP + MQTT-Client
- LED-Heartbeat: schnell blinken = AP, langsam blinken = alles OK, aus = Fehler
http://deye-bridge.local/ oder http://<IP>/. Im AP-Mode http://192.168.4.1/.
Sektionen:
- Live-Daten (PV/Batterie/Grid/Inverter/Load/Energie)
- MQTT-Status (Verbindung, Topics, Publish-Counter)
- Allgemeine Einstellungen (Poll-Intervall, Cold-Block-Frequenz, NTP, Zeitzone)
- MQTT-Broker (Host/Port/User/Pwd/ClientID/BaseTopic/DiscoveryPrefix/Publish-Intervall)
- Deye RTU Konfiguration (Pin-Mapping, Slave-ID, Baudrate - Reboot beim Speichern)
- WLAN (Scan, Connect)
- Firmware-Update (OTA)
- Web-Console (Live-Tail des Serial-Logs)
Default:
| Zweck | Topic |
|---|---|
| State (JSON) | deye/<deviceId>/state |
| Availability (LWT) | deye/<deviceId>/status (retained, online/offline) |
| HA Discovery | homeassistant/sensor/<deviceId>/<key>/config (retained) |
<deviceId> ergibt sich aus der MQTT-Client-ID (default deye-bridge-<chip-id>).
State-Payload (Auszug):
{
"pv1_power": 1240, "pv2_power": 980, "pv_total_power": 2220,
"batt_soc": 78, "batt_voltage": 51.20, "batt_power": -1200,
"grid_power_total": 250, "ct_power_total": -150,
"load_power_total": 1850,
"e_day_pv": 12.4, "e_day_load": 18.7, ...
}HA legt nach dem Discovery-Publish die Sensoren automatisch unter dem Geraet
Deye SUN SG04LP3 an. State wird im konfigurierten Intervall (default 5 s)
neu publiziert; Discovery nur einmal beim Verbinden.
Drei Bloecke pro Slave-Request, eModbus:
| Block | Adress-Bereich | Register | Frequenz |
|---|---|---|---|
| HOT | 586..638 | 53 | jeder Zyklus (default 2 s) |
| COLD | 500..558 | 59 | jeder N. Zyklus (default 3) |
| COLD2 | 644..683 | 40 | jeder N. Zyklus |
| SN | 3..7 | 5 | einmal beim Boot |
Quelle: kbialek/deye-inverter-mqtt + kellerza/sunsynk (3-Phase LV).
Jedes Release unter Releases
enthaelt eine gebaute deye-bridge-<version>.bin. Diese Datei im Web-UI unter
Firmware-Update (OTA) hochladen - die Bridge rebootet danach selbst.
Fuer den Erstflash eines jungfraeulichen ESP32-C3 wird trotzdem einmal USB-C gebraucht (siehe unten), weil OTA ein bereits laufendes Web-UI voraussetzt.
pio run -t upload
pio device monitor
Erstes Flashen ueber USB-C (BOOT-Taster halten + RST). Danach OTA ueber Web-UI.
version.py (PlatformIO-pre-build) stempelt bei jedem Build drei Defines ein,
Fallbacks stehen in include/version.h:
| Define | Inhalt |
|---|---|
FW_VERSION |
Release-Version, identisch zum Git-Tag |
FW_BUILD_NUMBER |
lokaler Zaehler aus build_number.txt (nicht im Repo) |
FW_BUILD_DATE |
Zeitpunkt des Builds |
FW_VERSION wird in dieser Reihenfolge ermittelt:
- Umgebungsvariable
FW_VERSION- die CI setzt hier den Release-Tag, ein Tag-Build liefert damit exaktv1.0.0. git describe --tags --dirty- lokaler Build aus dem Repo: genau auf dem Tagv1.0.0, danachv1.0.0-3-gabc1234(ggf.-dirty).VERSION-Datei plus Commit-Hash - Repo ohne Tags oder Quell-Zip.
Die Version steht damit im Boot-Banner (Serial), im Web-UI-Footer
(v1.0.0 #12 (Datum)) und als sw_version am HA-Geraet. Man sieht also
jederzeit, welches Release auf dem ESP laeuft.
Der Workflow .github/workflows/build.yml baut jeden Push auf main und jeden
PR. Ein Tag v* baut zusaetzlich das Release-Artefakt und veroeffentlicht es:
git tag -a v1.1.0 -m "v1.1.0"
git push origin v1.1.0
Die Action haengt deye-bridge-v1.1.0.bin samt SHA256 und generiertem
Changelog an das GitHub-Release. VERSION sollte im selben Commit auf den
neuen Stand gezogen werden, damit Quell-Zips ohne Git-Historie stimmen.
- Temperatur-Konvention
raw/10 - 100ist Deye-FW-abhaengig; bei Abweichungen indeye_master.cppdecodeTempOffset/decodeTempPlainanpassen. - Battery-Strom-Vorzeichen je nach Modell verschieden; im Web-UI verifizieren.
- 16-bit-Power-Register (Sensor16) wickeln bei >32 kW um - fuer SG04LP3 (max 12 kW) unkritisch.