Decoding outdoor wireless weather station sensor data

Recently acquired USB TV tuner and antennae that I built for it had to be put into use. For some time it is fun just to listen to nearby radio and aircraft communications. In addition, I wanted to do something useful. I thought of an old weather station that is constantly (every 30 seconds) sending data to an indoor unit on a 433MHz frequency.

Indoor and outdoor weather station unit

The 433 – 434MHz ISM band is full of various short messages from different commercial gadgets. To figure out the exact frequency of my wireless sensor I put it close to the receiving 400MHz discone antenna (for ensuring the strongest signal), and observed the spectrum of the band using SDR# software.

Spectrum of the signal observed in SDR#

After obtaining the frequency it was time to record signals at different sensor temperatures and settings (audio sample 1, audio sample 2). The channel switch does not really change the working frequency but only changes a few bits in data stream as will be shown below.

Entire signal sent by outdoor sensor

Recorded audio was imported and processed by Matlab’s function wavread and then plotted using plot function. The received signal consists of wake up pulse followed by a pause and eight or nine data bursts. The last data burst varies in length for a reason that the entire signal is always the same length.

One of the data bursts

The picture above shows one of those data bursts. While watching this picture I started thinking about the way how to decode the signal. The first thought was to read signal peaks as ones and wider gaps between them as zeros. Processing few different temperature readings gave me following bits:

  • 18.7°C 1110101101110101111111011010101101010101011
  • 12.6°C 111011101110101111111101010101010110101011
  • 7.0°C   11010101101110101111111101111010110101011
  • -1.9°C  110101011011101011101010101010101101011010101011

It looks like the message is not decoded as simply as I hoped. Something else must be behind because the messages have different numbers of bits. After some time and mapping options I found the correct one. Bits with value 1 are mapped to 0 and set of bits 10 as 1. This gave me much better results, messages that have the same bit lengths:

  • 18.7°C 00110100110000001011101111100
  • 12.6°C 00100100110000000111111011100
  • 7.0°C   01110100110000000100011011100
  • -1.9°C  01110100110011111110110111100

That way I was able to group bits into meaningful groups. Detailed process of the decryption will be shown for the temperature values 18.7°C and -1.9°C. For better visibility message must be first broken into seven groups.

Graphical representation of the protocol with digits representing a number of the bits.

0011 01001100 000010111011 11 1 0 0 equals to 18.7°C

  • 0011 this part changes for every different temperature reading, probably some kind of CRC/checksum code, have not yet manage to decipher it
  • 01001100 random sensor serial number, it changes every time your restart the sensor
  • 000010111011 converted from binary to decimal gives us 187, divided by 10 returns the correct value of 18.7
  • 11 channel number, possible variants are 01 for CH1, 10 for CH2 and 11 for CH3
  • 1 battery indicator, 1 battery OK, 0 low battery
  • 0 indicates the sensor normal working mode. You can force it to send data by pressing TX button on it. At that time this bit will change to 1, telling the indoor unit that you forced the sensor to send data and maybe changed the channel setting.
  • 0 tail constant every time

0111 01001100 111111101101 11 1 0 0 equals to -1.9°C

  • 111111101101 is the two’s complement of the sensor reading, first -1 must be subtracted returning 111111101100, this is then inverted to 000000010011 and converted to decimal values giving 19. Taking into account the sign and the division factor 10, the result is -1.9

All the calculations were done by hand. Next possible step is to write a Matlab program that would automatically convert recorded audio to sensor readings. Few more images can be found in gallery.

Circuit board inside outdoor sensor unit

8 thoughts on “Decoding outdoor wireless weather station sensor data”

  1. Have you figured out that CRC/Checksum calculation yet? I have same kind of transmitter, and i have been able to sniff the packets and send them with arduino. But i cant make my own packets becouse i cant calculate the checksum for the packet. Btw, i dont have that trailing zero with my packets.

      1. I am now at the point, where i can send packets to the station, by brute forcing the checksum. Its only 4-bits, so you have only 16 possibilities, and that goes fast with 200 ms pauses between different packets. So i could gather some data with only 1 bit changes in the packet, and record the checksum. That way it would be possible to find out the calculation needed for the checksum by comparing those packets,

    1. Hi

      I may have the calculation

      split your reading into 7 blocs of four bits dropping the last 0 i.e.
      0010 0100 1100 0000 0111 1110 1110
      sum the 6 last blocks
      0x4+0xC+0x0+0x7+0xE+0xE=0x33
      remove 1 and take the last digit
      0x33-1=0x32 – > 2=0010
      You’ve got your checksum !
      It has always given the right answer until now.
      I let you try

      Aristide

      1. Hi Aristide,

        thank you so much! I suffered a lot of time trying different CRC polynomials and other checksum algorithms. Your solution works just perfectly!

        Petr

  2. I have to confirm your analysis.

    I already implemented this weather station protocol on 8-bit AVR microcontroller (as sender – temperature sonde). I was not satisfied with NTC inaccurate sensor.

    The protocol uses time differences between TX toggles as data bits.
    TX duration = 470 us
    Pivot = (1st bit) = approx. 9500 us
    High = (binary 1) = 4500 us
    Low (binary 0) = 1900 us

    The checksum is calculated based on sum of all nibbles (4-bit parity) minus one – four least significant bits are used.
    1st nibble = checksum
    2nd, 3rd nibble = device id (randomly generated)
    4th, 5th, 6th nibble = temperature stored in “signed int”
    7th nibble = flags as Klemen described

    The sequence is repetitively transmitted (approx. 8 times) – transmission nearly 1 second! My original device sends temperature every 45 sec.

Leave a Reply

Your email address will not be published. Required fields are marked *

Type the result of the equation to post the comment. * Time limit is exhausted. Please reload the CAPTCHA.