Feb 262015
 

This post continues the tear down and reverse engineering of the Acurite 0077XW / 00592TX Wireless Remote Temperature Probe Part 1 & Part 2.

After tearing apart the wireless temperature base station and seeing the straightforward electrical connection between the radio module and the base station logic board, Part 1, and then picking apart the remote probe temperature data protocol, Part 2, I was ready to read the wireless data into a microcontroller.

Given that I want to receive the data from the probes wirelessly then I am going to need a wireless receiver. Also given that I purchased 3 probe plus base station combos just to get the 3 probes I have extra base stations I wont be using. The obvious answer is to pull the wireless module from one of the base stations.

The surgery was pretty straightforward. I desoldered a wireless module from the ribbon cable in the base station, cleaned the solder out of the holes, and soldered in a 4 pin header so I could plug the module into a breadboard.

Acurite00771W_50s

Acurite00771W_51s

I plugged the wireless module into a breadboard with an Arduino Pro Mini 3.3V and an oled display.

For this exercise ignore the oled display and the wiring on the backside of the breadboard. We are only interested in the four wires going from the Arduino to the wireless module. The red wire is 3.3 volts, the black wire is ground, the yellow wire goes from D on the wireless module to digital pin D3 on the Pro Mini, and the green wire goes from SH on the wireless module to digital pin D4 on the Pro Mini.

Acurite00771W_52s

The squelch pin (SH) is an input to the wireless module and so is configured as an output on the Arduino.

The data pin (D) is an output from the wireless module and so is configured as an input on the Arduino.

Arduino pin D3 was specifically chosen as the data input as it is a change triggerable interrupt pin. The bit stream from the probe is captured by the Arduino by taking an interrupt on every level change of the data line from the wireless module and measuring the time from the last change in the data stream to this change. This allows the Pro Mini to measure the width of the high and low parts of each pulse and determine if the pulse is a data sync or data bit.

It is known that interesting pulses are close to 0.2 msec, 0.4 msec, and 0.61 msec long. Pulses that are significantly shorter than 0.2 msec or significantly longer than 0.61 msec are not interesting, are not part of the data stream, and signify the data stream is not yet in sync and Pro Mini should be looking for the data sync pulses.

It is known that the start of the interesting data, the data sync, is eight 0.61 msec pulses in a row. The data sync consists of a 0.61 msec high pulse followed by a 0.61 msec low pulse, with this combination repeated four times.

Since the Pro Mini interrupt pin is configured for change, every time the interrupt is called you can assume there is a change from high to low or low to high on the data line. If the Pro Mini measures the time between every interrupt and every sees eight 0.61 msec times in a row that indicates a data sync has been seen. If a data sync is seen the Pro Mini should immediately start measuring pulse times until 56 data bits, or 112 edges (interrupts) are counted.

Once the 112 high or low pulses are counted the data is filtered two pulses at a time to determine if a 0 or a 1 bit was detected. If the captured pulse stream is a 0.4 msec pulse followed by a 0.2 msec pulse a logic high (1) is recorded. If a 0.2 msec pulse followed by a 0.4 msec pulse is detected then a logic low (0) is recorded. All 112 pulses give the 56 bits or 7 data bytes of the data stream.

Once the data stream is recorded the bytes can be decoded as follows:


The first and second bytes of the data are the unique probe address. The upper two bits of the first byte are the probe channel indicator:

11 = channel A 10 = channel B 00 = channel C

The remaining 6 bits of the first byte and the 8 bits of the second byte are a unique identifier per probe.

[strike]The next two bytes are always 0x44 followed by 0x90, for all of the probes I tested (a sample of 6 probes).[/strike]

[update – see Part 4]
The upper nybble of the third byte carries the remote probe low battery indication.

When the remote probe batteries are fresh, voltage above 2.5V, the third byte is 0x44.
When the remote probe batteries get low, below 2.4V, the third byte changes to 0x84.

The fourth byte continues to stay at 0x90 for all conditions.
[/update]

The next two bytes are the temperature value. The temperature is encoded as the lower 7 bits of both bytes with the most significant bit being an even parity bit. The MSB will be set if required to insure an even number of bits are set to 1 in the byte. If the least significant seven bits have an even number of 1 bits set the MSB will be 0, otherwise the MSB will be set to 1 to insure an even number of bits.

The last byte is a simple running sum, modulo 256, of the previous 6 data bytes.


Code to capture and decode the bit stream can be found at my github repo.

I’ve created a spreadsheet ProbeX6.xls to paste the decoded data into to check the checksum of each transmission and decode the temperature data.

Decoded data from four different probes is shown here. The data is formatted as hex codes decoded and emitted by the Pro Mini followed by the same data in binary format, and then the calculated temperature.

Acurite00771W_SpreadSheet06C

One thing to keep in mind is that each probe requires a “correction factor” to convert from the probe reading to the correct temperature. After having such success with this portion of the project I went out and purchased three more probe / base station modules. I checked all six probes and each had a different offset to convert from sensor reading to actual temperature.

Acurite00771W_02cs

Acurite00771W_02ds

The next step is to pull the data into a RasPi and create a presentation layer to map temperatures around my house. The first part of this project, the reverse engineering and decoding of the 00592TX protocol was a blast. I expect the next phase of the project, the RasPi and data warehousing to be just as much fun.

I hope this series was helpful and if you have any comments, questions, or suggestions please leave a comment below.

  13 Responses to “Hacking the Acurite 0077XW / 00592TX Wireless Remote Temperature Probe – Part 3 – capturing and decoding the data stream”

  1. I think you’ll find the checksum is the simple summation of all of the bytes in the message. (If your raw data were here I’d check it.) The data from another article, and the data off of my own wireless temperature sensors, conforms.

    From another article:

    10010011 00000010 01000100 10010000 00001010 11010111 01001010 (36°C/16%)
    = 0x93 + 0x02 + 0x44 + 0x90 + 0x0a + 0xd7 = 0x24A & 0xFF = 0x4A
    checksum byte is 01001010 == 0x4a

    From my own sensor:

    11000010 01111110 01000100 11111111 00001001 10011010 00100110 (59.72 degrees F)

    = 0xc2 + 0x7e + 0x44 + 0xff + 0x09 + 0x9a = 0x326 & 0xFF = 0x26
    checksum byte 00100110 == 0x26

    Aha, and in your first part, here’s the data off your Saleae Logic graphic:

    11001100 = CC
    00110100 = 34
    01000100 = 44
    10010000 = 90
    00001001 = 09
    10100011 = a3
    10000000 = 80

    0xCC + 0x34 + 0x44 + 0x90 + 0x09 + 0xa3 = 0x280 & 0xFF = 0x80.

  2. My 00592TX talks to an Acurite Model 1097B. It shows the Temp and Humidity (inside and outside) as well as the barometric pressure. What I received is this:

    1c,38,44,59,88,41,ba,11100,111000,1000100,1011001,10001000,1000001,10111010,8,48,15115

    So first and second bytes are probe ID, third byte is the same as yours.

    Byte [3] is the humidity. (59 above). You have to strip bit 7 so the mod to your sketch I put in like this:

    Serial.print("H:");
    Serial.print(dataBytes[3] & 0x7F);
    Serial.print("%,");
    Serial.print("C:");
    Serial.print((int)((temp-1024)/10+2.4+0.5)); // round to the nearest integer
    Serial.print(",F:");
    Serial.print((int)(((temp-1024)/10+2.4+0.5)*9/5+32)); // convert to F
    Serial.println();

    For the barometric pressure, I don’t think the TX unit has that sensor. There’s one inside the receiver that looks like an IC with a hole in it (like a BMP180 but that’s not what it is). And whatever is printed on requires an electron microscope to read.

    • Mel,

      I’m curious about the humidity reading from your sensor. Is 59 hex, 89 decimal, 89% humidity a reasonable value for where you are located?

      Do you ever see large variations in humidity readings during short time span?

      • I’m in the Pacific Northwest (Vancouver BC) and when it’s liquid sunshine, yep. The 89% was just starting to rain when I took it, and later it went to 98% when it was a downpour.

        Right now (10pm), no rain all day, mostly cloudy it’s sitting at 71%. So yep, perfectly normal readings for where I am. I have two other weather stations that I checked it with as well and it’s within 1% of them.

        As for big changes in a short time, depends how you define a short time. A few hours, oh yeah, I can see some large changes. Especially if there’s a storm moving in or out.

  3. Great project. Any thoughts on how to increase the update rate? I’m guessing default is 60 seconds.

    • The update is set by the tx unit, I see no way to adjust that. Probably a battery saving criteria.

    • If you look at the last field in the spreadsheet above it is the time between packets received from the temperature probe. For my probes, a sample of six units, the packet transmit interval is right around 16 seconds (~16000 milli seconds)

  4. I’ve been looking at the “signal strength” indicator on the base unit’s display. After much fiddling around, I find out it’s not signal strength at all. There’s an antenna symbol and 4 bars. The four bars are there because the TX unit sends out four identical packets when it does transmit.

    The base unit shows the number of packets received in “bars”. So four bars means it didn’t miss any and to extrapolate that, they assume full signal strength. Where one or more packets are missed, the bars reflect that.

    The receive code would need some timers worked into it to simulate this.

  5. The 00592TX also transmits its battery status. The Model 1097B Acurite display I have shows a message when the TX battery drops to about 2.3VDC (Change Sensor Batteries Soon).

    Where the temperature data is extracted in the sketch you can get the battery status like this:

    theBattery = dataBytes[2] >> 6;// values 2=GOOD, 1=LOW

    • In my data stream I always get a 0x44 in dataBytes[2].

      0x44 = 0100 0100

      Right shift 6 bits yields 01, or LOW. I did the experiments with all fresh batteries from my stockpile but they could be older and partially discharged. I’ll have to check.

      Do the lower 6 bits contain interesting data?

      How are you figuring out the additional data fields? Is it purely by observation or do you have datasheets for the 00592TX?

      • Sorry about that Brad, trying to read my own coffee stained notes, I managed to get them backwards….sheeesh.

        0x84 - 1000 0100 - LOW BATTERY
        0x44 - 0100 0100 - FULL BATTERY

        Haven’t found anything in the lower bits yet.

        To test that out what I did was place a diode in series with an external battery pack. I used a IN4001 so I managed a .7vdc drop from a fresh set of batteries. I measured it with a DVM and it seemed right at 2.3v it flipped on the “Replace” message on my base display unit.

        At 2.1V the TX pretty much died. I couldn’t detect anything being transmitted from it.

        Oh I did try powering it from a bench supply but I’m thinking there might be a little too much ripple in the DC because I couldn’t get the RX to read anything the TX sent.

        I WISH I had a datasheet for the 00592TX but sadly, no I don’t. Simply observation and see what happens.

        That’s I found out the “signal” strength bars which are really packet counters. The 00592TX sends out four packets. If you move the TX far enough away the RX won’t sync to start with and you’ll lose packets, which is kind of a round about way of indicating signal strength. I guess.

        I wish the 433Mhz receivers I am using weren’t so noisy because it’s trigging the interrupt all the time. Either than or there’s someone close by that’s got his finger jammed on a TX button.

  6. Wow, this is a super interesting article! Do you have some sort of quick tutorial on how to do this for a IOT/engineering newbie? Just looking for a basic list of parts necessary and a simple step by step instructions to pulling in temps into my HA/IOT network.
    Thanks!

  7. TCM radio kontroled clock / temperature station 433mhz 32 bit manshester coded protocol;
    23.1 c = 00000000 10001100 01000001 11001101.
    decode format = U. TEMP. TEMP+SIGN. TRANSMITCJECK
    U = 8x bite unnoun.
    1000 TEMP AFTER DECDOT=0.1
    1100 TEMP = 3
    0100 TEMP = 210 = 20 C
    TEMP= 0.1+3+(2
    10)

    1000 1100 0100 = 1 3 2 is in revers that is 231 and that is temperature 23.1
    next 0001 = 0 -unnoun. 0 is +sign(1 is minus temp).0- unnoun. last 1 sender baterrylov(0 baterry ok).
    last 8 bits is transmition check formul : (temp XOR tempsignl) 10001100 xor 01000001 = 11001101

 Leave a Reply

To create code blocks or other preformatted text, indent by four spaces:

    This will be displayed in a monospaced font. The first four 
    spaces will be stripped off, but all other whitespace
    will be preserved.
    
    Markdown is turned off in code blocks:
     [This is not a link](http://example.com)

To create not a block, but an inline code span, use backticks:

Here is some inline `code`.

For more help see http://daringfireball.net/projects/markdown/syntax

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

(required)

(required)