Hallo,
nachdem ich mir bei eB** einige günstige 433MHz Sender und Empfänger beschafft hatte, wollte ich natürlich was sinnvolles damit anfangen.
Zu Tchibo Wetterstationen gab es ja schon einige Beiträge und die Autoren haben ja teilweise graue Haare bekommen, wenn's um die Dekodierung des Datenstroms ging.
Dass es auch anders sein kann, möchte ich mit diesem Beitrag zeigen.
Ich habe bei mir eine Tchibo Wetterstation im Einsatz, die schon einige Jahre auf dem Buckel hat. Die Artikelnummer ist TCM 218943. Der Außensensor sendet seine Daten auf 433 MHz. Beim Test der besagten Receiver hatte ich schon den Datenstrom des Außensensors "gesehen" und wollte mir den dann mal näher ansehen.
Als ersten Schritt habe ich das Signal des Receivers über einen 10k Widerstand und einen 1uF Kondensator auf den Mikrofoneingang der Soundkarte gelegt und mit Audacity aufgezeichnet (s. Screenshot). Da immer 36 Pausen zwischen kurzen HIGH-Pulsen übertragen werden, habe ich angenommen, dass kurze Pause eine "1" sind und lange Pause eine "0". Um das Ergebnis vorwegzunehmen, es war genau umgekehrt.
Nachdem ich dann einige Datenströme mit unterschiedlichen Temperatur und Feuchtewerten aufgezeichnet hatte, fand ich schnell raus, welche Nibbles für Temperatur und welche für Feuchte stehen.
Die letzten 12 Bits des Datenstroms stehen für die Temperatur und die 8 Bit davor für die Feuchte. Bei negativen Temperaturen sind die ersten 4 Bits der Temperatur "1111".
Die ersten 8 Bits stehen vermutlich für die Kennung des Außensensors.
Hier ein Beispiel:
11101011 00000000 00111101 000000010001
Kennung Feuchte Temperatur
Die Werte sind einfach aus dem Byte herzuleiten, also hier
Feuchte 00111101 = 16 (also 16%)
Temperatur 0000 00010001 = 17 (also +1.7°)
Natürlich wär ich hier im falschen Forum, wenn ich das Signal nicht auch per Software verarbeiten wollte, hier der Code.
Der Ausgang des Receivers liegt auf dem Interrupt 0, also Digital 2. Der Interrupt wird durch die fallenden Flanken getriggert und die Zeit zwischen den Flanken wird ausgewertet.
Das Programm ist recht überschaubar und kann auch leicht auf andere Pulslängen adaptiert werden. Für Anregungen, wie man das besser programmieren kann, bin ich natürlich dankbar.
#define PINA 2
#define INTERRUPT 0 // that is, pin 2
volatile unsigned long EdgeTime; // zur Speicherung der Zeit
unsigned long LastEdgeTime=0;
unsigned long DiffEdgeTime=0;
unsigned long LastMillis;
unsigned int Counter;
unsigned long Sequenz, OldSequenz;
unsigned int BitCount, ByteCount, SeqCounter;
volatile boolean BitSet;
// Interrupt Service Routine for a falling edge
void isr ()
{
if (!BitSet) {
EdgeTime=micros();
BitSet=true;
}
} // end of isr
void setup ()
{
attachInterrupt (INTERRUPT, isr, FALLING); // interrupt 0 is pin 2
Serial.begin(115200);
}
void loop ()
{
while(millis()-LastMillis < 5000) { // jede 5 Sekunden Status
if (BitSet) {
DiffEdgeTime = EdgeTime-LastEdgeTime;
if (DiffEdgeTime > 800) { // alles kleiner ist Fehler
if (DiffEdgeTime>8000 && DiffEdgeTime<8500) { // Synchronisationpuls
Counter=0;
Sequenz=0;
}
else if (DiffEdgeTime>1800 && DiffEdgeTime<2300) {
Sequenz <<= 1;
Sequenz |= 1; // eine 1 von rechts rein
Counter++;
}
else if (DiffEdgeTime>900 && DiffEdgeTime<1300) {
Sequenz <<= 1; // eine 0 von rechts rein
Counter++;
}
if (Counter==8 && Sequenz!= B11111011) { // Sensor Kennung
Counter=0;
Sequenz=0;
}
if (Counter==36) {
if (OldSequenz==Sequenz) {
SeqCounter++; // Anzahl gleicher Sequenzen in Folge
}
else {
SeqCounter=1;
}
OldSequenz=Sequenz;
Serial.print("SeqC ");
Serial.print(SeqCounter);
Serial.print(" ");
Serial.print(Sequenz,BIN);
Serial.print(" ");
if (Sequenz& 0x0F00) { // negative Werte
Serial.print("-");
Serial.print(Sequenz & 0xFF);
}
Serial.print(Sequenz & 0xFF); // Temp
Serial.print(" ");
Sequenz >>= 12;
Serial.println(Sequenz & 0xFF); // Feuchte
Counter=0;
Sequenz=0;
}
}
LastEdgeTime=EdgeTime;
BitSet=false;
}
}
LastMillis=millis();
Serial.println("*");
}
Gruß
Reinhard