The RF transmissions use on-off-keying (OOK) with Manchester coding on a
carrier frequency of 433.92MHz. See the Wikipedia entry on Manchester coding
for more information or consult a basic text on digital RF communications.
All OS protocol versions use the “normal” polarity definition of Manchester
coding. This convention requires that a zero bit be represented by an off-to-on
transition of the RF signal at the middle of a clock period. Another way to
describe this is that the bit value is equal to the RF signal state before the
By definition, RF transitions must occur in the middle of each clock period. In
this document, that point will be designated by an integer number. The
boundary between two clock periods will therefore be equal to an integer plus
OS version 1.0 sensors transmit bits with a clock rate of approximately 342Hz,
while version 2.1 and 3.0 sensors use a bit rate of 1024Hz. In all version 2.1 and
3.0 sensors measured to date, this rate does not vary by more than a few
tenths of a Hertz.
Version 2.1 Message Formatting
For version 2.1 sensors only, each data bit is actually sent four times. This is accomplished by first sending each data bit twice (inverted the first time), doubling the size of the original message. A one bit is sent as a “01” sequence and a zero bit is sent as “10”. Secondly, the entire message is repeated once.
Some sensors will insert a gap (about 10.9 msec for the THGR122NX) between the two repetitions, while others (e.g. UVR128) have no gap at all.
For an example of this, consider the message “111101010111” as it would be sent by a version 2.1 sensor. First an inverted copy of the message is created, and then interleaved with the original message, taking the inverted bit first.
Original Message: 1 1 1 1 0 1 0 1 0 1 1 1
Inverted Message: 0 0 0 0 1 0 1 0 1 0 0 0
Transmitted Bits: 01 01 01 01 10 01 10 01 10 01 01 01
When decoding a version 2.1 message, only every other bit need be used (and possibly inverted, depending on whether the first or second bit is kept). If the second bit in each bit pair is kept, no inversion is required.
It should be apparent for version 2.1 messages now, that one can assume the opposite polarity for Manchester coding (e.g. a zero bit is represented by an on-to-off transition in the RF signal) – this only changes which of the two interleaved bit streams is considered to be inverted.
RF Pulse Widths
The duration of Manchester-coded RF pulses is exactly either ½ or 1 data clock period. OS version 2.1 and 3.0 protocols shorten the RF pulse width by truncating the end of the pulse (not the start of the pulse). As a result, RF transitions do not occur on exactly regular time boundaries and may be displaced in time from data clock edges. Pulses are shortened by about 138us for v3.0 sensors and 93us in v2.1.
All message data is “nibble-oriented” (a nibble is 4-bits). The next depicts the message structure of version 2.1 and 3.0 messages. The size of each block (in nibbles) is given in parentheses.
Both 2.1 and 3.0 protocols have a similar message structure containing four parts.
1. The preamble consists of “1” bits, 24 bits (6 nibbles) for v3.0 sensors and 16 bits (4 nibbles) for v2.1 sensors (since a v2.1 sensor bit stream contains an inverted and interleaved copy of the data bits, there is in fact a 32 bit sequence of alternating “0” and “1” bits in the preamble).
2. A sync nibble (4-bits) which is “0101” in the order of transmission. With v2.1 sensors this actually appears as “10011001”. Since nibbles are sent LSB first, the preamble nibble is actually “1010” or a hexadecimal “A”.
3. The sensor data payload, which is described in the “Message Formats” section below.
4. A post-amble (usually) containing two nibbles, the purpose or format of which is not understood at this time. At least one sensor (THR238NF) sends a 5-nibble post-amble where the last four nibbles are all zero. The number of bits in each message is sensor-dependent. The duration of most v3.0 messages is about 100msec. Since each bit is doubled in v2.1 messages, and each v2.1 message is repeated once in its entirety, these messages last about four times as long, or 400msec.
Reception and decoding is possible using an Arduino board combined with one of the inexpensive 434MHz receiver modules which are readily available.
Hardware available for decoding on the Atmel processor includes a hardware timer with an edge-triggered sampling input. Edges on the trigger input will cause the timer value to be latched and a processor interrupt is then generated. One easy way to handle decoding then is not to attempt clock recovery, but to examine the time difference between transitions on the OOK RF signal.
Classifying Time Intervals
The decoding algorithm works by classifying time intervals between RF transitions (on-to-off and off-to-on) as either short or long.
Because the RF pulses are shortened, separate time thresholds are used for classifying the time period (short or long) depending on the RF state (on or off). Based on the data rate (1024Hz) and the two amounts by which pulses are shortened (96us and 138us), the table below shows the expected values of time intervals (in microseconds) based on the protocol version and RF state.
Averaged thresholds for classifying time intervals as short or long have been determined. Times given in the table below are in microseconds. Time intervals which fall outside the “Short Min” or “Long Max” values are considered invalid. These are for version 2.1 and 3.0 sensors.
These averaged thresholds only vary by about 20usec from the ideal threshold that would be chosen for either version of sensor (2.1 versus 3.0).
A small improvement in performance might be possible by using different threshold values for each protocol version – which would be possible after the preamble is identified and the protocol version is known.
Decoding Using Time Intervals
The decoding algorithm works by capturing a timer value when RF transitions (on-to-off or off-to-on) occur, and calculating the time interval between successive transitions. These intervals are classified as either short (one-half clock period) or long (one full clock period).
An integer counter keeps track of time in units of one-half clock tick; this counter’s value will be called “half-time”. After being properly initialized, half-time is incremented by one when a short interval occurs and by two for long intervals. Half time is a very useful quantity for decoding RF messages:
• When half-time is even, we are at the middle of a clock period. The transition occurring at this point determines the bit being transmitted.
• When half-time is odd we are at the boundary between two clock periods.
Transitions occurring here are of no interest in determining transmitted bits.
• When half time is even, dividing it by two yields the current message bit
Using half-time, some very simple logic can be used to decode the RF signal.
When a transition falls on a boundary between two clock periods (i.e. half-time is odd), there is no message bit to be decoded. There may still be some useful information here however; if the current time period is long it means that the last transition also occurred at a clock period boundary. This means that there was no transition in the middle of the currently ending clock period, and signifies a violation of Manchester-coding format. This should be detected as an error condition.
When a transition falls in the middle of a clock period (half-time is even), a
message bit can be detected and its value is simply equal to the RF state
(on=”1” and off=”0”) just prior to the transition.
The decoding algorithm described above is simple and correctly determines the
polarity of each bit based on the current RF signal state (on/off). Another
algorithm has been developed by others which also works but does not consider
the RF state when detecting bits (except for the first bit). This algorithm is
The half-time value is also useful for verifying that bit-doubling is correct in version 2.1 messages. Since a long transition period is required to change from a 1 to a 0 bit (or vice-versa), every bit pair in these messages is required to end with a long transition period. Furthermore, when time is aligned with the end of a double-bit period, half-time taken modulo-4 will be zero.
When decoding a message from a version 2.1 sensor, and half-time modulo-4 is non-zero, no bit is detected. When half-time modulo-4 is zero, a bit is detected and a check is made that the current transition period is a long one (otherwise an error exists).
These algorithms have been published on the internet previously by various people.
As will be shown below, if the value of the first message bit is known then the message can be decoded by considering only the time intervals between RF state transitions, and ignoring the actual RF state value at each transition.
In a Manchester coded signal, each source data bit generates either a pair of short transition intervals or a single long transition interval. A source bit will generate a pair of short transition intervals when it is the same value as the preceding source bit. When a source bit has the opposite value as the preceding source bit, a single long transition interval is generated.
This description of Manchester coding lends itself to decoding based solely on transition timing. A pair of short transitions represents a bit identical to the previous bit. A long transition means the current bit is the opposite of the previous bit. This works as long as the value of the first bit can be correctly determined – otherwise the resulting decoded bit stream will be inverted.
Here is another algorithm that will properly decode version 2.1 messages:
every long period represents no change in bit state while every pair of short periods represents the bit state changing. Under this interpretation, the preamble decodes as 32 “1” bits instead of a repeating “1010…” pattern.
Furthermore, each bit in the message appears doubled without inversion – the sync nibble would be “00110011” for example. Answering the question of why this works is an exercise left for the reader.
All messages decoded so far (versions 2.1 and 3.0) appear to have an identical format for the sensor data payload, as shown in the table below. Figure 1 (earlier in this document) depicts the payload format. The message is assumed to contain “n” nibbles, numbered from zero to n-1. For convenience, this table also shows the checksum and post-amble portions of the message.
The coding of sensor-specific data varies according to the type of measurements being reported by the sensor. Some sensors use the same coding as others which report the similar data – but this is not always the case. For example, the THGR810 and THGR122NX temperature/humidity sensors use the same data coding, but the RGR968 and PCR800 rain gauges do not.
Most (but not all) sensor data is in BCD format, least significant digit (LSD) first. For example the value of 27.5 degrees Celsius would be coded as the hex nibbles “572”. The decimal point is assumed to be in a fixed location and is not actually transmitted.