Marstek CT002 / CT003 emulator

TinyC program for Tasmota · turns your reading head into a Marstek CTTinyC-Programm für Tasmota · macht aus deinem Lesekopf ein Marstek-CT

OverviewÜberblick

Marstek batteries (Venus, Jupiter, B2500) need a meter to know how much power your house is using right now. Marstek sells a device for this, the CT002 / CT003. This program turns your reading head into such a device: it reads your electricity meter and answers the batteries exactly like a real CT. That way your battery can feed in just as much as your house needs (zero feed-in).

There are three ways to connect a battery to an emulated meter: Shelly Pro 3EM, EcoTracker and this CT002. The big advantage of the CT002: it coordinates several batteries. Each battery tells the CT its power and its phase, and the CT tells each battery how many batteries share its phase. So two batteries on the same phase do not work against each other. Phase D is also supported: the battery then uses the sum of all three phases, which is usually right with a normal (netting) meter.

With Active control switched off, the program simply passes the meter value on and each battery regulates itself. With it switched on, the program helps the batteries to regulate more calmly and precisely (see Battery).

You need: an ESP32 (not an ESP8266), my Tasmota image with TinyC 1.6.64 or newer, and a reading head (examples on my blog). An older firmware refuses to load the program and tells you so.

ESP8266: for this there is a separate script for up to 4 Marstek batteries, 2_CT002_Emulator.tas (by next145), without the extra control described here. It needs the image tasmota1m_ct002_ottelo_tas (for an OTA update, load the minimal image first). It has the page Marstek CT002 (/ctreg, under Tools) for registering the CT in the Marstek cloud once.

Marstek-Akkus (Venus, Jupiter, B2500) brauchen einen Zähler, damit sie wissen, wie viel Strom dein Haus gerade braucht. Marstek verkauft dafür ein eigenes Gerät, das CT002 / CT003. Dieses Programm macht aus deinem Lesekopf so ein Gerät: Es liest deinen Stromzähler aus und antwortet den Akkus genau wie ein echtes CT. So kann dein Akku genau so viel einspeisen, wie dein Haus braucht (Nulleinspeisung).

Es gibt drei Wege, einen Akku mit einem nachgebildeten Zähler zu verbinden: Shelly Pro 3EM, EcoTracker und dieses CT002. Der große Vorteil des CT002: Es stimmt mehrere Akkus aufeinander ab. Jeder Akku meldet dem CT seine Leistung und seine Phase, und das CT sagt jedem Akku, wie viele Akkus sich seine Phase teilen. So arbeiten zwei Akkus auf derselben Phase nicht mehr gegeneinander. Auch Phase D wird unterstützt: Der Akku nimmt dann die Summe aller drei Phasen, was bei einem normalen (saldierenden) Zähler meistens richtig ist.

Ist Aktive Regelung aus, gibt das Programm den Zählerwert einfach weiter und jeder Akku regelt selbst. Ist sie an, hilft das Programm den Akkus, ruhiger und genauer zu regeln (siehe Akku).

Du brauchst: einen ESP32 (keinen ESP8266), mein Tasmota-Image mit TinyC 1.6.64 oder neuer und einen Lesekopf (Beispiele auf meinem Blog). Eine ältere Firmware lädt das Programm nicht und sagt dir das auch.

ESP8266: Dafür gibt es ein eigenes Script für bis zu 4 Marstek-Akkus, 2_CT002_Emulator.tas (von next145), ohne die hier beschriebene zusätzliche Regelung. Es braucht das Image tasmota1m_ct002_ottelo_tas (für ein OTA-Update vorher das Minimal-Image laden). Darin gibt es die Seite Marstek CT002 (/ctreg, unter Tools), um das CT einmalig in der Marstek-Cloud anzumelden.

SetupEinrichtung

  1. Load SML + Marstek CT002 (or SML Chart + Marstek CT002 if you want charts) into slot 0. How this works is described step by step under Install.
  2. Switch on A in the slot row, so the program starts by itself after a reboot.
  3. Set up your meter first (see Meter). Without meter values the CT reports 0 W.
  4. Create the CT in your Marstek account and select it in the Marstek app.

Only in slot 0. The registration page /ctreg only works there.

  1. SML + Marstek CT002 (oder SML Chart + Marstek CT002, wenn du Diagramme willst) in Slot 0 laden. Wie das geht, steht Schritt für Schritt unter Installation.
  2. In der Zeile des Slots A einschalten, damit das Programm nach einem Neustart von selbst startet.
  3. Zuerst deinen Zähler einrichten (siehe Zähler). Ohne Zählerwerte meldet das CT 0 W.
  4. Das CT in deinem Marstek-Konto anlegen und in der Marstek-App auswählen.

Nur in Slot 0. Die Anmeldeseite /ctreg funktioniert nur dort.

CT

You find all CT and battery settings on their own page: the 🔋 CT button in the Tasmota main menu, or the link at the top of the settings page.

TypeCT002 or CT003. Choose the one you created in the app. Takes effect after the program restarts.
CT MACThe MAC address of the CT in your Marstek account (12 characters). It is filled in automatically when you register the CT. With a MAC set, the CT only answers batteries that ask for exactly this CT. Empty means it answers every battery, handy for testing, but wrong as soon as there are several CTs.
PortThe network port the batteries talk to. Always 12345. Only change it if you know why.
RSSI [dBm]The Wi-Fi strength the CT reports to the battery. Just leave it.
Timeout [s]After how many seconds a battery that stopped asking is removed from the list. 0 = automatic (about two of its own polls, at least 5 s), like a real CT does it.

Below the settings you see three counters: rx = requests received, tx = answers sent, bad = broken requests. bad should stay at 0.

Alle CT- und Akku-Einstellungen findest du auf einer eigenen Seite: Knopf 🔋 CT im Tasmota-Hauptmenü, oder der Link oben auf der Einstellungsseite.

TypCT002 oder CT003. Nimm das, was du in der App angelegt hast. Wirkt nach einem Neustart des Programms.
CT MACDie MAC-Adresse des CT in deinem Marstek-Konto (12 Zeichen). Sie wird bei der Anmeldung des CT automatisch eingetragen. Mit MAC antwortet das CT nur Akkus, die genau nach diesem CT fragen. Leer heißt: Es antwortet jedem Akku. Praktisch zum Testen, aber falsch, sobald es mehrere CTs gibt.
PortDer Netzwerk-Port, über den die Akkus fragen. Immer 12345. Nur ändern, wenn du weißt, warum.
RSSI [dBm]Die WLAN-Stärke, die das CT dem Akku meldet. Einfach so lassen.
Timeout [s]Nach wie vielen Sekunden ein Akku, der nicht mehr fragt, aus der Liste fliegt. 0 = automatisch (etwa zwei seiner eigenen Abfragen, mindestens 5 s), so wie es ein echtes CT macht.

Unter den Einstellungen siehst du drei Zähler: rx = empfangene Anfragen, tx = gesendete Antworten, bad = kaputte Anfragen. bad sollte bei 0 bleiben.

BatteryAkku

Offset [W]The value the battery aims for, instead of exactly 0 W. A small positive value (e.g. 20) means you always buy a few watts and never feed in by accident. The offset applies per phase: with three batteries on three phases you end up at three times the value.
Active controlOFF: the meter value is passed on unchanged, the battery decides alone. ON: the program helps with regulating (see below). Recommended.
Trim [W]Recommended 15 (already set on a new install). Marstek batteries always stop a few watts too early and leave a small import standing. Trim pushes them those last few watts further, but only when things are calm (between 0 and 120 W import for a few seconds). 0 = off.
Step [W]Recommended 30 (already set on a new install). Limits how big a change the battery is told each second. That makes the regulation calmer. When the batteries follow well, the step grows by itself up to three times this value. If a battery does not react at all for four seconds (empty, limited, or the step is too small for it), the limit is opened so it does not get stuck. 0 = off.
Min DC [W]Default 0 = off. Only for a B2500: it switches off at 0 W and falls asleep when there is a lot of solar power. With e.g. 20 W the CT always reports at least this much import, so the battery keeps running. Costs exactly those watts of feed-in when the sun shines. Venus batteries do not need it.
Max DC [W]Default 0 = off. The most each battery may discharge. The rest comes from the grid. Charging is not limited. A negative value makes each battery charge with at least that much, see Discharge limit. You can also change it from Home Assistant, see Discharge limit.

Offset and Trim together: the offset is the margin you want, the trim makes sure that margin is really reached. With an offset of 50 and a trim of 15 you get 50 W import, not 65.

What Active control also does (no settings needed, following the proven control of AstraMeter):

  • It takes into account what the batteries have already changed but the meter does not show yet. Without this, a correction would be made twice, and the batteries would swing up and down.
  • If the corrections keep changing direction, it calms them down. A real change in your consumption still comes through at full strength.
  • It ignores a meter value that has not changed since the last time, so a slow meter is not counted twice.

3 phases is set on the main settings page under Meter. Switched off, the whole power goes to L1, and L2/L3 stay at 0. Then set all batteries to phase A or D, otherwise a battery on B or C always sees 0 W.

Choosing the phase

You choose the phase on the battery in the Marstek app, not here:

  • A / B / C: the battery regulates on this one phase and shares it with other batteries on the same phase.
  • D: the battery uses the sum of all three phases. With a normal (netting) meter this is usually the right choice.
  • x on the web page means: the battery is still searching for its phase. It changes its own power and watches which phase moves. With a simulator that always sends the same values it never finishes; then set the phase in the app.
  • While a battery searches, it gets the unchanged meter value without offset and without control, otherwise the search would not work. The log shows ph? when it starts and ph A (or B, C, D) when it is done, then reseed: the control starts fresh. A Venus with firmware 1.50 repeats this search about every 35 minutes.
  • The other batteries must not cancel out the search step. On D they are controlled as if the searching battery were not there. On A/B/C they hold their output while the searching battery is pushing power, because nobody knows yet which phase it is on. That takes at most about 40 seconds.
  • Right after a restart, before the meter has sent its first value, a searching battery gets no answer. It waits and tries again instead of storing a wrong phase.
Offset [W]Der Wert, auf den der Akku regelt, statt genau 0 W. Ein kleiner positiver Wert (z.B. 20) heißt: Du kaufst immer ein paar Watt und speist nie aus Versehen ein. Der Offset gilt pro Phase: Bei drei Akkus auf drei Phasen landest du beim Dreifachen.
Aktive RegelungAUS: Der Zählerwert wird unverändert weitergegeben, der Akku entscheidet allein. EIN: Das Programm hilft beim Regeln (siehe unten). Empfohlen.
Trim [W]Empfohlen 15 (bei einer Neuinstallation schon eingestellt). Marstek-Akkus hören immer ein paar Watt zu früh auf und lassen einen kleinen Bezug stehen. Trim schiebt sie diese letzten Watt weiter, aber nur, wenn es ruhig ist (einige Sekunden zwischen 0 und 120 W Bezug). 0 = aus.
Schritt [W]Empfohlen 30 (bei einer Neuinstallation schon eingestellt). Begrenzt, wie große Änderungen dem Akku pro Sekunde gemeldet werden. Das macht die Regelung ruhiger. Folgen die Akkus gut, wird der Schritt von selbst größer, bis zum Dreifachen. Reagiert ein Akku vier Sekunden lang gar nicht (leer, begrenzt, oder der Schritt ist ihm zu klein), wird die Grenze geöffnet, damit er nicht hängen bleibt. 0 = aus.
Min DC [W]Standard 0 = aus. Nur für einen B2500: Er schaltet bei 0 W ab und schläft bei viel Solarstrom ein. Mit z.B. 20 W meldet das CT immer mindestens so viel Bezug, damit der Akku weiterläuft. Kostet bei Sonne genau diese Watt an Einspeisung. Venus-Akkus brauchen das nicht.
Max DC [W]Standard 0 = aus. So viel darf jeder Akku höchstens entladen. Den Rest liefert das Netz. Laden wird nicht begrenzt. Ein negativer Wert lässt jeden Akku mit mindestens so viel laden, siehe Entladelimit. Du kannst den Wert auch aus Home Assistant ändern, siehe Entladelimit.

Offset und Trim zusammen: Der Offset ist der Abstand, den du willst, der Trim sorgt dafür, dass er auch wirklich erreicht wird. Mit Offset 50 und Trim 15 bekommst du 50 W Bezug und nicht 65.

Was die Aktive Regelung außerdem macht (ohne Einstellungen, nach dem bewährten Vorbild von AstraMeter):

  • Sie berücksichtigt, was die Akkus schon geändert haben, der Zähler aber noch nicht zeigt. Ohne das würde eine Korrektur doppelt gemacht, und die Akkus würden hoch und runter schwingen.
  • Wechseln die Korrekturen ständig die Richtung, bremst sie sie ab. Eine echte Änderung deines Verbrauchs kommt trotzdem voll durch.
  • Sie überspringt einen Zählerwert, der sich seit dem letzten Mal nicht geändert hat. So wird ein langsamer Zähler nicht doppelt gezählt.

3 Phasen stellst du auf der Haupt-Einstellungsseite unter Zähler ein. Ist es aus, liegt die ganze Leistung auf L1, und L2/L3 bleiben 0. Stelle dann alle Akkus auf Phase A oder D, sonst sieht ein Akku auf B oder C immer 0 W.

Phase wählen

Die Phase stellst du am Akku in der Marstek-App ein, nicht hier:

  • A / B / C: Der Akku regelt auf diese eine Phase und teilt sie sich mit anderen Akkus auf derselben Phase.
  • D: Der Akku nimmt die Summe aller drei Phasen. Bei einem normalen (saldierenden) Zähler meistens die richtige Wahl.
  • x auf der Webseite heißt: Der Akku sucht noch seine Phase. Er ändert dazu seine eigene Leistung und schaut, welche Phase sich mitbewegt. Mit einem Simulator, der immer dieselben Werte schickt, wird er nie fertig. Stelle die Phase dann in der App fest ein.
  • Solange ein Akku sucht, bekommt er den unveränderten Zählerwert, ohne Offset und ohne Regelung, sonst würde die Suche nicht funktionieren. Im Log steht zu Beginn ph? und am Ende ph A (oder B, C, D), danach reseed: Die Regelung fängt frisch an. Eine Venus mit Firmware 1.50 wiederholt diese Suche etwa alle 35 Minuten.
  • Die anderen Akkus dürfen den Suchschritt nicht wegregeln. Auf D werden sie geregelt, als wäre der suchende Akku nicht da. Auf A/B/C halten sie ihre Leistung, solange der suchende Akku Leistung schiebt, denn auf welcher Phase er hängt, weiß noch keiner. Das dauert höchstens etwa 40 Sekunden.
  • Direkt nach einem Neustart, bevor der Zähler seinen ersten Wert geliefert hat, bekommt ein suchender Akku keine Antwort. Er wartet und versucht es erneut, statt eine falsche Phase zu speichern.

Several batteriesMehrere Akkus

This section only matters if two or more batteries are on the same phase. With one battery you can leave everything here off.

With several batteries, switch on Share the load. Otherwise every battery is told the whole difference of its phase. Two batteries then both deliver the full amount, and together they overshoot by double.

Share the loadSplits the difference of a phase between the batteries on it and keeps them at a similar level.
SaturationNotices when a battery no longer follows, because it is full, empty, or limited in its own settings. Its share then goes to the others. Without this, a battery limited to 800 W would slow down a bigger one next to it.

B2500: at least 80 W

A B2500 (device types HMA, HMJ, HMK) can not deliver less than about 80 W. If two of them shared a demand of 100 W, each would be told 50 W, and both would stay off.

The CT recognises a B2500 by its device type and handles this by itself, nothing to set:

  • It gives each active B2500 at least 80 W instead of splitting the demand too thinly. A second one only joins at about 190 W.
  • If only one is needed, the active one changes every 15 minutes, so all of them wear evenly. The old one ramps down slowly, so there is no gap at the handover.
  • If the active one is full, empty or at its limit, another one takes over at once, not only at the next change. This needs Saturation switched on.
  • It does not judge a B2500 as "not reacting" below 80 W, because it simply can not.
  • Min DC only applies to a B2500. A Venus or Jupiter can not fall asleep.
  • On a phase with a B2500, Step is at least 80 W, otherwise the battery would never start.

Background

The control follows AstraMeter and uses its proven values. A few things that used to be settings are now fixed, on the advice of AstraMeter's author: too many knobs make it harder, and nobody can set them well without measurements.

Two things are done differently on purpose, because of open reports there: very small corrections are not sent at all, because a Marstek battery ignores them anyway (issue 600). And Min DC applies to each battery, not to the whole phase (issue 624).

Dieser Abschnitt ist nur wichtig, wenn zwei oder mehr Akkus auf derselben Phase hängen. Bei einem Akku kannst du hier alles ausgeschaltet lassen.

Bei mehreren Akkus Last verteilen einschalten. Sonst bekommt jeder Akku den ganzen Unterschied seiner Phase gemeldet. Zwei Akkus liefern dann beide den vollen Betrag und schießen zusammen um das Doppelte übers Ziel.

Last verteilenTeilt den Unterschied einer Phase auf die Akkus darauf auf und hält sie auf ähnlichem Stand.
SättigungMerkt, wenn ein Akku nicht mehr folgt, weil er voll, leer oder in seinen eigenen Einstellungen begrenzt ist. Sein Anteil geht dann an die anderen. Ohne das würde ein auf 800 W begrenzter Akku einen größeren daneben ausbremsen.

B2500: mindestens 80 W

Ein B2500 (Gerätetypen HMA, HMJ, HMK) kann nicht weniger als etwa 80 W liefern. Teilen sich zwei davon einen Bedarf von 100 W, bekäme jeder 50 W gemeldet, und beide blieben aus.

Das CT erkennt einen B2500 an seinem Gerätetyp und regelt das selbst, du musst nichts einstellen:

  • Es gibt jedem aktiven B2500 mindestens 80 W, statt den Bedarf zu fein aufzuteilen. Ein zweiter kommt erst bei etwa 190 W dazu.
  • Wird nur einer gebraucht, wechselt der aktive alle 15 Minuten, damit alle gleich abgenutzt werden. Der alte fährt dabei langsam herunter, so entsteht keine Lücke.
  • Ist der aktive voll, leer oder an seiner Grenze, übernimmt sofort ein anderer, nicht erst beim nächsten Wechsel. Dafür muss Sättigung an sein.
  • Es bewertet einen B2500 unter 80 W nicht als „reagiert nicht“, weil er das gar nicht kann.
  • Min DC gilt nur für einen B2500. Eine Venus oder ein Jupiter kann nicht einschlafen.
  • Auf einer Phase mit B2500 ist Schritt mindestens 80 W, sonst würde der Akku nie anlaufen.

Hintergrund

Die Regelung folgt AstraMeter und nutzt dessen bewährte Werte. Ein paar Dinge, die früher einstellbar waren, sind jetzt fest, auf Rat des AstraMeter-Autors: Zu viele Stellschrauben machen es schwerer, und ohne Messungen kann sie niemand gut einstellen.

Zwei Dinge sind bewusst anders, wegen offener Meldungen dort: Sehr kleine Korrekturen werden gar nicht erst gesendet, weil ein Marstek-Akku sie sowieso ignoriert (Meldung 600). Und Min DC gilt für jeden Akku einzeln, nicht für die ganze Phase (Meldung 624).

MeterZähler

The meter is set up on the main settings page, the same way as in all my programs. Everything is explained on the SML help page. The short version:

Meter activeMust be on. Without meter values the CT reports 0 W.
MeterChoose your meter from the list.
RX / TXThe pins of your reading head. Usually RX 3 / TX 1 (Hichi, Stromleser, Wattwächter) or RX 5 / TX 4 (bitShake).
SML FilterSmooths single wrong values, but makes the values a bit slower. For zero feed-in it is better to leave it off, the batteries smooth themselves.

The CT needs value 1 = power. For 3 phases the meter must also deliver the power of each phase as values 4, 5 and 6.

Der Zähler wird auf der Haupt-Einstellungsseite eingerichtet, genau wie in allen meinen Programmen. Alles dazu steht auf der SML-Hilfeseite. Kurz gesagt:

Zähler aktivMuss an sein. Ohne Zählerwerte meldet das CT 0 W.
ZählerDeinen Zähler aus der Liste wählen.
RX / TXDie Pins deines Lesekopfs. Meist RX 3 / TX 1 (Hichi, Stromleser, Wattwächter) oder RX 5 / TX 4 (bitShake).
SML FilterGlättet einzelne falsche Werte, macht die Werte aber etwas langsamer. Für Nulleinspeisung besser aus lassen, die Akkus glätten selbst.

Das CT braucht Wert 1 = Leistung. Für 3 Phasen muss der Zähler zusätzlich die Leistung jeder Phase als Wert 4, 5 und 6 liefern.

TelemetryTelemetrie

PwrAvg / PwrSP (MQTT) sends two values over MQTT every 5 seconds: PwrAvg, the smoothed grid power, and PwrSP, what this CT reports to the batteries (with offset). Both are also shown below the switch. /pwr always delivers them, even with the switch off.

MQTT

stat/<topic>/script/PwrAvg
stat/<topic>/script/PwrSP

These are the same topics as in the old scripts, so existing Home Assistant sensors keep working. In MQTT Explorer: stat → <topic> → script, for example stat/tasmota_31F8D4/script/PwrSP.

HTTP

http://<ip>/pwr
{"sml1":-440,"sml2":26714.950,"sml3":659.775,"sml4":-440,"sml5":0,"sml6":0,"PwrAvg":-217,"PwrSP":-180}

For a second battery that asks for the grid power over the network (e.g. opendtu-onbattery): enter this address and use PwrAvg. No password needed.

PwrAvg reacts slowly on purpose (it takes about a minute to follow a change). It is meant for something that should not follow every short spike. For the live value use PwrSP or sml1.

With every telemetry message (tele/<topic>/SENSOR, every TelePeriod) the program adds a block CT002: Power and L1–L3 are what the CT reports, plus Slaves, Offset and Limit. Each battery gets its own entry Bat1, Bat2 … with MAC, Phase, Power (what the battery says it delivers, + = discharge), and beside it Bat1Target … with what the CT last told that battery. Every watt value is called Power, so that Home Assistant's Tasmota integration shows it in W (e.g. CT002 L1 Power). Before 14.10.2026 L1–L3, Offset and Limit were plain numbers; sensors set up on those have to be set up again. The SML driver's own quick messages carry only the meter value, so in MQTT Explorer look at the history, or type Status 10 in the console.

"CT002":{"Power":-180,"L1":{"Power":-180},"L2":{"Power":0},"L3":{"Power":0},
         "Slaves":1,"Offset":{"Power":0},"Limit":{"Power":0},
         "Bat1":{"MAC":"aabbccddeeff","Phase":"A","Power":300},"Bat1Target":{"Power":-180}}

PwrAvg / PwrSP (MQTT) schickt alle 5 Sekunden zwei Werte per MQTT: PwrAvg, die geglättete Netzleistung, und PwrSP, das, was dieses CT den Akkus meldet (mit Offset). Beide stehen auch unter dem Schalter. /pwr liefert sie immer, auch wenn der Schalter aus ist.

MQTT

stat/<topic>/script/PwrAvg
stat/<topic>/script/PwrSP

Das sind dieselben Topics wie in den alten Scripten, vorhandene Home-Assistant-Sensoren laufen also weiter. Im MQTT Explorer: stat → <topic> → script, zum Beispiel stat/tasmota_31F8D4/script/PwrSP.

HTTP

http://<ip>/pwr
{"sml1":-440,"sml2":26714.950,"sml3":659.775,"sml4":-440,"sml5":0,"sml6":0,"PwrAvg":-217,"PwrSP":-180}

Für einen zweiten Akku, der die Netzleistung übers Netzwerk abfragt (z.B. opendtu-onbattery): diese Adresse eintragen und PwrAvg verwenden. Ein Passwort brauchst du nicht.

PwrAvg reagiert absichtlich langsam (es braucht etwa eine Minute, um einer Änderung zu folgen). Es ist für etwas gedacht, das nicht jeder kurzen Spitze folgen soll. Für den aktuellen Wert nimm PwrSP oder sml1.

Mit jeder Telemetrie (tele/<topic>/SENSOR, alle TelePeriod) hängt das Programm einen Block CT002 an: Power und L1–L3 sind das, was das CT meldet, dazu Slaves, Offset und Limit. Jeder Akku bekommt einen eigenen Eintrag Bat1, Bat2 … mit MAC, Phase, Power (was der Akku nach eigener Angabe liefert, + = Entladen), daneben Bat1Target … mit dem, was das CT diesem Akku zuletzt gemeldet hat. Jeder Wattwert heißt Power, damit die Tasmota-Integration in Home Assistant ihn in W anzeigt (z. B. CT002 L1 Power). Bis 14.10.2026 waren L1–L3, Offset und Limit einfache Zahlen. Sensoren, die darauf eingerichtet sind, musst du neu einrichten. Die schnellen Meldungen des SML-Treibers enthalten nur den Zählerwert. Schau im MQTT Explorer deshalb in den Verlauf, oder gib in der Konsole Status 10 ein.

"CT002":{"Power":-180,"L1":{"Power":-180},"L2":{"Power":0},"L3":{"Power":0},
         "Slaves":1,"Offset":{"Power":0},"Limit":{"Power":0},
         "Bat1":{"MAC":"aabbccddeeff","Phase":"A","Power":300},"Bat1Target":{"Power":-180}}

Home Assistant

Offset from Home Assistant

Automatic: the program registers the offset and Max DC with Home Assistant by itself (MQTT discovery). They appear as number fields on the Tasmota device, you do not have to set anything up. This needs MQTT discovery in Home Assistant (on by default) and Tasmota's standard FullTopic.

You can also change the offset with the command CTOffset <W>. CTOffset without a value shows the current one. Over MQTT: cmnd/<topic>/CTOffset, over HTTP: /cm?cmnd=CTOffset%20-50. The current value is also in tele/<topic>/SENSOR as "CT002":{…,"Offset":-50}. Lowest value −200 W.

A value set this way is only kept until the next restart. So an automation can change it as often as it likes without wearing out the flash memory. After a restart, the value saved on the page applies again. The field on the page shows the saved value, the value currently in use is shown right next to it. To keep a value, enter it in the field and press Save.

Without discovery you can create the field yourself in configuration.yaml (replace <topic> with the MQTT topic of your device):

mqtt:
  number:
    - name: "CT002 Offset"
      unique_id: ct002_offset
      command_topic: "cmnd/<topic>/CTOffset"
      state_topic: "tele/<topic>/SENSOR"
      value_template: >-
        {% if value_json.CT002 is defined %}{{ value_json.CT002.Offset.Power }}
        {% else %}{{ states('number.ct002_offset') }}{% endif %}
      optimistic: true
      min: -200
      max: 2000
      step: 5
      mode: box
      unit_of_measurement: "W"

Without MQTT, the same over HTTP:

rest_command:
  pv_offset:
    url: "http://<ip>/cm?cmnd=CTOffset%20{{ offset }}"

Then call rest_command.pv_offset with offset: -50. Example of an automation that sets a bigger margin at night:

automation:
  - alias: "Offset 50 W at night"
    triggers:
      - trigger: time
        at: "22:00:00"
    actions:
      - action: number.set_value
        target:
          entity_id: number.ct002_offset
        data:
          value: 50

Discharge limit

CTLimit <W> limits how much each battery may discharge. CTLimit 0 switches the limit off, CTLimit alone shows it. A negative value turns it around: CTLimit -300 makes each battery charge with at least 300 W, from the grid if there is no surplus. That only works with batteries that can charge from the mains, the Venus for example. A B2500 just stops discharging. Like the offset, it is only kept until the next restart; then the Max DC value saved on the page applies again. While a limit is active, the main page shows a Max DC row.

The limit applies to each battery separately, works on every phase setting, and a positive limit does not affect charging. While a battery searches for its phase, the limit is paused. The rest of your consumption comes from the grid.

mqtt:
  number:
    - name: "CT002 Limit"
      unique_id: ct002_limit
      command_topic: "cmnd/<topic>/CTLimit"
      state_topic: "tele/<topic>/SENSOR"
      value_template: >-
        {% if value_json.CT002 is defined %}{{ value_json.CT002.Limit.Power }}
        {% else %}{{ states('number.ct002_limit') }}{% endif %}
      optimistic: true
      min: -2500
      max: 2500
      step: 10
      mode: box
      unit_of_measurement: "W"

A limit of 0 switches the limit off, it does not stop the battery. To keep a battery at zero, use 1 W.

Offset aus Home Assistant

Automatisch: Das Programm meldet Offset und Max DC selbst bei Home Assistant an (MQTT-Discovery). Sie erscheinen als Zahlenfelder am Tasmota-Gerät, du musst nichts einrichten. Dafür muss in Home Assistant die MQTT-Discovery an sein (ist sie standardmäßig) und Tasmota das Standard-FullTopic nutzen.

Du kannst den Offset auch mit dem Befehl CTOffset <W> ändern. CTOffset ohne Wert zeigt den aktuellen an. Per MQTT: cmnd/<topic>/CTOffset, per HTTP: /cm?cmnd=CTOffset%20-50. Der aktuelle Wert steht außerdem in tele/<topic>/SENSOR als "CT002":{…,"Offset":-50}. Kleinster Wert −200 W.

Ein so gesetzter Wert gilt nur bis zum nächsten Neustart. Eine Automation darf ihn also beliebig oft ändern, ohne den Flash-Speicher abzunutzen. Nach einem Neustart gilt wieder der auf der Seite gespeicherte Wert. Das Feld auf der Seite zeigt den gespeicherten Wert, rechts daneben steht der gerade benutzte. Soll ein Wert bleiben, trag ihn ins Feld ein und drücke Speichern.

Ohne Discovery kannst du das Feld selbst in der configuration.yaml anlegen (<topic> durch das MQTT-Topic deines Geräts ersetzen):

mqtt:
  number:
    - name: "CT002 Offset"
      unique_id: ct002_offset
      command_topic: "cmnd/<topic>/CTOffset"
      state_topic: "tele/<topic>/SENSOR"
      value_template: >-
        {% if value_json.CT002 is defined %}{{ value_json.CT002.Offset.Power }}
        {% else %}{{ states('number.ct002_offset') }}{% endif %}
      optimistic: true
      min: -200
      max: 2000
      step: 5
      mode: box
      unit_of_measurement: "W"

Ohne MQTT dasselbe per HTTP:

rest_command:
  pv_offset:
    url: "http://<ip>/cm?cmnd=CTOffset%20{{ offset }}"

Dann rest_command.pv_offset mit offset: -50 aufrufen. Beispiel für eine Automation, die nachts einen größeren Abstand einstellt:

automation:
  - alias: "Offset 50 W at night"
    triggers:
      - trigger: time
        at: "22:00:00"
    actions:
      - action: number.set_value
        target:
          entity_id: number.ct002_offset
        data:
          value: 50

Entladelimit

CTLimit <W> begrenzt, wie viel jeder Akku entladen darf. CTLimit 0 schaltet die Begrenzung aus, CTLimit allein zeigt sie an. Ein negativer Wert dreht es um: CTLimit -300 lässt jeden Akku mit mindestens 300 W laden, ohne Überschuss aus dem Netz. Das geht nur mit Akkus, die aus dem Netz laden können, zum Beispiel dem Venus. Ein B2500 entlädt dann einfach nicht mehr. Wie der Offset gilt sie nur bis zum nächsten Neustart, danach gilt wieder der auf der Seite gespeicherte Wert Max DC. Solange eine Begrenzung aktiv ist, zeigt die Hauptseite eine Zeile Max DC.

Die Begrenzung gilt für jeden Akku einzeln, wirkt bei jeder Phaseneinstellung, und ein positiver Wert lässt das Laden in Ruhe. Während ein Akku seine Phase sucht, ist sie ausgesetzt. Den Rest deines Verbrauchs liefert das Netz.

mqtt:
  number:
    - name: "CT002 Limit"
      unique_id: ct002_limit
      command_topic: "cmnd/<topic>/CTLimit"
      state_topic: "tele/<topic>/SENSOR"
      value_template: >-
        {% if value_json.CT002 is defined %}{{ value_json.CT002.Limit.Power }}
        {% else %}{{ states('number.ct002_limit') }}{% endif %}
      optimistic: true
      min: -2500
      max: 2500
      step: 10
      mode: box
      unit_of_measurement: "W"

Ein Limit von 0 schaltet die Begrenzung aus, es hält den Akku nicht an. Um einen Akku bei null zu halten, nimm 1 W.

Marstek accountMarstek-Konto

A battery only talks to a CT that exists in your Marstek account. The program can create such a CT in your account for you (the same way AstraMeter does it).

  1. Press ☁️ Marstek in the Tasmota main menu and enter your Marstek e-mail and password.
  2. Press Log in + check account. If there is already a CT created this way, it is taken over.
  3. If none was found: press Create fake CT and confirm. The status line turns green when it worked.
  4. In the Marstek app, refresh the CT list (if needed, log out and in again), select the new CT and set the battery to automatic.

Create is greyed out while a CT MAC is set. Clear CT MAC at the bottom of the same page clears it. That only clears the MAC on the device. The CT in your Marstek account stays and must be deleted in the app.

Good to know

  • The CT shows as offline in the app, and its values show --. That is normal and does not affect the regulation: the battery talks to the CT directly in your home network, while the app gets its display from the Marstek cloud, and the program never connects to that.
  • Only create one CT. If there are several, the app may use a different one than your device answers for.

Your password goes unencrypted through your home network from the browser to the device. It is not saved on the device, it is kept in memory for 10 minutes and deleted after the CT has been created.

Creating the CT uses an undocumented Marstek interface with your own account. That may be against Marstek's terms of use. It is your account and your risk. In the worst case, Marstek removes the device or takes action against the account.

Ein Akku spricht nur mit einem CT, das in deinem Marstek-Konto existiert. Das Programm kann so ein CT für dich in deinem Konto anlegen (genau wie AstraMeter es macht).

  1. Im Tasmota-Hauptmenü auf ☁️ Marstek drücken und deine Marstek-E-Mail und dein Passwort eintragen.
  2. Log in + check account drücken. Gibt es schon ein so angelegtes CT, wird es übernommen.
  3. Wurde keins gefunden: Create fake CT drücken und bestätigen. Die Statuszeile wird grün, wenn es geklappt hat.
  4. In der Marstek-App die CT-Liste aktualisieren (notfalls ab- und wieder anmelden), das neue CT auswählen und den Akku auf Automatik stellen.

Create ist ausgegraut, solange eine CT MAC eingetragen ist. Clear CT MAC unten auf derselben Seite löscht sie. Das löscht nur die MAC auf dem Gerät. Das CT in deinem Marstek-Konto bleibt und muss in der App gelöscht werden.

Gut zu wissen

  • Das CT steht in der App auf offline, und seine Werte zeigen --. Das ist normal und stört die Regelung nicht: Der Akku spricht direkt in deinem Heimnetz mit dem CT, die App holt ihre Anzeige aber aus der Marstek-Cloud, und mit der verbindet sich das Programm nie.
  • Lege nur ein CT an. Gibt es mehrere, nutzt die App vielleicht ein anderes, als dein Gerät bedient.

Dein Passwort geht unverschlüsselt durch dein Heimnetz vom Browser zum Gerät. Es wird nicht auf dem Gerät gespeichert, bleibt 10 Minuten im Arbeitsspeicher und wird nach dem Anlegen gelöscht.

Das Anlegen nutzt eine nicht offizielle Marstek-Schnittstelle mit deinem eigenen Konto. Das kann gegen die Nutzungsbedingungen von Marstek verstoßen. Es ist dein Konto und dein Risiko. Im schlimmsten Fall entfernt Marstek das Gerät oder geht gegen das Konto vor.

Console commandsKonsolen-Befehle

CTSTAT            rx/tx/bad counters, one log line per battery
CTCLR             clear the battery table
CTOFFSET [W]      set the offset until restart (no value = show it)
CTLIMIT [W]       discharge limit per battery until restart, 0 = off, <0 = charge
CTMAC <hex12>     set the CT MAC (empty = answer every battery)
CTMAIL <address>  set the Marstek account e-mail
CTPASS <password> set the password (not saved)
CTLOGIN           step 1: log in
CTCREATE JA       step 2: create the CT (JA confirms)

Log messages are always in English, so they are easier to compare when you ask for help.

Log-Meldungen sind immer englisch. So lassen sie sich leichter vergleichen, wenn du um Hilfe fragst.

TroubleshootingFehlersuche

rx stays 0No battery is asking. The battery is not set to this CT, or it lost the connection. In the app, switch the mode (automatic off and on again). After a program restart the battery does not always find the CT again by itself.
bad counts upRequests arrive broken. Please save the log with weblog 4 and contact me.
Battery shows Ph xIt is still searching for its phase. See Battery.
All values 0 WNo meter values. Check Meter active, pins and meter, see Meter.
App shows --That is normal. See Marstek account.
rx bleibt 0Kein Akku fragt. Der Akku ist nicht auf dieses CT eingestellt oder hat die Verbindung verloren. In der App den Modus umschalten (Automatik aus und wieder ein). Nach einem Neustart des Programms findet der Akku das CT nicht immer von selbst wieder.
bad zählt hochAnfragen kommen kaputt an. Bitte das Log mit weblog 4 sichern und dich bei mir melden.
Akku zeigt Ph xEr sucht noch seine Phase. Siehe Akku.
Alle Werte 0 WKeine Zählerwerte. Zähler aktiv, Pins und Zähler prüfen, siehe Zähler.
App zeigt --Das ist normal. Siehe Marstek-Konto.