Projekt: Smarter Elekrozähler

Ein digitaler Zähler

Hurra, nun bin ich auch in der digitalen Welt angekommen. Seit einigen Wochen hängt bei uns ein digitaler "Stromzähler". Die alte Drehscheibe wurde in Rente geschickt.
Bei dem Gerät handelt es sich um den Typ: EasyMeter Q3A / Drehstrom-Zweirichtungszähler.
Es ist kein Kommunikationsmodul angeschlossen, d.h. der Zähler ist nicht „smart“. Es werden keine Daten nach außen gesendet oder von außerhalb empfangen und das ist gut so.

Ein Wechsel in die digitale Generation legt die Vermutung nahe, dass nun Informationen abrufbar sind, die der alte Ferraris-Zähler nicht liefern konnte.

Ein erster Check brachte zwei Erkenntnisse:

1. Ohne Bedienungsanleitung geht es nicht.
2. So wie er dort hängt, verrät er weniger als der alte Zähler.

Es werden erst einmal nur die beiden Zählerstände (Bezug und Lieferung) angezeigt und die zu allem Überfluss auch noch abwechselnd innerhalb einer Zeile, obwohl das LCD-Display über eine zweite Zeile verfügt.
Beim alten Ferraris ließ sich an der Rotationsgeschwindigkeit der Scheibe die aktuelle Leistungsaufnahme abschätzen. Der neue verrät nicht einmal das.

Weitere Informationen rückt der Zähler erst nach Eingabe eines 4-stelligen Pincodes heraus. Die Anforderung der Pin war beim Messstellenbetreiber problemlos per Webformular möglich. Kaum 2 Wochen hat es gedauert und schon lag das Schreiben mit der Pin im Briefkasten.

Mal abgesehen davon, dass Pin-Eingabe und weitere Bedienung nicht so leicht von der Hand gehen (alles erfolgt durch anblinken mit einer Taschenlampe), werden als Zusatzinformationen über das Display nur die aktuelle Gesamtwirkleistung sowie historische Zählerstände geliefert.
Nun hängt hier ein Gerät, das dem Stromanbieter zwar alles Notwendige zur Abrechnung bereitstellt, mir aber nur wenige Informationen zur Energieeinsparung preisgibt.

An weitere Messwerte kommt man nur über das Mitlesen von Daten einer Infrarot-LED.
Bei der Recherche nach dem "Wie" zeigte sich, dass es im deutschen Energienetz eine überschaubare Anzahl von Anbietern solcher Geräte gibt. Die meisten Hersteller vertreiben jedoch unterschiedliche Modelle und innerhalb eines Modells (so zumindest beim Q3A von EasyMeter) sind unterschiedliche Konfigurationen zu finden. Eine Universallösung ist damit kaum machbar.
Die Gemeinsamkeit besteht darin, dass sich alle Anbieter an das SML-Protokoll des BSI zu halten haben.

Eine Fundgrube rund um dieses Thema ist das Forum „volkszähler.de“. Von den fertigen, im Netz zu findenden Lösungen passte allerdings nichts zu meinen Vorstellungen und Gegebenheiten.

testbild

Ziel ist der Aufbau eines Messstellenadapters (MSA), der die IR-Daten permanent einliest, auswertet, archiviert und als MQTT-Daten per WLan in das lokale Netzwerk sendet.
Hier läuft auf einem Raspi bereits ein MQTT-Server, der sich um das Sammeln und Verteilen von Daten im "SmartHome" kümmert. Die Visualisierung der Zählerdaten erfolgt über eine Node-Red-Instanz auf dem gleichen Raspi und Darstellung im Browser.

Kernstück des MSA ist ein ESP32 mit nur wenig Außenbeschaltung. Selbst wenn alle Teile neu über den Versandhandel beschafft werden müssten, sollte dies für unter 10€ möglich sein (ohne Versandkosten).

Im Ergebnis liefert das Gerät die aktuellen Zählerstände, die Gesamt-Wirkleistung, Wirkleistungen der Einzelphasen und Spannungen der Phasen gegen Null.
Die Ausgabe der Zählerstände erfolgt im Minutentakt. Die Live-Daten lassen sich in beliebigen Zeitabständen (>= 1 Sek) abrufen.


Als Erstlingswerk auf dem ESP32 ist dieses Projekt sicher nicht geeignet. Die Lernphasen „Hello World“ und „Hurra die LED blinkt“ sollte man schon hinter sich haben.

Nach dem Stöbern in einigen Foren scheinen mir vorab zwei grundsätzliche Bemerkungen angebracht:

Der Zähler ist Eigentum des Messstellenbetreibers (MSB). Das Gerät darf nicht beschädigt und es dürfen keine Siegel entfernt werden !

Der Zähler ist Teil der Niederspannungsanlage. Bei allen Arbeiten und Experimenten muss sichergestellt sein, dass es zu keinen Berührungen mit spannungsführenden Teilen der NS-Anlage kommen kann. Achtung - Lebensgefahr !

Schnittstellen des Q3A

testbild

Der Zähler Q3A verfügt über mehrere optische Daten-Schnittstellen, die im Folgenden kurz beschrieben werden.
Andere elektrische Schnittstellen oder mechanische Taster sind nicht vorhanden bzw. zugänglich. Auf diese Weise lässt sich die Schutzklasse II leichter erreichen und wird die Störanfälligkeit verbessert.

Alles was sich hinter Siegeln verbirgt, ist für den Anwender tabu.


Quelle Foto


MSB-Schnittstelle

Auf der Oberseite des Zählers ist die MSB-Schnittstelle (MSB = Messstellenbetreiber) zu finden, die aber nach Recherchen in Foren bei den meisten Anwendern versiegelt ist, so auch bei mir.
Es handelt sich um eine bidirektionale IR-Schnittstelle, über die der MSB ein Kommunikationsmodem koppeln kann.

Im cc2.tv / Folge333 wurde diese Schnittstelle ausgabeseitig näher untersucht (vermutl. war sie nicht versiegelt ?). Es wird gezeigt, dass sich die verfügbaren Daten auf einfache Weise auslesen lassen.

Aber wie gesagt, ist der Bereich am Gehäuse mit einen Aufkleber geschützt. Eine Nachfrage beim Betreiber habe ich mir auf Grund der zu erwartenden Antwort erspart. Außerdem möchte ich einen Eintrag in meine Akte „spielt an seinem Zähler rum“ vermeiden.

Man kommt auch auf anderem Wege an den gleichen Datensatz, nur nicht so einfach.



Info-Datenschnittstelle (Info-DSS)

Vorn links sendet eine Infrarot-LED permanent Datenpakete. Dies soll sich mit einigen Smartphone-Kameras sichtbar machen lassen. Alternativ testen lässt sich die Funktion mit einer Reihenschaltung aus Vorwiderstand, Fototransistor und LED. Wenn alles richtig dimensioniert und gepolt an eine Spannungsquelle gelegt wird, sollte die LED im Sekundentakt blinken.

Die Info-DSS ist in der Bedienungsanleitung des Herstellers ausdrücklich als Schnittstelle für den Endkunden bezeichnet. Da ich das Teil gemietet habe, sehe ich mich als solcher.

Die Daten werden asynchron mit 9600 baud / 8N1 übertragen. Es werden permanent Telegramme im 1-Sek-Takt gesendet.
In der Grundstellung sind allerdings nur Zählerstände (abgerundet auf volle kWh) enthalten. Um an den vollständigen Datensatz zu kommen, muss die Pin aktiv sein.

Einige Hersteller spendieren ihren Zählern an dieser Stelle eine Metallplatte, um den Lesekopf magnetisch befestigen zu können. Diesen Service hat die Fa. EasyMeter beim Q3A eingespart. Für erste Experimente reicht ein Moosgummistreifen, in dem der IR-Fototransistor steckt. Befestigt man das ganze mit Tesafilm an der Frontseite, lässt es sich später rückstandsfrei entfernen. Beim Kleben aber auf die Siegel achten!



Optischer Prüfausgang (Telemetrie)

Auf der Frontseite in der Mitte befindet sich eine weitere IR-LED, die Impulsfolgen abhängig von der aktuellen Wirkleistung sendet. Vergleichbar ist dies mit der Drehgeschwindigkeit der alten Scheibe. Wer nur den momentanen Leistungsbezug benötigt, hätte hier einen passenden Ansatz.



Optische Taster

Auf der rechten Frontseite sitzt ein Fototransistor, der auf weißes Licht (400Lx) reagiert. Durch anblinken dieses Elementes werden Eingaben angenommen, bspw. die Pin.
Für den Anwender ist die Bedienung allerdings ....., ggf. sollte man zuvor seinen Kaffee-Konsum einschränken.
Bedienungsanleitungen sind beim Hersteller zu finden.

Pin & Zählerkonfiguration

Über die Info-DSS werden im Regelfall nur Kurztelegramme mit eingeschränktem Datensatz gesendet. Um an die Langtelegramme zu kommen, muss die Pin aktiviert sein.
Eigentlich kein Problem..., der Haken:
Der Zähler vergisst nach 2min die Pin wieder und die Info-DSS fällt zurück auf Kurztelegramme.

Lt. Betriebsanleitung gibt es im Anwender-Menu zwei Punkte, mit denen sich dieses Verhalten beeinflussen lässt:

INFO-Schnittstelle Datensatz on/off
PIN Schutz Status on/off

Der nächste Haken:
Diese beiden Optionen lassen sich bei der Bestellung durch den MSB in der Firmenkonfiguration ausblenden. Hat der MSB die Teile ohne diese Optionen liefern lassen, hat man Pech und im Endeffekt einen höheren Aufwand, um permanent an die Langtelegramme zu kommen.
Informationen über die Varianten und Konfigurationsmöglichkeiten sind auf den Webseiten des Herstellers zu finden.

Die Lösung:
Die Vergesslichkeit startet nicht mit Eingabe der Pin, sondern mit dem Empfang des letzten optischen Signals. Blinkt man den Zähler je 90Sek einmal an, bleibt die Pin aktiv.
Einfaches anblinken führt allerdings zur Weiterschaltung der Anzeigefunktion, sodass zumeist irgendwelche Historiendaten, aber keine Zählerstände im Display mehr anzeigt werden.
Der Zähler unterscheidet kurze und lange optische Signale.
Ein Lichtzeichen > 5 Sek wird als „Langer Tastendruck“ gewertet, resetet den Pin-Timeout, bewirkt aber keine Weiterschaltung der Anzeigefunktion.
Das bedeutet allerdings, dass ein zweiter LED-Kopf an der Zählerfront befestigt werden muss.

In der ESP-SW wird das Problem folgendermaßen gelöst:
Sobald ein Kurztelegramm erkannt wird, startet die Pin-Prozedur und blinkt gemächlich die Pin ein. Werden Langtelegramme erkannt, folgt alle 90 Sek ein Lichtzeichen für 5,5Sek. Auf diese Weise bleibt die Pin aktiv und die Anzeige stabil. In der oberen LCD-Zeile werden abwechselnd die beiden Zählerstände angezeigt, in der unteren die aktuelle Wirkleistung.

Etwas umständlich, aber es geht.

Grundsätzliches

Die drei ???

Bevor man über die praktische Umsetzung nachdenkt, sollte geklärt werden, ob das Ganze im eigenen Umfeld überhaupt realisierbar ist.

1. Montageplatz

Der ESP32 samt minimaler Außenbeschaltung nimmt nicht viel Platz weg. Die Tür des Zählerschrankes sollte sich mit aufgesetzten LED-Köpfen aber noch schließen lassen.


2. WLan - Verbindung

Der ESP ist permanent mit dem Router verbunden. Eine stabile WLan-Verbindung zum nächsten Accesspoint muss möglich sein. Ist der Zähler in einem Blechschrank eingebaut, so ist bei geschlossener Tür mit erheblicher Signaldämpfung zu rechnen. Auch Einbaulage und Position des ESP haben in solchem Umfeld einen signifikanten Einfluss auf die zu erwartende Feldstärke.

Der Test kann mit einer beliebigen WLan-SW aus den IDF-Examples durchgeführt werden. Alternativ lässt sich auch die MSA-Firmware auf einen NodeMCU flashen. Diesen (kurzschlussfrei) in den Zählerschrank gehängt und die am Router anliegende Feldstärke prüfen.

Meine Erfahrungen bei der Empfangsfeldstärke der Fritzbox 7490:

kleiner -80dBm wird zu Problemen führen
größer -75dBm ist Ok
größer -70dBm läuft problemlos

In der Grundkonfiguration sendet der EPS32 mit seiner Maximalleistung von 20dBm (100mW). In den Konfigurationseinstellungen (Component config → PHY) lässt sich dieser Wert bis auf 10dBm (10mW) reduzieren. Wenn auch damit eine stabile Verbindung möglich ist, lässt sich der Punkt abhaken.


3. Stromversorgung

Der ESP läuft im Dauerbetrieb und gönnt sich dabei etwa 300mW. Das kann im Testbetrieb eine Powerbank für einige Stunden leisten. Im Dauerbetrieb ist aber nur Netzbetrieb sinnvoll.

Mit einer Service-Steckdose im Zähler- / Verteilerschrank lässt sich das Gerät problemlos über ein Steckernetzteil versorgen. In meinem Fall ist die Sekundärseite des 12V-AC Klingeltrafo zugänglich. Bastelarbeiten sind an dieser Stelle problematisch. Wie auch immer geartete Eingriffe in die Niederspannungsanlage darf nur ausführen, wer dazu qualifiziert ist.


Fazit

Sollten hier jetzt keine 3 Ausrufezeichen stehen, lassen sich die LED-Köpfe auch über einige Meter vom ESP absetzen. Oder alternativ die Daten nicht per WLan, sondern kabelgebunden übertragen und vom Ziel die StrV über eine Doppelader Kabel beziehen.
Möglichkeiten gibt es bestimmt viele.

Datentelegramme

Smart-Meter-Language

Grundsätzlich müssen sich alle am deutschen Stromnetz eingesetzten digitalen Hauptzähler an die Technische Richtlinie TR-03109-1 des BSI halten. Es lohnt sich schon mal da rein zu schauen. Eine tiefgehende Analyse wäre aber übertrieben, da nur einige Daten ausgefiltert werden sollen.
Lange Passagen, in denen es um das XML-Format und Version 2 geht, können getrost übersprungen werden.

Sehr hilfreich zum Verständnis sind die Blogs von Roland und Stefan , die sich mit dem Aufbau der SML-Telegramme auseinandergesetzt haben.
Auf die Gefahr, dass ich mich wiederhole, hier ein paar Grundlagen:

Die SML-Richtlinie unterscheidet vorerst die Protokollversionen V1 und V2. Für höhere Versionen sind Platzhalter vorhanden. Im vorliegenden Fall geht es ausschließlich um die V1. Mit höheren SML-Versionen kann diese ESP-SW nichts anfangen.

Mein Zähler sendet über die Info-DSS Kurztelegramme mit 264 Bytes und Langtelegramme mit 440 Bytes. Dies nur zur Veranschaulichung der zu erwartenden Datenmenge. Die tatsächliche Länge ist abhängig von den zu übertragenden Daten.

Ein Datenpaket beginnt immer mit der Escape-Sequenz (4* 0x1B) gefolgt von der Protokollversion (4* 0x01)

1B 1B 1B 1B 01 01 01 01

Alle folgenden Bytes werden als Daten interpretiert und auf die Schluss-Sequenz untersucht.

1B 1B 1B 1B 1A XX YY ZZ

Nach erkennen von 0x1B 0x1B 0x1B 0x1B 0x1A werden noch die 3 folgenden Bytes gelesen und der Block als vollständig erklärt.

Sollte zufällig innerhalb des Datenstromes die Folge von 4* 0x1B auftreten, so werden diese durch eine zusätzliche Escapesequenz maskiert. D.h. es werden in dieser Stelle 8* 0x1B gesendet. Der Parser muss 4* 0x1B erkennen und an der 5. Position entscheiden, ob dort 0x1A steht und damit das Paket beenden oder 0x1B und an dieser Stelle die Datenaufzeichnung fortsetzen.

Die Bytes der Schluss-Sequenz haben folgende Bedeutung:

XX - Anzahl der Füllbytes. Wertebereich: 0x01 .. 0x03
YY - Low-Byte der CRC16 - Prüfsumme
ZZ - High-Byte der CRC16 - Prüfsumme

Die Datenlänge muss durch 4 teilbar sein. Um dies zu erreichen, werden vor der Schluss-Sequenz ggf. Füll-Bytes (0x00) eingefügt.

Die Prüfsumme wird über den gesamten Block vom ersten 0x1B bis incl. XX erstellt.

Berechnet wird der Wert über das CCITT Polynom x16+x12+x5+1 ==> 0x1021.
Beim ESP32 muss hier nicht viel Aufwand getrieben werden. Er bringt die ROM-Funktion „crc16_le“ mit, die nach diesem Polynom rechnet.
Es ist wichtig zu wissen, dass YY das niederwertige und ZZ das höherwertige Byte ist. In der Richtlinie des BSI (S.68/69) ist dies genau anders herum festgelegt.

Nach erfolgreicher Prüfung wird das Telegramm intern an den SML-Filter weitergereicht.

Datenanalyse

Hier der Hexdump eines Langtelegramms des Q3A:

Server-ID und Seriennummer sind willkürlich geändert.

Hellgrün hinterlegt sind die Start- und Schlusssequenz. In Dunkelgrün ein Datensatz, der im Folgenden näher betrachtet werden soll.

77 
  07 01 00 01 08 00 ff        -- objName
  64 00 00 80                 -- status
  01                          -- valTime
  62 1e                       -- unit
  52 fc                       -- scaler
  59 00 00 00 01 f0 99 7d e7  -- value
  01                          -- valueSignature


SML-Struktur

Jeder Eintrag startet mit einem TL-Byte (Typ & Länge). Die 1.Ziffer (Bit 7..4) gibt den Datentyp an.

0 - Octet String oder einfach: Bytefolge (0 .. 14 Bytes)
4 - Boolean (false = 0x00 / true <> 0x00)
5 - Signed Integer (I8 / I16 / I32 / I64) 
6 - Unsigned Integer (U8 / U16 / U32 / U64)
7 - Liste

Die zweite Stelle (Bit 3..0) ist die Längeninformation. Damit das Ganze nicht so einfach ist, wird dieser Wert unterschiedlich interpretiert:
Bei Listen (Typ 7) folgen n Listeneinträge. Bei allen anderen Typen folgen n-1 Bytes, da in diesem Fall das TL-Byte in der Längenangabe mitgezählt wird.

Das 1. Byte hinter der Start-Sequenz (0x76) bedeutet : Es folgt eine Liste mit 6 Einträgen.

Einige Besonderheiten:
Die Länge eines Eintrags wäre damit auf 14 Bytes begrenzt. Bei längeren Daten folgt dem TL-Byte ein zusätzliches Längenbyte und Bit 7 des TL wird auf 1 gesetzt. Da das bei dieser Auswertung nicht vorkommt, verzichte ich auf weitere Erläuterungen.

Listen können selbst wieder Listen enthalten. So kommt es zu Verschachtelungen. Die gesuchten Messwerte sind in diesem Beispiel in der 5.Ebene zu finden.

Eine weitere Besonderheit ist das TL-Byte 0x01. Das sagt aus: Es folgen 0 Bytes.
Dieser Wert wird immer eingesetzt, wenn das Protokoll grundsätzlich einen Eintrag an dieser Stelle verlangt, aber im speziellen Fall nichts angegeben werden soll (optional)

Auf unser obiges Beispiel angewandt bedeutet dies:

77                            -- Liste mit 7 Einträgen
  07 01 00 01 08 00 ff        -- Folge von 6 Bytes
  64 00 00 80                 -- uint24 ???
  01                          -- optional
  62 1e                       -- uint8
  52 fc                       -- int8
  59 00 00 00 01 f0 99 7d e7  -- int64
  01                          -- optional

Eine Merkwürdigkeit findet sich in der 3. Zeile.
Der Q3A gibt als Statusinformation bei Zählerständen einen unsigned Integer mit 3 Bytes, also uint24 aus. Dieser Typ ist im SML-Protokoll nicht definiert.
Da der Wert immer 0x000080 zu sein scheint und die Bedeutung mir unklar ist, wird dieser Eintrag ignoriert.

Eine Zusammensetzung der beiden Interpretationen angereichert mit Detailinformationen ergibt folgendes Bild:

77                            -- Beginn der Daten-Liste eines Wertes
  07 01 00 01 08 00 ff        -- OBIS-Kennziffer 1.8.0 (Zählerstand Bezug, tariflos)
  64 00 00 80                 -- Status 128
  01                          -- frei
  62 1e                       -- Maßeinheit: Wh
  52 fc                       -- Multiplikator: 10^-4
  59 00 00 00 01 f0 99 7d e7  -- Wert: 8331558375
  01                          -- frei

Dieser Datensatz hat somit folgende Aussage:
Zählerstand Bezug: 8331558375 *10⁻4 = 833155,8375 Wh oder 833,2 kWh.

Die Bedeutung der Maßeinheiten habe ich aus verschiedenen Quellen zusammengetragen. Hier die interessierenden:

  • 0x1E: elektrische Arbeit in Wh
  • 0x1B: Wirkleistung in W
  • 0x23: Spannung in V

Mit der Kenntnis, dass das erste Byte im Datenblock ein TL-Byte ist, könnte man sich von Eintrag zu Eintrag hangeln und untersuchen, ob relevante Daten enthalten sind.
Hier der Versuch einer Gesamtinterpretation des Datenblocks. Es sind 3 Messages enthalten. Nur in der zweiten stecken interessante Daten.

1b 1b 1b 1b                                 -- ESCAPE - Sequenz
01 01 01 01                                 -- Version 1

76                                          -- Message "open"
    0b 45 53 59 41 4e b9 00 f5 19 2b        -- Message-ID -> ESYAN + fortlfd. Zählnummer
    62 00                                   -- groupNo
    62 00                                   -- abortOnError
    72                                      -- messageBody
        63 01 01                            -- OpenResponse
        76 
            01 
            04 45 53 59                     -- ESY
            08 45 53 59 b3 0f 19 2b         -- 2x 16-Bitzäher je Telegramm - ESY - b30f | 192b
            0b 09 01 45 53 59 22 14 cf e4 9b -- Server - ID (*)
            01 
            01 
    63 4a 9b                                -- CRC16 Message, Msg-length - 4,  (*)
    00                                      -- End of Message

76                                          -- Message "list"
    0b 45 53 59 41 4e b9 00 f5 19 2c        -- Message-ID -> ESYAN + fortlfd. Zählnummer
    62 00 
    62 00 
    72 
        63 07 01                            -- GetListResponse
        77 
            01 
            0b 09 01 45 53 59 22 14 cf e4 9b -- Server -ID (*)
            08 01 00 62 0a ff ff 00 
            72 
                62 01                       -- ggf. Boot-Zähler ???
                65 00 51 b3 0f              -- Runtime in Sek (Anz Datenpakete)
            7d                              -- Datenliste, 14 Einträge
                77 
                    07 81 81 c7 82 03 ff 
                    01 
                    01 
                    01 
                    01 
                    04 45 53 59             -- ESY
                    01 
                77 
                    07 01 00 00 00 09 ff 
                    01 
                    01 
                    01 
                    01 
                    0b 09 01 45 53 59 22 14 cf e4 9b -- Server - ID (*)
                    01 
                77 
                    07 01 00 01 08 00 ff    -- OBIS 1.8.0 - Zählerstand Bezug, tariflos
                    64 00 00 80             -- Status 24Bit ???
                    01      
                    62 1e                   -- Maßeinheit Wh
                    52 fc                   -- Multiplikator 10^⁻4
                    59 00 00 00 01 f0 99 7d e7 -- Wert 8331558375
                    01 
                77 
                    07 01 00 02 08 00 ff    -- OBIS 2.8.0 - Zählerstand Lieferung, tariflos
                    64 00 00 80 
                    01 
                    62 1e
                    52 fc 
                    59 00 00 00 00 00 21 0d 8a 
                    01 
                77 
                    07 01 00 10 07 00 ff    -- OBIS 10.7.0 - Wirkleistung Total
                    01 
                    01 
                    62 1b                   -- W
                    52 fe                   -- * 10^-2
                    59 00 00 00 00 00 00 4c e7 -- 19687
                    01 
                77 
                    07 01 00 24 07 00 ff   -- OBIS 24.7.0 - Wirkleistung L1 
                    01 
                    01 
                    62 1b
                    52 fe 
                    59 00 00 00 00 00 00 48 c5 
                    01 
                77 
                    07 01 00 38 07 00 ff    -- OBIS 38.7.0 - Wirkleistung L2
                    01 
                    01 
                    62 1b 
                    52 fe 
                    59 00 00 00 00 00 00 03 92 
                    01 
                77 
                    07 01 00 4c 07 00 ff    -- OBIS 4C.7.0 - Wirkleistung L3
                    01 
                    01 
                    62 1b
                    52 fe 
                    59 00 00 00 00 00 00 00 8f 
                    01 
                77 
                    07 01 00 20 07 00 ff    -- OBIS 20.7.0 - Spannung L1
                    01 
                    01 
                    62 23                   -- V
                    52 ff                   -- * 10⁻1
                    63 08 fc                -- 2300
                    01 
                77 
                    07 01 00 34 07 00 ff    -- OBIS 34.7.0 - Spannung L2
                    01 
                    01 
                    62 23 
                    52 ff 
                    63 08 ee 
                    01
                77 
                    07 01 00 48 07 00 ff    -- OBIS 48.7.0 - Spannung L3
                    01 
                    01 
                    62 23 
                    52 ff 
                    63 08 fa 
                    01 
                77 
                    07 01 00 00 00 00 ff 
                    01 
                    01 
                    01 
                    01 
                    0f 31 45 53 59 31 31 36 32 36 30 37 41 73 58 -- Zähler S/N (*)
                    01 
                77 
                    07 81 81 c7 f0 06 ff 
                    01 
                    01 
                    01 
                    01 
                    04 21 07 0e             -- fix bei Langtelegrammen (Kurztlg: 31 07 0e)
                    01 
            01
            01 
    63 14 ac                                -- CRC16 Message, Msg-length - 4,  (*)
    00                                      -- End of Message


76                                          -- Message "close"
    0b 45 53 59 41 4e b9 00 f5 19 2d        -- Message-ID -> ESYAN + fortlfd. Zählnummer
    62 00 
    62 00 
    72 
        63 02 01                            -- CloseResponse
        71 
            01  
    63 a7 4a                                -- CRC16 Message, Msg-length - 4,  (*)
    00                                      -- End of Message

00                                          -- Füllbyte      

1b 1b 1b 1b                                 -- Escape-Sequenz
1a                                          -- Ende-Kennung 
01                                          -- Anz. Füllbytes
ec 62                                       -- CRC16 Gesamt-Telegramm (*)

(*) - Wert geändert



SML-Filter

Ein Parser, der sich durch den kompletten Baum arbeitet, schien mir an dieser Stelle übertrieben. Die interessierenden Daten treten immer in Listen mit 7 Einträgen nach folgender Start-Struktur auf:

77 07 01 00 UU VV WW ff
77 - TL-Byte, alle relevanten Daten werden in Listen mit 7 Einträgen geliefert.
07 - TL-Byte, die erste Bytefolge besteht immer aus 6 Bytes
01 - Elektrozähler
00 - Kanal (immer 0)
UU - Messgröße
VV - Messart
WW - Tarifstufe
FF - Ende-Kennzeichen

Nach folgenden variablen Kriterien (OBIS-Kennziffern) wird gesucht:

UU VV WW	OBIS   Bedeutung 
----------------------------------------
01 08 00	 1.8.0 Zählerstand Bezug
02 08 00	 2.8.0 Zählerstand Lieferung
10 07 00	10.7.0 Wirkleistung total
24 07 00	24.7.0 Wirkleistung L1
38 07 00	38.7.0 Wirkleistung L2
4c 07 00	4C.7.0 Wirkleistung L3
20 07 00	20.7.0 Spannung L1
34 07 00	34.7.0 Spannung L2
48 07 00	48.7.0 Spannung L3

Mein Zähler kennt keine Tarifunterschiede. Bei Geräten, die Haupt- und Nebentarif unterscheiden, müssen die Suchkriterien erweitert und die SW angepasst werden.
Am Ende der Bytefolge hängt noch ein 0xFF. Das scheint nicht spezifiziert zu sein, ist jedoch immer vorhanden und wird daher in die Suchmaske einbezogen.

Bei dieser Suchmethode sind Fehlinterpretationen zwar möglich, aber unwahrscheinlich.

Datenverarbeitung

Bei den im Datentelegramm gefundenen Werten wird unterschieden nach Zählerständen und "Live"-Daten. Nicht vorhandene Daten werden in der Ausgabe grundsätzlich ignoriert. Je nach Zählerkonfiguration ist es bspw. möglich, dass keine Spannungen geliefert werden.


Zählerstände

Die Zählerstände der OBIS-Kennziffern 1.8.0 / 2.8.0 werden zur vollen Minute in einen JSON-String verpackt und als MQTT-Payload an den Server geschickt. Folgendes Format ist zu erwarten:

{
  "ts": 1676739120,     # Timestamp, Unix-Time UTC in Sek
  "xa": 993918.8881,    # Zähler Bezug in Wh
  "xb": 216.6154        # Zähler Lieferung in Wh
}

Weiterhin werden diese Werte (ebenfalls zur vollen Minute) im ESP gespeichert.
Einerseits in einem Stundenpuffer, der im RAM liegt. Der Zeiger auf diesen Speicher wird zur vollen Stunde weiter geschaltet, sodass der Stand der 59.Minute jeder Stunde erhalten bleibt. Der Speicher ist als Ringpuffer für 256 Datensätze ausgelegt, sodass die Stundendaten der letzten 10Tage abrufbar sind. Aus der Differenz zur jeweils vorhergehenden Stunde lässt sich der Stundenverbrauch ermitteln. Der Abruf erfolgt per MQTT-Kommando. Nach einem Stromausfall oder Reset sind diese Daten allerdings verloren.

Andererseits werden die Zählerdaten im Flash in Tagesdatensätzen gespeichert. Die Werte eines Tages um jeweils 23:59 Uhr bleiben dauerhaft erhalten und überstehen selbst einen Firmwarewechsel. Nur nach Änderung der Datenstruktur in der SW oder einem Flash-Erase gehen die Daten verloren. Der reservierte Speicher sollte für etwa 25 Jahre reichen (nur berechnet, nicht getestet). Der Datenabruft erfolgt ebenfalls per MQTT-Kommando. Einzelheiten versuche ich in der Readme.md des Projektes auf Codeberg zu erläutern.



Livedaten

Livedaten sind: Gesamtwirkleistung, Wirkleistungen der drei Phasen sowie Spannungen der Phasen. Diese Daten werden, wie auch die Zählerstände, zwar jede Sekunde aktuell über die IR-Diode geliefert. Um den Trafic am MQTT-Server nicht unnötig zu erhöhen, erfolgt die Sendung nur nach Anforderung. Hierfür ist das Frontend zuständig, bspw. wenn die zugehörige Webseite geöffnet wird. Als Payload wird eine Zahl erwartet, die die Taktrate in Sekunden angibt. Die minimale Zeit beträgt eine Sekunde. Bei größeren Abständen wird das arithmetische Mittel der Einzelwerte gebildet. Erfolgt in einer Zeitspanne von 5min keine erneute Anforderung, wird die Aussendung abgebrochen. Die Livedaten werden in der Grundstellung mit einem Interval von 1h gesendet.

Ein JSON-String mit Live-Daten sieht folgendermaßen aus:

{
  "ts": 1676739883,  # Timestamp
  "pt": 263.69,      # Wirkleistung Total
  "p1": 224.67,      # Wirkleistung L1
  "p2": 37.25,       #   L2
  "p3": 1.76,        #   L3
  "u1": 230.5,       # Spannung L1
  "u2": 229.96,      #   L2
  "u3": 230.74,      #   L3
  "cnt": 5           # Anzahl der gemittelten Daten
}

Versuchsaufbau


Hardware


Für erste Versuche sollte ein NodeMCU-ESP32 auf einem Steckbrett genügen. Hier ein Vorschlag:

MSA_nodeMCU32.fds.png
   Ansicht / Download

Die Auswahl der Bauelemente erfolgte auf Basis meiner Bastelvorräte, bietet allerdings auch nur wenig Besonderheiten.
Die Infrarotsignale werden über einen Fototransistor (FT) BPW40 empfangen und an GPIO26 eingelesen. Der Vorwiderstand (R4) ist mit 1,2kΩ dimensioniert. Dieser Wert zeigte ein gutes Bild im Oszillogramm. Höhere Widerstände führen zu verschliffenen Signalen. Der interne PullUp des ESP ist deutlich zu hochohmig.

Die weiße LED (D3) zur Betätigung des "optischen Tasters" wird über GPIO25 gesteuert. Zwischengeschaltet ist ein Treibertransistor (T1), um den ESP nicht zu überlasten. Das Gate des Transistors wird über R5 nach Masse gezogen, um in der Initialisierungsphase nicht bereits den ersten Impuls zu senden. Die LED ist aus einer alten Taschenlampe recycelt, 5mm, Typ unbekannt.
Wer das Glück hat, die Pin des Zählers dauerhaft aktivieren zu können, kann auf diesen Schaltungsteil verzichten.

Die LED gn/rt dienen der Statusanzeige, einfache 3mm-Typen, nicht spezifiziert. Die Vorwiderstände sind nach der gewünschten Leuchtstärke dimensioniert.
Das Blinken von D1 (gn) im 1s-Takt zeigt gelesene Datenpakete an:

  • 100ms bei Kurztelegrammen
  • 300ms bei Langtelegrammen

D2 (rt) signalisiert verschiedene Zustände:
  • leuchtet dauerhaft nach dem Booten: der ESP hat keine Wifi-Anmeldedaten gespeichert
  • schnelles Blinken: Verbindungsaufnahme mit Wifi-Accesspoint
  • langsames blinken: Verbindungsaufnahme mit MQTT-Server
  • blinken im Gleichtakt mit der grünen LED: CRC-Telegramm-Fehler
  • LED rt aus: Grundstellung, Ok


Der Taster an GPIO32 hat folgende Funktionen, abhängig vom Zeitpunkt der Betätigung:

  • während des Bootens: ESP fordert neue Wifi-Anmeldedaten beim Router an (WPS-Button-Verfahren)
  • nach Wifi-Connect: ESP aktiviert den internen Webserver zur Konfiguration




Software bauen und flashen

Espressif stellt zur Anwendungsprogrammierung ihrer ESP32xx-Familie ein "Integrated Development Framework" IDF kostenfrei zur Verfügung. Dieses Framework muss auf dem PC installiert sein, um aus dem C-Sourceode ein Maschinenprogramm zu bauen.
Die Art und Weise wie das unter Linux funktioniert, hatte ich hier beschrieben. Für die kommerziellen Betriebssysteme gibt es Hilfe auf den Webseiten von Espressif.

Eine dicke Entwicklungsumgebung wie Eclipse oder VS-Code ist nicht unbedingt erforderlich, aber hilfreich beim Arbeiten mit dem Sourcecode.

Die Projektdateien werden in ein beliebiges Verzeichnis mit User-Rechten geladen. Ausgangspunkt für jede IDF-Bedienung ist ein geöffnetes Terminalfenster auf der Ebene des Projektverzeichnisses, d.h. dort wo die sdkconfig und das Verzeichnis main zu finden sind.

Nach öffnen des Terminalfensters muss einmalig der Befehl

source $IDF_PATH/export.sh
ausgeführt werden, um die erforderlichen Variablen zu setzen. Nur einmal nach dem Öffnen, aber in jedem Terminalfenster neu !

Ein ESP, der noch Altlasten enthält, sollte zum Projektstart erst einmal komplett gelöscht werden.

idf.py erase-flash

Zu Beginn eines Projektes muss im IDF die ESP-Zielplattform festgelegt werden.
Die ESP32-Familie beherbergt verschiedene Mitglieder mit teilweise völlig unterschiedlichen Prozessoren. Trotzdem fühlen sich die meisten Funktionsaufrufe für den Anwendungsprogrammierer dank des gemeinsamen API einheitlich an. Soll heißen: Wenn man Hardwareunterschiede wie Anzahl und Bezeichnung der Schnittellen und einiges andere berücksichtigt, lässt sich aus ein und dem selben Quellcode für unterschiedliche ESP-Prozessoren / SOC passender Maschinencode bauen.
Dieses Projekt habe ich auf einem ESP32 (LX6) entwickelt. Das fertige Gerät lauft mit einem ESP32C3 (RISC-V).

Eine Plattformkonfiguration sieht wie folgt aus:

idf.py fullclean
idf.py set-target esp32       # oder esp32c3,...
cp sdkconfig.esp32 sdkconfig

Der Copy-Befehl am Ende bedarf noch einer Erklärung:
Die sdkconfig ist Bestandteil jedes IDF-Projektes. In ihr werden eine Unmenge (teilweise plattformspezifische) Konfigurationsdaten gespeichert. Die meisten wird man wohl im Laufe seiner Bastlerkarriere nicht beachten. Einige wenige müssen aber während der Entwicklung angepasst werden.
Mit einem Wechsel der Zielplattform löscht das IDF die bestehende sdkconfig und würde mit den nächsten build eine Datei mit Defaultwerten an die Stelle kopieren.
Daher ist es sinnvoll, eine Kopie der sdkconfig zu erstellen und diese plattformspezifisch zu speichern. Dann lässt sie sich im Bedarfsfall (wie oben) zurückkopieren.
Von Hause aus ist diese Datei nicht vorhanden.

Nun kann man sich an das bauen des Maschinencodes wagen. Ganz simpel:

idf.py build

Im Terminalfenster gibt es dann einiges zu lesen. Keine Panik, wenn man nicht alles mitbekommt.
Wenn am Ende diese Zeile gefolgt vom Flash-Kommando zu finden ist, hat man gewonnen:

Project build complete. To flash, run this command:
...
...
run 'idf.py -p (PORT) flash'

Wenn kein Erfolg gemeldet wird, sind mit großer Wahrscheinlichkeit Fehlermeldungen in Rot zu finden, denen man nachgehen muss.

Häufige Ursache bei eigentlich fehlerfreiem Quellcode sind Inkompatibilitäten der IDF-Versionen. Bisher hat Espressif bei jedem größeren Versionssprung Änderungen an Bestandsbibliotheken vorgenommen, Funktionsaufrufe in andere Bibliotheken verschoben, Header-Dateien in andere Verzeichnisse verfrachtet oder das komplette make-System umgestellt.
Der Messstellenadapter wurde mit der Version IDF V5.1 entwickelt.


Im Ergebnis des Build-Prozesses wurden drei Binaries gebaut: Bootloader, Partitionstabelle und die Firmware. Mit dem Befehl:

idf.py -p /dev/ttyUSB0 flash
sorgt das Framework (IDF-Tools) dafür, dass alles von der richtigen Stelle abgeholt und an den seinen Platz im ESP geflasht wird.

Nach einem (automatischen) Reset sollte der ESP mit seiner Arbeit beginnen.
Eigentlich alles ganz einfach.




Konfiguration

Die Einstellung der Parameter zur Anpassung an das eigene Netzwerk erfolgt in zwei Schritten.


1. Wifi Verbindung

Nach jedem Booten sucht das Programm im NVS (Flash-ROM) nach den Wifi-Daten: SSID und Passwort. Sind dort Werte gespeichert, werden diese zur Anmeldung am Accesspoint genutzt.

Beim ersten Start sind die Speicherplätze leer. Das Gerät schaltet in den WPS-Modus und die rote LED leuchtet. Am Wifi-Router muss nun die Anmeldung per WPS-Button-Verfahren freigegeben werden. Daraufhin werden SSID und Passwort an den ESP übertragen, im NVS dauerhaft gespeichert und das Gerät neu gestartet.
Danach sollte es sich mit dem WLan verbinden, erkennbar am hektischen Blinken. Ist die Verbindung hergestellt, wechselt der ESP in langsames Blinken, da er dann versucht den MQTT-Server zu finden.

Möchte man sich an an einem anderen Netzwerk anmelden oder mit geänderten Anmeldedaten ins Netzwerk gehen, kann dazu die Config-Taste während des Bootens gedrückt werden.
Der Status der Taste wird beim Programmstart abgefragt. Ist die Taste in den ersten Millisekunden aktiv, wird in den WPS-Modus gewechselt.

Es wird vorausgesetzt, dass im lokalen Netzwerk ein DHCP-Server läuft, von dem eine IPv4-Adresse bezogen wird. Im Router sollte dann ein neues Gerät mit dem Namen "EMeter" zu finden sein.


2. Sonstige Einstellungen

Durch Drücken der Config-Taste nach dem Einloggen im WLan öffnet sich auf dem MSA für 5 Minuten ein Webserver, der eine simple Eingabemaske bereitstellt. Erreichbar ist der Server auf dem Standardport 80 unter http://EMeter oder der zugewiesenen IP-Adresse falls die Namensauflösung im Netzwerk nicht funktioniert. Wichtig ist der Protokollprefix http://, da die Verbindung nicht verschlüsselt wird.

testbild

Der Hostname kann, aber muss nicht geändert werden.

Im zweiten Feld muss der Hostname oder die IPv4-Adresse des Gerätes eingeben werden, auf dem der MQTT-Server (bspw. Mosquitto) läuft. Es wird vorausgesetzt, dass der Server auf dem Standardport 1883 erreichbar ist. Die Protokollkennung kann, muss aber nicht angegeben werden. Im Bedarfsfall wird sie intern ergänzt.

Der MQTT-Topic ist eine Zeichenkette mit der die Nachrichten adressiert werden. Zu Aufbau und Bedeutung findet man sehr gute Erklärungen im Netz.

Zur Archivierung der Daten benötigt der MSA die aktuelle Uhrzeit. Diese holt er sich von einem NTP-Server aus dem Internet oder im günstigeren Fall von einem lokalen Server wie der Fritzbox. In diesem Fall wäre in dem Feld "fritz.box" einzutragen.
Die Synchronisation mit dem Server wird nach jeweils 60 Minuten wiederholt.
Soll die Verbindung mit einem NTP-Server unterbunden werden, so ist in diesem Feld no.ntp einzutragen. Alternativ kann die Synchronisation der Zeit auch per MQTT-Kommando erfolgen.

Und ins letzte Feld gehört noch die 4-stellig Pin des Zählers, falls die Nummer automatisch eingeblinkt werden soll.

Nach Bestätigung werden die Daten im nichtflüchtigen Speicher abgelegt und das Gerät neu gestartet. Es werden nur geänderte Daten übernommen. Wird in keinem Feld etwas eingetragen, läuft das Gerät weiter und der Webserver schaltet nach Zeitablauf ab.

Noch eine Anmerkung zur Uhrzeit:
Das Programm arbeitet mit der UNIX-Time in Sekunden, d.h. der Anzahl der Sekunden seit dem 01.01.1970 00:00 UTC. Alle Timestamps, die per MQTT gesendet oder empfangen werden, müssen diesem Format entsprechen.
Grundsätzlich hat das Programm kein Problem damit, ohne Zeitsynchronisation zu arbeiten. Die Systemzeit fängt einfach bei Null nach einem Reset an. Zum Archivieren der Zählerstände ist jedoch eine gültige UNIX-Zeit erforderlich. Als gültig werden alle Werte ab dem 01.01.2023 akzeptiert.
Da die Zählerstände als Tagesdaten archiviert werden, erfolgt für diesen Fall eine Umrechnung der Zeitzone nach MEZ durch einen Offset von 3600Sek. DST-Sprünge kennt das Programm nicht.

Sicherheitsfragen

Bei jedem Gerät, das Zugang zum Netzwerk erhält, sollte man sich Fragen zur Sicherheit stellen.

Der Zähler ist in meinem privaten Umfeld eingebaut. Es besteht kein ungehinderter Zugang für Dritte. Damit entfällt jeglicher mechanischer Schutz. Dieser wäre in einem Gemeinschaftskeller ohnehin schwer realisierbar.

Die WLan-Verbindung zum Router ist mit WPA2 verschlüsselt und sollte damit dem Stand der Technik entsprechen. Andere Verschlüsselungsverfahren sind möglich, aber nicht getestet und bedürfen u.U. einer SW-Änderung.

Ein spezielles Thema ist die Wifi-Anmeldung am Netzwerk. Diese erfolgt hier per WPS-Button-Verfahren im Zusammenspiel mit dem Router.
Es muss jedem der dieses Verfahren verwendet klar sein, dass auf Knopfdruck am Router die SSID und das geheime Passwort an den Anfragenden geschickt werden. Es liegt in der Phantasie jedes Einzelnen zu entscheiden, ob das immer das eigene Gerät oder vielleicht auch mal das des Nachbarn ist.
Andere WPS-Verfahren, per Pin- oder QR-Code, kommen auf Grund des HW-Aufwandes nicht in Frage, zumal das Pin-Verfahren von meiner Fritzbox nicht mal unterstützt wird.
Wem das zu unheimlich ist, kann in der Datei "interface.h" den SSID und das Passwort im Sourcecode fest vorgeben. Dann steht man jedoch bei einer Passwortänderung im Netzwerk vor dem Problem, die Firmware des Adapters neu bauen und flashen zu müssen.

Die Übertragung der MQTT-Messages in Netzwerk erfolgt unverschlüsselt. Es wird vorausgesetzt, dass vom MQTT-Server keine Anmeldedaten gefordert werden, d.h. ein offener Zugang möglich ist.
Beide Punkte sollten in einem privaten Netzwerk kein Problem darstellen. Die Verwendung eines öffentlichen MQTT-Servers oder eines Servers außerhalb des eigenen Netzwerkes ist damit jedoch aus Sicherheitsgründen ausgeschlossen.

Sofern man keine Löcher in seine Router-Firewall bohrt, sollte das Gesamtsystem gegen Zugriffe von Außen geschützt sein.

Es muss aber auch die andere Richtung betrachtet werden. Kann mein ESP-Gerät vielleicht "nach Hause telefonieren"? Diese Frage lässt sich nicht mit absoluter Sicherheit verneinen.
Für meinen Quellcode lege ich die Hand ins Feuer. Sofern keine externen IP-Adressen für NTP- und MQTT-Server konfiguriert werden, bleiben alle Daten im eigenen Netzwerk. Außerdem kann sich jeder den Quellcode anschauen und vor dem Flashen selbst entscheiden.
Unterhalb der API-Schnittstellen des IDF werkelt aber eine Vielzahl an Bibliotheken, die zum allergrößten Teil Closed Source und damit Firmengeheimnis der chinesischen Firma Espressif sind.
Inwieweit man diesen Chips über den Weg traut und sie in sein LAN lässt, muss jeder selbst entscheiden.

Jeder, der bereits smarte Geräte wie Fernseher, Saugroboter oder Wohnungsschloss in seinem Netzwerk angemeldet hat, braucht sich an dieser Stelle keine Gedanken zu machen. Dem ist ohnehin nicht mehr zu helfen.

Das Endprodukt

Im Testaufbau war der ESP32-NodeMCU mit den Komponenten auf einem Steckbrett frei verdrahtet und Fototransistor & LED in Moosgummistücken mit Tesaband am Zähler befestigt.
Für einen kurzen Zeitraum mag das in Ordnung sein. Auf längere Sicht hat solch ein Drahtverhau jedoch nichts in diesem Umfeld zu suchen.


LED-Köpfe

Zum Einen stellt sich die Frage nach Montage von Fototransistor und weißer LED.
Der eingangs genannte Grundsatz: "Der Zähler darf nicht beschädigt werden" bleibt bestehen.

Es ist derzeit noch unklar, wie das Ablesen der Zählerstände durch den MSB erfolgen wird. Vielleicht wie bisher durch abfotografieren der Anzeigen und Gerätenummer / Barcode? Oder durch Scannen der IR-Telegramme an der Info-DSS? Daher sollen sowohl die Diode als auch die relevanten Beschriftungen ohne größere Umstände weiterhin zugänglich sein.

ledkopf

Beide Bauelemente haben die gleichen Abmessungen. Dazu habe ich dieses 3D-Modell mit OnShape entworfen und meinem Prusa I3 MK3 gedruckt. Die kleine Führungsplatte wird mit einem zweiseitigen Klebepad neben der LED-Öffnung befestigt.
Da erfahrungsgemäß selbstklebende Folien auf die Dauer schlecht auf PETG-Druckteilen haften, streiche ich die Flächen der Druckteile zuvor mit Billig-Sekundenkleber ein, lege die Klebefolie auf und lasse die Verbindung unter sanftem Druck abbinden. Danach ist zumindest diese Seite nicht mehr lösbar.

Die Führungsplatten sollten recht genau auf der Zählerfront positioniert werden. Dazu die Führungsplatte mit aufgestecktem LED-Träger (ohne LED) vor dem Loch ausrichten und ankleben .
Danach die LED einbauen, verdrahten und testen ob alles funktioniert. Dann erst die Kappe aufstecken. Nach dem Zusammenstecken sind die Teile nicht mehr zerstörungsfrei zu trennen.
Führungsplatte und Kopf sollten mit mäßiger Reibung aneinander haften.


Steuerung

Wer bei der ESP32-Lösung mit dem NodeMCU oder einem beliebigen anderen Board bleibt, kann die Schaltung vernünftig verdrahten, in eine Verteilerdose einbauen und im Zählerschrank befestigen. Mit einer geeigneten Stromversorgung ist das Projekt fertig.

Messstellenadapter_q.fds.png
   Ansicht / Download

In letzter Zeit habe ich einige Projekte mit dem ESP32C3 realisiert. Die Module sind handlicher, sind nicht so überladen mit Pins wie der ESP32 oder S2 und unglaublich preiswert. In Projekten, in denen kein ULP-Prozessor benötigt wird, sind das derzeit meine Favoriten.

Die Schaltungsbeschreibung kann vom Versuchsaufbau übertragen werden. Zusätzlich sind zwei Pullup-Widerstände an GPIO 2 & 8 projektiert. Aus der Dokumentation glaube ich herauszulesen, dass diese beiden Pins in bestimmten Betriebszuständen nach oben gezogen werden sollen. In Testschaltungen habe ich bisher keinen Unterschied festgestellt, wenn die Pins offen bleiben. Aber sicher ist sicher.
Zusätzlich ist der Reset-Taster, der auf Entwicklungsboard mit dabei ist und die Buchse X1 zum Anstecken eines USB-RS232-Wandlers. Bei meinen FTDI232-Exemplaren ist es erforderlich RTS und CTS mit einer Drahtbrücke zu verbinden, sonst funktioniert das flashen nicht.

Der ESP zieht etwa 80-100mA an 3,3V. Die Stromversorgung sollte Spitzen bis 500mA abfangen können.
Versorgt wird die Schaltung aus der Sekundärseite des Klingeltrafos. Auf der 12V-Seite beträgt die Stromaufnahme ca. 25mA.

ledkopf

Montiert ist die Schaltung auf einer einseitig geätzten Leiterplatte, die sowohl konventionell als auch mit SMD bestückt ist. Das Layout bietet noch viel Optimierungspotential hinsichtlich der Größe. Die Bauelementeauswahl erfolgte auf Basis meiner Vorräte. Die Beschaffung sollte im Versandhandel für unter 10€ möglich sein.

Die Leiterplatte ist in einem Gehäuse aus dem 3D-Drucker eingebaut. Das Teil beinhaltet keine Highlights. Es ist funktionell und auf die Größen- und Befestigungsverhältnisse im Zählerschrank abgestimmt. Bei einem Nachbau sollte dieser Entwurf durch einen eigenen ersetzt werden.

Was man sonst noch braucht

Im lokalen Netzwerk muss ein MQTT-Server laufen. Der Quasi-Standard hierfür ist Mosquitto, der sich auf einem Raspberry in wenigen Minuten aus dem Repository installieren lässt. Das PiOS sollte dabei aktuell sein.
Nach der Installation hört der Server auf Port 1883 und wird auch nach einem Reboot automatisch wieder gestartet. Es muss lediglich das lokale Netzwerk für Verbindungsaufnahmen freigegeben werden. Nach der Installation hört er erst einmal nur auf Verbindungsanfragen des Localhost.

Zwangsläufig muss man sich näher mit dem MQTT-Protokoll auseinandersetzen und Messages analysieren. Hierfür ist es sinnvoll, auf einem PC ein Analysetool wie beispielsweise den MQTT-Explorer zu installieren.

Mosquitto kümmert sich um Empfang und Verteilung der Nachrichten. Jeder Client im Netz der einen Topic abonniert, bekommt die zugehörigen Nachrichten zugestellt. Der MSA selbst ist auch ein Abonnent. Er erhält auf diesem Weg Kommandos bspw. von einem Frontend.

Wie es von dort weitergeht, hängt von den eigenen Vorlieben und Bedürfnissen ab. Ein weiterer Abonnent könnte bspw. ioBroker oder Node-Red sein. Diese Programme empfangen Nachrichten, werten die Payloads aus, verarbeiten die Daten und bereiten sie grafisch auf. Die Darstellung kann dann in jedem beliebigen Browser erfolgen.

Erläuterungen dazu würden hier aber zu weit führen. Der Artikel ist jetzt schon einige Zeilen länger geworden als geplant.

Fazit

ledkopf

Der Messstellenadapter läuft jetzt seit einigen Monaten im Dauerbetrieb. Der beschriebene Pin-Refresh funktioniert wie geplant und Daten sind kontinuierlich abrufbar.

Ob das Ganze einen Sinn ergibt oder nur eine technische Spielerei ist, wird die Zukunft zeigen.




nach oben