Monday, February 17, 2014

Build Your Own Davis Weather Station Console!!!

This Davis weather station hacking stuff is addictive like crack cocaine is addictive.  I always seem to be taking another hit from the pipe.  I've figured out how to get into the Davis console's serial port (after which the two of us had a complete and frank discussion COMPLETELY IN UPPERCASE).  I then built my own Data Logger so I wouldn't have to buy the ridiculously expensive Davis dongle.  Then, after I figured out the wireless transmissions from the outdoor sensor suite, I made my own ISS receiver with a Pretty Pink Pager.  But of course, I can quit any time I want.  Me and Amy Winehouse.
"They tried to make me go to rehab I said No, No, No"  -  Bad Decision

Famous dead drug-addled musicians aside (and how long a list is that?  Don't they know that only Keith Richards is Immortal?), the path I was to go down became clear after Davis pulled a ridiculously stupid stunt in the infamous Firmware 3.0 release they started shipping in new consoles a while back.  The new firmware read 64 bytes from a fab-written, read-only section on the data logger's memory chip.  It took this data, did some algorithmic juggling, and then did a check against another 64 byte write-once block on the data logger put there by Davis.  If the console didn't like what it saw, it declared that the logger was invalid and refused to function further.

This was an obvious and misguided attempt to shut down a few hackers from building and selling third-party data loggers for a fraction of the price Davis charged.  Problem #1 was that people with an older, authentic Davis logger discovered that their pricey little dongle stopped working after a firmware "upgrade".  Problem #2 was it also disabled the serial interface connection I had discovered.  And that pissed me off.

Unfortunately for Davis, the console does not run a 2 GHz Core i7 processor capable of state of the art encryption and decryption algorithms.  It has a little Atmel Atmega processor running at 1 MHz or something like that.  It's abilities are somewhat more... restricted.  Like something that could be cracked by a 256 byte lookup table and a trivial bit of code. Hats off to Watson on WXForum for figuring this out. His most excellent hack is posted below for posterity.  Break out your Arduino and start cutting and pasting if you want to calculate a valid security code for a DIY logger.

u8 const GreenDot_Table[256] =
0x00, 0x04, 0x08, 0x0C, 0x10, 0x14, 0x18, 0x1C, 0x21, 0x25, 0x29, 0x2D, 0x31, 0x35, 0x39, 0x3D,
0x46, 0x42, 0x4E, 0x4A, 0x56, 0x52, 0x5E, 0x5A, 0x67, 0x63, 0x6F, 0x6B, 0x77, 0x73, 0x7F, 0x7B, 
0x8C, 0x88, 0x84, 0x80, 0x9C, 0x98, 0x94, 0x90, 0xAD, 0xA9, 0xA5, 0xA1, 0xBD, 0xB9, 0xB5, 0xB1, 
0xCA, 0xCE, 0xC2, 0xC6, 0xDA, 0xDE, 0xD2, 0xD6, 0xEB, 0xEF, 0xE3, 0xE7, 0xFB, 0xFF, 0xF3, 0xF7,
0x18, 0x1C, 0x10, 0x14, 0x08, 0x0C, 0x00, 0x04, 0x39, 0x3D, 0x31, 0x35, 0x29, 0x2D, 0x21, 0x25,
0x5E, 0x5A, 0x56, 0x52, 0x4E, 0x4A, 0x46, 0x42, 0x7F, 0x7B, 0x77, 0x73, 0x6F, 0x6B, 0x67, 0x63,
0x94, 0x90, 0x9C, 0x98, 0x84, 0x80, 0x8C, 0x88, 0xB5, 0xB1, 0xBD, 0xB9, 0xA5, 0xA1, 0xAD, 0xA9,
0xD2, 0xD6, 0xDA, 0xDE, 0xC2, 0xC6, 0xCA, 0xCE, 0xF3, 0xF7, 0xFB, 0xFF, 0xE3, 0xE7, 0xEB, 0xEF,
0x31, 0x35, 0x39, 0x3D, 0x21, 0x25, 0x29, 0x2D, 0x10, 0x14, 0x18, 0x1C, 0x00, 0x04, 0x08, 0x0C,
0x77, 0x73, 0x7F, 0x7B, 0x67, 0x63, 0x6F, 0x6B, 0x56, 0x52, 0x5E, 0x5A, 0x46, 0x42, 0x4E, 0x4A,
0xBD, 0xB9, 0xB5, 0xB1, 0xAD, 0xA9, 0xA5, 0xA1, 0x9C, 0x98, 0x94, 0x90, 0x8C, 0x88, 0x84, 0x80,
0xFB, 0xFF, 0xF3, 0xF7, 0xEB, 0xEF, 0xE3, 0xE7, 0xDA, 0xDE, 0xD2, 0xD6, 0xCA, 0xCE, 0xC2, 0xC6,
0x29, 0x2D, 0x21, 0x25, 0x39, 0x3D, 0x31, 0x35, 0x08, 0x0C, 0x00, 0x04, 0x18, 0x1C, 0x10, 0x14,
0x6F, 0x6B, 0x67, 0x63, 0x7F, 0x7B, 0x77, 0x73, 0x4E, 0x4A, 0x46, 0x42, 0x5E, 0x5A, 0x56, 0x52,
0xA5, 0xA1, 0xAD, 0xA9, 0xB5, 0xB1, 0xBD, 0xB9, 0x84, 0x80, 0x8C, 0x88, 0x94, 0x90, 0x9C, 0x98,
0xE3, 0xE7, 0xEB, 0xEF, 0xF3, 0xF7, 0xFB, 0xFF, 0xC2, 0xC6, 0xCA, 0xCE, 0xD2, 0xD6, 0xDA, 0xDE

u8 const Adesto_Factory_Programmed[64] = 
  // put here AT45DB011D Security Register from byte 64 to 127

u8 OneTime_User_Programmable[64];

OneTime_User_Programmable[0] = 0x00; // or whatever you want
OneTime_User_Programmable[1] = 0x00; // or whatever you want
OneTime_User_Programmable[2] = 0x00; // or whatever you want

u8 n, value;

for(n=3;n<64 br="" n="">{
 value = (u8)(Adesto_Factory_Programmed[n] + n);
 OneTime_User_Programmable[n] = GreenDot_Table[value];

For more on this whole sad saga, you'll want to read this masterwork by torkelmj, especially if you enjoy reading stuff dripping with spite and vitriol.  Like I do.  Or skip that and just buy a security-coded third party logger from WXForum awesomedude Belfryboy.  Or order up his PCB on oshpark and build your own.  There are options now, and options are good.

Now one might think that everything is just peachy now that DIY loggers are possible once again.  Not me.  I was pretty grumpy that Davis had tried to screw their customers over even if they did release subsequent firmware updates that tried to undo some of the damage.  Once burned, twice shy, so they say.  I started thinking of a Plan B.  I want to build my own console.
Gratuitous Picture of My Dog
My IM-ME thing was a neat hack, but that is about as far as it goes.  IM-ME's aren't actually rolling off the production lines in millions of units per month these days, and their ability to hook up to other little do-dads would not be easily done.  Cheap transceiver boards based off of the popular CC1101 chip that work in the 915 MHz band are hard as hell to come by.  Ask me how I know.  The Seeedstudio RFBee comes tantalizingly close, but others who have tried to go this route run out of RAM and Flash on the limited processor found on this unit before getting too far.

I needed another way and that led me to the Moteino with its awesome little RFM69B transceiver module.  I got it picking up Davis ISS transmissions earlier this year.  Since then I have been coding away in my spare time and have been pulling together the various bits of hardware that I need to get something going.  Something like this.
Beautiful, Isn't It?

Some cool stuff has sprung up from this very breadboard.  My serial connection to the console grew up there on the left side.  The DIY logger design is in the middle.  The stuff on the right half starting from the left is the humidity sensor, the pressure sensor module, the Moteino itself, and finally my USB to Serial Adapter for the project I'm writing about today.

Now I know what you are saying to yourself: "The title of the blog is "Build Your Own Davis Weather Station Console!!!" but that doesn't look like a console at all!  Where is the keyboard?  Where is the display?" Well, I guess I'm not going to get anything past you today.  There isn't a keyboard or a display... unless you want to add one.  The hardware and software here is all open for you to add on what you'd like.  Me, I'm thinking of hooking this bad boy to a serial port on my Beaglebone running Openhab and having all my weather data available from anything in my house that can bring up a web browser.  Very doable, and no display or keyboard necessary for that kind of application.

But why call it a "Console"?  Because I couldn't think of a better name.  And I did indeed try.  It isn't a "Receiver" because it does more than receive given that it has its own sensors hanging off of it.  "Indoor Unit" sounds stupid.  "Thingamahooie" was tempting, I must admit, but didn't quite convey the application well enough.  And hey, the guy that builds the hardware, develops the code, and writes the blog gets to call what he comes up with whatever the hell he wants.  I'm going with "Console", and you'll just have to deal with it.

But I, as I so often do, digress.  Back to business.  On the hardware side of things, here is what I'm working with in more detail:
  • Moteino with an RFM69 module on it.  Pick the 915 MHz RFM69W (standard transmit power) or RFM69HW (high transmit power) at your option.  I have the serial version but it probably would have made sense to pick up the USB variant so I wouldn't need to tie up my USB-Serial converter all the time.  You probably want to add on the male headers option (why even think about it for the one dollar price?) and the flash memory option for four dollars.  I'm not using that yet, but it might come in handy for data logging at some point.  And if you re-dedicate the Moteino to something else later, this memory can be used for wireless remote programming.  Cool.
  • a DHT22 Temperature and Humidity Sensor for less than five bucks.
  • a BMP085 Temperature and Pressure Sensor for less than six bucks.  But it looks like that module is now much cheaper thanks to the compatible BMP180 sensors now out there for under three bucks.  The two are compatible, and I'd probably go with the newer BMP180 myself just because it is smaller.
  • a (yet to arrive and be connected) DS3231 Real Time Clock and Memory Module for less than three bucks (I felt bad for getting something at this price with free shipping so I bought two).  Note that this module also has a 24C32 EEPROM on it that is bound to come in handy.  Don't be dumb and order a DS1307 clock module instead: that one doesn't work well with the 3.3V Moteino and it is horribly inaccurate.  What good is a clock chip that can't keep time?
Arduino is all about little software libraries, and these are the ones I'm working with right now.
  • the LowPowerLab RFM69 library.  Felix has merged the changes I've needed so no need to use my fork of his code any longer.  I don't know if I'll be using this in the long term or come up with my own that is better suited for this application.  Another library that I'm including right now but not really using yet is his SPIFlash library.
  • the JeeLabs DHT22 code.  I have extracted what I need from the JeeLib code and included it into my own library.  JCW's stuff is a leaner and meaner version of some of the other ones floating around on the net.
  • the Adafruit BMP085 library.  I used this as is.  I did look at using the JeeLabs code but it was a little too tied up with JCW's PortsLib for me to bother untangling at the time.
  • the Arduino Serial Command library to parse command input.  This is a really great little library that lets you register callbacks for each separate command and also does command line argument parsing.  I needed to make a few tweaks as noted below, but nothing major.  My changes have been pushed but not merged at this time, so use my fork here.
  • my own DavisRFM69 library, of course.  I've got to be doing something to make all this stuff work together.
Enough chitchat.  Let's cut to the chase, shall we?  Take a look at this thing actually doing something.
Success - I Never Tire of It
This is SandaySoft's Cumulus software talking to my homebrew weather station console.  The outdoor readings are those from my ISS in the front yard.  The indoor readings are from the sensors I have hanging off the Moteino.  On the left you can see the Serial Port Monitor Software recording the RS-232 messages going back and forth.  Cumulus has no idea that it isn't talking to a real Davis console.

Thanks to the Davis Serial Protocol Manual, getting this working wasn't too terribly difficult.   I knew Cumulus used the Davis SDK to talk to the console so the Cumulus author might not be aware of every single command being sent to the station and back.  I also knew that the LOOP command was used to get the data out of the station so I implemented that and some other useful commands on the Moteino.  Then I hooked my real console up and watched some packets go by and found a few more I needed to implement (namely BARDATA, HILOWS, and RXCHECK).  I had a few hiccups of course.  For example, Davis says that a command should always be terminated with '\n' (0x0a) like this...
 except when they don't, like this...
And that is the fun with emulation: you have to emulate not only the functionality, but the bugs as well.  This one caused me to tweak the serial port library to accept multiple command terminators.  Another oddity is that the console itself goes to sleep all the time and is woken by simply sending a lone '\n' that the console is supposed to acknowledge.  The serial library I'm using hadn't actually accounted for that situation.  Now it does.

Want to play along?  Here is what you need to do.   From within your Arduino's libraries directory...
  • Get my version of the SerialCommand library that supports empty commands and a second line terminator.  And of course, you'll want to get a copy of my DavisRFM69 library.  The pared down DHT22 library is tucked away inside the latter.
git clone SerialCommand
git clone
git clone Adafruit_BMP085
git clone
git clone
Hardware hookup is like this.

DHT22 Pin 1 -> Moteino 3.3V Out
DHT22 Pin 2 -> Moteino D4 with 10K Pullup resistor to Moteino 3.3V Out
DHT22 Pin 3 -> Not connected
DHT22 Pin 4 -> Moteino GND

BMP085 Module Pin VCC -> Moteino 3.3V Out
BMP085 Module Pin SDA -> Moteino SDA
BMP085 Module Pin SCL -> Moteino SCL
BMP085 Module Pin GND -> Moteino GND
Once you've got all of this hooked up, you'll find a "VP2.ino" sketch in the DavisRFM69 library's Examples directory.  Open that up in the Arduino IDE and select Control-U to compile and download it to the Moteino (be sure to tell the Arduino IDE that you are using an Arduino Uno).  Open up the serial monitor, set the baud rate to 19200 and "Newline" as the line ending.  You should see... absolutely nothing.  Nothing that is, until you type in some (uppercase) commands like "LOOP 1", "TEST", or "STRMON".  The Moteino will respond exactly the same way as a real console would.  Hook it up to Cumulus (with the "Use Data Logger" option unchecked) and revel in a job well done.

I'm off to a decent start here but there is still lots to do.  Here are some things on my list.

  • integrate the real time clock functionality
  • put in the frequencies for consoles in Europe and other regions
  • add some more useful commands like PUTRAIN so you can tell this thing how much rain you've had this year that it can keep a running count of afterward
  • add in some kind of EEPROM functionality so it retains settings like total rainfall between power downs.  Conveniently, there is an EEPROM on my yet to arrive three dollar clock module just begging to be used.
  • make the reception more resilient.  There are some odd things going on here: I get a spurious interrupt on startup (setup issue?) and when I move the board around (need a pulldown on the interrupt line?)  Reception is also poor during the day.  Might be that I just need to adjust the clear channel RSSI value a bit to accommodate more background noise.
  • integrate the real time clock functionality (daily / weekly / monthly / year highs and lows)
  • etc
Anyone that has done much coding on the Arduino gets to know memory limits.  The Moteino has double the RAM and EEPROM than the standard Arduino UNO, so I've got a whopping 2K of RAM and 32K of Flash to play with.  So far I have used roughly half of each, so I've got some headroom.  I haven't done much to try and streamline any of the code besides a few const arrays here and strings stuffed in the F() macro there, so I am sure there is room for improvement if things get really tight.

With this project, I think I've hit the goals I set out to achieve: come up with something functional, inexpensive, and with a low barrier to entry so that other people can dig in.  Have a new feature you'd like to see?  Send me a pull request on Github.  Want to develop a plug in circuit board (kind of like this) with all the dodads attached to lower the barrier to entry even further while making a few bucks on the side?  Be my guest.

I'll wrap this up by saying that the Davis guys make good stuff.  The ISS is very well put together and I love that the thing is solar powered with battery backup.  I've had mine for years and it has been operating trouble free on Battery #1.  The display on the indoor console is nice, big, and easy to read and it also just sips on battery.  I'm guessing that 99.9% of Davis' customers are going to continue buying standard Davis stuff off the shelf despite whatever I come up with here.  Anything I play around with  is ony going to be picked up by that other 0.1% of enthusiasts.  And it is those enthusiasts that are not only going to continue buying Davis products but will recommend them to their friends as long as they are kept happy.  If Davis pulls another stupid Firmware 3.0 thing, they'll do more damage to themselves than I ever did.  I hope they continue documenting their communication protocol and maintaining accessible expansion ports in their current and future products.  That would be a win-win for everybody.

With that in mind, it seems as good a time as any to unveil the new profile picture.
Be Nice


  1. Very cool. I will try to usw your code for a European Vue ISS.

  2. Hi DeKay,
    I'm in EU testing with an Arduino Uno connected to an RFM69W(868Mhz) trying to receive a Vue ISS. I changed to the DAVIS_FREQS_EU but I'm currently not receiving anything, after typing LOOP it returns " LOO" and "±o". This should work with an Arduino Uno too, using voltage dividers to get 3.3V as one would connect an RFM12? The IRQ is connected to D2.

    1. Never mind... I seem to have modified the wrong DavisRFM69.h file, it works now :-)

    2. Wow. I now have two users! That is two more than I ever thought I would have!

  3. The Australian one is a modified U.S. device. Here in Oz the lower part of the 900Mhz band is used by mobile phone networks. On this forum about half way down a poster lists what is on the compliance sticker.
    915-928 MHz
    ID Codes Available 8
    Output Power: Less than 8mW

    would this mean I could just use the U.S. setting in DavisRFM69.h

    1. Dunno. Maybe. Hopefully. Only one way to find out, and that would be to try it with the frequencies outside this range pruned out.

  4. Great work! Valuable source of information for my future weaterstation project. I've added link to your site from my own blog (

  5. I've been following your journey for months hoping to make use of the info gleaned to do some home monitoring, including weather of my home in MT. I've also been thinking about reading ubiquitous temp sensors from indoor/outdoor thermometers... That lead to wanting to snoop my power meter for electricity consumption (916MHz freq hopped MA). Your find of the Moteino looks to be capable of solving all these dreams!

    So my question to you is to ask for advice on snooping out the frequency hopping sequence. It seems you had the advantage of peeking at the console talking to the RF module changing channels. Do you think it will be possible to scan the channels to find the channel off the air?

    Joe Sestrich

    1. Possible, but certainly a challenge. First thing you'd want to do is see if you can decode the data at a single frequency (a lot harder than it sounds) and then see if you can figure out the hopping sequence. It may be that the sequence is more random than the fixed sequence used by Davis. If I were you, I would be looking at a cheap little USB stick to do software defined radio (eg and something like SDR Sharp to give you a better idea of what is going on in the frequency domain. And I'd be trying to find out if anyone had done any prior research. Google is your friend here. Good luck.

  6. I have no words to say how grateful I am for your work. During the last year I have developed a complete weather station based onArduinos, and now thanks to what I could learn by studying your code, I got the Cumulus recognizes my hardware as a VP2. Thank you so much for publishing it ... I will follow this subject closely.

    1. Nice! Have you written this up somewhere?

  7. By now just design specifications (, the code is still not quite ready. Do you mind if I use parts of your code that emulate the Davis?


    1. I'm good with that as long as your source code is made available.

    2. Thanks. I always publish the source code. The WeatherDuino Pro2 will be no exception.


    3. The source code for the WeatherDuino Pro2 project is now published. The WeatherDuino Pro2 project allows you to build a full weather station with davis vp2 emulation.
      More info and source code here:

      Thanks DeKay for your work.

    4. That is pretty damn cool.

  8. Hi DeKay

    In VP2.ino:

    void cmdSettime() {
    byte davisDateTime[8];
    // delay(2000); Why were these delays here if read() is blocking? Kobuki code bug?
    // Read six bytes for time and another two bytes for CRC
    for (byte i = 0; i < 8; i++) {
    davisDateTime[i] =;
    // delay(200);

    In my case, if I don't uncomment the delay lines, my arduino rtc does not sync when Cumulus starts.


    1. Thanks for the heads up. I'll look into this and uncomment it in my master.

  9. I'm confused about which RFM69 library to use, LowPowerLab's or yours. In the above blog post it says LowPowerLabs has incorporated your changes so you don't need yours. On your RFM69 github readme it says you don't need LowPowerLab library. So which should I use? My project is to get the wireless data from my Davis outdoor weather station and send it to my Weather Underground personal weather station account (using an Ethernet shield with the Moteino). I won't be using any of the indoor sensors like you have in your project.
    Great job on figuring all this out. It's quite an accomplishment.

    1. "I don't know if I'll be using this in the long term or come up with my own that is better suited for this application." Turned out to be the latter. See also.

      Good question! And thanks for the compliment.

  10. The Moteino I ordered doesn't have the flash chip. So should I remove the flash code from VP2.ino? Or is there some other flash on the Moteino that this code is communicating with?

    1. The code uses the Moteino flash to store archive records and the EEPROM on the microprocessor to store configuration data.

  11. In my project, I'm sending weather station data to Weather Underground; I won't be communicating with a console. I'm trying to understand the VP2.ino sketch. Is all the serial command stuff (sCmd) for communicating with the console? If so, I can remove it, right?

  12. I'm up at my ski house this weekend and I've got the Moteino receiving data from my Davis weather station and displaying on the Arduino serial console. It seems to be working so far. Unfortunately it's dead calm, so I can't see any wind data. I had a couple questions. My battery status is 0, I assume that means the battery is okay (the battery is only a week old), but I wanted to double check. What's the battery status for a low battery, 1? Also, how do I get the rain data? I don't see anything in the example program for rain. Once I get this finished, I'll put on on github for others to use.

    1. For battery status:

      For rain:

    2. Thanks for the links. I've got the Moteino working with a WIZ811MJ network module. Next steps are to grab the time from NTP server instead of a RTC chip and figure out what to upload to weather underground. Rain seems to be the most confusing.

    3. BTW - I'm Scott216 in the wxforum

  13. DeKay,
    I'm using your DavisRFM69.h library on the Moteino and it's working well except my sketch keeps locking up. It seems to happen when I'm making the Ethernet connection to weather underground. Does your library have any interrupts or anything that might interfere with the Ethernet connection? If so, do yo have any suggestions on how to fix?

    1. I should add that it everything works fine for 5 to 10 minutes. I did come across this post about an RFM12B messing up the Ethernet connection. Maybe I have a similar problem.
      I'm using a modified Ethernet library that a guy named SurferTim (on Arduino forum) created. He made a small change that let's the sketch choose a different SS pin for the Ethernet hardware. See

  14. I think I've got it working. I modified w5100 library as so setSS() disables interrupts with cli() and resetSS() enables them again with sei(). I've had the program running for about 30 minutes now and it hasn't locked up. Previously it would go about 5 minutes, 10 at the most. I'm not sure if there are unattended consequences with this mod, I hope not.

    1. Only one way to find out! It is very possible that there is some kind of interrupt contention going on that you have now worked around.

  15. I'm trying to figure out the station ID. Your code says "The low order three bits are the station ID", I think you're talking about radio.DATA[0]. My station ID is 1, but the low order bits of DATA[0] are always zeros. Here's a few of them

    1. Davis' ID codes of #1 to #8 map to zero through seven in DATA[0].

  16. Thanks. So transmitter ID 1 is 0 in the data. Did you ever determine if the transmitter ID changes the frequency hopping? Will your library work just as well with any ID?

  17. It turns out the the frequency hop sequence is the same regardless of the ID. The difference is the timing between hops, which increments by 62.5 ms for every increment of the transmitter ID. Off the top of my head, I think the current code would work but I've never tested it, and I haven't looked at this stuff in a while. I get busy with yardwork during the summer and play with it again in the winter.