Hello World SML-Protokoll auslesen

Hi zusammen,

ich hab mir den folgenden TTL IR-Lesekopf in der Bucht gezogen und möchte gerne das SML-Protokoll meines Stromzählers (EasyMeter Q3CA 1081) auslesen:

grafik

Ich weiß, dass das Ganze ein sehr sehr komplexes Thema ist und das es schon fertige Lösungen wie z.B. Tasmota gibt.

Aber könnte mir trotzdem jemand
erklären, wie ich den Sensor an einen ESP32 anschließe (RX/TX oder besser/egal SoftwareSerial und beliebige Pins)
anhand eines einfachen Sketches zeigen, wie ich das vom Stromzähler gesendete SIgnal (in meinem Fall SML-Protokoll 1.04) lesbar am Serial-Monitor ausgeben kann

Am Ende sollte ja sowas in der Art

1.8.0255(000471.6452kWh)
2.8.0255(000528.9178kWh)

rauskommen.

Laut Support von EasyMeter sendet die MSB-Datenschnittstelle oben auf dem Zählerrand selbstständig alle 2 Sekunden einen SML-Datensatz mit Zähler-ID und abrechnungsrelevanten Werten (SML Version 1.04).

Ich hab für den ersten Test mal den RX Pin des Sensors mit GPIO 13 des ESP32 verbunden und das Script hier verwendet:

#include <IRremoteESP8266.h>
#include <IRrecv.h>
#include <IRutils.h>

const int IR_RECEIVER_PIN = 13;

IRrecv irrecv(IR_RECEIVER_PIN);
decode_results results;

void setup() {
  Serial.begin(9600);
  irrecv.enableIRIn();
}

void loop() {
  if (irrecv.decode(&results)) {
    Serial.print("Raw-Daten: ");

    for (int i = 0; i < results.rawlen; i++) {
      Serial.print((char)results.rawbuf[i], HEX);
    }
    Serial.println();

    irrecv.resume(); 
  }
}

Damit werden mir dann folgende Daten am Serial-Monitor ausgegeben:

Raw-Daten:
13B2D742B3D2C742C712BA45F3B2D3C603C60A42C712B84174F194D1A858444244C1A4F194E194E1AF216F217B9164E1A854C3C60715F702D3B2C742B3C953A943B2D3B95C2C3C2C742CDD2B3C2C702C3C2B702C3C95B2DDC2C3BCD3B2E732D3B2C74
Raw-Daten:
13D5E3E5EB8184E4E4B51B9174E4E4C50B8174E4E4D50B8173C2D742B3C2C742C3C2C752B3C2D742B715F3C943B2D3C2D3C2BC2DDD2BA4943B2C3C2D7060D960715FA394712BA55E3E2ADD2C712BA45F3B2DDC2C8518847F4A1E4D1B4E19844B4C1BF1
Raw-Daten:
12D3C95B2C3C2C752C3C2C752B3B2C752BD92CD82C3C2C752B3CCE3A62A4603B2C3B2C742DD2B7060702B7094491E8517B84A4D1B4E1A8A174E1B4D19844B4C1C4E4E8517B81884178516B8184EB64820702BA52B3CFD702BA55F3B2D70C8A32C702C
Raw-Daten:
13A2D742C3C2C742D8417B84B4C1C4F4E4C4FBA16861784174E1A4E19868345234D1B4D1A3C2D3B2CDD2CDD2B3C2DA42B7060A42B3CFD3A2D752B3B953B943B2E3B95B2D3B2C752BDD2B3C2D702B3B2C702C3D94C2CDD2C3BCD3A2E752C4D1A891786

Ist das völliger Blödsinn oder kann man aus den Daten mit der korrekten Entschlüsselung irgendwie mein erwartetes Ergebnis (siehe oben) rausbekommen?

Für eine kleine EInstiegshilfe wäre ich euch sehr dankbar - quasi als Weihnachtsgeschenk :slight_smile:

Such mall im hier im Forum das Thema wurde Minimum 10 mal gewalzt

Okidoki

hast du andere Boards?

Diverse, an was genau denkst du denn?
Das Board ist doch prinzipiell egal

anstatt die Dauer der Flanken einfach Serial Port betrachten, ob da text Nachrichten sind

Ab hier

Kannst Du alles lesen.
Wenn Du etwas nicht verstehst, dann kannst Du fragen.
Ich habe die Spec zerlegt und wir haben auch viel Code und Zeit investiert - das Projekt ist dann leider eingeschlafen, als ich daraus eine allgemeingültige Basis bauen wollte.

Da fällt mir gerade auf, dass wir mit so einem Kopf unsre Probleme hatten - ich such mal nach dem Einstieg, was wir damals gemacht haben.

1 Like

Les ich mich mal ein.
Was mir aber schon etwas spanisch vorkommt:

Bei den Beispielen, die ich bisher gefunden habe, fängt das empfangene Signal immer mit 1b 1b 1b usw. an.

Meine raw Daten sind ja völlig anders.
Aber ich les mich mal rein, Danke dir🤗

Schönen Abend, für heute bin ich raus😴

ohoh....

quelle

Wenn da mal nicht genau das passieren muss, was ich damals prophezeit habe...
Ausgabe erst auf Abruf....
Wäre natürlich blöd, aber halte ich nicht für unlösbar.

Bei der Info-Schnittstelle ist das wohl so.
Aber es gibt noch eine zweite Infrarot-Schnittstelle auf der Oberseite:

grafik

Und die sollte laut EasyMeter-Support was brauchbares Senden :wink:

Dann nehmen wir die :slight_smile:
Du must in jedem Fall die ESC-Sequenz (4x 1b) bekommen.
Alles andere ergibt sich dann.

1 Like

Ich muss aus dem damaligen Post auch mal raus"parsen", welchen Sensor der Ersteller verwendet hat. Auf den ersten Blick war es ein gewöhnlicher TCRT5000 und angeschlossen an RX/TX.
Ich verwende ja den oben verlinkten Sensor mit SoftwareSerial. Evtl. macht das ja auch schon den Unterschied. Ich bleib dran :slight_smile:

Du kannst auch den normalen Hardwareserial nehmen.
RX für den Sensor - TX für den SerMon.
nurmalso um SS auszuschliessen.

Aber nur nochmal zum Verständnis: Es gibt quasi auch Stromzähler-Modelle, die man per TX anstupsen muss, dass diese einem was per RX ausspucken, korrekt? Wobei das in meinem Fall ja dann nicht der Fall sein sollte.

Genau.
Das wäre dann die zweite Schnittstelle.
Und andere Zähler sind zwingend so gebaut (z.B. alle die, die direkt funkauslesbar sind und dafür kein SM-Gateway benötigen)

Ich überleg nur grad, ob das mit der Verwendung von IR-lib richtig ist...
Ich hätte einfach via Serial.read() gelesen ...

Der Satz "Der Zähler sendet alle 2 Sekunden einen Datensatz" suggeriert zumindest etwas anderes.
Ich hänge gern eine LED mit Vorwiderstand zwischen Vcc und Rx und sehe sofort, ob überhaupt was kommt, oder ob der IR-Lesekopf garnichts erkennt.

Im SML - Protokoll natürlich erheblich mehr als nur die Zählerstände, was dezent durch "nach Lastenheft Smart Message Language" angedeutet ist.

Yep, das probier ich mal.

Hi, ich hatte das auch nicht auf meinen Fall bezogen, das war nur eine allgemeine Feststellung :slight_smile:

Hallo,
ich weiß nicht ob das inzwischen schon geschrieben wurde, aber der Lesekopf den DU hast der hat eine serielle Schnittstelle. Den kannst Du beim ESP32 dann an die zweite serielle Schnittstelle RX2, TX2 anschließen und mittels Serial2.read() einlesen. In der Regel sollte das mit 9600 laufen. Also mit IRremote wird das mit Sicherheit nichts werden.

In dem von @my_xy_projekt angegeben Link findest Du Beispiele wie man ein Hexdum einlesen kann. Damit solltest Du erst mal anfangen um das Thema Schnittstelle und das Timing dazu in den Griff zu bekommen. Wenn Du dann stabil Daten für einen Datensatz lesen kannst die einem SML Protokoll entsprechen dann kannst Du ans auswerten gehen. Und ja das was Du auswerten willst muss mit 1b1b1b1b anfangen. Am Ende gibt es ebenfalls noch mal 1b1b1b1b und danach die Prüfsumme. Eventuell gibt es vor den nächsten Datensatz eine Pause.
Schreibe Dir einen Sketch mit dem Du erst mal alles was kommt byte für byte Hex auf dem Monitor darstellst. Wenn der Zähler kontinuierlich die erforderlichen Daten sendet dann wirst Du damit schon mal was erkennen können. Wie Du dann letztlich das Auswerten des SML der Datenstrukturen machst kannst Du dann entscheiden.

Wenn Du mal ein Hexdump hast kannst Du das gerne hier reinstellen und sicher wird dir geholfen.

Heinz

1 Like

Jetzt siehts gut aus!
Ich hab den oben verlinkten Sensor an GPIO16 angeschlossen (also RX2).

Mit diesem Script hier (das ich im oben verlinkten Beitrag gefunden habe, danke an @agmue , @Muecke und @my_xy_projekt für die Vorarbeit)....

// Quelle: https://forum.arduino.cc/t/sml-protokoll-identifiziren-und-zerlegen/1076696/276
// Quelle: Agmue & Muecke
// "Dump"-Ausgabe; Undefiniertes Ende ist eine Pause von mehreren (vielen) Millisekunden zwischen zwei Zeichen.

unsigned long inByteIndex = 0;
unsigned long UndefiniertesEnde = 300;          // Pausenzeit eingeben

void setup()
{
  Serial.begin(115200);
  Serial2.begin(9600);  // RXD2 = GPIO16
}
void loop()
{
  static unsigned long myTime;
  byte inByte = 0;
  if (Serial2.available())                        // Daten im Serial2
  {
    myTime = millis();
    inByte = Serial2.read();                      // auslesen
    switch (inByteIndex)                          // Aufruf einer Ausgabevariante in Abhängigkeit vom Index
    {
      case 0:                                     // erstes Byte in der Übertragung
        Serial.print("0x");
        Serial.printf("%02X", inByte );
        break;
      default:                                     // nicht das erste Zeichen in der Übertragung
        Serial.print(", 0x");
        Serial.printf("%02X", inByte );
        break;
    } // switch
    inByteIndex++;                                // Byte-Index-Inkrement
  }
  if (millis() - myTime > UndefiniertesEnde && inByteIndex != 0) // Längere Pause erkannt, daher Zeilenumbruch einfügen
  {
    Serial.println ();
    Serial.println ("MSG-Länge: " + String(inByteIndex) + " Byte");
    inByteIndex = 0;
  }
} // loop

Bekomme ich diese Ausgabe:

0x1B, 0x1B, 0x1B, 0x1B, 0x01, 0x01, 0x01, 0x01, 0x76, 0x05, 0xF2, 0x01, 0x32,
0x19, 0x62, 0x00, 0x62, 0x00, 0x72, 0x65, 0x00, 0x00, 0x01, 0x01, 0x76, 0x01,
0x01, 0x07, 0x45, 0x53, 0x59, 0x51, 0x33, 0x43, 0x0B, 0x06, 0x45, 0x53, 0x59,
0x01, 0x07, 0x1A, 0x33, 0xD0, 0xBA, 0x01, 0x01, 0x63, 0xFF, 0xF2, 0x00, 0x76,
0x05, 0xF2, 0x01, 0x32, 0x1A, 0x62, 0x00, 0x62, 0x00, 0x72, 0x65, 0x00, 0x00,
0x07, 0x01, 0x77, 0x01, 0x0B, 0x06, 0x45, 0x53, 0x59, 0x01, 0x07, 0x1A, 0x33,
0xD0, 0xBA, 0x01, 0x72, 0x62, 0x01, 0x65, 0x13, 0x14, 0xEE, 0x6C, 0x7F, 0x77,
0x07, 0x81, 0x81, 0xC7, 0x82, 0x03, 0xFF, 0x01, 0x01, 0x01, 0x01, 0x04, 0x45,
0x53, 0x59, 0x01, 0x77, 0x07, 0x01, 0x01, 0x01, 0x08, 0x00, 0xFF, 0x63, 0x01,
0x90, 0x72, 0x62, 0x01, 0x65, 0x13, 0x14, 0xEE, 0x6C, 0x62, 0x1E, 0x52, 0xFC,
0x69, 0x00, 0x00, 0x00, 0x67, 0x3A, 0x9C, 0x99, 0xB9, 0x01, 0x77, 0x07, 0x01,
0x01, 0x01, 0x08, 0x01, 0xFF, 0x63, 0x01, 0x90, 0x72, 0x62, 0x01, 0x65, 0x13,
0x14, 0xEE, 0x6C, 0x62, 0x1E, 0x52, 0x01, 0x65, 0x00, 0x43, 0xA3, 0xEC, 0x01,
0x77, 0x07, 0x01, 0x01, 0x01, 0x08, 0x02, 0xFF, 0x63, 0x01, 0x90, 0x72, 0x62,
0x01, 0x65, 0x13, 0x14, 0xEE, 0x6C, 0x62, 0x1E, 0x52, 0x01, 0x65, 0x00, 0x00,
0x00, 0x6E, 0x01, 0x77, 0x07, 0x01, 0x01, 0x01, 0x08, 0x03, 0xFF, 0x63, 0x01,
0x90, 0x72, 0x62, 0x01, 0x65, 0x13, 0x14, 0xEE, 0x6C, 0x62, 0x1E, 0x52, 0x01,
0x65, 0x00, 0x00, 0x00, 0x6F, 0x01, 0x77, 0x07, 0x01, 0x01, 0x01, 0x08, 0x04,
0xFF, 0x63, 0x01, 0x90, 0x72, 0x62, 0x01, 0x65, 0x13, 0x14, 0xEE, 0x6C, 0x62,
0x1E, 0x52, 0x01, 0x65, 0x00, 0x00, 0x00, 0x6E, 0x01, 0x77, 0x07, 0x01, 0x01,
0x01, 0x08, 0x05, 0xFF, 0x63, 0x01, 0x90, 0x72, 0x62, 0x01, 0x65, 0x13, 0x14,
0xEE, 0x6C, 0x62, 0x1E, 0x52, 0x01, 0x65, 0x00, 0x00, 0x00, 0x6F, 0x01, 0x77,
0x07, 0x01, 0x01, 0x01, 0x08, 0x06, 0xFF, 0x63, 0x01, 0x90, 0x72, 0x62, 0x01,
0x65, 0x13, 0x14, 0xEE, 0x6C, 0x62, 0x1E, 0x52, 0x01, 0x65, 0x00, 0x00, 0x00,
0x6E, 0x01, 0x77, 0x07, 0x01, 0x01, 0x01, 0x08, 0x07, 0xFF, 0x63, 0x01, 0x90,
0x72, 0x62, 0x01, 0x65, 0x13, 0x14, 0xEE, 0x6C, 0x62, 0x1E, 0x52, 0x01, 0x65,
0x00, 0x00, 0x00, 0x6F, 0x01, 0x77, 0x07, 0x01, 0x01, 0x01, 0x08, 0x08, 0xFF,
0x63, 0x01, 0x90, 0x72, 0x62, 0x01, 0x65, 0x13, 0x14, 0xEE, 0x6C, 0x62, 0x1E,
0x52, 0x01, 0x65, 0x00, 0x00, 0x00, 0x6E, 0x01, 0x77, 0x07, 0x01, 0x00, 0x01,
0x07, 0x00, 0xFF, 0x01, 0x01, 0x62, 0x1B, 0x52, 0xFE, 0x55, 0x00, 0x01, 0x5F,
0x3B, 0x01, 0x77, 0x07, 0x01, 0x00, 0x15, 0x07, 0x00, 0xFF, 0x01, 0x01, 0x62,
0x1B, 0x52, 0xFE, 0x55, 0x00, 0x00, 0xF3, 0x3E, 0x01, 0x77, 0x07, 0x01, 0x00,
0x29, 0x07, 0x00, 0xFF, 0x01, 0x01, 0x62, 0x1B, 0x52, 0xFE, 0x55, 0x00, 0x00,
0x54, 0x93, 0x01, 0x77, 0x07, 0x01, 0x00, 0x3D, 0x07, 0x00, 0xFF, 0x01, 0x01,
0x62, 0x1B, 0x52, 0xFE, 0x55, 0x00, 0x00, 0x17, 0x6A, 0x01, 0x77, 0x07, 0x01,
0x00, 0x60, 0x05, 0x05, 0xFF, 0x01, 0x01, 0x01, 0x01, 0x63, 0x01, 0x90, 0x01,
0x01, 0x01, 0x63, 0xB3, 0x92, 0x00, 0x76, 0x05, 0xF2, 0x01, 0x32, 0x1B, 0x62,
0x00, 0x62, 0x00, 0x72, 0x65, 0x00, 0x00, 0x02, 0x01, 0x71, 0x01, 0x63, 0x03,
0xCD, 0x00, 0x1B, 0x1B, 0x1B, 0x1B, 0x1A, 0x00, 0x75, 0xD8
MSG-Länge: 504 Byte

Also hab ich jetzt mein "Hello World".
Jetzt kämpf ich mich durch den POst und alle darin verlinkten und hoffe mal, irgendwann dann meinen Stromzähler erfolgreich auszulesen.

Danke euch!

1 Like

Na dann. Wie eine Msg aussieht hab ich ja schonmal dargestellt.
Versuch mal das jetzt hier in Werte umzubauen:

1B 1B 1B 1B 
01 01 01 01 
76 
 05 F2 01 32 19 
 62 00 
 62 00 
 72 
  65 00 00 01 01 
  76 
   01
   01 
   07 45 53 59 51 33 43 
   0B 06 45 53 59 01 07 1A 33 D0 BA 
   01 
   01 
 63 FF F2 
 00 
76
 05 F2 01 32 1A 
 62 00 
 62 00 
 72 
  65 00 00 07 01 
  77 
   01 0B 
   06 45 53 59 01 07 
   1A 33 D0 BA 01 72 62 01 65 13 14 EE 6C 7F 77 07 81 81 C7 82 03 FF 01 01 01 01 04 45 53 59 01 
 77 
  07 01 01 01 08 00 FF 
  63 01 90 
  72 
   62 01 
   65 13 14 EE 6C 
  62 1E 
  52 FC
  69 00 00 00 67 3A 9C 99 B9 
  01 
 77 
  07 01 01 01 08 01 FF 
  63 01 90 
  72 
   62 01 
   65 13 14 EE 6C 
  62 1E 
  52 01 
  65 00 43 A3 EC 
  01
 77 
  07 01 01 01 08 02 FF 
  63 01 90 
  72 
   62 01 
   65 13 14 EE 6C 
  62 1E 
  52 01 
  65 00 00 00 6E 
  01 
 77 
  07 01 01 01 08 03 FF 
  63 01 90 
  72 
   62 01 
   65 13 14 EE 6C 
  62 1E 
  52 01
  65 00 00 00 6F 
  01 
 77 
  07 01 01 01 08 04 FF 
  63 01 90 
  72 
   62 01 
   65 13 14 EE 6C 
  62 1E 
  52 01 
  65 00 00 00 6E 
  01
 77 
  07 01 01 01 08 05 FF 
  63 01 90 
  72 
   62 01 
   65 13 14 EE 6C 
  62 1E 
  52 01 
  65 00 00 00 6F 
  01 
 77
  07 01 01 01 08 06 FF 
  63 01 90 
  72 
   62 01
   65 13 14 EE 6C 
  62 1E 
  52 01 
  65 00 00 00 6E 
  01 
 77 
  07 01 01 01 08 07 FF 
  63 01 90
  72 
   62 01 
   65 13 14 EE 6C 
   62 1E 
   52 01 
   65 00 00 00 6F 
   01 
  77 
   07 01 01 01 08 08 FF
   63 01 90 
   72 
    62 01 
    65 13 14 EE 6C 
   62 1E
   52 01 
   65 00 00 00 6E 
   01 
  77 
   07 01 00 01 07 00 FF 
   01 
   01 
   62 1B 
   52 FE 
   55 00 01 5F 3B 
   01 
  77 
   07 01 00 15 07 00 FF 
   01 
   01 
   62 1B 
   52 FE 
   55 00 00 F3 3E 
   01 
  77 
   07 01 00 29 07 00 FF 
   01 
   01 
   62 1B 
   52 FE 
   55 00 00 54 93 
   01 
  77 
   07 01 00 3D 07 00 FF 
   01 
   01
   62 1B 
   52 FE 
   55 00 00 17 6A 
   01 
  77 
   07 01 00 60 05 05 FF 
   01 
   01 
   01 
   01 
   63 01 90 
   01
 01 
 01 
 63 B3 92 
 00 
 76 
  05 F2 01 32 1B 
  62 00 
  62 00 
  72 
   65 00 00 02 01 
   71 
    01 
    63 03 CD 
   00 
1B 1B 1B 1B 
1A 00 75 D8
MSG-Länge: 504 Byte