Low Power High Accuracy Weather Station

'Professional' wind instruments are mounted high on a pole in an exposed location with LoRa data transmission

Similar projects worth following
So what's interesting about this project? ... It uses 'industrial grade' wind sensors, a programmable watch dog chip to keep the system alive, it uses peer to peer LoRa for data transission, it's hackable so that other sensors and circuits can be added and it's an upgrade from a system that's been up and running for about 3 years. What's not to like? ❀


  • Wind speed
  • Wind direction
  • Humidity
  • Pressure
  • Temperature
  • Battery volts
  • Soil moisture and temperature
  • Rain (even in deep sleep)
  • LoRa connectivity
  • Adafruit Feather M0 MCU and radio module
  • MCU watch dog (auto reset if MCU crashes)
  • Full Deep Sleep (everything is turned off between taking readings)
  • Arduino IDE (easy to program)
  • Hacking zone for extra circuits
  • Spare RJ25 slot for cheapo wind instruments (if you really must).
  • Server based PHP driven GUI

My previous version of a weather station used 2G GPRS for the data transmission which proved to be very power hungry and, even with a 40 watt solar panel, went dead during the dark months of December and January. The other problem was that, every now and again, the GPRS server would decide to kick the sim card off the network which sometimes required the card to be removed, inserted into a normal phone and an 'upgrade' downloaded. Moving to 3G or 4G would not solve these problems, even though 4G is far less power hungry.

I decided to create a new version of the control system based on LoRa technology which could potentially send data straight to a LoRa gateway if one existed. Unfortunately, I live on an island in the middle of nowhere so there's no chance of a gateway in the foreseeable future so I had to build a LoRa receiver as well.

Other than power requirements and data transmission, the main focus of this project is getting accurate wind measurements using high grade instruments and sensible positioning of those instruments up the top of a pole.

So why use these expensive wind instruments?

The generic wind vanes use eight sets of resistors to give a basic resolution of 45 degrees which can be further refined by using averaging, but wouldn't it be great to have 360 degrees (or better) resolution? The generic wind anemometers are 'ok', but don't last very long before the bearings need changing and are not calibrated so we have no idea how accurate they are.


On a positive note, the cheap generic rain gauges are actually very good and having tested them for over 3 years, the only problem was spiders running up and down the rocker arm playing some kind of game of chase and then getting bored and creating a web to seize everything up. They just needed a quick clean every six months or so.

One of the things that worked really well in the previous version of this weather station was the code for the wind instruments. The anemometer was relatively simple to implement as I could use a simple 'pulsein' command although, technically, this is 'blocking' and will introduce an unwanted delay in the code speed. Also, the rain gauge could theoretically interrupt the pulsein midway during the process causing an error so pulsein is wrapped in 'nointerrupts'. We could still miss rain readings, but this is helped by the fact that the gauge triggers twice per reading so we can filter for one or two interrupts in the code, dramatically decreasing the chances of missing a reading to 'almost' zero.

The wind vane is far more complicated to code as it relies on polar coordinates (0 to 360) which means that normal oversampling and averaging using the 'mean' is not possible. Think of the situation where the wind is blowing from the north ...... one moment we get a reading of say 2 degrees, the next a reading of 355 degrees which would give a mean value of approx:

(2+355)/2  = 180

 To overcome this I had to use 'mode', which necessitates creating a large 1D matrix of possible values and then evaluating which ones were most common over a particular time period. This...

Read more »

description - 1.90 kB - 04/30/2019 at 12:32


  • 1 × Adafruit Feather M0 LoRa radio MCU
  • 3 × C100nF capacitor (1206)
  • 2 × R1K restors (1206)
  • 2 × R4.7K resistor (1206)
  • 1 × R100K (1206)

View all 21 components

  • Rain Gauge 'Memory Block' Implementation

    Tegwyn☠Twmffat04/30/2019 at 12:02 0 comments

    After a bit of head scratching, I realised I'd need to charge the capacitor from another pin via a diode or else when the pin goes low again, the charge will be lost back to the MCU. I was also worried that the act of reading the capacitor using the analogRead() function would also discharge the device and it took a bit of trial and error to select a capacitor that was big enough such that it did not discharge too quickly. In an ideal world it would not discharge at all, until it rains, of course.

    The other thing that caused slight confusion was the 'sharp' saw tooth pattern on the 'scope until I realised that the same thing was happening - the 'scope probe was also absorbing charge from the capacitor:

    The two low flat spots in the graph above show where I tested the rain gauge. It works!
    Since the capacitor selected is 10 micro Farads, the energy wasted can be calculated:
    Energy Stored in a Capacitor formula - RF Cafe... and the average power, and average current = 3.2 uA ....... Nothing to worry about! It's probably more like 1.0 uA due to the fact that the capacitor does not discharge to zero unless it rains.

  • Tuning the Code for Deep Sleep and Watchdog to Work Together

    Tegwyn☠Twmffat04/28/2019 at 15:34 0 comments

    To get the deep sleep function and supervisory watchdog playing nicely with each other required a bit of tuning using well placed delay() functions in the code. Previously, all timings could be done using the millis() function, but with deep sleep, this no longer works as millis() does not operate in deep sleep.

    The watchdog chip needs to be pulsed regularly with 3.3 v to stop it from pulling the reset bus low and resetting the MCU. This was easy enough when taking wind and rain readings, but slightly more challenging when it came to reading from the BME260 at the 5 minute interval and allowing 10 seconds for a callback from the raspberry pi internet 'gateway'. A bit of trial and error whilst connected up to a 'scope was the answer. The above image shows the Adafruit M0 feather LoRa radio power profile with deep sleep very close to zero between each set of wind readings in red and the watchdog pulse in blue.

  • This is Where Weather Stations Start to get Interesting

    Tegwyn☠Twmffat04/27/2019 at 15:15 0 comments

    It could be said that building a weather station is trivial - it's just a bunch of sensors plugged into an MCU - too easy to take seriously. But once we get stuck into the details of low power everything becomes more challenging (thankfully). The photo below shows a 'state of the art' watchdog chip and circuit which lurks underneath the Adafruit LoRa Feather module:

    The main chip is a Texas Instruments TPS3430 and it's programmable by means of a capacitor (middle right). The resistor in the foreground is 0805, so it can be seen that the chip is rather small, but not too difficult to solder thanks to good PCB design with the four square pads for positioning rather than relying on the screen print. The chip requires a short pulse every 5 seconds to to keep it from setting the MCU's reset bus low. This is not difficult until it's combined with a 'deep sleep' library such as Sleepy Dog, which effectively throws a 5 second delay into the runtime and turns off the MCU, which results in no more serial console for debugging, but keeps all the variables in RAM and Flash.

    One of the other restrictions with Deep Sleep and the Adafruit Feather M0, is that the rain gauge can no longer be on a simple interrupt and instead I used the gauge filter capacitor as a memory block. Every 5 seconds the capacitor is kept charged up using analogWrite and if it rains, the gauge discharges that capacitor. Then, after every Sleepy Dog deep sleep, the value of the voltage on the capacitor is read using analogRead and if it's less than '20' out of a possible 1024 it indicates that it has rained. Simple! (Apparently this is similar to how DRAM works:

  • Compare Low Power Properties of Adafruit Feather M0 to Arduino MKR1300

    Tegwyn☠Twmffat04/20/2019 at 08:59 0 comments

    A 5.5V power supply was connected to the Vin / USB bus pins on the two devices with a high accuracy 20 Ohm resistor in series for current measurement. An oscilloscope was connected either side of the resistor and it's measurements are displayed in red below:

    On the left is the Arduino and n the right the feather and the 'pulse' represent the Adafruit 'Sleepy Dog' deep sleep function kicking in. We're interested in the minimum values and the Arduino gave  11.5 mA in deep sleep and the Feather 2 mA. Also, in 'steady state' operation the Arduino consumed a lot more power, 20 mA compared to 11.5 mA for the feather. The MCUs and radios are the same so there's obviously other devices burning up a lot of power in the Arduino such as the 5V to 3.3V regulator.

    I then tried to perform a LoRa transmit on the MKR1300 and the oscilloscope showed one hell of a mess, with a large zone shown by the large area where nothing much seems to happen, in spite of the code! The best that Sleepy Dog could achieve was about 18 mA.

    Compare this with the feather:

    ..... and we've got nice, quick, clean transmission spikes and deep sleep of 2 mA. Steady state of the MCU is 11.5 mA. The smaller spikes in the deep sleep zone are caused when the Sleepy Dog wakes up momentarily every 15 seconds or so to have a quick look around in case there are any cats to chase. There's no way around this, it's just how it works, but it's quite handy to flash an LED for about 2 ms here just to indicate that the device is still alive.

    Conclusion: Adafruit wins hands done compared to Arduino!
    By the way, Sleepy Dog does mess up serial logging so it's good policy to use LEDs to signal what's happening.

  • Swap MKR 1300 LoRaWAN for Adafruit Feather M0 LoRa Radio

    Tegwyn☠Twmffat04/15/2019 at 14:16 0 comments

    I've been really struggling getting the Arduino MKR1300 to work properly - A simple delay after powering up moisture pin seemed to fix it:

    Old code:
    digitalWrite(moisturePowerPin, HIGH);              // Powers up the moisture sensor for 0.1 seconds to prevent corrosion.
    moisture = (analogRead(sensorPin)*0.120)-9; 
    New code:
    digitalWrite(moisturePowerPin, HIGH);              // Powers up the moisture sensor for 0.1 seconds to prevent corrosion.
    delay (50);
    moisture = (analogRead(sensorPin)*0.120)-19;  

    Also, I think there was some type casting of variables problem which I fixed at the same time (eg we cant just cast integers to floats without using memcpy function in 32 bit system or similar) but on top of that there's a well known hardware fault with the device that stops it going into sleep mode. I say well known, but when I selected the device, I did not know about it! Nevertheless, swapping out for the Adafruit version was only a few hours work on DesignSpark PCB software and here's the new version:

    As the name of this project suggests, having a low power consumption is vitally important, and from the Adafruit documentation it looks like those guys actually went through the various power profiles and it certainly looks like it works properly from the various graphs at: . The MCU on the feather has 256k of flash and 32k RAM memory so it's easily big enough for all my code. It's also pretty fast although speed is not really an issue. There are also 3 spare input pins which can be hacked if necessary in the future. PCB and Gerber files are on the GitHub page and have just been sent to JLC PCB for a 10 day turnaround for $10 including postage - they now have a swanky airmail service which should speed things up quite a bit.

    Looking at the image above, you might notice a crazy small chip inside the yellow feather module box. This is a programmable watchdog that will trigger reset if the MCU crashes or starts producing erratic data. It works really well with the current MKR1300 setup, but will it work with the various Adafruit sleep modes? I'm guessing I can put the device into deep sleep for 3 seconds at a time, which is within the current watchdog timeframe. Should be interesting to see how it performs.

    The current draw for the device is documented as being 11mA for the MCU and an additional 2mA for the radio. To transmit a data payload of 20 bytes, about 130mA is required for 70ms. When the radio is actively listening for data, the whole device consumes 40mA and when in deep sleep, about 300uA. Will the rain gauge work in deep sleep mode?

  • Soil Moisture Calibration

    Tegwyn☠Twmffat04/13/2019 at 08:19 0 comments

    Having tried both capacitive and resistive moisture sensors, I found the resistive much more stable and accurate and then spent a bit of time calibrating it against changes in temperature:

    The blue line shows how the moisture readings change with temperature and it appears to be a straight line. In reality, it tapers off as temperatures rise above 50 degrees C. I used a very simple formula: 

    moisture = moisture - (moisture * soilTemp * 0.065)

    by trial and error to get the red line. As can be seen, it's not a flat line so the cobbled formula could be refined by incorporating a cobbled sine function, but accuracy to +- 2% moistre is absolutely fine foe me at least!

    Calibration files for the weather station are available here:

    I also fixed some of the graphs on the GUI so that, among other functions, soil moisture and temperature can be viewed side by side: to check that the calibration is going to work. It should display a steady decline, irrespective of temperature, until it rains again.

  • Rain Gauge Repair / Service

    Tegwyn☠Twmffat03/12/2019 at 12:48 0 comments

    From memory, the rain gauge is now about 2 years old and, today, the reed switch failed :( . Fortunately, it's quite easy to repair by soldering in a new switch:

    The replacement part is a Cynergy3 TRA291G/20-30

    ... And there's a couple of things to watch out for:

    • The component has flat legs and can be positioned in 2 ways, so check by closely examining the reed, checking that the magnet will actually close the contact when it swivels past.
    • As standard, the reed is positioned on the underside of the board, but positioning on the topside, as shown above, ensures it gets activated by the magnet more readily.

  • Upgrade from Hacked to Hackable

    Tegwyn☠Twmffat03/08/2019 at 11:25 0 comments

    The previous version of this project was hacked on a spare PCB I had lying around and tested in the field for a couple of years. This enabled me to create a 'proper' version that, rather than being hacked is now custom made but still hackable with facility to use the generic Chinese wind instruments and add other sensors if so required.

  • Testing Non Programmable Watchdog Circuit

    Tegwyn☠Twmffat03/07/2019 at 11:26 0 comments

    I really thought that implementing the watchdog (STWD100NYWY3F) was going to be effortless, but after carefully soldering the components and adding the appropriate code, it just would not work!

    Fortunately I had some spare PCBs  and watch dog chips so I set up a test rig to diagnose the problem. Using an oscilloscope it was easy to see where the problem lay as the watchdog was actually responding as expected, but the MCU reset line was not responding. According to the STWD100NYWY3F documentation, a 4.7k resistor is required to allow 'signal contention' between the watchdog and the MCU reset and replacing this with a 2k allowed the signal to come low enough to trigger a proper reset:

    During implementing code to control the watch dog, I realised that I had to disable the device whilst the BME280 sensor chip was 'doing it's thing', which takes about 3 seconds. The watchdog has a window 1.6 seconds long in which it expects a heart beat pulse from the MCU so, unfortunately, it seems that the STWD100NYWY3F is not the best solution. I'm guessing that the chances of the system crashing during that 3 second long period is very low, but for the sake of selecting the correct component, it's worth making another PCB upgrade. It will also give the opportunity to incorporate a switch in the circuit to isolate the reset so that code can be uploaded without having to remove the MKR WAN 1300 from the board. The new watchdog will be the programmable Texas instruments TPS3430WDRCR for which there is an evaluation board to make life easier.

  • Next Step in Debugging Effort

    Tegwyn☠Twmffat03/07/2019 at 11:07 0 comments

    After a few weeks of running the weather station close to my office, I was able to find out what might be causing it to crash so often. Well, actually, whatever I did in the code made no difference and the crash seemed to be entirely random. This could only mean that there was a problem with the track routing on the PCB, so the design was improved to give logical precedence to the wind instrument data lines, particularly the anemometer, which carries a pulse:

    Rebuilding the PCB also gave me the opportunity to incorporate a simple watchdog circuit which would reset the MCU after a crash. 

    Fortunately, after the rebuild, the frequency of crashes diminished to greater than 3 days. Next step is to implement the watch dog.

View all 11 project logs

  • 1
    Pole Construction

    To get meaningful results, it's important to get the wind instruments high up in the air, away from trees, buidlings etc.

    The pole itself is made from 1" high pressure water pipe and can be used with standard 1" BSP plumbing fittings for joining sections together.

    The first section is stainless steel 1" as above and is concreted into the ground.
    The next section is also stainless steel 1" , which then connects to the final section which tapers to 1/2":
    The wind vane is mounted as above. The last section also has the guy rope attachments and the Anemometer

View all instructions

Enjoy this project?



Justin Niedzialek wrote 05/04/2019 at 12:02 point

Very nice project, if only I had this know how and ready access to today's SOC boards 15 years ago as a grad student. I deployed and maintained these in remote locations and I was constantly worried about power requirements punching holes in my data collection. I wish I met LoRa at that time life would have been so much easier.

  Are you sure? yes | no

Jan wrote 04/30/2019 at 16:04 point

I like this project very much because it is one of your projects which is not about killing insects or snails! 

Jokes aside, building a proper weather station really is one of the things most tinkerers talk about at least once in their life :) 

  Are you sure? yes | no

Tegwyn☠Twmffat wrote 04/30/2019 at 17:18 point

Hopefully I'll finish it! Not too far off.

  Are you sure? yes | no

Jan wrote 04/30/2019 at 17:31 point

Yeah, I say that too often :)
By the way, especially regarding measuring outside temperatures: Do you plan on making a special housing for your sensors to get "standardized" measurements?
Those are kind of mandatory to get the proper readings from your (temperature) sensors:
At least that's the typical style around here... has a crazy detailed paper btw.:

  Are you sure? yes | no

Tegwyn☠Twmffat wrote 04/30/2019 at 17:47 point

special housing for your sensors ….. Yes, that's a good idea. I've got some limited shielding, but have noticed bad temperature data when the sun comes round onto the device box.

  Are you sure? yes | no

Similar Projects

Does this project spark your interest?

Become a member to follow this project and never miss any updates