Go Down

Topic: decoded LaCrosse TX2U temperature sensor 433MHz (Read 12226 times) previous topic - next topic

bobal

After reading articles everywhere in the forum(including this older post that I thought was the best of the lot: http://arduino.cc/forum/index.php/topic,22165.0.html) and on the web, I realized I have a slightly different temperature sensor than others are listing; eventually I decoded it and wanted to share what I found for anyone else who needs it.

This sensor only delivers temperature.  You can see a picture of it (and its base unit) at
www.lacrossetechnology.com/7013

I figured out its basic signal by just logging the signal with a cheap FS1000A 433MHz receiver (see followup post for the code and how I spotted the signal and starting thinking about it).  Then I went looking online and the best description I found was through instructables, where a guy has decoded a number of different 433MHz transmissions.  Mine was what he called Type 2 in this paper: http://www.instructables.com/files/orig/FAY/0LCL/H2WERYWD/FAY0LCLH2WERYWD.pdf

So, the signal is 44 bits: (12bit ModelID)(7bit DeviceID)(1bit Checksum)(4bits tens) (4bits ones) (4bits tenths) (4bits tens) (4bits ones) (4bits ???)

Model ID is always 1111 0101 1111
Sensor ID is new each time batteries are put in the sensor
Checksum is 1 if the number of one bits in the following 12 bits is even
"tens" is the decimal tens value of the temperature in centigrade, calculated as (10-tens)
"ones" if the decimal ones value of the temperature in centigrade, calculated as (15-ones)
"tenths" is the decimal tenths-of-a-degree value of the temperature, calculated as (15-tenths)

(for example, if the desired temperature to send is 21.3 degrees C, the twelve bits of temperature would be "1000 1110 1100" (10-2=8, 15-1=14, 15-3=12) and checksum would be 1.

People label the last nibble as the repeat of tenths of degree, but it isn't.  It turns out to be another checksum and the receiver really wants to see the correct value if you want to transmit temperature to the receiver.  (For picking up the signal from the sensor, you can just ignore it, but I want to send a temperature to the base unit). 

This second checksum turns out to be the sum of the four-bit quantities starting with the SensorID (take the eight bits of SensorID and checksum and split them into two 4-bit quantities) and then subtract 4.

So, for a SensorID of 0010000 and a temperature of 24.5 degrees C, the entire string would be:
[1111 0101 1111] [0010 000] 1 [1000 1011 1010] [1000 1011] 1111
(I put brackets around the groupings that I thought were helpful, sorry if that makes it more confusing).

In my observation, ones are encoded with a pulse of about 975 microseconds, zeroes are encoded with a pulse of about 250 microseconds, and in between each one or zero you delay about 1450 microseconds.  The sensor transmits the signal, waits about 20 milliseconds, transmits again, pauses about 30 seconds, and then repeats (quicker repetition for the first couple minutes after you put the battery in the sensor).

I have attached a sketch providing coding demonstrating how to send such an encoded temperature signal.

bobal

This is how I used an XY-MK-5V 433MHz receiver to detect the signal from the LaCrosse temperature sensor.  The XY-MK-5V receiver is nice, because you just attach a 5V supply to the VCC pin, ground to GND, and pin 13 to either of the DATA pins (they are shorted together, so it doesn't matter which one).

No need for an oscilloscope or wiring to a sound card, just use the receiver and look for signal in the noise.

I ran a quick loop (code below) grabbing pulseIn(13, HIGH), watching for the signal and saved the length of the signal and the elapsed time since the last signal to an array.  Then, when the array was full, I dumped it out the Serial port, and went again. 

Array size is limited by available memory, and it didn't have to be an unsigned long, but it turned out to be big enough to catch the signal often enough.  Also, I set the Serial baud rate to 115200 so it didn't spend as much time writing the data out (less downtime between data captures).

Looking at the data, it is mostly random noise and generally very short intervals, sometimes often less than 50usec.  Then you get a pretty consistent series of signals of about 950us and about 250us and elapsed durations that were either about 2450us or about 1750 us.  The durations between signals ended up being a lot more consistent than the signal length.  I deduced that these were the bits being transmitted and the longer signals were ones. 

There are plenty of bits which get garbled in the transmission, there are a lot of ways to correct: you can catch a couple transmissions in a row, or really employ the checksums, or you can actually figure out the data even with a lot of bits missing (for instance, a garbled zero in between solidly readable bits is deducible because the "noise" lasted for about 1750us).

Here's the code:

Code: [Select]

byte pin = 13;
unsigned long ulStartTime;

const int ArraySize=200;
unsigned long ulaDuration[ArraySize];
unsigned long ulaMicros[ArraySize];

long iIdx=0;

void outputArray();

void setup() {
  pinMode(pin, INPUT);
  Serial.begin(115200);  // Set Serial Monitor to match
  Serial.flush();
  Serial.println("Test data");
  ulStartTime = millis();
}

void loop() {

  ulaDuration[iIdx] = pulseIn(pin, HIGH);
  ulaMicros[iIdx] = micros();
  ++iIdx;
 
  if (iIdx == ArraySize-1) outputArray();
}

void outputArray() {
  int i;
 
  Serial.println("Entering OutputArray");
  for (i=0;i<=iIdx; ++i) {
    Serial.print(ulaDuration[i]);
    Serial.print("     ");
    if (i==0) Serial.println(); else Serial.println(ulaMicros[i]-ulaMicros[i-1]);
  }
  iIdx = 0;
}


uhu1

Thank you bobal, your code got me running in no time with another Lacrosse sensor:
LaCrosse TX141TH-B http://forum.arduino.cc/index.php?topic=390843.msg2692215#msg2692215

Go Up