Following on the great work by DeKay and others, I've started implementing a Si1000 based wireless receiver for the Davis ISS 900MHz protocol.
The motivation for this work is that some vandals smashed the Davis console on a weather station I had setup for my local RC model flying club (see
http://weather.cmac.org.au). I thought that instead of buying a new console I would build my own. I'm the author of the firmware for an open source telemetry radio commonly used in UAVs, so I just took one of our Si1000 based radios and adapted it for receiving the Davis messages. That involved looking at the CC1101 register settings from the code that DeKay and others had done, and creating equivalent register settings for the Si1000 transceiver.
In case it helps anyone else, the key wireless information is:
Symbol rate: 19.191 kbaud
Modulation: GFSK, no manchester
Deviation: 9.521 kHz
Band: 900MHz
Preamble: 32 bits
Preamble detection: 16 bits
Sync words: 0xCB 0x89 (MSB)
Packet format: fixed packet length, 10 data bytes
Checksum: CCITT over 8 bytes, results in constant. Constant varies by protocol version
Trailer: fixed 2 bytes of 0xC2 0x16 (bytes 8 and 9)
Frequency hopping pattern: 911380218, 902349090, 911882476, 922921051, 914892852, 906363189, 925931427, 918405487, 908872100, 920412139, 913387664, 903854278, 916899505, 924426239, 910377288, 904858001, 915896575, 921415863, 907366912, 926935150, 912886199, 903352813, 917401763, 923422515, 909373565, 926432891, 905861724, 914391387, 919408416, 924927703, 902850555, 910878753, 921917327, 915394317, 906864654, 917903228, 927436614, 920913604, 908369842, 912383941, 918906951, 904355743, 923923980, 916398040, 909875030, 919910675, 905359466, 922418792, 907868377, 913889129, 925429962
I have put a current version of my code in the davis-wip branch of my SiK tree, at
http://github.com/tridge/SiKThe code works on the 3DR 900MHz radio (see
http://store.diydrones.com) and should also work on the various clones out there.
Now the remaining puzzle is decoding the leading 8 bytes of the protocol. For my ISS the protocol is clearly different to the protocol decoded by DeKay and others, although it is closely related.
The first 4 bits of the leading byte is the packet type, but the packet types don't match what previous people have found. For example, DeKay found that type 8 was temperature, whereas in mine it became clear that temperature is type 7.
My current theory is that the console uses the result of the checksum calculation to determine the protocol version, or perhaps use the two trailer bytes. The fact that the freq hopping and modulation is the same would mean that can have one console that supports many different protocols.
The bottom 3 bits of byte 1 are the transmitter ID. Changing the ID of the ISS changes these bits, and doesn't affect anything else in the protocol (so same hopping sequence).
The second byte is the wind speed, but it isn't in the simple linear format that others have found. It seems to be byte1 xor 0xE. I tested this by driving around with my ISS hanging out the window of a car, and logging the driving speed with a GPS. This formula gave a good match.
The 3rd byte is wind direction, but it is permuted in a strange way. The two nibbles are permuted in the following way (python code):
def wind_direction(b):
n1 = [0xD, 0xE, 0xF, 0x0, 0x9, 0xA, 0xB, 0xC, 0x5, 0x6, 0x7, 0x8, 0x1, 0x2, 0x3, 0x4]
n2 = [0xD, 0xC, 0xF, 0xE, 0x9, 0x8, 0xB, 0xA, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2]
v = (n1[b>>4]<<4) | n2[b&0xF]
return v * 360 / 255
That gives the direction in degrees.
The other readings all seem to be based on a 12 bit number derived from the 4th and 5th bytes. The basic formula for the 12 bits seems to be something like this:
def decode(b1, b2):
n1 = [ 0xF, 0xE, 0xD, 0xC, 0xB, 0xA, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 ]
n2 = [ 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xE, 0xF, 0xC, 0xD, 0xA, 0xB, 0x8, 0x9 ]
n3 = [ 0xC, 0xD, 0xE, 0xF, 0x8, 0x9, 0xA, 0xB, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 ]
v = (n1[b1>>4]<<8) | (n2[b1&0xF]<<4) | n3[b2>>4]
return v
I derived these permutations by putting the ISS in a freezer to make the 12 bits cover a good range, with slow movement of the temperature. The n1 permutation is not really certain, and contains quite a lot of guesswork (as temperature only covered two of these values), but n2 and n3 are more certain. This results in the following temperature formula for message type 7:
def temperature(b1, b2):
v = decode(b1, b2)
farenheit = v / 7.0 - 30.0
celcius = (farenheit - 32) * 5 / 9
return celcius
That seems to match the temperature recorded by an independent sensor (my EnviR home monitor) quite well.
I haven't yet worked out the message types and scaling of barometric pressure, humidity and rain. I'll put the ISS under a slow tap tomorrow to get the rain readings.
I'm planning on making the firmware react much like a real ISS console, so it can be used as a simple USB dongle that behaves just like a real davis console, so the various commands work. I'd like it to work "out of the box" with the weewx weather program, which is what we use at the flying field.
Cheers, Tridge
PS: Thanks to the people at Davis for making the protocol interesting enough to be a challenge, but easy enough to work out with a bit of effort!