Thursday, December 6, 2012

Observing the 433MHz band

I recently "stumbled" over a 433 MHz transmitter-receiver set from iteadstudio. Hooking the receiver up to my logic analyzer I could observe three different signals that appeared regularly, 30 - 60 seconds,

Signal 1

Signal 2


Signal 3








Signal 1 were repeated 12 times in a burst and signal 3 were repeated a little bit more than 8 times, leaving the ninth repetition partially complete.

Signal 1 were easy to identify, it disappeared when I stopped my wireless thermometer...

Signal 1, decoding the Denver TRC-1480

The Denver TRC-1480 have the possibility to read from three different temperature sensors.
All pulses are of the same length, 0.55 ms with different delays in between. Each packet starts with a pulse and a 4.4 ms delay. Each "1" is a pulse with a 2.45 ms delay and a "0" is a pulse with a 1.45 ms delay.
By varying different parameters the following information were revealed:

bit 1 - 8   sensor ID
bit 9       0 indicates low battery
bit 10      always 0
bit 11 - 12 channel-1
bit 13 - 24 temperature * 10 as two's complement (invert all bits,
                 add 1 and negate for numbers starting with "11".
bit 25 - 28 always 1
bit 29 - 31 always 0
bit 32 - 36 some sort of checksum?


Some readings from channel 3

In addition channel 1 sends at 57 seconds interval, channel 2 at 67 seconds and channel 3 at 80 seconds.

Signal 2, unknown origin

Transmits every 48 seconds. Consists of 0.5 ms "short" pulses and 1.5 ms "long pulses. A short pulse indicates a "0" and a long pulse a "1". The transmission starts with eight "0". The signal are sometimes very weak.

Bit 17 to 24 may be correlated to the outside temperature by subtracting 234 and dividing by 10. There have to be more to this since the temperature reading with those eight bits are limited to -23.4 to 2.1C. [EDIT:] Or the temperature may be stored as two's complement as well.[]
I do not yet know the brand of this thermometer.

Signal 3, unknown origin

Transmits every 36 seconds. Consists of 0.4 ms pulses with either 4.6 ms ("1") or 2.4 ms ("0") delays. Each signal frame starts with a pulse followed by a 9.6 ms. delay.

Bits 17 to 24 correlates to the temperature by subtracting 238 and dividing by 10.
[EDIT:] Or the temperature may be stored as two's complement as well.[]
As with signal 2, clearly more data are needed to assign the different bits.


Sources used

A description of some Lacrosse sensors,  Jean-Paul ROUBELAT - F6FBB @ http://www.f6fbb.org
A very informative series from spook @ http://lucsmall.com regarding Fine Offset Electronics instruments.
An eye opener from bertrik.

More important things yet to be followed up


3 comments:

  1. For signal 3.
    If it is the same as mine, it is:
    - 4 bits checksum (sum of nibbles minus 1)
    - 8 bits sensor identifier
    - 12 bits 2's complement of temperature
    - 2 bits (channel 1, 2 or 3)
    - 1 bit (Low batt indicator)
    - 1 bit (if low station beeps upon reception of packet, maybe it is related to forcing send of temperature from the button in the sensor, I haven't checked this)

    Using an Arduino and a low cost 433 Mhz transmitter, the (non-optimized) code below transmits toward the station (at least to my model).

    //************************** Example ****************//

    #include "RemoteTransmitter.h"

    #define TXPIN 2

    RemoteTransmitter tx=RemoteTransmitter(TXPIN, 0x6B, 0x1);


    void setup() {

    }


    void loop() {

    delay(1000);
    tx.send(-8.2);
    //tx.send(9.4,true,false);
    }

    //********************* RemoteTransmitter.h **************//

    #ifndef RemoteTransmitter_h
    #define RemoteTransmitter_h

    #include

    #define TXPIN 2
    #define PULSEDURATION 500
    #define ZERO 2000
    #define ONE 4500
    #define PREAMBLE 9500
    #define BITS 28
    #define REPETITIONS 8

    class RemoteTransmitter {
    public:
    // pin is the pin connected to the data of the 433 transmitter
    // id is an 8 bit identifier (you can create your own)
    // The channel which can be (1,2,3)
    RemoteTransmitter(uint8_t pin, uint8_t id, uint8_t channel);

    void send(float temperature,bool battery=false, bool beep=false);

    protected:
    void sendPacket(uint8_t pin, uint32_t packet, uint8_t nbits);
    void sendFrame(uint8_t pin, uint32_t packet, uint8_t nbits, uint8_t repetitions);
    protected:
    uint8_t _pin;
    uint8_t _id;
    uint8_t _chan;
    };

    #endif

    //********************* RemoteTransmitter.cpp *************//

    #include "RemoteTransmitter.h"


    /************
    * RemoteTransmitter
    ************/

    RemoteTransmitter::RemoteTransmitter(uint8_t pin,uint8_t id, uint8_t channel)
    {
    _pin=pin;
    _id=id;
    _chan=(channel & 0x03); // it is just two bits (never trust the user ! ;-P)
    pinMode(_pin, OUTPUT);
    }

    void RemoteTransmitter::send(float temperature,bool battery, bool beep)
    {
    int16_t temp= (int16_t)(temperature * 10);
    uint32_t packet= _id ;
    packet<<= 12;
    packet|= (temp & 0x8000)==0x8000?((temp & 0x07FF) | 0x0800):(temp & 0x07FF);
    packet<<= 2;
    packet|=_chan;
    packet<<=2;
    packet|= (battery==false)?0x2:00;
    packet|= (beep==true)?0x1:00;

    // Checksum (summatory of nibbles +1)
    uint32_t temppacket=packet;
    uint8_t checksum= (uint8_t)temppacket;
    uint8_t i;
    for(i=1;i<7;i++)
    checksum+=(temppacket >>= 4);
    checksum-=1;

    temppacket=checksum; // variable reuse
    temppacket<<= 24;
    packet|=temppacket;

    sendFrame(_pin,packet,BITS,REPETITIONS);
    }

    void RemoteTransmitter::sendPacket(uint8_t pin, uint32_t packet, uint8_t nbits)
    {
    //send preamble
    digitalWrite(pin, HIGH);
    delayMicroseconds(PULSEDURATION);
    digitalWrite(pin, LOW);
    delayMicroseconds(PREAMBLE);

    int8_t i;
    for(i=(nbits-1);i>=0;i--)
    {
    if( (packet >> i) & 0x00000001)
    {// send 1
    digitalWrite(pin, HIGH);
    delayMicroseconds(PULSEDURATION);
    digitalWrite(pin, LOW);
    delayMicroseconds(ONE);
    }
    else
    {// send 0
    digitalWrite(pin, HIGH);
    delayMicroseconds(PULSEDURATION);
    digitalWrite(pin, LOW);
    delayMicroseconds(ZERO);
    }
    }
    }

    void RemoteTransmitter::sendFrame(uint8_t pin, uint32_t packet, uint8_t nbits, uint8_t repetitions)
    {
    uint8_t j=0;
    for(j=0;j<repetitions;j++)
    sendPacket(pin, packet, nbits);
    }

    ReplyDelete
  2. Thanks for the information, most useful.

    ReplyDelete
  3. I second that - most useful information, thank you. The Abdullah's source code indeed works perfectly.

    ReplyDelete