bytes in HEX zu int (LSB und Basis DEC)

so nun muss ich auch mal fragen.

ich bekomme von einem mbus slave 4bytes in HEX
z.B.
45300000

dies stellt 35,4kWh dar. bedeutet also die die Reihenfolge ist LSB und die Basis der Werte ist Dezimal aber die Codierung ist in HEX.

wie kann ich nun z.B. die erst 4bit (die 4) extrahieren und zu einem Integer kopieren?

Du schreibst die ankommenden Bytes in ein array und liest es umgekehrt aus.

for (int i=0; i<=3; i++)
{
Zahl[i]= SerialRead();
}


for (int i=3; i>=0; i--)
{ 
verbrauch = verbrauch*256+Zahl[i]
}
float VerbrauchkW = verbrauch /10;

Grüße Uwe

Bist du mit deiner Kodierung sicher?

Das wäre schon sehr ungewönlich, LSB für die Bytes, aber MSB für die Ziffern.

Normalerweise würde 0x4530 30.45 ergeben.

uint32_t muster = 0x00000345;

uint32_t fromBCD(uint32_t in) {
  uint32_t ergebnis = 0;
  byte* p = ((byte*)&in) + 3;
  for (byte i = 0; i < 4; i++) {
    ergebnis *= 10;
    ergebnis += (*p & 0xF0) >> 4;
    ergebnis *= 10;
    ergebnis += *p-- & 0x0F;
  }
  return ergebnis;
}
void setup() {
  Serial.begin(250000);
  Serial.print(F("0x"));
  Serial.println(muster, HEX);
  Serial.print(F("decimal "));
  Serial.println(fromBCD(muster));
}
void loop() {}
0x345
decimal 345

uwefed:
Du schreibst die ankommenden Bytes in ein array und liest es umgekehrt aus.

for (int i=0; i<=3; i++)

{
Zahl[i]= SerialRead();
}

for (int i=3; i>=0; i--)
{
verbrauch = verbrauch*256+Zahl[i]
}
float VerbrauchkW = verbrauch /10;




Grüße Uwe

das würde mit dem Beispiel vom ersten Post 34,5kWh ergeben gefordert wäre aber 35,4, man müsste also jede 4bit lesen

Whandall:
Bist du mit deiner Kodierung sicher?

Das wäre schon sehr ungewönlich, LSB für die Bytes, aber MSB für die Ziffern.

Normalerweise würde 0x4530 30.45 ergeben.

uint32_t muster = 0x00000345;

uint32_t fromBCD(uint32_t in) {
 uint32_t ergebnis = 0;
 byte* p = ((byte*)&in) + 3;
 for (byte i = 0; i < 4; i++) {
   ergebnis *= 10;
   ergebnis += (*p & 0xF0) >> 4;
   ergebnis *= 10;
   ergebnis += *p-- & 0x0F;
 }
 return ergebnis;
}
void setup() {
 Serial.begin(250000);
 Serial.print(F("0x"));
 Serial.println(muster, HEX);
 Serial.print(F("decimal "));
 Serial.println(fromBCD(muster));
}
void loop() {}





0x345
decimal 345

ganz sicher, hier ein Foto:
https://photos.app.goo.gl/nJw3bBx3goCtmDQ3A

angekommen ist 0x65200000

Wie wird das übertragen, welchen Kode benutzt du um diese Zahl zu erzeugen?

Bild vom TO.
Unbenannt.jpg

Unbenannt.jpg

ich sende ein Anfrage an den Wärmemengenmesser:
10 7b 00 7b 16

und bekomme dann eine Antwort:

void serialEvent2() //mbus
{
  while (Serial2.available())
  {
    // ein byte laden und speichern
    inByteMbus = Serial2.read();
    // hinzufügen
    TelegramMbus[indexMbus] = inByteMbus;
    indexMbus++;
    if (inByteMbus == 0x16 && TelegramMbus[0] == 0x68)  // 0x16 ist das Stopzeichen und 0x68 das Startzeichen eines Telegramms
    {
      Serial.println("Antwort vom Slave komplett:");
      indexMbus = 0;
      // Gesamt kWh
      Serial.print(TelegramMbus[21],HEX);
      Serial.print(TelegramMbus[22],HEX);
      Serial.print(TelegramMbus[23],HEX);
      Serial.println(TelegramMbus[24],HEX);
    }
  }
}

die Antwort im Gesamten sieht so aus:

68 71 71 68 08 00 72 97 68 80 06 65 32 10 0D B9 00 00 00 0C 05 BB BB BB BB 0B 22 74 41 05 04 6D 3B 0B 72 21 32 6C 00 00 0C 78 97 68 80 06 06 FD 0C F2 03 01 00 F7 01 0D FD 0B 05 31 32 4E 46 57 01 FD 0E 00 4C 05 BB BB BB BB 42 6C 5F 2C 8C 10 05 00 00 00 00 CC 10 05 00 00 00 00 C2 10 6C 5F 2C 0F 37 FD 17 00 00 00 00 00 00 00 00 02 7A 25 02 02 78 25 02 11 16

in dem Beispiel hier lag der Messer noch auf dem Schreibtisch und der Wert war noch BB BB BB BB

An BB BB BB BB kann man nichts erkennen, das ist völlig ungeeignet.

      Serial.print(TelegramMbus[21],HEX);
      Serial.print(TelegramMbus[22],HEX);
      Serial.print(TelegramMbus[23],HEX);
      Serial.println(TelegramMbus[24],HEX);

Da du keine führenden Nullen ausgibst kann man auch damit nur sehr wenig erkennen
und dein eingangs erwähntes "45300000" kann mit der Sequenz nicht ausgegeben werden.

verzeihe mir die Ungenauigkeit :slight_smile: , die print Methode gibt keine führende Null aus, sagen wir in den 4byte steht nacheinander 0x45 0x30 0x00 0x00.

ich war gerade am Wärmemengenzähler und er zeigt 72.6kWh an.

in meiner console steht nun:
fordere mbus telegram an
Antwort vom Slave komplett:
62700

edit
also in:
TelegramMbus[21] 0x62
TelegramMbus[22] 0x07
TelegramMbus[23] 0x00
TelegramMbus[24] 0x00

Rothammel:
verzeihe mir die Ungenauigkeit :slight_smile: , die print Methode gibt keine führende Null aus, sagen wir in den 4byte steht nacheinander 0x45 0x30 0x00 0x00.

Wahrscheinlich steht da eher 0x45 0x03 0x00 0x00. aber an nachgetippten Ausgaben kann man das nicht erkennen.

Whandall:
Wahrscheinlich steht da eher 0x45 0x03 0x00 0x00. aber an nachgetippten Ausgaben kann man das nicht erkennen.

stimmt natürlich

eigenartige Codierung. Binär so wie einige Daten auf Chipkarten.

TelegramMbus[21] 0x62
TelegramMbus[22] 0x07
TelegramMbus[23] 0x00
TelegramMbus[24] 0x00

zu 72.6 ... also

TelegramMbus[21]&0b00001111 =2 das /10 in deinen Buffer addieren
TelegramMbus[21]>>4 =6 .... in deinen Buffer addieren

TelegramMbus[22]&0b00001111 =7 ... *10 in deinen Buffer addieren
TelegramMbus[22]>>4 =0 ..... *100 in deinen Buffer addieren

TelegramMbus[23]&0b00001111 =0 ... *1000 in deinen Buffer addieren
TelegramMbus[23]>>4 =0 ..... *10000 in deinen Buffer addieren

TelegramMbus[24]&0b00001111 =0 ... *100000 in deinen Buffer addieren
TelegramMbus[24]>>4 =0 ..... *1000000 in deinen Buffer addieren

geht sicher schöner, hab nur momentan keine andere Idee.

noiasca:
eigenartige Codierung. Binär so wie einige Daten auf Chipkarten.

TelegramMbus[21] 0x62
TelegramMbus[22] 0x07
TelegramMbus[23] 0x00
TelegramMbus[24] 0x00

zu 72.6 ... also

wieso 72.6 und nicht 702.6 ?

ist sein Muster. Wenn es falsch ist, muss er es richtig stellen. Sollte ihm aber gelingen. Es ging mir darum zu zeigen, wie er zu den einzelnen Stellen kommt, und das tut es. Bei Byte 23 und 24 habe ich mangels Testdaten geraten.

Ein realer Dump (mit führenden Nullen und Leerzeichen) würde Klarheit bringen.

ich habe das Beispiel getestet und es ist genau das Ergebnis entstanden, was ich benötige.

wie soll ich einen Dump erstellen? noch mal nen FTDI anstecken und mit hterm aufzeichenen? oder geht das aus dem Arduino auch?

kein Thema, ich bin euch zu großem Dank verpflichtet:

0x68 0x71 0x71 0x68 0x08 0x00 0x72 0x97 0x68 0x80 0x06 0x65 0x32 0x10 0x0D 0x49 0x00 0x00 0x00 0x0C 0x05 0x06 0x10 0x00 0x00 0x0B 0x22 0x79 0x42 0x05 0x04 0x6D 0x09 0x14 0x76 0x21 0x32 0x6C 0x00 0x00 0x0C 0x78 0x97 0x68 0x80
0x06 0x06 0xFD 0x0C 0xF2 0x03 0x01 0x00 0xF7 0x01 0x0D 0xFD 0x0B 0x05 0x31 0x32 0x4E 0x46 0x57 0x01 0xFD 0x0E 0x00 0x4C 0x05 0xBB 0xBB 0xBB 0xBB 0x42 0x6C 0x5F 0x2C 0x8C 0x10 0x05 0x14 0x00 0x00 0x00 0xCC 0x10 0x05 0x00 0x00
0x00 0x00 0xC2 0x10 0x6C 0x5F 0x2C 0x0F 0x37 0xFD 0x17 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x02 0x7A 0x25 0x02 0x02 0x78 0x25 0x02 0xC0 0x16

weil ihr fragt, erstellt mit:

inByteMbus = Serial2.read();
    Serial.print("0x");
    if (inByteMbus < 0x10) Serial.print("0");
    Serial.print(inByteMbus, HEX);
    Serial.print(" ");

Wenn man jetzt noch wüsste was gleichzeitig auf dem Display stand...

weiß ich auch nicht, das Ding sitzt im Rücklauf von unserem Holzvergaser, aber für dich war ich gerade noch mal guggen gegangen, die Pumpe steht und der Stand ist 104,3kWh und hier der dump:

0xE5 0x68 0x71 0x71 0x68 0x08 0x00 0x72 0x97 0x68 0x80 0x06 0x65 0x32 0x10 0x0D 0x62 0x00 0x00 0x00 0x0C 0x05 0x43 0x10 0x00 0x00 0x0B 0x22 0x81 0x42 0x05 0x04 0x6D 0x26 0x16 0x76 0x21 0x32 0x6C 0x00 0x00 0x0C 0x78 0x97 0x68
0x80 0x06 0x06 0xFD 0x0C 0xF2 0x03 0x01 0x00 0xF7 0x01 0x0D 0xFD 0x0B 0x05 0x31 0x32 0x4E 0x46 0x57 0x01 0xFD 0x0E 0x00 0x4C 0x05 0xBB 0xBB 0xBB 0xBB 0x42 0x6C 0x5F 0x2C 0x8C 0x10 0x05 0x14 0x00 0x00 0x00 0xCC 0x10 0x05 0x00
0x00 0x00 0x00 0xC2 0x10 0x6C 0x5F 0x2C 0x0F 0x37 0xFD 0x17 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x02 0x7A 0x25 0x02 0x02 0x78 0x25 0x02 0x3D 0x16