LÖSUNG:Dekodieren Temperatur Feuchte T/H sensor von PEARL NC7427(NC7415) 433MHz

Begonnen von maxtox, 25 September 2016, 19:37:33

Vorheriges Thema - Nächstes Thema

FHEm2005

Hallo Jürgen,

ich weiß, dass ich nerve, aber es bleibt mir (und den anderen, die auch ein Pearl NC7427 haben) nicht anderes übrig als auf das Update zu warten. Darf ich fragen, wann es voraussichtlich fertig sein wird?

Viele Grüße
Eberhard
Raspi3: FHEM, CULV3 (V1.61), EnOcean Pi 868, nanoCUL433, HUE-Bridge; Raspi4: Node-red, MQTT, Gaszähler auslesen mit ESP32-CAM

juergs

Hallo Eberhard,
Bin "leider" auf der grüner Insel bei 17Grad ...
Deshalb musste das Thema etwas warten....

Ich bin aber noch dabei... melde mich wieder ...  8)

Juergen

FHEm2005

@Jürgen
ZitatBin "leider" auf der grüner Insel bei 17Grad ...
Unter Sommer stelle ich mir aber etwas anderes vor. Trotzdem gute Erholung.

@rmax
ZitatDaß es sich um 36 Nutzdatenbits und 4 Bit Prüfsumme handelt, hatte ich ja in meinem ersten Post schon vermutet.
Fakt ist, dass das gesamte Datentelegramm aus 48 Bits besteht. Das sind 12 Bytes oder 24 Nibbles. Wir sind bisher immer davon ausgegangen, dass bis zum 34. Bit die Nutzdaten reichen. Die Bits von Nr. 35 bis 46 gehörten unserer bisherigen Lesart nach zur Prüfsumme. Darauf folgen zwei Bits Nr. 47 und 48 die das Ende des Datentelegramms markieren.

Ich habe deshalb zwei Fragen:
1. Wo liegen die 4 Bits zur Prüfsummenberechnung. Sie müssen ja irgendwo zwischen Bit 37 und 46 liegen, da Bit 35, 36 und bit 47,48 bei meinen Messungen immer "00" waren. Das sind aber immer noch 10 Bits, von denen nur 4 benutzt werden.
2. Was könnten Deiner Meinung nach die Bits zwischen Nutz- und Prüfdaten enthalten?

Viele Grüße
Eberhard

EDIT: Die Frage 1 hat sich inzwischen geklärt: Nach der Feuchtigkeitsangabe folgen 4 Bits mit "0" und dann die 4 Bits mit der Prüfziffer. Den Abschluiss bilden noch einmal sechs Nullen. Man möge mich korrigieren wenn ich falsch liege.
Frage 2 ist offen.
Raspi3: FHEM, CULV3 (V1.61), EnOcean Pi 868, nanoCUL433, HUE-Bridge; Raspi4: Node-red, MQTT, Gaszähler auslesen mit ESP32-CAM

FHEm2005

Ich versuche gerade die beiden Zeilen
Zitatif (bits & (1UL<<63)) crc |= 1;
        if (crc & 0x10) crc ^= 0x3;
zu verstehen und stolpere über die beiden obigen Anweisungen. Warum folgt kein "?" bzw. ein geschweifter Klammerausdruck? Das ist doch C - oder?

Gruß Eberhard
Raspi3: FHEM, CULV3 (V1.61), EnOcean Pi 868, nanoCUL433, HUE-Bridge; Raspi4: Node-red, MQTT, Gaszähler auslesen mit ESP32-CAM

JoWiemann

Ja, aber geht beides:

if (bits & (1UL<<63)) crc |= 1;

oder

if (bits & (1UL<<63)) {crc |= 1;}

Grüße Jörg
Jörg Wiemann

Slave: RPi B+ mit 512 MB, COC (868 MHz), CUL V3 (433.92MHz SlowRF); FHEMduino, Aktuelles FHEM

Master: CubieTruck; Debian; Aktuelles FHEM

FHEm2005

Hallo Jörg,
vielen Dank für Deine Hilfe - den if Bereich habe ich hoffentlich kapiert. Obwohl es im eigentlichen Sinne nicht hierhin gehört. Ist es richtig wenn ich formuliere:
Wenn die bitweise UND-Verknüpfung von 'bits' maskiert mit '1 gefolgt von 63 Nullen' = wahr (also "1") ergibt, dann bitweises ODER von crc (4bits) mit "1" .

Das würde bedeuten, dass das rechte Bit von crc auf "1" gesetzt wird, wenn der erste (linke Wert) von bits ebenfalls 1 ist. Wie falsch liege ich?

Meine Güte ist das kompliziert.  :-[

@rmax
Ich habe die Telegramme meines Sensor mal gelogged:

Hier ein Muster: 2017-07-17_11:36:17 Pearl_1 CRCBIN: 00|10111001|00|00|001001010110|00000100|00|001011|000000[/size

Die wesentlichen Inhalte sind durch ein "|" getrennt.
LD|ID|Bat|Ch|Temp|Hum|00|CRC|unbekannt. Bei meinen Ergebnissen sind die Prüfbits nicht 4 sondern 6 bit  breit. Ich bekomme ab und zu Ergebnisse wie dieses:
2017-07-14_23:06:55 Pearl_1 CRCBIN: 00|01100111|00|01|010001010110|00110011|00|101001|000000
2017-07-14_23:07:00 Pearl_1 CRCBIN: 00|10111001|00|00|101101000110|01100011|00|001110|000000
2017-07-14_23:07:49 Pearl_1 CRCBIN: 00|01100111|00|01|010001010110|00110011|00|101001|000000
2017-07-14_23:08:40 Pearl_1 CRCBIN: 00|10111001|00|00|101101000110|01100011|00|001110|000000
2017-07-14_23:09:30 Pearl_1 CRCBIN: 00|10111001|00|00|101101000110|01100011|00|001110|000000
2017-07-14_23:10:20 Pearl_1 CRCBIN: 00|10111001|00|00|101101000110|01100011|00|001110|000000
2017-07-14_23:10:28 Pearl_1 CRCBIN: 00|01100111|00|01|010001010110|00110011|00|101001|000000
2017-07-14_23:11:10 Pearl_1 CRCBIN: 00|10111001|00|00|101101000110|01100011|00|001110|000000
2017-07-14_23:11:20 Pearl_1 CRCBIN: 00|01100111|00|01|010001010110|00110011|00|001011|000000
2017-07-14_23:12:00 Pearl_1 CRCBIN: 00|10111001|00|00|101101000110|01100011|00|001110|000000
2017-07-14_23:12:13 Pearl_1 CRCBIN: 00|01100111|00|01|010001010110|00110011|00|001011|000000
2017-07-14_23:12:50 Pearl_1 CRCBIN: 00|10111001|00|00|101101000110|01100011|00|001110|000000
2017-07-14_23:13:06 Pearl_1 CRCBIN: 00|01100111|00|01|010001010110|00110011|00|001011|000000
2017-07-14_23:13:40 Pearl_1 CRCBIN: 00|10111001|00|00|101101000110|01100011|00|001110|000000
2017-07-14_23:14:00 Pearl_1 CRCBIN: 00|01100111|00|01|010001010110|00110011|00|001011|000000
2017-07-14_23:14:30 Pearl_1 CRCBIN: 00|10111001|00|00|101101000110|01100011|00|001110|000000
2017-07-14_23:15:20 Pearl_1 CRCBIN: 00|10111001|00|00|101101000110|01100011|00|001110|000000
2017-07-14_23:16:10 Pearl_1 CRCBIN: 00|10111001|00|00|101101000110|01100011|00|001110|000000
2017-07-14_23:17:00 Pearl_1 CRCBIN: 00|10111001|00|00|101101000110|01100011|00|001110|000000
2017-07-14_23:17:32 Pearl_1 CRCBIN: 00|01100111|00|01|010001010110|00110011|00|001011|000000
2017-07-14_23:17:50 Pearl_1 CRCBIN: 00|10111001|00|00|101101000110|01100011|00|001110|000000
2017-07-14_23:18:24 Pearl_1 CRCBIN: 00|01100111|00|01|010001010110|00110011|00|001011|000000
2017-07-14_23:18:40 Pearl_1 CRCBIN: 00|10111001|00|00|101101000110|01100011|00|001110|000000
2017-07-14_23:19:30 Pearl_1 CRCBIN: 00|10111001|00|00|101101000110|01100011|00|001110|000000
2017-07-14_23:20:20 Pearl_1 CRCBIN: 00|10111001|00|00|101101000110|01100011|00|001110|000000
2017-07-14_23:21:10 Pearl_1 CRCBIN: 00|10111001|00|00|101101000110|01100011|00|001110|000000
2017-07-14_23:21:57 Pearl_1 CRCBIN: 00|01100111|00|01|001101010110|00110011|00|001010|000000
2017-07-14_23:22:50 Pearl_1 CRCBIN: 00|10111001|00|00|101001000110|01100011|00|001000|000000
2017-07-14_23:23:40 Pearl_1 CRCBIN: 00|10111001|00|00|101001000110|01100011|00|001000|000000
2017-07-14_23:24:30 Pearl_1 CRCBIN: 00|10111001|00|00|101001000110|01100011|00|001000|000000
2017-07-14_23:25:20 Pearl_1 CRCBIN: 00|10111001|00|00|101001000110|01100011|00|001000|000000
2017-07-14_23:25:28 Pearl_1 CRCBIN: 00|01100111|00|01|001101010110|00110011|00|001010|000000
2017-07-14_23:26:10 Pearl_1 CRCBIN: 00|10111001|00|00|101001000110|01100011|00|001000|000000
2017-07-14_23:27:00 Pearl_1 CRCBIN: 00|10111001|00|00|101001000110|01100011|00|001000|000000
2017-07-14_23:27:14 Pearl_1 CRCBIN: 00|01100111|00|01|001101010110|00110011|00|001010|000000
2017-07-14_23:27:50 Pearl_1 CRCBIN: 00|10111001|00|00|101001000110|01100011|00|001000|000000
2017-07-14_23:28:08 Pearl_1 CRCBIN: 00|01100111|00|01|001101010110|00110011|00|001010|000000
2017-07-14_23:28:40 Pearl_1 CRCBIN: 00|10111001|00|00|101001000110|01100011|00|001000|000000


Nicht irritieren lassen: Ich habe zwei Sensoren mit unterschiedlichen ID's im Einsatz. ID 185 und 103
Kannst Du mal überprüfen, ob Dein Algorithmus hier auch passt? Wie sieht an einem Bsp der Inhalt von bits aus?

Gruß Eberhard

Raspi3: FHEM, CULV3 (V1.61), EnOcean Pi 868, nanoCUL433, HUE-Bridge; Raspi4: Node-red, MQTT, Gaszähler auslesen mit ESP32-CAM

rmax

Bei C müssen Anweisungsblöcke nur dann in geschwefte Klammern, wenn sie mehr als eine Anweisung enthalten.
Bei Kontrollstrukturen (if, for, while), die nur eine Anweisung enthalten, können die Klammern entfallen.

Die Datenblöcke bestehen aus 42 Bits, die ersten zwei und die letzten sechs Nullen gehören nicht dazu. Mein Empfänger mit eigener Firmware auf einem ATmega32U4 liefert die letzten sechs Nullen gleich gar nicht. Er intepretiert Pausen ab 7ms als End of Frame. Ich nehme an, daß Dein Empfänger die Pause am Ende jedes Frames fälschlich als mehrere Nullen interpretiert.

Die 42 Bits teilen sich nun in 38 Daten- und 4 CRC-Bits. Die beiden Bits vor dem CRC, die Du als Teil des CRC annimmst, gehören definitiv nicht dazu, sondern sind noch Datenbits. Sie verhalten sich bei mir ähnlich wie die beiden, die Du als "Bat" bezeichnet hast. Sie nehmen nur die Werte 00, 01 und 10 an, aber niemals 11. Es wurde ja schon gemutmaßt, es könnte sich bei der ersten Gruppe um die Tendenz der Temperatur handeln, also steigend, fallend oder gleichbleibend. Überprüft habe ich das allerdings noch nicht. Entsprechend könnte die hintere Gruppe die Tendenz der Luftfeuchtigkeit sein. Ich bin mir jedenfalls ziemlich sicher, daß der Batteriestand in keiner der beiden Gruppen enthalten ist, denn dafür zappeln sie zu viel, selbst mit neuen Batterien.

Von den beiden linken Nullen im vorletzten Nibble geht eine auf 1, wenn man die Übertragung mit der Taste (soweit vorhanden) erzwingt. Die andere könnte Low-Bat signalisieren, ein entsprechender Test steht aber noch aus.

Was den Algorithmus angeht, habe ich ihn mit einer 64Bit-Variablen implementiert, weil das als Schnellschuß am einfachsten war, denn da passen die 38 Datenbits auf einen Rutsch rein und dem Algorithmus sind führende Nullen egal. Man könnte stattdessen natürlich auch nacheinander die einzelnen Bytes oder Nibbles hineinschieben, wenn das Ganze auf einem 8-Bitter laufen soll, oder sogar die einzelnen Bits, wenn der CRC bereits während des Empfangs berechnet werden soll.

In jeder Runde werden zuerst im Schieberegister die Bits um eine Position nach links bewegt. Dann wird das nächste Bit der Eingangsdaten als neues unterstes Bit ins Schieberegister kopiert. Jetzt wird noch das gerade aus dem Schieberegister "herausgefallene" Bit mit den unteren beiden XOR-Verknüpft, d.H. wenn es 1 war werden die beiden unteren invertiert, wenn es 0 war bleiben sie wie sie sind. Zuletzt schiebe ich die Eingangsdaten um eine Position nach links, so daß sich in der nächsten Runde das zu verarbeitende Eingangsbit wieder auf Position 63 befindet.

Wenn man das für die 38 Datenbits durchspielt, sollten die 4 Bit im Register mit den letzten 4 Bit der Übertragung übereinstimmen.

FHEm2005

Hallo rmax,
danke für die ausführliche Darstellung und Korrektur meiner Sichtweise. Jetzt sind m.E. alle Voraussetzungen vorhanden, um zu dem gleichen Ergebnis zu kommen wie Du. Ich werde berichten, wenn ich es geschafft habe.

Gruß Eberhard
Raspi3: FHEM, CULV3 (V1.61), EnOcean Pi 868, nanoCUL433, HUE-Bridge; Raspi4: Node-red, MQTT, Gaszähler auslesen mit ESP32-CAM

FHEm2005

Hallo rmax,
ZitatDie Datenblöcke bestehen aus 42 Bits, die ersten zwei und die letzten sechs Nullen gehören nicht dazu.

Mein Datentelegramm besteht aus 48 bits (12 x 4bits). Wenn ich jetzt rechne: Deine 42 bits und meine 8 Nullen, dann bin ich bei 50 bits. Da beißt sich etwas.

Kann es sein, das die Daten nur 36 bit lang sind?

Meine 2 Nullen + 36 Datenbits + 4 Prüfsequenzbits + Meine 6 Nullen= 48 bits  =>  Passt.

Gruß Eberhard

Raspi3: FHEM, CULV3 (V1.61), EnOcean Pi 868, nanoCUL433, HUE-Bridge; Raspi4: Node-red, MQTT, Gaszähler auslesen mit ESP32-CAM

rmax

Ja, stimmt, die beiden "Startbits" gehören doch dazu, um auf meine 42 Bits zu kommen (oder halt weg, dann sind es nur 40, also glatte 10 Nibbles).
Das hatte ich gestern nicht mehr richtig in Erinnerung, war mir dessen aber so sicher, daß ich es auch nicht nochmal nachgeschaut habe.
Sorry.

Solange die Startbits aber immer als 0 empfangen werden, ist es für den hier verwendeten CRC aber egal, ob man sie hinzunimmt oder nicht, denn führende Nullen ignoriert er in beliebiger Anzahl. Die Startbits mit hinzuzunehmen bringt halt zusätzliche Sicherheit, falls mal eines davon fälschlicherweise als 1 ankommt, das kann man andererseits aber auch vorneweg prüfen.

Um herauszufinden, ob die Original-Wetterstation die Startbits beim CRC berücksichtigt oder nicht oder gar Telegramme, die nicht mit 00 anfangen schon vor der CRC-Berechnung verwirft, müßte man mal ein paar entsprechend konstruierte Telegramme an die Wetterstation senden und dabei den Stromverlauf beobachten. Ich habe aber keine solche Station und will mir auch keine kaufen.

FHEm2005

Ich habe mal mit meinen rudimentären Kenntnissen versucht den C-Code von rmax in Perl umzusetzen. Vielleicht hilft das bei der Implementierung in das Modul. Ich habe ein UserReading mit dem Namen crc kreiert und kann es dann mit der mitgelieferten Prüfziffer, die in CRC gespeichert wird vergleichen. Das reading state ist der Ausgangspunkt.

Aus dem Reading state wird das Datentelegramm als BIN-String in stateBIN gespeichert:

stateBIN {my $s = (ReadingsVal($name,'state',''));
my @a = split(/\s+/,$s);
$s = $a[1];
my $u=sprintf( "%.48b", hex( $s ) );
return($u);},

Die eigentlichen Nutzdaten werden in dem Reading bits gespeichert

bits {my $s = (ReadingsVal($name,'stateBIN',''));
my @a = split("",$s);
my $u = $a[2].$a[3].$a[4].$a[5].$a[6].$a[7].$a[8].$a[9].$a[10].$a[11].$a[12].$a[13].$a[14].$a[15].$a[16].$a[17].$a[18].$a[19].$a[20].$a[21].$a[22].$a[23].$a[24].$a[25].$a[26].$a[27].$a[28].$a[29].$a[30].$a[31].$a[32].$a[33].$a[34].$a[35].$a[36].$a[37];
return($u);},

Die mitgelieferte Prüfziffer wird in CRC gepeichert:

CRC {my $s = (ReadingsVal($name,'stateHEX',''));
my @a = split("",$s);
my $CRC = (hex($a[9].$a[10]) & 0x3F) >> 2;
return($CRC);},

Und letztendlich wird die berechnete Prüfziffer in crc gespeichert:

crc {my $bits = (ReadingsVal($name,'bits',''));
$bits = oct("0b".$bits);
my $crc = (ReadingsVal($name,'CRCBIN',''));
$crc = 0b00000000;
my $i=0;
for ($i = 0; $i < 64; $i++) {
$crc <<= 1;
my $UL1 = 0b000000000000000000000000000000000000000000000000000000000001;
if ($bits & ($UL1<<63)) {$crc |= 1};
if ($crc & 0x10) {$crc ^= 0x3};
$bits <<= 1;
}
$crc &=0xf;
return ($crc & 0xf);},


Jetzt können CRC und crc miteinander verglichen werden. Bis jetzt stimmen crc und CRC noch überein.
Da ist jede Menge Optimierungspotential enthalten, aber ich kann's nicht besser.

Gruß Eberhard

PS: Ein LogFile zeigt die Schwächen der Programmierung: Während CRC bereits einen neuen Wert besitzt wird der crc noch mit dem bisherigen Wert geloggt. Grundsätzlich scheint es zu funktionieren.
Raspi3: FHEM, CULV3 (V1.61), EnOcean Pi 868, nanoCUL433, HUE-Bridge; Raspi4: Node-red, MQTT, Gaszähler auslesen mit ESP32-CAM

rmax

Ich kann auch kein Perl, aber zwei Optimierungsmöglichkeiten sind mir trotzdem spontan ins Auge gesprungen:
1. Du kannst die Zuweisung von UL1 vor die for-Schleife ziehen, dann muß sie nur einmal passieren und nicht bei jedem Durchlauf von neuem.
2. Du kanst UL1 gleich mit dem Wert 1<<63 initialisieren, dann fällt der Teil der Bitschieberei auch noch aus der Schleife raus.

FHEm2005

Funktioniert. Zwei Einäugige sehen nun mal besser als einer. Danke.
Schönen Tag
Eberhard
Raspi3: FHEM, CULV3 (V1.61), EnOcean Pi 868, nanoCUL433, HUE-Bridge; Raspi4: Node-red, MQTT, Gaszähler auslesen mit ESP32-CAM

rmax

Jetzt ist mir noch was aufgefallen:

Wenn ich das richtig sehe, setzt Du die 64-Bit-Variable zuerst aus den einzelnen Bits zusammen, die in einem Array von Bitwerten vorliegen. Dann nimmst Du den Wert durch Shifting und Maskierung wieder Bit für Bit auseinander. Stattdessen könntest Du in der CRC-Schleife über den Array-Index iterieren und die Bits direkt aus dem Array ins CRC-Register schieben.

Alternativ liegt das Telegramm vielleicht in Deinen Eingabedaten eh schon in einer Form vor, die Du direkt in einen langen Integer wandeln und an die CRC-Schleife übergeben kannst. Die müßte statt über alle 64 bits zu laufen stattdessen nur die Bits herauspicken, über die der CRC berechnet werden soll, was auch wieder einige Schleifendurchläufe einsparen würde.

FHEm2005

Hallo rmax,
ZitatWenn ich das richtig sehe, setzt Du die 64-Bit-Variable zuerst aus den einzelnen Bits zusammen, die in einem Array von Bitwerten vorliegen.
Siehst Du - ich verstehe Dich nicht, weil meine Kenntnisse absolut nicht ausreichen. Welche 64-Bit-Variable? Ich habe nur die $UL1 mit 64 bits definiert. $bits ist nur so breit, wie die binären Nutzdaten breit sind, nämlich nur 36 bit.

ZitatAlternativ liegt das Telegramm vielleicht in Deinen Eingabedaten eh schon in einer Form vor, die Du direkt in einen langen Integer wandeln und an die CRC-Schleife übergeben kannst.
Ich habe mal irgendwo gelesen, dass Perl die Variablendeklarierung wie integer, long integer, unsigned integer usw. automatisch machen soll. Ich weiß z.B. nicht wie ich ein 64bit lange binäre Zahl definieren soll/kann. Deshalb habe ich auch zu dem Konstrukt mit $UL1 =0b.... gegriffen.

Am momentanen Punkt bin ich mit meinem Latein am Ende. Du scheinst für mich in C tiefer drin zu stecken als ich.

Gruß Eberhard
Raspi3: FHEM, CULV3 (V1.61), EnOcean Pi 868, nanoCUL433, HUE-Bridge; Raspi4: Node-red, MQTT, Gaszähler auslesen mit ESP32-CAM