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,

nachdem ich fast erschlagen wurde von Deinem vorletzten Code und ich einmal durchatmen musste, versuche ich nun den Code des letzten Posts auf Arduino zu portieren. Der soll die Berechnung machen. In welcher Sprache ist der Codeschnipsel eigentlich geschrieben? Ich hänge an dem Ausdruck: If crc.7 = 1, dort genau an dem crc.7 . Kannst Du mir da kurz helfen?

Gruß 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,

die Codeschnipsel stammen aus einem PIC-Basic-Dialekt.
Aber dessen Methodik sollte einfach in C umsetzbar sein.
Dient aber eher zum Verständnis wie der Gesamt-CRC gebildet wird.

Für mich war die CRC-Bildung interessant, aber ebenso der außer dem Empfang auch der Sendevorgang bzw. Algorithmus.
Die Links waren natürlich eher (un-)eigennützig ...  ;)
Damit kann ich mich auf die Suche begeben.

Das Thema ist bei mir gerade etwas durch einen 3D-Drucker-Aufbau interrupted worden.
Verfolge das Thema aber nach einer kleinen Pause gerne weiter.

Grüße,
Jürgen






FHEm2005

Hallo Jürgen,
wenn ich mich der Umsetzung fertig bin, bzw. nicht weiterkomme, melde ich mich nochmal. Bei Dir ist es wie bei mir: Tausend Projekte und alle wollen in der ersten Reihe sitzen.  8) 8)
ZitatDie Links waren natürlich eher (un-)eigennützig ...
Ja DARAUF wäre ich ja überhaupt nicht gekommen...  ::) ::)

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

juergs

ZitatBei Dir ist es wie bei mir: Tausend Projekte und alle wollen in der ersten Reihe sitzen.

... das in einem begrenztem Zeitraum, man nennt es auch "Wochenende" ....  ;D

FHEm2005

Hallo Jürgen,

gibt es eigentlich bei dem Thema CRC irgendwelche Neuigkeiten? Ich habe es nach etlichen Versuchen aufgegeben.

Gruß 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,

hatte mich in der Zwischenzeit ein paar anderen Projekten zugewandt.

Sidey und Ralf9 haben im Signalduino-Thread einiges an neuen Sensoren implementiert.
Ich werde es noch mal mit einer neuen Signalduino-Version mit dem CC1101 versuchen.

Aber leider hakt es hier nur noch an dem Thema CRC, schade eigentlich.
Vielleicht versuche ich doch noch einen neuen Anlauf ... 

Grüße,
Jürgen



rmax

Ich habe mich heute auch mal ein bißchen mit der Prüfsumme beschäftigt (ich sage bewußt nicht CRC, weil noch nicht klar ist, ob es sich überhaupt um einen CRC handelt) und bin zu der Erkenntnis gelangt, daß nur die letzten 4 Bit die Prüfsumme darstellen und das vorletzte Nibble noch vollständig Teil der Nutzdaten ist.

Das MSB des vorletzten Nibble ist immer dann 1, wenn der Test-Button gedrückt wurde, das nächste Bit war bei mir bisher immer 0 und die letzten beiden nehmen die Werte 00, 01 und 10 an, ich weiß aber noch nicht, was die bedeuten.

Daß dise beiden Bits nicht zur Prüfsumme gehören schließe ich daraus, daß ich in den Logs der letzten Monate ettliche Fälle gefunden habe, bei denen die ersten 32 Bit identisch waren, die letzten 8 aber nicht. Das läßt sich nach meinem Verständnis nur dadurch erklären, daß die Nutzdaten 36 Bit umfassen und die Prüfsumme 4. Außerdem ändern sich die letzten 4 Bit mehr oder weniger beliebig, während die beiden davor meist über ettliche Messungen hinweg unverändert bleiben.

Basierend auf dieser These habe ich mal verschiedene 4-Bit-CRCs durchprobiert, aber leider hat bisher keiner gepaßt. :(

BTW, der Sensor NC-5849-675  von PEARL hat auch dieses Protokoll.

rmax

Mit Unterstützung von Torsten Duwe (Grüße an Rudi) habe ich den CRC geknackt!

Es handelt sich um ein Schieberegister mit 4 Bit.
Die Datenbits werden in der Reihenfolge der Übertragung von rechts nach links hineingeschoben.
Vor dem ersten und zweiten Bit des Registers sitzt jeweils ein XOR dessen zweiter Eingang mit dem Ausgang des vierten Bits verbunden ist.


+---+      +---+      +---+      +---+
|   |<-----|   |<-----|   |<--X--|   |<--X-- INPUT
+---+      +---+      +---+   ^  +---+   ^
  |                           |          |
  +------------->-------------+----->----+


Als C-Code sieht das dann so aus, wenn man annimmt, daß die Daten nicht länger als 64 Bit sind und rechtsbündig in einem 64-Bit Integer vorliegen:


#include <stdint.h>

uint8_t CRC (uint64_t bits)
{
    uint8_t crc; int i;
    for (i = 0; i < 64; i++) {
        crc <<= 1;
        if (bits & (1UL<<63)) crc |= 1;
        if (crc & 0x10) crc ^= 0x3;
        bits <<= 1;
    }
    return (crc & 0xf);
}


Das kann man sicher noch optimieren, aber so funktioniert es zumindest mal.

Von über 10.000 verschiedenen Datagrammen habe ich damit bei allen außer 4 den CRC korrekt verifizieren könnnen und bei den falschen war ziemlich offensichtlich das letzte Bit von 1 auf 0 gekippt.

Falls Interesse besteht, kann ich bei Gelegenheit nochmal etwas ausführlicher schreiben, wie wir drauf gekommen sind.

juergs

Hallo rmax,

das hört sich ja sehr gut an:

ZitatMit Unterstützung von Torsten Duwe (Grüße an Rudi) habe ich den CRC geknackt!

Es handelt sich um ein Schieberegister mit 4 Bit.
Die Datenbits werden in der Reihenfolge der Übertragung von rechts nach links hineingeschoben.
Vor dem ersten und zweiten Bit des Registers sitzt jeweils ein XOR dessen zweiter Eingang mit dem Ausgang des vierten Bits verbunden ist.

Code: [Auswählen]
+---+      +---+      +---+      +---+
|   |<-----|   |<-----|   |<--X--|   |<--X-- INPUT
+---+      +---+      +---+   ^  +---+   ^
  |                           |          |
  +------------->-------------+----->----+
Als C-Code sieht das dann so aus, wenn man annimmt, daß die Daten nicht länger als 64 Bit sind und rechtsbündig in einem 64-Bit Integer vorliegen:
Code: [Auswählen]
#include <stdint.h>

uint8_t CRC (uint64_t bits)
{
    uint8_t crc; int i;
    for (i = 0; i < 64; i++) {
        crc <<= 1;
        if (bits & (1UL<<63)) crc |= 1;
        if (crc & 0x10) crc ^= 0x3;
        bits <<= 1;
    }
    return (crc & 0xf);
}
Das kann man sicher noch optimieren, aber so funktioniert es zumindest mal.
Von über 10.000 verschiedenen Datagrammen habe ich damit bei allen außer 4 den CRC korrekt verifizieren könnnen und bei den falschen war ziemlich offensichtlich das letzte Bit von 1 auf 0 gekippt.
Falls Interesse besteht, kann ich bei Gelegenheit nochmal etwas ausführlicher schreiben, wie wir drauf gekommen sind.

Chapeau! :D

ZitatFalls Interesse besteht, kann ich bei Gelegenheit nochmal etwas ausführlicher schreiben, wie wir drauf gekommen sind

Na klar doch! Tolle Arbeit!

Ggf. könnte man noch Björn oder Sidey mit informieren, um das mit in die aculfw oder den Signalduino mit einfließen zu lassen. (done: https://github.com/RFD-FHEM/RFFHEM/issues/117)


Grüße,
Jürgen

rmax

Hallo Jürgen,

OK, hier also der "Lösungsweg":

Daß es sich um 36 Nutzdatenbits und 4 Bit Prüfsumme handelt, hatte ich ja in meinem ersten Post schon vermutet.
Auf dieser Annahme, basierten alle weiteren Überlegungen.

Nach ettlichen erfolglosen Versuchen (automatisch und manuell) mit CRC reveng hatte ich schon Zweifel, ob es sich bei den Prüfbits überhaupt um einen CRC handelt. Daß es Prüfbits sein müssen, war ich mir sicher, denn in meinen gesammelten Meßwerten gab es ettliche Doubletten, aber keinen Fall, in dem die ersten 36 Bit identisch und die letzten 4 anders waren.

Torsten brachte mich dann drauf, daß bei einer linearen Prüfsummenfunktion (dazu gehört CRC) ein XOR über zwei Datenfelder samt Prüfbits wieder ein Datenfeld mit der dazu passender Prüfsumme ergibt. Macht man das nun mit Datenfeldern, die sich jeweils nur in einem Bit unterscheiden, sieht man an den Einsen in der resultierenden Prüfsume, welche Prüfbits von diesem Datenbit beeinflußt werden.

Also habe ich meine gut 10.000 unterschiedlichen Datenpakete paarweise miteinander verglichen und das XOR-Ergebnis von solchen ausgegeben, die sich nur in einem Bit unterschieden haben. Heraus kamen gut 8000 Datenfelder mit je einem gesetzten Bit, die erfreulicherweise beim gleichen gesetzten Bit auch immer die gleiche Prüfsumme hatten. Es mußte also etwas CRC-artiges sein. Sortiert und ohne Doubletten ergab sich daraus folgende Tabelle, die angibt, welches Datenbit welche Prüfsummenbits beeinflußt:


000000000000000000000000000000000001 0001
000000000000000000000000000000000010 0010

000000000000000000000000000000001000 1000
000000000000000000000000000000010000 0011
000000000000000000000000000000100000 0110

000000000000000000000000000100000000 0101
000000000000000000000000001000000000 1010
000000000000000000000000010000000000 0111
000000000000000000000000100000000000 1110
000000000000000000000001000000000000 1111

000000000000000000010000000000000000 0010
000000000000000000100000000000000000 0100
000000000000000001000000000000000000 1000
000000000000000010000000000000000000 0011
000000000000000100000000000000000000 0110
000000000000001000000000000000000000 1100
000000000000010000000000000000000000 1011
000000000000100000000000000000000000 0101
000000000001000000000000000000000000 1010
000000000010000000000000000000000000 0111
000000000100000000000000000000000000 1110
000000001000000000000000000000000000 1111


Die Leerzeilen markieren Stellen, an denen die Tabelle unvollständig ist, weil es in meiner Sammlung keine zwei Datensätze gab, die sich nur in diesem einen Bit unterscheiden. Trotz der Lücken kann man erkennen, daß die Abfolge der Prufsummen Regelmäßigkeiten aufweist, z.B. finden sich die Bitmuster aus dem dritten Block am Ende der Tabelle wieder und Teile des ersten und zweiten Blocks kommen am Anfang des vierten wieder vor.

Mit dieser Erkenntnis lassen sich nun einige der Lücken schließen oder zumindest verkleinern.
Der Anfang der Tabelle sieht dann so aus:


000000000000000000000000000000000001 0001
000000000000000000000000000000000010 0010
000000000000000000000000000000000100 0100
000000000000000000000000000000001000 1000
000000000000000000000000000000010000 0011
000000000000000000000000000000100000 0110
000000000000000000000000000001000000 1100
000000000000000000000000000010000000 1011


Nun habe ich mir überlegt, wie ein Schieberegister mit XOR-Rückkopplungen aussehen muß, das ausgehend vom Zustand 0000 nach Einschieben einer Eins gefolgt von der entsprechenden Anzahl Nullen das jeweilige CRC-Muster enthält. Die ersten vier Zeilen sind trivial, da wird ja nur das Eingabemuster durchgeschoben. Weil derweil hinten nur Nullen herausfallen bleiben evtl. vorhandene XOR-Glieder zwischen den FFs wirkungslos. Interessant ist die 5. Zeile, denn hier fällt zum ersten Mal eine 1 links aus dem Register heraus und taucht in den rechten beiden Bits wieder auf. Das läßt sich nur dadurch erklären, daß der Ausgang des MSB per XOR auf die Eingänge der unteren beiden Bits rückwirkt. Weil diese beiden Einsen in den folgenden Zeilen dann auch wieder einfach durch das Register wandern, bevor sich in Zeile 8 dann beim Herausschieben der nächsten Eins wieder die beiden unteren Stellen von 0 auf 1 ändern, war klar, daß es auch keine weiteren Rückkopplungen gibt.

Es folgte eine anschauliche Implementierung in Tcl mit der ich anhand meiner Datensammlung überprüfen konnte, daß ich die richtige Funktion gefunden hatte, und eine effizientere Implementierung in C, die ich dann hier gepostet habe.

juergs

Super, danke für den Lösungsweg!

Dann versuche ich mal das Ganze in den Code einzubauen.

Grüße
Jürgen

FHEm2005

Erst einmal ein großes Lob für rmax. Da muss man ja erstmal drauf kommen! Chapeau!! (standing ovation!  :) :) :) :) )

Ich war jetzt einige Zeit nicht hier und bin mir nicht sicher ob in dem Modul CUL_TCM97001 schon der neune Sensor eingearbeitet ist. Ich fürchte mich nämlich für einem Batteriewechsel und der damit verbundenen neuen ID. Dann muss ich in meine übergangsweise gebastelten Lösung eingreifen.

Also wie sieht es aus?  ;)

Einen schönen Sonntag. Bei mir rollt die Tour de France durchs Dorf. 8)
Gruß 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,

wie der Zufall so will ... ;D :)
Bei so einem miesen Wetter ist das genau das richtige Projekt ...

Grüße,
Jürgen

FHEm2005

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