This second post of this year is not about a hack but about a fairly nifty contraption that I just completed building.
In the local flying club we've had pretty bad experiences with our wind stations in the past. But with the lay of the valleys around our flying sites the local wind conditions often aren't even close to what the publicly accessible coastal stations report, so we really needed something to be done.
So I decided to build a new wind station for the club. Being a believer in the KISS principle I wanted it to be simple and robust, and as self-contained as possible: no grid power, no fixed-line Internet comms, no nothing. As usual I'm presenting my experiences and code here for anybody interested in building their own.
While investigating the hardware options I decided that gutting one of the cheap backyard weather stations for its sensors wouldn't make much sense as they're not sufficiently durable; so I got a Davis 7911 anemometer - the single most expensive part of the station, $180 in Oz. Interfacing the Davis sensor with a microprocessor isn't too hard, and T.T. Allen's documentation contains all the relevant info: the wind vane is a potentiometer, and the wind cups drive a reed switch.
First I thought about using a Raspberry Pi and a USB mobile data modem for the brains, but then discarded the idea: the pi uses quite a bit of energy, and with the ridiculous charges for mobile data here it wouldn't make economical sense to have everybody access the readings on the station itself anyway. Therefore the wind station should only take readings and send them off to my server for processing and display, hence a lot less computing power is needed at the station.
So I went back to the basics and considered using a solo microcontroller. I needed something with a TCP/IP stack, and a GSM modem. Eventually I found out that the SIMCom SIM300 GSM/GPRS module has TCP/IP on board and talks normal serial, that it has been around for a while and that devel boards with that module can be had for not too much money ($49). With that sorted out I chose the cheapest suitable microcontroller that I had around, which is the Microchip PIC16F88 (as I required a serial port and an analog-to-digital converter).
The 16F88 consumes only a few micro-Amperes by itself, the SIM300 needs up to 400mA when transmitting (but less than 25mA otherwise), so that option made the energy budget much more manageable. My limited testing (no Watt meter) led me to guesstimate that running everything 24 hrs/7 days would consume about 1Ah for a whole day, or 12Wh.
I added a 20W solar panel, a deep-cycle 12V 20Ah SLA battery and a Steca Solsum 6.6 charge controller to the shopping list. With the 20W panel and decent weather the battery should stay topped up without any dramas.
Electrically the setup is very simple. The Solsum keeps the battery charged and disconnects the load if the battery voltage should drop too low. The Solsum's load terminals are connected to the input of the SIM300 board, which comes with its own switch-mode DC-DC converter (in: anything up to 40V, out: 3.85V). 3.85V is perfectly fine for the PIC so it is powered by the SIM300 board as well.
The PIC converts the analog direction signal of the anemometer into a digital value, and counts the pulses of the wind cups. To make the speed readings accurate the PIC needs a decent time base; I used a 32.768kHz crystal (with Timer 1) to get precise one-second interrupts without any manual busy-waiting. The reed switch for the wind speed cups showed a lot of bounce during testing, so I added a 100nF cap which cured the problem.
The SIM300 exhibits some substantial current spikes, so I decided for good measure to put a extra 2200uF cap on my board; I also put an in-circuit programming header in, but then I made a silly mistake: while I could and should have made it possible to isolate the big cap, I didn't do that - and therefore ICSP doesn't work on my board; the programmer sees very slow voltage rises and falls and gets completely confused.
In my initial design I planned to switch on power for the direction pot only briefly when the readings are taken, but that didn't work out too well: the Davis has a few degrees of deadband where the pot wiper isn't connected to anything. In that region the analog-to-digital conversion returned nonsensical values if I had switched the power on just a few microseconds earlier. I suspect that stray capacitance in that area confuses the (capacitance-based) ADC, and the problem went away when I powered the direction pot permanently; at 20Kohm it won't break the energy budget.
Here is the schematic as I should have wired it up, and some photos of the finished item:
The software side is even simpler: every second the PIC makes an analog-to-digital conversion to capture a direction reading and stores it temporarily. The ADC is 10 bit, but I only use the most significant 8 bits = 1 byte.
The wind speed readings are continuous, using Timer 0 to count pulses. Given the Davis' setup of 60 pulses/sec = 135 miles/hr and wanting useful ranges with single-byte readings, I decided on counting periods of 5 seconds. That way the station can record 0 to 99.8 knots (with a resolution of 0.39 knots).
Every 5 seconds the PIC records and resets the speed pulse count, and
sends everything off: a 16-bit uptime counter, the one-byte speed reading,
five one-byte direction readings and a one-byte crc-8 checksum. The
resulting 9 byte observation is handed to the SIM300
AT+CIPSEND) and sent as a 37-byte UDP packet
(20 bytes IP header, 8 bytes UDP header, 9 bytes payload) to my server.
The PIC blindly assumes that the SIM300 is ready and active; no buffering
or retries or status verification takes place (outdated readings wouldn't
be of much use anyway). However, every 320 seconds the PIC asks the SIM300
to reset the UDP pseudo-connection (using
the SIM300 should have restarted or lost network access in the meantime,
then that's sufficient to get us on track again.
This time I programmed the PIC in a mix of C and assembler, using the open+free SDCC compiler (which has a few quirks when used with PICs but does the job fine).
The server side consists of a small bit of perl which listens on the appropriate UDP port, unpacks the readings and dumps them into BerkeleyDB databases. There's also another perl program that computes and displays some metrics from the data in the db.
The whole source code is available here (I've blanked the port number, though); as always it's under the GPL and can be used freely.
Testing and Install
The SIM300 needs to be primed with a few settings once, but it can fortunately remember these in flash memory:
AT+IPR=38400to disable autobauding and fix the serial speed
AT+CDNSORIP=1to allow host names and not just IPs
AT+CIPCSGP=1,"telstra.internet"to use the right(bah) APN for data comms
AT+CIPSCONTto memorize all those settings.
I could have had the PIC store and send these, but as the PIC has very little EEPROM and as I didn't want to run into trouble with a mis-initialized SIM300 I preferred to have the stuff preset there.
The first test run was behind my house, with everything simply screwed to a conveniently located palm tree.
The black box in the photo is a marine battery box for battery and solar charger.
Almost everything worked fine during testing. One issue was that the SIM300 would transmit garbage every once in a while (maybe 5-10 packets over a day). I tracked that down to the SIM300 losing track and/or a bit or two and then misinterpreting the next 'transmit this' command as the data to transmit. Originally sending the uptime counter was meant to let me detect such garbage data, but it turned out to be less than ideal for this purpose. I fixed the problem by a) transmitting 9 spare "\r"s before any real commands so that the SIM300 gets out of 'wait for data' mode, and b) by adding a crc8 checksum to the packet.
The solar panel and anemometer received a fair bit of stress-testing from a hungry possum: the palm tree in question is carrying fruit right now, and the possum absolutely bombarded everything below with seeds and half-eaten fruit every evening for a whole week. You can see his beady eyes on the first photo (and his butt on the second).
Last Friday I drove up to Rob Wilton's place (he offered to have the wind station on the power pole outside his house, which is 1500m from launch) and we installed the whole setup. The installation was fun: we jury-rigged two 3.7m ladders into one and I didn't overly enjoy the swaying of the frankenladder and the pole itself. The remainder of the install went without a hitch - except that it didn't work at all: it turned out of a number of different Telstra APNs I had picked the wrong one. It had worked fine at my place but not in the much more remote final location.
I really would have liked to avoid Telstra, the extortionist extraordinaire, in the first place; even with a prepaid SIM I could have gotten a megabyte of data for $0.05 from the other providers - but unfortunately at Rob's place there is zip coverage by those more sensible providers. Lovely Telstra charges you $2 per megabyte on prepaid - or you have to manually fart around on their website to periodically buy a 'plus pack' which gives you 30meg (over 30 days) for $5, or 200meg (over 30 days) for $10. Telstra really sucks, bigtime.
Here are some more pictures of the installed wind station, which you can observe in action on the CHGC website.
The first incarnation of the hardware and software suffered from a few problems which I've fixed recently. Overall the SIM300 may have been a suboptimal choice of module; it seems to go AWOL every now and then. More specifically, this particular board design definitely isn't ideal as it doesn't expose a number of useful signals of the SIM300. The "SIM300 goes away occasionally" issue I fixed by having the PIC completely restart the SIM300 every 1.5 hours. Unfortunately the SIM300 doesn't restart by itself (at least not with this board's wiring of the PWRKEY signal), so doing this in software only was not possible. I had some further trouble getting the SIM300 to reliably distinguish between the 'please power off' and 'do power on' signal timings, so I made the PIC check and sense VDD_EXT (which isn't accessible easily, and which I took off the system LED). I updated the schematic to suit.
The SIM300 occasionally loses some chars (even at a lowly 38400 bps), but my board doesn't break out the RTS/CTS signals so hardware flow control isn't an option; fortunately this doesn't happen too often and sending the extra "\r"s plus CRC take care of defusing this issue. I've fixed a few minor programming gotchas (e.g. the watchdog timout was wrong and too short), had the PIC check and start the SIM300 on the go if required, and have it send both 'please connect' and 'please transmit these bytes' commands for every transmission (to kick the SIM300 into operation if it starts up slowly or otherwise loses net access). In addition to that I fixed one minor gotcha that caused major headache: intermittently the PIC would power up straight into an endless loop, sending some garbage to the SIM300 and then restarting when the watchdog timer expired. I had a hard time reproducing the problem, but eventually found my small oversight: "X marks the spot" in adventure stories, and occasionally in datasheets, too. As per the PIC16F88 datasheet the EEPGD bit has no defined value at start (hence marked neither 0 nor 1 but X), and only if it's cleared the PIC reads from EEPROM. If set, the PIC reads from flash memory (where there's nothing useful in my case) and - at least in my tests - somehow managed to lock up at some point afterwards. My code didn't clear the EEPGD bit because when I last programmed an EEPROM data read it was on a different model PIC which doesn't have this config bit at all. The source code archive has been updated to incorporate those changes.
Check out the new and hopefully final version of the wind station.