# Modbus TCP – Schnellstartanleitung

Ergänzung zur [Modbus-TCP-Registerdokumentation](/de/modbus-tcp/documentation).
Diese Seite beschreibt, was die Ladestation von einem EMS erwartet, bevor die
Ladesteuerung über Modbus TCP wie erwartet arbeitet, und die Schreibsequenzen,
gegen die wir testen. Entspricht dem Firmware-Verhalten mit Stand Juli 2026.

## Adressierung

Registeradressen erscheinen in zwei Schreibweisen, und Modbus-Werkzeuge sind
sich uneinig, welche sie erwarten. Diese Anleitung nennt immer beide:

* die Registernummer (40202, 30027, …) – die übliche 1-basierte Schreibweise
  aus den Registertabellen, und
* die PDU-Adresse – der Wert, der tatsächlich über die Leitung geht:
  Registernummer minus 40001 bei Holding-Registern, minus 30001 bei
  Input-Registern.

Holding-Register (4xxxx) werden mit FC03 gelesen und mit FC06/FC16
geschrieben. Input-Register (3xxxx) sind nur lesbar, FC04. Wenn Ihr Werkzeug
einen Versatz um eins zeigt, verwechselt es fast immer diese beiden
Schreibweisen. Ein Wert, der zulässig aussieht und trotzdem abgelehnt wird,
liegt dagegen meist an der zweiten clientseitigen Ursache – siehe
Wertcodierung weiter unten.

Register, die in dieser Anleitung vorkommen:

| Name | Register | PDU (dez) | PDU (hex) | Zugriff |
| --- | --- | --- | --- | --- |
| ChargeMode | 40107 | 106 | 0x006A | FC03 lesen, FC06/16 schreiben |
| Set_Charge_Current_Target | 40202 | 201 | 0x00C9 | FC03 lesen, FC06/16 schreiben |
| Start_Stop_Charging | 40203 | 202 | 0x00CA | FC03 lesen, FC06/16 schreiben |
| Failsafe_Timeout | 40204 | 203 | 0x00CB | FC03 lesen, FC06/16 schreiben |
| Failsafe_Current_Target | 40206 | 205 | 0x00CD | FC03 lesen, FC06/16 schreiben |
| Heartbeat | 40208 | 207 | 0x00CF | FC06/16 schreiben |
| EVCS_State | 30001 | 0 | 0x0000 | FC04 |
| ErrorCode | 30004 | 3 | 0x0003 | FC04 |
| Failsafe_Active | 30027 | 26 | 0x001A | FC04 |
| DaemonStatus | 30050 | 49 | 0x0031 | FC04 |
| Availability | 30101 | 100 | 0x0064 | FC04 |
| OfferedCurrentLimit | 30105 | 104 | 0x0068 | FC04 |
| EV_Present | 30201 | 200 | 0x00C8 | FC04 |
| Charging | 30202 | 201 | 0x00C9 | FC04 |
| CP_Status | 30203 | 202 | 0x00CA | FC04 |

## Wertcodierung

Modbus ist Big-Endian, und dieses Gateway hält sich in beide Richtungen exakt
daran:

* Bytereihenfolge: Jedes 16-Bit-Register wird mit dem höherwertigen Byte
  zuerst übertragen. Ein Stromsollwert von 10 A geht als `00 0A` auf den Bus,
  niemals als `0A 00`.
* Wortreihenfolge: Werte über mehrere Register tragen das höherwertige Wort an
  der niedrigeren Registeradresse. Das betrifft nur die f32- und
  u32-Telemetrieregister – jedes beschreibbare Steuerregister dieser Anleitung
  ist ein einzelnes u16.

Manche Clients bieten beides als Einstellung pro Objekt an, statt es aus dem
Protokoll abzuleiten. Dann müssen alle Objekte auf Big-Endian stehen, und
korrekt dekodierte Telemetrie ist kein Beleg dafür, dass die Schreibobjekte
genauso eingestellt sind. Die Wortreihenfolge ist bei den Steuerregistern
harmlos, weil es Einzelregister sind – die Bytereihenfolge ist es nicht. Ein
bytevertauschter Wert kommt trotzdem an, nur still verändert: Aus einem
Sollwert 10 wird 2560, aus 8 wird 2048, beides weit außerhalb des zulässigen
Bereichs. Der Schreibzugriff wird mit Exception 0x03 abgelehnt, während der
Wert auf Ihrem Bildschirm völlig korrekt aussieht.

Das Erkennungsmerkmal: Jeder Stromsollwert wird abgelehnt, egal welchen Sie
wählen – nur 0 funktioniert, denn eine Bytevertauschung lässt 0 unverändert.
Wenn Sie die Einstellung in Ihrem Client nicht finden, senden Sie 2560 als
Sollwert: bytevertauscht ist das 10. Wird der Schreibzugriff angenommen und
lädt die Ladestation mit 10 A, ist die Vertauschung bestätigt. Skalierungen
oder Korrekturtabellen im Client für diesen Test abschalten.

## Die Kurzfassung

1. Fahrzeug anstecken. EV_Present 30201 (PDU 200) muss 1 sein, CP_Status 30203
   (PDU 202) muss 1, 2 oder 3 sein (IEC-61851-Zustände B/C/D).
2. Ladestation in den manuellen Lademodus schalten: ChargeMode 40107
   (PDU 106) = 2 schreiben. Das muss vor jedem Sollwert geschehen – jeder
   Moduswechsel setzt die Strombegrenzung auf das konfigurierte Maximum zurück.
3. Ladung mit einem einzigen FC16-Telegramm starten, das
   Set_Charge_Current_Target 40202 (PDU 201) = 6..32 A und Start_Stop_Charging
   40203 (PDU 202) = 1 gemeinsam schreibt:

   ```
   10 00 C9 00 02 04 00 10 00 01     (16 A + Start)
   ```

4. Sitzung am Leben halten. Der Failsafe-Watchdog ist ab Werk aktiv mit 20 s
   Timeout, also Heartbeat 40208 (PDU 207, beliebiger Wert) mindestens alle
   10 s schreiben – oder 40202 in diesem Takt erneut schreiben.
5. Zum Ändern des Stroms 40202 erneut schreiben. Die Ladestation folgt binnen
   weniger Sekunden; die Telemetrieregister aktualisieren im Abstand von bis
   zu 5 s.
6. Zum Beenden 40203 = 0 schreiben (oder 40202 = 0).

Anfragen gehen an die konfigurierte Unit ID (Standard 1, im
Web-Oberfläche sichtbar). Bei einem Master mit angebundenen Slave-Boxen
antwortet jede Slave-Ladestation unter ihrer eigenen Unit ID hinter der
IP-Adresse des Masters.

## Manueller Modus – und warum die anderen Modi dagegenhalten

Die Salia kennt drei Lademodi: Eco (0), Power (1) und Manuell (2). Nur Manuell
übergibt die Strombegrenzung an eine externe Steuerung.

In Eco und Power läuft die interne Ladesteuerung alle 3 Sekunden
(`charge_control_interval` in der Stationskonfiguration, Standard 3.0) und
schreibt ihr eigenes Ergebnis auf denselben Begrenzungskanal, den auch das
Modbus-Gateway beschreibt:

* Power hebt die Begrenzung je Takt um rund 1 A an, bis das konfigurierte
  Maximum erreicht ist. Solange ein Fahrzeug angesteckt ist, aber noch nicht
  lädt, setzt Power die Begrenzung in jedem Takt direkt auf das Maximum.
* Eco bewegt die Begrenzung je Takt um 1 A nach oben oder unten und folgt
  damit dem Solarüberschuss. Der wandernde Strom im Eco-Modus ist gewolltes
  Verhalten, kein Fehler.

Ein über Modbus geschriebener Sollwert überlebt daher höchstens bis zum
nächsten Takt. Im manuellen Modus lässt die interne Steuerung den
Begrenzungskanal in Ruhe, und der Modbus-Wert bleibt in Kraft.

Weitere Punkte, die dazugehören:

* Der Modus wird von der Ladestation persistent gespeichert, 40107 = 2
  übersteht also einen Neustart. Solar- und Eco-Logik bleiben aus, bis jemand
  den Modus zurückschaltet (Web-Oberfläche oder Register).
* Jeder Moduswechsel setzt die Strombegrenzung zurück: Wechsel nach Power oder
  Manuell setzt sie auf das konfigurierte Maximum, Wechsel nach Eco während
  einer laufenden Ladung auf das Minimum. Also erst den Modus schreiben, dann
  den Sollwert – und nach jedem späteren Moduswechsel 40202 erneut schreiben.
* Der Wechsel nach Power schaltet außerdem Eco+ ab und erzwingt bei
  Ladestationen mit Phasenumschaltung dreiphasigen Betrieb.
* Der Autorisierungsmodus (frei / RFID / OCPP / Schlüsselschalter) ist eine
  Stationseinstellung; ein Modbus-Register dafür gibt es nicht (Register 30022
  / PDU 21 meldet ihn nur). Bei Ladestationen an einem OCPP-Backend kann das
  Backend Sitzungen autorisieren oder die Autorisierung entziehen und eigene Grenzen auf dieselbe
  Ladestation legen – für Integrationstests ist es daher einfacher, den
  Autorisierungsmodus in der Web-Oberfläche auf „free“ (frei) zu stellen. Ein Modbus-Start
  (40203 = 1) setzt die Sitzungsautorisierung auf der Ladestation selbst.

## Was den Strom sonst noch bewegt – in jedem Modus

Die folgenden Mechanismen greifen auch im manuellen Modus. Sie sind gewollt
und keine Modbus-Fehler:

* Hausanschluss-Absicherung. Bei Anlagen mit Netzzähler senkt die Ladesteuerung
  die Begrenzung oder pausiert die Ladung, wenn die Gebäudeversorgung an ihre
  Sicherungsgrenze läuft. Wird eine solche Pause aufgehoben, steht die
  Begrenzung wieder auf dem konfigurierten Maximum – danach 40202 erneut
  schreiben.
* Lastmanagement und Netzbetreibergrenze. Verbundene Ladestationen teilen sich
  ein Strombudget, die Netzbetreibergrenze liegt auf einem eigenen Kanal. Der
  dem Fahrzeug tatsächlich angebotene Strom ist durch den niedrigsten aktiven
  Kanal begrenzt; ein zweites ladendes Fahrzeug oder eine Netzvorgabe kann den
  gelieferten Strom jederzeit unter Ihren Sollwert ziehen. Werden 32 A an einer
  auf 16 A begrenzten Ladestation angefordert, ergibt das 16 A – eine
  Begrenzung, kein Fehler.

## Das alte Heartbeat-Flag (nicht der Modbus-Failsafe)

Die Salia hat zusätzlich eine ältere, separate Heartbeat-Funktion: das Flag
`heartbeat` in der Stationskonfiguration (saliaconf), geschaltet über das
MQTT-Topic `port0/salia/heartbeat`. Ist dieses Flag gesetzt und trifft auf dem
Topic länger als 60 s keine Nachricht ein, zwingt die Ladesteuerung die
Strombegrenzung in jedem 3-s-Takt auf das konfigurierte Minimum, solange ein
Fahrzeug lädt – in jedem Lademodus, auch im manuellen. Das Modbus-Gateway
veröffentlicht dieses Topic nie.

Auf einer Modbus-gesteuerten Ladestation muss dieses Flag auf false stehen.
Wir haben Ladestationen im Feld gesehen, bei denen es aktiv war; das
Erkennungsmerkmal ist ein Strom, der alle paar Sekunden exakt auf das
Stationsminimum (meist 6 A) einbricht.

## Prüfliste vor der Registersuche

| Prüfung | Wo | Erwartet |
| --- | --- | --- |
| Fahrzeug angesteckt | 30201 / PDU 200, 30203 / PDU 202 | 1; CP in B/C/D |
| Ladestation betriebsbereit | 30101 / PDU 100 | 1 |
| Kein aktiver Fehler | 30004 / PDU 3 | 0 (7 bedeutet Failsafe aktiv) |
| Lademodus | 40107 / PDU 106 | 2 (manuell) |
| Ladung kommandiert | 40203 / PDU 202 | 1 (nach Neustart wieder 0) |
| Stromsollwert | 40202 / PDU 201 | 6..32 (0 = Stopp) |
| Daemon bereit | 30050 / PDU 49, Bit 0 | 1 (Anfragen im Startvorgang liefern 0x06) |
| Altes Heartbeat-Flag aus | saliaconf `heartbeat` | false (Web-/Service-Zugang) |

## Stolperfallen

* 40202 allein zu schreiben bewirkt nichts, solange 40203 = 0 ist. Das Gateway
  kommandiert dann 0 A an die Ladestation, unabhängig vom geschriebenen
  Sollwert. Immer mit dem Paar 40202 + 40203 in einem FC16-Telegramm starten.
* 40202 und 40203 sind flüchtig. Nach einem Daemon-Neustart oder einem Reboot
  der Box stehen sie wieder auf 0, und das EMS muss die Startsequenz erneut
  senden.
* Der Failsafe-Watchdog ist ab Werk aktiv: Failsafe_Timeout 40204 (PDU 203)
  steht standardmäßig auf 20 s, Failsafe_Current_Target 40206 (PDU 205)
  standardmäßig auf 0 A. Trifft innerhalb des Timeouts kein angenommener
  Steuerschreibzugriff (40202, 40203, 40208, 40209) ein, fällt die Ladestation
  auf den Failsafe-Strom zurück, ErrorCode 30004 liest 7 und Failsafe_Active
  30027 (PDU 26) liest 1. Der nächste angenommene Schreibzugriff stellt Ihren
  Sollwert wieder her. Ein EMS, das nur einmal pro Minute schreibt, sieht den
  Strom zwischen Sollwert und Rückfallwert springen. Entweder Heartbeats im
  halben Timeout senden, 40204/40206 auf Werte setzen, die zu Ihrem Regeltakt
  passen (10..3600 s, 0 oder 6..32 A), oder den Watchdog mit 40204 = 0
  abschalten. An einer im Leerlauf stehenden Ladestation ohne EMS-Verkehr ist
  ErrorCode 7 mit Failsafe_Active 1 der normale Ruhezustand und kein Defekt.
* Der Sollwert ist eine Anforderung, keine Zusage. Siehe den Abschnitt zu den
  Begrenzungen oben; OfferedCurrentLimit 30105 (PDU 104), CurrentOffered 30106+
  und die Zählerströme 31009+ (PDU 1008+) zeigen, was tatsächlich angeboten und
  gezogen wird.
* Set_Charge_Power_Target 40201 (PDU 200) ist nicht implementiert.
  Schreibzugriffe werden angenommen und gespeichert, bleiben aber wirkungslos.
  Stattdessen den Stromsollwert 40202 verwenden.
* 30202 („Charging“, PDU 201, FC04) ist ein reines Lesestatus-Flag und nicht
  beschreibbar. Es wird leicht mit 40202 verwechselt – gleiche Endziffern,
  anderer Registerraum.
* Der Rücklesewert von 40107 kann veralten: Er wird beim Start des Daemons und
  bei EMS-Schreibzugriffen gesetzt, ein späterer Moduswechsel in der Web-Oberfläche
  wird aber nicht ins Register zurückgespiegelt. Im Zweifel zeigt das
  Web-Oberfläche den tatsächlich wirksamen Modus.

## Symptome und Ursachen

Eine nützliche Abkürzung: Der Wert, auf den der Strom springt, verrät meist,
welcher Mechanismus beteiligt ist.

| Symptom | Wahrscheinliche Ursache |
| --- | --- |
| Schreiben auf 40202 angenommen, es lädt nichts | 40203 = 0, kein Fahrzeug / CP = A, oder ErrorCode ≠ 0 |
| Strom kriecht zurück Richtung Maximum, ~1 A alle 3 s | Lademodus ist Power → 40107 = 2 setzen |
| Strom wandert ±1 A um einen solargeführten Wert | Lademodus ist Eco (so gewollt) → für EMS-Steuerung Manuell |
| Strom fällt ~20 s nach dem letzten Schreibzugriff auf den Failsafe-Wert (Standard 0 A), ErrorCode = 7 | Failsafe-Watchdog ausgelöst → häufiger Heartbeat, oder 40204 anpassen/abschalten |
| Strom bricht alle paar Sekunden exakt auf das Stationsminimum ein | saliaconf-Flag `heartbeat` steht auf true → auf false setzen |
| Strom springt direkt nach einem Moduswechsel auf das Maximum | Rücksetzen der Begrenzung durch den Moduswechsel → nach Ändern von 40107 erneut 40202 schreiben |
| Strom niedriger als der Sollwert, während eine verbundene Box mitlädt | Aufteilung des Lastmanagement-Budgets (kein Fehler) |
| Jeder Schreibzugriff auf 40202 wird abgelehnt, egal welcher Wert – nur 0 wird angenommen | Bytereihenfolge des Clients ist nicht Big-Endian → siehe Wertcodierung |
| Exception 0x03 beim Schreiben | Wert außerhalb 0 / 6..32 (die Stationskonfiguration kann den Bereich enger ziehen). Liegt der gesendete Wert im Bereich, ist die Bytereihenfolge des Clients verdächtig – eine vertauschte 10 kommt als 2560 an |
| Exception 0x03 beim Start (40203 = 1); 0x04 bei Firmware vor MapVersion 2.1.0 | Stromsollwert 40202 steht noch auf 0 – erst den Sollwert schreiben, am besten beides in einem FC16-Telegramm |
| Exception 0x06 | Ratenbegrenzung (50 Anfragen/s je IP) oder Daemon startet noch (30050 Bit 0 prüfen) |
| Lief vor einem Neustart, danach nie wieder | Die flüchtigen 40202/40203 stehen wieder auf 0 → Startsequenz erneut senden |

## Eine Sitzung überprüfen

Nach dem Start abfragen (FC04, sofern nicht anders angegeben):

* 30001 EVCS_State (PDU 0) = 2 (CHARGING) und 30202 Charging (PDU 201) = 1
* 30004 ErrorCode (PDU 3) = 0 und 30027 Failsafe_Active (PDU 26) = 0
* 30105 OfferedCurrentLimit (PDU 104) und 30106+ CurrentOffered = Ihr Sollwert
  oder die Begrenzung der Ladestation
* 31009+ Zählerströme (PDU 1008+) = was das Fahrzeug tatsächlich zieht; dass
  das Fahrzeug weniger zieht als angeboten, ist normal

Wenn Ihre Beobachtung nicht zu dieser Anleitung passt, senden Sie uns die
Firmware-Version zusammen mit den Werten aus localhost/api der Salia – wir
schauen uns das an.
