SML Protokoll identifiziren und zerlegen

das war mir schon klar, wie ich jedoch schon von Anfang sage ist mein Start nicht Korrekt. und das war er warum auch immer noch nie.

Da ich jedoch die Server-ID korrekt raus gelesen habe schon mal, muss das noch bei den Daten von Gesten Nacht prüfen, gehe ich davon aus das ich irgend was Falsch mache mein Code zu langsam ist etc. denn ich bezweifle das ich der ein zigste bin der einen Stromzähler mit einem anderen Protokoll Anfang ausgeliefert bekommen habe.

Eventuell liegt es auch am ESP32?
Könnte Test halber auch ein UNO oder Mega dran klemmen, jedoch fehlt mir da dann zum Schluss das W-lan Modul .-(

grafik
leider ist mein 3D Druck nicht mit Absatz so das es in die vertiefen passt :frowning: es haftet jedoch per Supermagneten der sich im 3D Druck befindet am Stromzähler fest.

[EDIT] meine Server-ID die auf dem Gerät steht habe ich in den Datensätzen von Gesten Nacht gefunden fehlerfrei.
Start: A3 A3 A3 01 01 01 76 05 ....
Ende: ... 00 1B 1B 1B 1B 1A 00 E4 ED A3

[EDIT_2]
Hätte ich geahnt das das so ein problem wird hätte ich das gelassen.

Dabei möchte ich nur meinen Aktuellen verbrauch auf einer SD Karte Speichern (Archiv) und meinen Aktuellen verbrauch (eventuell mit Mini Historisiere 30 werte in die Vergangenheit) auf einer Webseite ausgeben die ich in meinem Heimnetzwerk abrufen kann. :see_no_evil:. alles andere interessiert mich in den Daten nicht.

Das diese jedoch nicht richtig übertragen werden ärgert mich, denn mir ist nicht klar wo mein Fehler ist.

Mach daraus, das nicht klar ist, wo der Fehler ist.
Es ist noch nicht sicher, ob der wirkliich bei Dir liegt.

Ich geh jetzt mal futtern...


// Serielle Schnittstelle TCRT5000 zum ISKRA-MT681
#define RXD2 15                         // TCRT5000 (D0)
#define TXD2 13                         // ohne belegung
#define Baudrate 9600                   // vorgabe vom Stromzähler
#define Protocol SERIAL_8N1             // vorgabe vom Stromzähler
// Serielle Schnittstelle ESP32 zu PC
#define Baudrate_USB 115200             // 

byte startSequenz[9] = {0};
byte sequenzIndex;
byte smlVersion = 0;
bool ende = false;
uint32_t tik;

void setup()
{
  Serial1.begin(Baudrate, Protocol, RXD2, TXD2);
  Serial.begin(Baudrate_USB);
}


void loop()
{
  while (Serial1.available())                   // Daten im Serial1 ?
  {
    if (ende)
    {
      uint32_t tak = millis() - tik;
      if (tak > 50)
      {
        Serial.print(F("Pause: "));
        Serial.print(tak);
        Serial.print(F(" bei; ")
                     Serial.println(millis());
      }
    }
    tik = millis();
    byte inByte = Serial1.read();               // auslesen
    switch (sequenzIndex)
    {
      case 0:                                   // 4 Bytes für ESC-Sequenz
      case 1:
      case 2:
      case 3:
        if (inByte == 0X1B)
        {
          Serial.println(F("1B erkannt"));
          ende = false;
          sequenzIndex++;
        }
        else if (sequenzIndex != 0)
        {
          Serial.print(F("ESC-Abbruch mit Index"));
          Serial.print(sequenzIndex);
          Serial.print(F(" Inhalt: "));
          ausgabe(inByte);
          sequenzIndex = 0;
        }
        break;
      case 4:                                    // Festlegung was als nächstes kommt
        smlVersion = 0;
        switch (inByte)
        {
          case 0x01:
            Serial.println(F("Transferstart SML-Version 1"));
            break;
          case 0x02:
            Serial.println(F("Blockstart SML-Version 2 erkannt"));
            break;
          case 0x03:
            Serial.println(F("SML-V2 TimeoutSequenz"));
            break;
          case 0x04:
            Serial.println(F("SML-V2 Blockgröße"));
            break;
          case 0x1A:
            Serial.print(F("Sequenzende erkannt"));
            ende = true;
            break;
          default:
            Serial.print(F("Nicht zuordbar: "));
            ausgabe(inByte);
            break;
        }
      /* FALLTHRU */
      case 5:                               // 3Bytes Inhalt je nach SML-Version
      case 6:
      case 7:
        sequenzIndex++;
        break;
      default:
        sequenzIndex = 0;
        // sequenzIndex++;
        break;
    }
  }
}
void ausgabe(const byte myByte)
{
  Serial.print("0x");
  if (myByte < 0x10)
  { Serial.print(0); }
  Serial.print(myByte, HEX);
}

Ich will nachher die Ausgabe in der mindestens 3 erkannte Endesequenzen drin sind.
Dann bau ich weiter.

1 Like

Das ist die Ausgabe,
leider sehe ich den kompletten Datensatz so nicht :frowning:

Ich gehe nicht davon aus das ich ein Fehlerhaftes gerät hier habe, eher das ich etwas Fehlerhaft gemacht habe oder mache.

Ich stelle dir auch gerne Komplette Datenströme zu Verfügung, bin mir nur nicht sicher wie das mit den privaten Daten in den Datenströmen ist. (wenn du mir per PN eine Mail Adresse nennst sende ich dir was per Mail. ?)

Hi,
ist erstmal egal.
Ich orientiere mich an der ESC-Sequenz.
Die gibt es einleitend beim Start und beim Ende.
Der Datenstrom wird auch noch aber erstmal will ich die Grundlagen haben.

Du bekommst die ESC-Sequenz und die Endekennung. (Da fehlt nen Zeilenumbruch in meinem Code, ist aber egal)
Danach ist ca. 1 Sekunde Pause.
Dann kommen 2 Bytes mit gutgehend 100ms Abstand.
Die ESC-Sequenz kommt immer nur bevor die EndeKennung kommt.

Deine ID steht immer drin, die EndeSequenz kommt immer, die Pausenzeiten sind plausibel.
Ich kann mir nicht vorstellen, das ausgerechnet immer die Startsequenz vom Sensor/Controller verkackt wird.
Aber ich hab jetzt einen Ansatzpunkt um mir den Stream aufzulösen. Las mich mal überlegen, was jetzt sinnvoll ist.

Sehr gerne.

mir ist aufgefallen das ich je nach Positionierung ein klein wenig andere Ergebnisse bekomme.
habe meinen 3D Druck über den Haufen geworfen und mit etwas Karton und klebe band das teil nun Fixiert, ist nicht schön hält jedoch die nächsten Jahre :rofl:
Jetzt bekomme ich das ESP32 jedoch auch nicht mehr ab, zum neu aufspielen muss ich demnach immer in den Keller (der ist kalt)

Bilder der Befestigung und einen neue Datenausgabe kann ich gleich Online stellen, ca. 5 - 10 min

Kein WLAN im Keller? Dann wäre OTA eine Möglichkeit.

Gruß Tommy

Doch das habe ich.
Was ist OTA ? kann ich so auf den ESP32 zugreifen und Programme aufspielen über W-Lan?

[Kosmetik]
Der ESP32 hat Serial1 an nicht benutzbaren Pins, weshalb eine Verlegung sinnvoll ist. Dann sollten die Pins aber RXD1 und TXD1 benannt werden.

Oder Du verwendest gleich Serial2 an GPIO16 und GPIO17 (RXD2 und TXD2).
[/Kosmetik]

Ja, aber dann geht der serielle Monitor nicht mehr. OTA = Over The Air

Das sind die Bilder der Befestigung nun.


grafik

Ja.

Gruß Tommy

1 Like

Richtig das habe ich gemacht, da ich so das IR-Bodr direkt anstecken kann ohne separate Kabel zu zihen.

  • 3V3
  • GND
  • PIN 15
    Die liegen alle direkt neben einander und ich kann das TCRT5000 direkt aufstecken eventuell sieht man das auf den Bildern etwas.

Ok, dann kommt das aktuell nicht in frage.

Ja das kann ich machen, das ist ja wirklich nur Kosmetik.
Die Pins möchte ich ungern ändern denn dann müsste ich Kabel verbauen.

Hier ist was richtig faul.
Das geht nicht. Da soll eigentlich ein Byte rauskommen. Das sind aber irgendwie zwei....

Dafür hast Du jetzt nur eine Pause. Das dürfte richtig sein.

Kann mir irgendwer erklären wie das byte 0x621B zusammenkommt?

Weil vermutlich noch immer irgendwas an dem Empfänger nicht stimmt. Es müssten ja auch 4 mal 0x1B erkannt werden, es sind jedoch nur 3 enthalten. Eigentlich müßte man 4x 0x1B gefolgt von 4 mal 0x01 in Folge sehen. Sehe ich nirgends bis jetzt. Solange Mücke immer nur probiert und nicht den Sensor einstellt, solange wird das nichts. Mit einstellen ist nicht nur die Positionierung gemeint. Die Magnethalterung war doch schon sehr gut, warum jetzt Tonnen von Klebeband. Es kann doch nicht so schwer sein eine passende Form zu feilen damit der Sensor plan aufliegt und sauber eingestellt wird. Mücke muss den Code dafür verwenden um seinen Sensor einzustellen.

Das ist alles klar. Ich hab ja darauf den Code gebaut.
Das diffuse ist, das die Endesequenz (4x1B & 1x 1A) oben sauber kommt und jetzt kommt da was anderes raus.
Wie passt in ein byte 0x621B / 0x521B? Richtig. Garnicht.
Also was passiert da?

Ich hatte gedacht das hier ein Zeilenumbruch fehlen würde.

Ach ja....
Ok. Dann kommt da ne 62/52 extra. Na dann bau ich mal ein kleines Array um Werte aufzunehmen.

Das glaube ich auch, wobei ich inzwischen schon ein neues Modul aus der Verpackung geholt habe.

Die ist leider immer wieder etwas verrutscht :-(, das jetzt mit Karton- und Klebeband hält vorerst seine Position.
Es macht einen Rissen unterschied ob ich um 0,5mm weiter links / Rechts Oben / unten bin.
Das ist extrem empfindlich. ich verstehe das gar nicht denn wenn ich mit einer Fernbedienung das ganze teste dann kann ich mit der egal woher aus welchen Winkel etc. senden und bekomme das selbe Ergebnis.

Du meinst mit dem Blauen Poti der auf der Platine ist?
Das habe ich auch schon gemacht, doch den Start bekomme ich dennoch nicht zu gesiecht.

oder was meinst du damit?

Ich habe das mit dem Poti noch mal probiert, doch nur in dieser Einstellung wie sie jetzt ist bekomme ich zumindest das Ende erkennt, und meine Server-ID ist korrekt im Datenstrom zu finden.
bei allen anderen Einstellungen am Poti ist das nicht der Fall.

Hier ein Kompletter mit schneit meiner Daten die Brauchbar sind.

Aufbau: Zeitstempel ->Daten vom Stromzähler ; Pause für (in ms)
Das zwischen -> und ; sind die ROH Daten des Stromzählers.

So, ich hoffe nix vergessen zu haben.
Der Code nimmt nach der Ende-Kennung 30 Bytes auf.
Mal sehen, was dabei raus kommt.
Der Code soll irgendwann von allein aufhören :wink:


// Serielle Schnittstelle TCRT5000 zum ISKRA-MT681
#define RXD2 15                         // TCRT5000 (D0)
#define TXD2 13                         // ohne belegung
#define Baudrate 9600                   // vorgabe vom Stromzähler
#define Protocol SERIAL_8N1             // vorgabe vom Stromzähler
// Serielle Schnittstelle ESP32 zu PC
#define Baudrate_USB 115200             // 

byte startSequenz[9] = {0};
byte sequenzIndex;
byte smlVersion = 0;
bool ende = false;
uint32_t tik;

const byte smlBytes = 31;
byte smlArray[smlBytes] = {0};
uint32_t smlTime[smlBytes] = {0};
byte smlIdx = 0;

const byte sollUmlauf = 5;
byte umlauf = 0;

void setup()
{
  Serial1.begin(Baudrate, Protocol, RXD2, TXD2);
  Serial.begin(Baudrate_USB);
}


void loop()
{
  while (Serial1.available())                   // Daten im Serial1 ?
  {
    byte inByte = Serial1.read();               // auslesen
    if (ende)                                   // letzte Nachricht Ende wurde bereits erkannt
    {
      uint32_t tak = millis() - tik;            // Zeit seit letztem ausgewertetem Byte
      /*
        if (tak > 50)
        {
        Serial.print(F("Pause: "));
        Serial.print(tak);
        Serial.print(F(" bei; "));
        Serial.println(millis());
        }
      */
      if (!smlVersion)                          // smlVersion noch nicht festgesetellt
      {
        if (smlIdx < smlBytes)                   // Nur wenn Platz ist im Array
        {
          smlArray[smlIdx] = inByte;
          smlTime[smlIdx] = tak;
          smlIdx++;
        }
      }
    }
    tik = millis();                             // Zeit merken für Auswertung
    switch (sequenzIndex)
    {
      case 0:                                   // 4 Bytes für ESC-Sequenz
        smlVersion = 0;
      /* FALLTHRU */
      case 1:
      case 2:
      case 3:
        if (inByte == 0X1B)
        {
          Serial.println(F("1B erkannt"));
          ende = false;
          sequenzIndex++;
        }
        else if (sequenzIndex != 0)
        {
          Serial.print(F("ESC-Abbruch mit Index"));
          Serial.print(sequenzIndex);
          Serial.print(F(" Inhalt: "));
          ausgabe(inByte);
          sequenzIndex = 0;
        }
        break;
      case 4:                                    // Festlegung was als nächstes kommt
        switch (inByte)
        {
          case 0x01:
            Serial.println(F("Transferstart SML-Version 1"));
            smlVersion = 1;
            break;
          case 0x02:
            Serial.println(F("Blockstart SML-Version 2 erkannt"));
            smlVersion = 2;
            break;
          case 0x03:
            Serial.println(F("SML-V2 TimeoutSequenz"));
            break;
          case 0x04:
            Serial.println(F("SML-V2 Blockgröße"));
            break;
          case 0x1A:
            Serial.println(F("Sequenzende erkannt"));
            ende = true;
            smlVersion = 0;
            if (smlIdx != 0)
            { printMessage(); }
            memset(smlArray, 0, smlBytes);
            memset(smlTime, 0, smlBytes);
            smlIdx = 0;
            umlauf++;
            if (umlauf > sollUmlauf)
            {
              Serial.println(F("\r\nENDE! - Zum Neustart reset"));
              while (1);
            }
            break;
          default:
            Serial.print(F("Nicht zuordbar: "));
            ausgabe(inByte);
            break;
        }
      /* FALLTHRU */
      case 5:                               // 3Bytes Inhalt je nach SML-Version
      case 6:
      case 7:
        sequenzIndex++;
        break;
      default:
        sequenzIndex = 0;
        // sequenzIndex++;
        break;
    }
  }
}
void ausgabe(const byte myByte)
{
  Serial.print("0x");
  if (myByte < 0x10)
  { Serial.print(0); }
  Serial.print(myByte, HEX);
}
void printMessage()
{
  byte b = 0;
  for (; b < 3; b++)                  // Auffülbytes, CRC-MSB, CRC-LSB
  {
    Serial.print(smlTime[b]);
    Serial.print('\t');
    ausgabe(smlArray[b]);
  }
  Serial.print(F("Auffüllbytes: "));
  for (byte a = 0; b < smlArray[0]; a++)  // Anzahl auffüllbytes
  {
    b++;
    ausgabe(smlArray[b]);
    Serial.print(' ');
  }
  Serial.println();
  Serial.println(F("Message: "));
  byte tmpByte = b;
  for (; b < smlBytes; b++)
  {
    ausgabe(smlArray[b]);
    Serial.print(' ');
    if ((b - tmpByte) % 4 == 0)
    { Serial.print(' '); }
  }
}