Heute stelle ich euch ein kleines Projekt vor, mit dem man ein Easymeter Q3DA per S0/D0 auslesen kann.

Vor kurzem wurde der alte analoge Stromzähler durch einen „smarten“ Easymeter Q3DA Zähler ersetzt.
Dieser gibt den summierten Zählerstand nicht nur über ein LCD aus sondern verfügt zusätzlich über eine S0/D0 Schnittstelle, über die das Gerät noch mehr Informationen ausspuckt. Genau diese Daten will ich abgreifen, aufbereiten und ausgeben.

Also hab ich mich an die Arbeit gemacht und als erstes recherchiert. Durch einen Arbeitskollegen wurden mir einige Beiträge im Netz empfohlen, die allerdings die Daten mit einem Raspberry auslesen und verarbeiten. In meinem Fall sollte aber ein Arduino zum Einsatz kommen. Ich entschied mich für einen Wemos D1 mini. Die Vorteile liegen auf der Hand (Bauform und vor allem WiFi OnBoard)!

Im Netz gab es auch hier einige Suchergebnisse, die ich anfing nachzubauen. Es wurde beschrieben, dass es ausreicht, wenn ein Fototransistor an Rx und G angeschlossen wird. Dem war bei mir nicht so, da PullUp Spannung des Rx Pin nicht ausreichend ist!

Also hab ich mehrere Schaltungen durchgemessen und bin schlussendlich zu dieser Lösung gekommen:

Schaltplan
Schaltplan

Zum Glück ist der ESP8266 sehr Spannungstolerant und verzeiht einem die Verstärkung der Spannung 😉 Und bevor jetzt jemand sowas sagt wie „ähh, warum nimmst du nicht die 3.3V“ dem möchte ich vorab sagen, ich habe es versucht und auch diese Spannung war nicht ausreichend…

Eine Alternative, bzw. sogar der bessere Weg wäre es, einen I/O Pin per SoftSerial zu verwenden. Auch die Verwendung eines zusätzlichen Transistors wäre ein möglicher Weg.

Nachdem nun die Schaltung erfolgreich getestet wurde, habe ich mir eine Platine zurecht geschnitten und diese mit Bauteile verlötet.

Damit die Platine nicht verrutscht habe ich noch am Pc eine kleines CAD gebastelt und am 3D-Drucker ausgedruckt, so dass die Platine genau da bleibt so sie sein soll.

(Wen es Interessiert, ich habe das Gehäuse mit einem Creality CR-10 mit MKS GEN 1.4 und TCM2130 Steppertreibern gedruckt.)

Sicher, hübscher geht es bekanntlich immer aber für den Anfang ist es genau das richtige.

Easymeter-S0Reader
Fertiger Reader auf Basis eines WeMos D1 Mini

+++Aktualisiert am 11.12.2020 – Der Link zum Download des Arduino Sketch (Der Source-Code ist befindet sich nun in einem GitLab Repo) +++

Download:

Wie versprochen stelle ich euch den ersten Teil meiner Projektdateien zur Verfügung:
Den Arduino-Sketch findet Ihr in hier: Link zum Sketch
Das STL der Adapter-Platte gibt es hier: Link zum STL

Falls Ihr mich ein wenig unterstützen wollt, nutzt doch gern die folgenden Affi-Links zu Amazon.

Hier ist meine Einkaufsliste:

Schau die auch meine anderen Projekte an, z.B. dieses hier: Sicherheitskopie eurer Amiibo erstellen

35 thoughts on “Easymeter Q3DA per S0/D0 auslesen”

      1. Passt schon, ging mehr darum wo die LED dann sitzt mit dem Gehäuse.

        Wäre nett wenn Du mir den Sketch und das CAD schicken könntest.

        1. Moin Frank,
          Hast du die Dateien gesehen, die ich verlinkt habe und kommst du damit zurecht?

          Wenn du Fragen hast melde dich einfach.
          Gruß Frederik

  1. Hallo Rik,
    besten Dank, konnte alles nachbauen, incl. Easymeter-Halterung. Leider erhalte ich am Seriellen Monitor zwar eine sinnvolle Struktur, aber viele „leere Zeichen“ (Rechtecke) von Serial.write(c) und Nullen von Serial.println(output). Die wenigen lesbaren Zeichen/Werte passen. Würde gerne den Screenshot anhängen, das gelingt aber nicht. Im Sketch habe ich WiFi und InfluxDb zur Vereinfachung auskommentiert. Habe vieles probiert: alle Baudraten-Varianten; elektrisch: kurze Kabel, Kondensator, zusätzliche Transistorstufe am Sensor. Nichts verbessert die Ausgabe! Gibt es einen hilfreichen Hinweis auf das Problem? Danke und Gruß, Reinhold

    1. Moin Reinhold,
      Sorry für die späte Antwort, bin momentan extrem eingespannt und komme nicht mal zum Schreiben neuer Artikel.
      Es freut mich zu hören, dass dir das Projekt gefällt und du es nachgebaut hast.

      Mir ist das von dir beschriebene Problem noch nicht aufgefallen, schick mir doch gern mal die Änderungen an dem Sketch dann kann ich das gleich aktualisieren.

      Viele Grüße Rik

  2. Hi,

    kann mir einer Erklären, warum ich die Leistungswerte in den „Rohdaten“ erkenne, aber bei der Ausgabe dann „0“ als Werte ausgegeben werden?:

    /ESY5Q3DA2004 V3.03

    1-0:0.0.0*255(183778)
    1-0:1.8.0*255(00003633.5262677*kWh)
    1-0:21.7.255*255(000000.00*W)
    1-0:41.7.255*255(000078.86*W)
    1-0:61.7.255*255(000005.43*W)
    1-0:1.7.255*255(000084.29*W)
    1-0:96.5.5*255(82)
    0-0:96.1.255*255(1ESY1217000778)
    !
    ID=183778;E=00003633.5262677*kWhkW/h;L1=0W;L2=0W;L3=0W;P=0W

    1. Hi Joopi,
      schau mal bitte, ob sich ändert wenn du den char rxBuffer von 20 auf 30 setzt.

      Ein Unterschied besteht schonmal an einer neueren Version (3.03) hier scheint es einige Neuerungen zu geben. Die einzelnen Speicherstellen des Zählers beinhalten bei dir bereits die Einheiten.

      Hier solltest du schauen, dass du das * und die führenden Nullen aus dem String schneidest.

      1. Hi, ich hab es jetzt mal mit rxBuffer 30 versucht, keine Veränderung. Ich habe allerdings einen zweiten Zähler getestet, dieser hat die Version 3.04 und da klappt es einwandfrei:

        /ESY5Q3DA2004 V3.03

        1-0:0.0.0*255(0223024810884)
        1-0:1.8.0*255(00003633.8541695*kWh)
        1-0:21.7.255*255(000000.00*W)
        1-0:41.7.255*255(000078.86*W)
        1-0:61.7.255*255(000005.43*W)
        1-0:1.7.255*255(000084.29*W)
        1-0:96.5.5*255(82)
        0-0:96.1.255*255(1ESY1217000778)
        !
        ID=UNKNOWN;E=00003633.5262677*kW/h;L1=000000.00*W;L2=000078.86*W;L3=000005.43*W;P=000084.29*W

        Hat einer noch eine Idee, wie man es auch mit der V3.03 ans laufen bekommt?

        Danke schonmal für die Hilfe

        1. Hi Joopi,
          Das was du gepostet hast ist genau der Output deines Easymeter richtig?

          Wenn dem so ist, erweitere ich heute Abend den sketch. Dann kannst du ihn direkt verwenden.

          Gruß Rik

  3. Hallo Richard
    Ich habe auch einen EasyMeter an unserer PV-Anlage, versuche schon seit Wochen das SML-Protokoll auszulesen, vergebens.Habe es mit IR-Transistoren & dem Wemos bzw, einem USBtoSerieladapter am Laptop probiert.Ich bekomme keine Daten ausgelesen.Auch mit dem Original-Lesekopf Fehlanzeige.Die PIN vom Zähler habe ich, aber das Menü zum freischalten lt.Anleitung erscheint nicht. Wollte es mit deinem Sketch probieren aber dein Link läuft ins Leere.
    Könntest du mir evtl.den Sketch schicken? Meine Emailadresse ist xxxxxx

    Vielen Dank schon mal im voraus & ein schönes Wochenende

    Gruß Norbert

    1. Hey Norbert,
      ich habe den Sketch neu verlinkt, danke für den Hinweis. (Ich bin mit dem Sketch auf GitLab umgezogen)

      Mich wundert, dass du überhaupt keine Daten empfängst. Allerdings kann es sein, dass du eine Revision hast bei der die IR an einem anderem Ort ist oder entfernt wurde.
      Freischalten musste ich bei meinem Easymeter nichts.

  4. Hallo Ric,

    ich habe habe auch vor, meinen Zähler auszulesen und freue mich, das ich nicht bei Null anfangen muss. Ich habe ein paar Fragen und hoffe du kannst mir helfen. Steck nicht so in der Elektrikmaterie drin wie ich gern würde.

    Mein Zähler ist ein Q3MA1170 V6.03.

    1. Ich muss am Zähler nichts durch Lichtsignale und PIN freischalten, richtig?
    2. Ein Fotowiderstand kann sicherlich keine IR-lesen (oder doch?) Weißt du wo Fototransistor verbaut sind? z.B alte Fernbedinung? Oder muss ich zwingend bestellen?
    3. Ich will einen NoteMCU V1.0 verwenden. Ist der Rx Port indentisch zum WeMos D1 mini oder muss ich da noch was anpassen. Hier vielleicht [Serial.begin(9600, SERIAL_7E1); ]

    Und schon mal im voraus vielen Dank. Auch wenn du mir meine Fragen nicht beantworten kannst, komme ich mit dem was du hier veröffentlicht hast schon eine ganze Ecke weiter. Daumen hoch!!

    1. Moin Joerich,
      es freut mich, dass dir mein Artikel weiterhilft. Gern versuche ich dich zu unterstützen und deine Fragen zu beantworten.

      Bei deinem Drehstromzähler handelt es sich um ein ähnliches Gerät, allerdings hat es ein paar entsprechende Unterschiede. Der größte Unterschied ist, dass das Gerät an der Vorderseite eine direkte Info Schnittstelle hat, die ggf. Freigeschaltet werden muss. Woran du erkennen kannst, ob sie freigeschaltet ist oder nicht kann ich dir nicht sagen.

      Mit einen Fotowiederstand kommst du nicht weit, du brauchst einen Fototransistor. Wo solche Transistoren verbaut sind kann ich dir nicht sagen.

      Die NodeMCU solltest du problemlos verwenden können.

      Auf der Webseite des Herstellers findest du einig PDF Dateien in denen viele wichtige Informationen zu finden sind. Ggf. wird auch die Ausgabe an der Info Schnittstelle eine andere sein, das müsste auch dokumentiert sein.

      Erstmal wünsche ich dir viel Spaß und Erfolg bei deinem Projekt und wenn du Fragen hast, schreib mir einfach. Ich versuche dir dann zu helfen.

      Gruß Rik

      1. Wollte nur kurz meinen Stand mitteilen und eine Frage habe ich auch noch.

        Also für meinen Zaehler Q3MA1170 V6.03. habe ich folgendes erfolgreich durchgeführt
        1. PIN via EMail beim Netzbetreiber beantragt.
        2. Nach Postzustellung über eine Handy APP (macht sich mit der Taschenlampe nicht so gut) am Zähler eingegeben
        Danach sieht man schon im Display mehr also vorher .
        3. Beim Mitstreiter mir Anregungen geholt für den 3D Druck
        4. Den Lesekopf aber noch einmal selber gezeichnet, da ich andere Magneten hatte
        5. Kopf gedruckt und Diode und Kabel etc. Verbaut.
        6. einfache Serial-Script aufgespielt und den HEX-Code nach einer SML Erklärung verstanden und aufgeschlüsselt.
        Dabei meine Zahlen gefunden. Mann muss durch 10.000.000 teilen.
        7. Leider konnte ich aus deinem Script nicht so viel rauslesen. Da fehlt mir wahrscheinlich zu viel Background.
        Aber andere Script halfen das ich den 16 Bit HEX zu Anzeige bekomme.

        Leider habe ich es immer noch nicht sauber geschaft, diesen auf dem Geräte in dein double oder Float zu konvertieren. Vielleicht kann hier jemand helfen. Derzeit habe ich mir geholfen in dem ich den iobroker (parseINT) die Arbeit machen lasse. Ich sende mir dazu einen String via mqtt. Auch bei der Erstellung dieses habe ich noch Schwierigkeiten
        ….
        { Gesammtzaehler =““;
        for(int y = 0; y< 8; y++){
        //hier muss für die folgenden 8 Bytes hoch gezählt werden
        consumption[y] = smlMessage[x+y+1];
        //strcat(lbuf,hex02str(consumption[y]));
        Gesammtzaehler += hex02str(consumption[y]);
        //Serial.print(consumption[y],HEX); DIESE ZEILE BRÄUCHTE ICH IN FLOAT ODER DOUBLE
        }

        Also jetzt geht's eigentlich nur noch ums "schön" machen. Leider wird bei dieser Umwandlung manchmal ein Byte wahrscheinlich ein 0 weggelassen. Damit kommt dann ein String mit 15 Zeichen heraus. Das könnte ich natürlich auch in iobroker abfagen, aber hier hört der Spass auf. Das muss doch auch eleganter gehen.

        Achja, und damit ich nicht immer im Keller sitzen muss, habe ich #include im Einsatz. Das Debug via mqtt zu schick ist nicht ganz so toll und braucht auch etwas länger, aber so kann ich wenigsten auf dem Sofa sitzen.

        Sieht hier jemand oder du Rik noch einen andere Möglichkeit? Deinen Parser verstehe ich leider nicht. 🙁

  5. Hin und wieder hängt sich der ESP8266 auf. Es werden keine Werte mehr übertragen. Per WLAN Ping antwortet das Gerät jedoch. Es tritt sporadisch auf, so alle 10-20 Tage mal. Meistens hilft der Resettaster. Es kommt aber auch vor, dass das Gerät von selber wieder mit der Übertragung startet. Der IR-Sensor ist dabei immer fest montiert gewesen und nicht angerührt worden. Weiß jemand woran das liegen könnte oder hat eine Idee zur Abhilfe? Watchdog oder ähnliches?

    1. Also ich weiß nicht welchen ESP8266 du benutzt, aber wenn ich das Problem bekomme werde, dann würde ich auf meinen NoteMCU V3 Nachts ein den DeepSleep für ein paar Sekunden schicken. Wenn er wieder aufweckt, ist alles wieder Frisch. Die Ursache findest du so natürlich nicht, aber muss ja auch nicht unbedingt.

  6. Hi Rik,
    Ich würde gern wissen welcher Fototransistor du verwendest.
    Ich habe ein sfh320fa (NPN, 880nm) und kann damit Daten aus einer Fernbedienung empfangen aber nichts vom Zahler.
    Zähler ist ein Q3DA1002 3.04

    Vielen Dank ?

  7. Ich habe auch einen Q3AD als Zweirichtungszähler und versuche ihn mit deinem Code auszuwerten. Ist wirklich gut und verständlich aufgebaut.
    Aber leider stoße ich noch auf Probleme. Im seriellen Monitor H-Term (in arduino werden kann man ja die Parität nicht einstellen) Wird auch alles richtig dargestellt für für 7e1.
    Aber die Auswertung macht Probleme. Er erkennt das Char `(` gut so die ID, aber er will ums verrecken das Char `)` nicht erkennen und somit passiert auch nichts weiter.

    Hast du da ne Idee? Habe es schon mit Hex werten Versuch, aber auch ohne Erfolg. Auch das `*` als Alternative will er nicht erfassen.

    Mache ich da was falsch? Habe ich das mit der Parität falsch verstanden? Würde das tolle Projekt gerne nutzen.

    Gruß Niklas

  8. Hallo Rik,

    ich habe einen Zweiwege Q3AA Zähler.
    Leiderwird hier auch überall 0 angezeigt.
    Am RX Eingang des NODEMCU liegt das Signal sauber an. Ohne Signal ein High.
    Folgendes wird an an der seriellen ausgegeben:
    ID=UNKNOWN;E=0kW/h;L1=0W;L2=0W;L3=0W;P=0W

    p HH0H@BBF@b
    ————— CUT HERE FOR EXCEPTION DECODER —————

    Exception (9):
    epc1=0x402013b0 epc2=0x00000000 epc3=0x00000000 excvaddr=0x3ffef562 depc=0x00000 000

    >>>stack>>>

    ctx: cont
    sp: 3ffffd40 end: 3fffffc0 offset: 0190
    3ffffed0: 007a1200 8b3ceaa7 00000000 3ffef774
    3ffffee0: 00000000 4bc6a7f0 07ef9db2 00340a59
    3ffffef0: 00000000 00000000 00000000 3ffef788
    3fffff00: 3fffdad0 00002d02 00000001 40211c5c
    3fffff10: 00002d02 00000000 00000000 40203c59
    3fffff20: 00000000 00002d02 3ffef5a4 40203c80
    3fffff30: 3fffdad0 00000000 3ffef5a4 40218980
    3fffff40: 40219870 00000000 3ffef5a4 40201dab
    3fffff50: 00002d02 3ffef644 3ffef774 40212fed
    3fffff60: 007a1200 8b3ce0da 3ffef700 3ffef788
    3fffff70: 3fffdad0 00000000 3ffef774 402027bd
    3fffff80: 00000000 00000000 00000001 401001a8
    3fffff90: 3fffdad0 00000000 3ffef774 3ffef788
    3fffffa0: 3fffdad0 00000000 3ffef774 40211d7c
    3fffffb0: feefeffe feefeffe 3ffe8630 40100d0d
    <<<stack<<<

    Muss man im Programm" row.addTag("sensor", "Q3D")"; den Zählertyp eintragen?
    Was kann man noch prüfen?

    Können auch negative Einspeisewerte dargestellt werden, die im Display ja angezeigt werden?
    Wäre interssant für evt. schaltbare Lasten um die Einpeisung von einem Balkonkraftwerk so niedrig wie möglich zu halten.

    Gruß Knut

  9. Hallo Rik

    ich habe deinen sketch hier durch zufall gefunden. ich habe leider nicht die erfahrung in c bzw arduino ,doch denke ich den sketch so um schreiben zu können das auch für mein zähler passen sollte.
    leider bekomme ich auch nur 0 werte ausgegeben kannst du bitte mal rüber schauen?

    #include

    #include //Local DNS Server used for redirecting all requests to the configuration portal
    #include //Local WebServer used to serve the configuration portal
    #include //https://github.com/tzapu/WiFiManager WiFi Configuration Magic WiFiManager wifiManager;
    #include

    const char* ssid = „FRITZ!Box 7490“;
    const char* pass = „**“;

    const char* ID = „PwrMtr1“;

    static uint16_t uploadInterval = 60000;
    static uint16_t outputInterval = 60000;

    uint32_t nextOutput = 0;
    uint32_t nextUpload = 0;
    uint8_t charsRead = 0;
    char rxBuffer [30];
    String rxID;
    String mtrID = „UNKNOWN“;
    String mtrModel = „UNKNOWN“;
    String consSum = „0“;
    String Aminus = „0“;
    String powerL1 = „0“;
    String powerL2 = „0“;
    String powerL3 = „0“;
    String powerSum = „0“;
    String mtrState = „UNK“;

    #define INFLUXDB_HOST „192.168.178.45“
    #define INFLUXDB_USER „chris“
    #define INFLUXDB_PASS „**“
    #define INFLUXDB_DATABASE „EASYMETER“
    unsigned int INFLUXDB_PORT = 8086; // INFLUXPort

    Influxdb influx(INFLUXDB_HOST);

    void parseValues();
    void uploadValues();
    void outputValues();

    void configModeCallback (WiFiManager *myWiFiManager) {
    }

    void setup() {
    Serial.begin(9600, SERIAL_7E1);
    WiFiManager wifiManager;
    Serial.println(„Connecting to WiFi…“);
    wifiManager.setAPCallback(configModeCallback);
    if (!wifiManager.autoConnect(ssid, pass)) {
    Serial.println(„WiFI ERROR!“);
    ESP.reset();
    delay(1000);
    }
    delay(1500);

    influx.setDb(INFLUXDB_DATABASE);
    }

    void parseValues() {
    if (rxID == „1-0:0.0.0*255“) { //BAUJAHR
    mtrID = String(rxBuffer);
    }
    if (rxID == „1-0:1.8.0*255“) { //Zählerstand A+
    consSum = String(rxBuffer);
    }
    if (rxID == „1-0:2.8.0*255“) { //Zählerstand A-
    Aminus = String(rxBuffer);
    }
    if (rxID == „1-0:21.7.255*255“) { //L1
    powerL1 = String(rxBuffer);
    }
    if (rxID == „1-0:41.7.255*255“) { // L2
    powerL2 = String(rxBuffer);
    }
    if (rxID == „1-0:61.7.255*255“) { // L3
    powerL3 = String(rxBuffer);
    }
    if (rxID == „1-0:1.7.255*255“) { // Last der zeit
    powerSum = String(rxBuffer);
    }
    if (rxID == „1-0:96.5.5*255“) { //UNKNOWN
    mtrState = String(rxBuffer);
    }
    if (rxID == „0-0:96.1.255*255“) { //Zählertyp
    mtrModel = String(rxBuffer);
    }
    }

    void loop() {
    if (Serial.available()) {
    char c = Serial.read();
    if (c == ‚(‚) {
    rxBuffer[charsRead] = ‚\0‘;
    rxID = String(rxBuffer);
    charsRead = 0;
    } else if (c == ‚)‘) {
    rxBuffer[charsRead] = ‚\0‘;
    if (charsRead > 1 && sizeof(rxID) > 1) {
    parseValues();
    }
    charsRead = 0;
    } else if (c == 0x0D || c == 0x0A) {
    // on CR or LF
    charsRead = 0;
    } else {
    rxBuffer[charsRead++] = c;
    }
    Serial.write(c);
    }

    if (nextOutput < millis()) {
    outputValues();
    nextOutput = ( millis() + outputInterval);
    }
    if (nextUpload < millis()) {
    uploadValues();
    nextUpload = ( millis() + uploadInterval);
    }
    }

    void uploadValues() {
    WiFiClient client;

    InfluxData row("strom");
    row.addTag("device", "Easymeter");
    row.addTag("sensor", "Q3D");
    row.addTag("mode", "ESP8266");
    row.addValue("E", consSum.toInt());
    row.addValue("Amin", consSum.toInt());
    row.addValue("L1", powerL1.toInt());
    row.addValue("L2", powerL2.toInt());
    row.addValue("L3", powerL3.toInt());
    row.addValue("Summe", powerSum.toInt());
    influx.write(row);
    }

    void outputValues() {
    String output = "ID=";
    output += mtrID + ";E=" + consSum + "kW/h;Amin=" + Aminus + "kW/h;L1=" + powerL1 + "W;L2=" + powerL2 + "W;L3=" + powerL3 + "W;P=" + powerSum + "W\n";
    Serial.println(output);
    }

    1. Moin Chris,

      wenn du nur NULL bzw. einen 0 String ausgegeben bekommst liegt es vermutlich daran, dass rx Werte nicht stimmen.
      Welchen Stromzähler hast du denn?

      Gruß,
      Rik

  10. Hallo Rik,

    Auf der Suche nach einem Arduino-Sketch zum Auslesen der Momentanleistung bin ich hier her gekommen.

    ich würde das gerne auf einem NANO laufen lassen. Benötige nur die outputValues powerL1; powerL2; powerL3 ; powerSum.

    //#include

    //#include //Local DNS Server used for redirecting all requests to the configuration portal
    //#include //Local WebServer used to serve the configuration portal
    //#include //https://github.com/tzapu/WiFiManager WiFi Configuration Magic WiFiManager wifiManager;
    Benötige ich dafür wohl nicht.

    //#include
    Was ist das? Muss das bleiben oder kann das weg? Jedenfalls läuft deswegen der Sketch nicht ohne Fehlermeldung durch.

    Hintergrund: Ich benötige die Leistungen um eine el. Last so zu regeln, dass ich keine oder nur wenig Leistung In das Netz speise.
    Das bekomme ich Software- und Hardwaretechnisch ohne fremde Hilfe hin. Die Soft für Auslesen der Leistungen ist für mich ein Buch mit sieben Siegeln.
    Daher bitte ich Dich um Hilfe.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

Diese Website verwendet Akismet, um Spam zu reduzieren. Erfahre mehr darüber, wie deine Kommentardaten verarbeitet werden.