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

Hall Jürgen,

ich sag' nur eines: nicht besser => fantastisch!!!

Jetzt komme ich weiter. Hab' vielen Dank.

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,
jetzt passt es auch bei meinem Code mit dem passenden Timing.
Ringpuffer ist auf 16 Elemente definiert. Erlaubt also mindestens 3 Sensoren direkt,
quasi gleichzeitig, einzulesen. Sind es mehr als 3 Sensoren werden die älteren Elemente überschrieben.
Die Wartezeit nach dem Empfang des ersten Protokoll bis zur ersten Ausgabe ist auf 5 s eingestellt.
Was dann letztendlich über LaCrosse wieder weiter versendet wird (Repetitions) werde ich noch klären.
Ebenfalls den CRC.  ;)

Zitat
Stored: 0   -> während Erfassung der Repetitions nur 64Bit-"Value" bilden und im Ringpuffer speichern.
Stored: 1
Stored: 2
Stored: 3
Stored: 4
Stored: 5  -> alle 6 Repetitions erfasst!

### Nach der Erfassung (+5s bei 30s Sende-Pause eines Sensors) :

buffer.read: [0 ]    ---> nach den Repetitions  bleibt Zeit auszuwerten 
0001101100100010100101010110000001110011000000000000000000000000
ld:   0
id:   115
id_c:   115
bat:   0
ch:   0
tempF:    0x659
tempC:    22.50
hum:   34
crc:   27
raw:   1955289429710995456
------------------------------------------------------------
buffer.read: [1]    
0001101100100010100101010110000001110011000000000000000000000000
ld:   0
id:   115
id_c:   115
bat:   0
ch:   0
tempF:    0x659
tempC:    22.50
hum:   34
crc:   27
raw:   1955289429710995456
------------------------------------------------------------
buffer.read: [2]    
0001101100100010100101010110000001110011000000000000000000000000
ld:   0
id:   115
id_c:   115
bat:   0
ch:   0
tempF:    0x659
tempC:    22.50
hum:   34
crc:   27
raw:   1955289429710995456
------------------------------------------------------------
buffer.read: [3]    
0001101100100010100101010110000001110011000000000000000000000000
ld:   0
id:   115
id_c:   115
bat:   0
ch:   0
tempF:    0x659
tempC:    22.50
hum:   34
crc:   27
raw:   1955289429710995456
------------------------------------------------------------
buffer.read: [4]    
0001101100100010100101010110000001110011000000000000000000000000
ld:   0
id:   115
id_c:   115       --> LaCrosse kann nur IDs < 127
bat:   0
ch:   0
tempF:    0x659
tempC:    22.50
hum:   34
crc:   27
raw:   1955289429710995456
------------------------------------------------------------
buffer.read: [5]    
0001101100100010100101010110000001110011000000000000000000000000
ld:   0
id:   115
id_c:   115
bat:   0
ch:   0
tempF:    0x659
tempC:    22.50
hum:   34
crc:   27
raw:   1955289429710995456
------------------------------------------------------------

Dann kann ich morgen das LaCrosse-Protokoll einbauen ...  :)

juergs

@Eberhard,
könntest Dir mal dieses Thema anschauen:
https://forum.fhem.de/index.php/topic,17196.msg259697.html#msg259697
https://github.com/mdorenkamp/fhemduino_modules/blob/master/14_FHEMduino_Env.pm
Dort ist die 35-Bit-Variante für Fhemduino behandelt. Vielleicht läßt sich das umbauen?

Jürgen

juergs

Transponder: NCS ==> LaCrosse(433Mhz)

Zitat------------------------------------------------------------
buffer.read: [1]    
0000110100100010101001000110000011110001000000000000000000000000
ld:   0
id:   241
id_c:   113
bat:   0
ch:   0
tempF:    0x64A
tempC:    21.67
hum:   34
crc:   13
raw:   946499607968350208
------------------------------------------------------------
FUNC    ID: 113 [113]   T: 21.67   H: 34.00
TX        ID: 113           T: 21.67   H: 34.00
------------------------------------------------------------

Zitat2017-01-29 10:27:59 CUL_TCM97001 Unknown Code: 01CA91808040
2017-01-29 10:27:59 CUL_TCM97001 Unknown Code: 01CA91808040
2017-01-29 10:27:59 CUL_TCM97001 Unknown Code: 01CA91808040
2017-01-29 10:28:00 CUL_TCM97001 Unknown Code: 01CA91808040
2017-01-29 10:28:00 CUL_TCM97001 Unknown Code: 01CA91808040
2017-01-29 10:28:05 CUL_TX CUL_TX_7 H: 02.0
2017-01-29 10:28:05 CUL_TX CUL_TX_7 humidity: 02.0
2017-01-29 10:28:06 CUL_TX CUL_TX_7 H: 02.0
2017-01-29 10:28:06 CUL_TX CUL_TX_7 humidity: 02.0
2017-01-29 10:28:06 CUL_TX CUL_TX_7 H: 02.0
2017-01-29 10:28:06 CUL_TX CUL_TX_7 humidity: 02.0

Muss noch die Toleranzen im LaCrosseProtocoll abstimmen, dann sollte es passen.  :)

FHEm2005

hallo Jürgen,

das sieht ja gut aus! Das sind Daten aus dem Sensor NC-7427? Hast Du denn eine Übereinstimmung mit dem CRC zwischen Deiner Berechnung und dem mitgelieferten CRC? Wie sieht denn der HEX-Code aus? Ist das 01CA91808040?

Mit den beiden Links bin ich noch nicht fertig. Gerade den 2. muss ich mal ausprobieren.

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,
ZitatDas sind Daten aus dem Sensor NC-7427?
Ja, zurechtgebogen, wenn die ID > 127 ist.
Da bei mir Funk-technisch viel los ist .... muss man eben die Batterie kurz rausnehmen wenn die ID nicht passt. ;)

Zum CRC bin ich noch nicht gekommen..  weil ich  dort auch noch unterwegs war ...
Dennoch scheint es mir doch erforderlich zu sein ...

Aber zwei Projekte gleichzeitig artet etwas in "Streß" aus  ;)
Also "One after the other" ...

Zitat2017-01-29 17:46:40 CUL_TCM97001 Unknown Code: 01C8D18481C0
2017-01-29 17:46:40 CUL_TCM97001 Unknown Code: 01C8D18481C0
2017-01-29 17:46:40 CUL_TCM97001 Unknown Code: 01C8D18481C0
2017-01-29 17:46:40 CUL_TCM97001 Unknown Code: 01C8D18481C0
2017-01-29 17:46:40 CUL_TCM97001 Unknown Code: 01C8D18481C0
2017-01-29 17:46:45 CUL_TX CUL_TX_7 H: 18.0
2017-01-29 17:46:45 CUL_TX CUL_TX_7 humidity: 18.0
2017-01-29 17:46:46 CUL_TX CUL_TX_7 H: 18.0
2017-01-29 17:46:46 CUL_TX CUL_TX_7 humidity: 18.0

Man sieht hier, das 5 Sekunden nach dem Empfang des NCS-Protokolls das LaCrosse feuert ...   :)

ZitatWie sieht denn der HEX-Code aus? Ist das 01CA91808040?
Sorrry, sind etwas zusammengestückelte Infos, da ich 2 Sensoren habe, ID 7 (TEMP = ok, liefert (noch) HUM falsch) und ID 113 (der eigentlich 241 ist, TEMP+HUM = ok)
Die HW-Signale kommen aber in der Tat so rein, und werden halt 1:1 dekodiert + weitergegeben  ...
ZitatStored: 2
buffer.read: [2]    
0001001100100010000101000110000011110001000000000000000000000000
ld:   0
id:   241
id_c:   113
bat:   0
ch:   0
tempF:    0x641
tempC:    21.17
hum:   34
crc:   19
raw:   1378686842521518080
------------------------------------------------------------
FUNC    ID: 113 [113]   T: 21.17   H: 34.00
TX    ID: 113   T: 21.17   H: 34.00
------------------------------------------------------------
Außerdem bekomme ich auch noch einige Nachbarsensoren mit dem NCS-Protokoll und ca. 6 eigene LaCrosse-Sensoren und einmal Bodenfeuchte mit 2 Ids rein.
Da diese weiter entfernt sind, kommen weniger Repetitions durch....

Leider kommt gerade bei LaCrosse die Temperatur noch nicht zu FHEM durch, obwohl die Daten dazu gesendet werden. (Siehe Log unten).
(hatte neulich auf aculw umgestellt und dann nicht mehr ausprobiert).

Das ist also auch noch eine Baustelle, evtl. muss ich die Timings dort noch etwas anpassen, da die Feuchte als zweite
Sende-Impulsreihe ausgesendet wird.  (Vielleicht stimmt das Pausetiming zwischen TEMP+HUM-Output  noch nicht ganz, mal analysieren).
Wenn es zu arg nervt, dann switche ich auf das Hideki-Protokoll um...

Ich hänge mal den aktuellen Stand des Sources (... as is ..) mal hier an.
Werde dann aber auf Github weitermachen.


Hardware:
RX Arduino Pin 2 (INT)
TX Arduino PIN 5 (frei wählbar)

Grüße,
Jürgen

FHEm2005

Hi Jürgen,
ich muss nochmal auf den CRC-Check zurückkommen:
ZitatCode: [Auswählen]

(byte)(value >> (i * 4))

Die "value" kommt ja mit uint32_t-Format rein. Das sind effektiv 4 Bytes à 8 Nibble (4Bit = 1 HalbByte).
Es werden jeweils 4 Bit in eine byte-Variable geschoben ( for i=0; i<8 ...) (also immer ein Halbbyte).
Das AND-en mit 0xf soll sicherstellen, dass die oberen Bits (7..4)  wirklich "0" sind.
Das heißt einfach, dass alle Nibble (Bit 0..3) aus "value" in einer einer Byte-Variablen (uin8_t) aufaddiert werden.
Mehr scheint es nicht zu sein. Aber der Algoritmus muss nicht unbedingt passen (also ohne Gewähr).
Das ließe sich auch auf uint64_t-Format (8 Byte) aufbohren ...
Man müsste also ausprobieren was aufsummiert werden soll, damit es passt ...

Zitat: Die "value" kommt ja mit uint32_t-Format rein. Das sind effektiv 4 Bytes à 8 Nibble. Diese Aussage ist soweit falsch, als dass 4Bytes aus insgesamt 8 Nibbles bestehen.
Zitat: Es werden jeweils 4 Bit in eine byte-Variable geschoben ( for i=0; i<8 ...) (also immer ein Halbbyte).  Das AND-en mit 0xf soll sicherstellen, dass die oberen Bits (7..4)  wirklich "0" sind.   Dann dürften in dem Programmbeispiel die WERte für die einzelnen Nibbles niemals 16 überschreiten. Also gehört dan AND-en mit 0xF in die Schleife hinein.

Die Zeile darf auch nicht:
calculatedChecksum &=0xF ;heißen sondern muß lauten:
nibble&=0xF;
Die Schleife lautet dann:
    {
        uint8_t nibble = (uint8_t)(value >> (i * 4));
        nibble &= 0xF;
        calculatedChecksum += nibble;
        printf("*** zwischen:  val: %u \t- nibble: %d \t- sum: %d \n",value, nibble, calculatedChecksum);
    }


Jetzt bin ich mit Klugscheissen fertig! ;)  Dann lautet das Ergebnis:
ZitatHello, World!                                                                                                                                                                                                   
*** calc: 3205772818                                                                                                                                                                                             
*** zwischen:  val: 3205772818  - nibble: 2     - sum: 2                                                                                                                                                         
*** zwischen:  val: 3205772818  - nibble: 1     - sum: 3                                                                                                                                                         
*** zwischen:  val: 3205772818  - nibble: 6     - sum: 9                                                                                                                                                         
*** zwischen:  val: 3205772818  - nibble: 3     - sum: 12                                                                                                                                                       
*** zwischen:  val: 3205772818  - nibble: 4     - sum: 16                                                                                                                                                       
*** zwischen:  val: 3205772818  - nibble: 1     - sum: 17                                                                                                                                                       
*** zwischen:  val: 3205772818  - nibble: 15    - sum: 32                                                                                                                                                       
*** zwischen:  val: 3205772818  - nibble: 11    - sum: 43                                                                                                                                                       
*** isChecksumOk: 0   

Die mitgelieferte war 28 und nicht 43.

Mach ich da einen Denkfehler, oder ist das richtig? Check das bitte erst dann, wenn das andere Projekt fertig ist. Ich habe Zeit.
Gruß Eberhard




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

juergs

Ok, Du hast mich jetzt verwirrt  ;)

Vielleicht ist auch der Name der Variablen irreführend.
Das AND wird ja benötigt weil beim 4 BIT rechtsschieben ja 8 Bit von "value" in die Byte-Variable "Nibble" gelangen.
Der nicht erwünschte höherwertige Teil wird mit dem AND 0xF verworfen. Das bei jedem 4er Bit schieben.
Soweit, denke ich, war mein Beispiel eigentlich ok.
Vielleicht muss man wie bei den anderen Werten auch LOW- und High-Nibble des CRCs tauschen ?

Bin leider gedanklich gerade noch nicht beim CRC, deshalb noch etwas Geduld ...
Github zickt gerade etwas herum, habe das Projekt aber soweit jetzt dort verankern können,
dass ich damit arbeiten kann.
Zitat! [rejected]        master -> master (non-fast-forward)
error: failed to push some refs

Hier unter NCS-433-Transponder ist der aktuelle Source zu finden.

Grüße,
Jürgen

juergs

 :) :)  Die Pause von 1 Sekunde zwischen TEMP und HUM hat geholfen:

Zitat2017-01-29 19:12:32 CUL_TCM97001 Unknown Code: 01C9D1848300
2017-01-29 19:12:32 CUL_TCM97001 Unknown Code: 01C9D1848300
2017-01-29 19:12:32 CUL_TCM97001 Unknown Code: 01C9D1848300
2017-01-29 19:12:32 CUL_TCM97001 Unknown Code: 01C9D1848300
2017-01-29 19:12:32 CUL_TCM97001 Unknown Code: 01C9D1848300
2017-01-29 19:12:38 CUL_TX CUL_TX_7 T: 21.4 H: 18.0
2017-01-29 19:12:38 CUL_TX CUL_TX_7 temperature: 21.4
2017-01-29 19:12:39 CUL_TX CUL_TX_7 T: 21.4 H: 18.0
2017-01-29 19:12:39 CUL_TX CUL_TX_7 humidity: 18.0
2017-01-29 19:12:42 CUL_TX CUL_TX_7 T: 21.4 H: 18.0

Die Anzahl der LaCrosse-Protokolle entspricht der Anzahl der NCS-Repeats ....   :D

DodiHudori

Hallo juergs,

mal ne ganz doof Frage. Wie bekomm ich denn deinen Github Code als Modul.pm in mein System?  ???

juergs

Hallo DodiHudori,

ZitatWie bekomm ich denn deinen Github Code als Modul.pm in mein System?

Ist leider ein Mißverständnis.
Der Code ist für einen Arduino gedacht, der die Telegramme des NCS7427 aufnimmt und in LaCrosse Telegramme-übersetzt
und wieder versendet. Die erscheinen dann als CUL_TX-Sensortyp, da FHEM diesen Typ kennt.

Das ist eine "Notlösung" um diese Art von Sensoren einzubinden und hat für mich den Charme,
dass dabei gleich eine Reichweitenerhöhung dabei heraus springt.
Ebenso aus einer gewissen "Ratlosigkeit" wie und von wem neue Module in FHEM eingebunden werden.
Der Aufwand dazu ist nicht unerheblich ... und sidey und bjoernh sind ja gut beschäftigt  ;)

Aber Eberhard (FHEm2005) wollte sich dem FHEM-Perl-Code annehmen. Teile hat er dazu ja schon umgesetzt.
Vielleicht kann er Dir mit einer Anleitung weiterhelfen, wie man sein Code in schon existierende Module mit einbindet?

@Eberhard:
Die CRC-Berechnung ist erforderlich, da überlagerte Telegramme zwangsläufig nicht korrekt sind und u. U. Müll fabrizieren.
Also als nächstes die Integration der CRC-Berechnung. (morgen...)

Grüße,
Jürgen




juergs

Durch Zufall habe ich eine fast elegantere und einfache Methode entdeckt, das NCS-Protokoll zu erfassen.
Es wird auf Interruptverarbeitung verzichtet und benutzt den Arduino Befehl "pulseIn"
der die PulseDauer in uS zurückgibt und in dieser Zeit aber die Code-Ausführung blockiert.


/*
  Liest dieses komische Tchibo-Wetterdingens per 433MhZ aus.
*/
#define telegramLength  42
boolean cnt=false;
int     reader=0;
int     cnter=0;
char    reading[telegramLength];

int   decodeTemp(String bitstream);
char    decodeTime(int time);

//-------------------------------------------------
void setup()
{
  Serial.begin(57600);
  Serial.println("*** go! **");
  pinMode(2, INPUT);
  pinMode(13,OUTPUT);
  pinMode(12,OUTPUT);
  digitalWrite(12,LOW);   
}
//-------------------------------------------------
void loop()
{
    //digitalWrite(12,LOW);   
    int LowVal=pulseIn(2,LOW);
    //digitalWrite(12,HIGH);
   
   
    if (LowVal < 11000)
  { 
    // Kuezer als 1100ms Low ? Koennte unserer Sensor sein
      if (decodeTime(LowVal) == 'S')
    { 
      // Startsequenz ?
        cnt=true;                       // Dann go fuer die Sammlung
        cnter=0;                        // BitCounter auf 0
        //Serial.println("S*");
      }
     
      if ( (cnter<=(telegramLength-1)) && cnt && ((decodeTime(LowVal) == '0') || (decodeTime(LowVal)=='1')))
    {
      // Stream noch nicht voll und ein Bit erkannt ?
        //Serial.print(decodeTime(LowVal));
        //Serial.print("LV: ");
        //Serial.println(LowVal);
        reading[cnter] = decodeTime(LowVal);  // Ab ins Array damit
        cnter = cnter+1;                      // Arraycounter fuers naechste Bit inkrementieren
      }
    }
    else
    {
      cnt=false;                           // Zurueck auf Anfang - nix fuer uns.
      //Serial.print("R*");
    }

    if ((cnter == telegramLength))
  {
      // Arrray Voll ?
        Serial.print('/');
        Serial.print(reading);
        Serial.print('/');
        Serial.println(decodeTemp(reading));
        cnter=0;
        cnt=false;
    } 
}
//-------------------------------------------------
//float decodeTemp(String bitstream)
int decodeTemp(String bitstream)
{  // Versucht aus dem Bitstrom die Temp. zu berechnen
  int x=0;
  int chk=0;
  for (int i=15;i<27;i++)
  {
    // Extrahiert das Byte zwischen Bit 16 und 24 und packt es als integer in "x"
    if (bitstream[i] == '1')
  {
      bitSet(x,(26-i));
    }
  }
 
  //for (int i=4;i<15;i++)
  for (int i=2;i<10;i++)
  {     
    // Kenner aus den 3 Nibbles zwischen Bit 4 und 15 holen (koennte auch der Kanal sein ?)
    if (bitstream[i] == '1')
  {
      //bitSet(chk,(14-i));
      bitSet(chk,(9-i));
    }
  }

  Serial.print("ID: "); Serial.print(chk); Serial.print(" / ");
  /*
  if (chk != 136)
  {            // Kenner = 136 ? Dann ist es unserer Sensor !
    return(-999);              // Wenn nicht, dann -999 zurueck
  }
  else
  {
  */
  return x;
    //return ((float)((int)x-900)/10);
  //}
}
//-------------------------------------------------
char decodeTime(int time)
{  // Wandelt die Pulse in Bits um.
   if (time > 700 && time < 11000)
   {     
      // passendes Signal (zwischen 150ms und 11000ms) ?
      if (time < 2200)
      {           
        // kleiner 250ms ? Dann LOW
        return '0';
      }

      if (time < 5000 && time >3900)
 
    // Zwischen 500ms und 1000ms dann HIGH
            return '1';
      }
         
      if (time > 7800)
      {   
        // Groesser 8ms dann Startsequenz !
        return 'S';
      }
  }
  else
  {
    return 'X';
  } 
}






juergs

Zum CRC:



01|2345.6789|01|23|4567.8901.2345|6789.0123|4567.8901              (Bitposition)

00|0100.1110|00|00|0111.0100.0110|0011.0010|0001.1100    ID: 78   (raw)

HEX  4 E                           7    4   6                32           CRC:  1 C                4 + E + 7 + 4 + 6 + 3 + 2  =   0x28

00|1110.0100|00|00|0110.0100.0111|0010.0011|11000001             (gedrehte nibble)

HEX  E4                            6    4   7                23             C 1                   




0x647 = 1607 dez  - 900 dez /10 = 70,7 = 21.5 °C
0x23 = 35 % LF

(4E & 0xF) + (0x746 & 0xF) + (0x32 &x0F)    = E + 6 + 2 = 0xD
(E4 & 0xF) + (0x647 & 0xF) + (0x23 &x0F)    = 4 + 7 + 3 = 0xE

... Ideen?

FHEm2005

Hallo Jürgen,

das Einzige, was mir auffällt ist die Rechnung E + 6 + 2 = 0xD . Das Ergebnis passt nicht, IMHO ist das Ergebnis 16 oder binär 0001 0110 .

Der Datenblock umfasst 8 Nibble, bei Dir sehe ich nur 7. Du hast das Nibble bit 10 bis bit 13 nicht berücksichtigt. Ist zwar 0x0, aber ich weiß nicht, ob es bei der byteweisen Berechnung irgendwie eine Rolle spielt.

Ich komme bei der CRC-Berechnung (ungedreht) auf 48dez bzw. 30HEX. Ich habe Dir mal meine Berechnung angehängt. Darin sind aus der Arduino-Berechnung die Werte der Schleife mal schrittweise aufgedröselt. Die Nibbles werden von hinten gezählt, da ja nach rechts geschoben wird. Ändert aber am Ergebnis nix.

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,
danke, werde morgen damit weitermachen.
Zwischenzeitlicht habe ich noch mal das hier  gesichtet.
Evtl. ist die dortige CRC-Bildung angepasst verwertbar....

Ohne es genau angeschaut zu haben:
vielleicht ist es so "Checksum: (0 + A + E + 0 + F + 5 + 2 + 0 + 5 + 2) and F = 5" gemeint?

Grüße,
Jürgen