Weather Station

Keeping on registering data from different sensors my next project has been the all-time favourite weather station. This time I wanted to build an 100% autonomous outdoor sensor.

To achieve this goal I started playing with a LiPo battery and a solar panel. The Arduino Fio looked like the perfect out-of-the-box platform to be the center of the project. It’s a ATmega328P (the same micro as the UNO), has a connection for a LiPo battery, a charge circuit based on the MAX1555 (with an USB connector) and a socket for an XBee radio module. So I just really had to wire things up and work on the code to reduce the power consumption to its minimum.


This first version of the weather station uses two sensors: a DHT22 and a BMP085. The former is a temperature and humidity sensor that uses a custom one wire digital protocol. The later is a barometric pressure sensor with I2C protocol. Both sensors are 3V3 compatible (like the Fio) and very easy to set up. Adafruit has tutorials and libraries for the two of them here and here.

Weather Station Schema

The schema is so simple I thought it could be a good opportunity to give Fritzing a try. The result could be better. You have to imagine that the CHG and ON holes are connected to the input of the two voltage dividers on the right to check the voltage from the solar panel and the LiPo battery. The other connector by the on/off switch is there to provide an external on/off switch in the future.

Here you have a picture of the sensor. I think I haven’t said this before: I prefer stripboards (veroboards) over perfboards because they are very suitable for rapid development and the final layout is cleaner.

Weather Station sensor

Power management

The main issue with this sensor is power management. The goal was to have an autonomous sensor that will not require battery replacements. Given that Sun is a natural resource freely available most days here in Barcelona that shouldn’t be a problem.

To provide power I chose the Medium 6V 2W solar panel from Adafruit. The Fio charging voltage requirement goes from 3.7V to 7V and this panel fits quite well in that range. The only drawback is the 3.5×1.3 jack connector – a mini USB would have been a perfect match. No worries, the Fio provides a place holder to connect a custom charging source.

And to store energy I’m using a Lithium-Polymer battery rated 3.7V 850mAh. That’s enough power to make it last for weeks applying simple sleeping strategies. When in power down mode the circuitry consumes a negligible amount of energy (not measurable by my instruments, something around 10 uA?). The problem arises when it wakes up.

The DHT22 sensor is a little picky. It requires a warm-up lapse before reading anything and you cannot perform two readings in a row without another delay in between. After some testing I found out that a 2 seconds warm-up time after wake-up produced constant reliable results. Besides, the reading itself is also time (and power) consuming. At the end every time the Arduino wakes up it waits 2 seconds for the DHT22 to warm-up and 2 more seconds to get the reading from it. The reading from the BMP085 is fast (in comparison) and then sending the data by radio produces a burst of ~55mA for 10 millisecs.

State mA ms/event events/h ms/h mA (avg)
Arduino (and XBee) sleeping ~0 - - 3474488 ~0
Warm-up 10 2000 60 120000 0.333
DHT22 reading 12.5 2000 60 120000 0.417
BMP085 reading 10 10 60 600 0.002
XBee awake 25 80 60 4800 0.033
XBee transmitting 54 10 12 120 0.002

The average is ~0.8mA which means around 44 days for a 850mAh battery. Note than 93% of the power consumption is due to the DHT22 reading process. So here there is a big source for power management improvement, but… don’t optimize until you need it.

Since I still had to buy the solar panel and while I was waiting for it to arrive, I powered the sensor and it started transmitting data. I carried the experiment for some weeks until the voltage from the battery fell below 3300mV and the Fio stopped working. It lasted for 37 days, quite accurate.

Then I plugged the solar panel and (after some trouble shooting) it has never gone below 4200mV except twice where it fell well below 3700mV for a short time. So apparently the current set up is more than good enough. I’m even slightly concerned about continuously charging the LiPo battery but the MAX1555 in the Fio should take care of that.


The software is pretty straight forward. I’m using Ben Adams’ DHT22 library and Adafruit’s BMP085 library to interface the sensors. Like in the Smartmeter Pulse Counter project, I’m using Rocket Scream’s Low Power library to put the Fio to sleep. It’s a very useful one-liner to turn ADC and BOD off and put the Arduino to sleep for two seconds (SLEEP_INTERVAL constant). The every 28 (MEASURE_EVERY constant) intervals it gets a reading from the sensors. Since the reading takes 4 seconds that’s roughly one reading per minute. Every 5 (SEND_EVERY constant) measures it awakes the Xbee and sends the average for all the magnitudes.

void loop() {
    if (interval % MEASURE_EVERY == 0) {
        interval = 0;
        if (measures % SEND_EVERY == 0) {
            measures = 0;
    LowPower.powerDown(SLEEP_INTERVAL, ADC_OFF, BOD_OFF);

The data for each magnitude is stored in a structure with 4 values: maximum and minimum values, sum of all values and number of readings so far. Then, when the code is ready to send the data it subtracts the maximum and minimum values from the sum and averages over the rest of values. This way it gets rid of inconsistent readings and the final value is smoother.

The voltage readings for the solar panel and the battery al calculated based on the actual value of the resistors in each voltage divider and they are expressed as constants in the code (BATT_VOLTAGE_FACTOR and PANEL_VOLTAGE_FACTOR).

Finally, I’ve added some code from Tinker London to get the values from the interval thermometer and voltmeter of the ATmega328.

All the code, along with the Fritzing schema and the XBee configuration file is available in Github.

Boxing it

The sensor is housed in a box to prevent direct Sun exposure. It’s common to use a Stevenson Screen as a shelter for a weather station. The “professional” screens are waaaay too expensive (in the 400€ and above range). There are kits online (most notably this one) to build your own shelter or you can always build one buying the parts from the carpenter or repurposing other items. A good source to get ideas and instructions is this site aimed to schools.

I built mine from scratch. It has slats on three sides (the other is attached to the building facade) and holes on the bottom to ease the air flow inside the box. It doesn’t have double roof or chimney since I have glued the solar panel to the top with a methacrylate stand to make it perpendicular to the winter sun. The solar panel angle was a hard decision but since there is a maximum of power I can store I decided it made more sense to get the maximum from the Sun in that not-so-bright days of winter. The perpendicular of the solar panel points SSW, almost 30 degrees above the horizon, to the winter afternoon Sun…

You will have to let me not showing you any pictures of the final box… it fulfils the requirements but it’s ugly as slapping a father with a wet sock (local quote). Definitely  carpentry is not for me.

To do

It would be interesting to add some sort of power monitoring to the solar panel. Right now I only get voltage readings but most of the time the panel is in nearly open circuit mode. Being able of actually get readings for the power it is providing to the charging circuit (in mW) will provide a more accurate view of the and maybe increase the performance or under-scale the solution (maybe a smaller battery or solar panel would do the job).

I’m also planning to add an anemometer to measure wind speed and a rain gauge. The readings from these two sensors will not be very significant, since the whole building could block the rain or the wind or even create twisted flows of wind around it that will fool the sensor but it will be fun nonetheless. If the battery, backed by the solar panel, has enough juice to permanently power the Arduino (that is, not in sleep mode) I could even get readings for maximum speed of wind gusts, if not I might use a binary counter IC or two (74HC590 will be perfect) to store the counts from the anemometer and get the readings from the Arduino once a minute, avoiding the use of interrupts in the code.

Finally, the data from the sensor is public and available in

CC BY-SA 4.0 Weather Station by Tinkerman is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License.

24 thoughts on “Weather Station

  1. Kike

    Nice project and post.
    Only one thing: When you talk about the battery consumption by the sensors, you say 0.8mA where I think it should say 0.8mAh (the same in the units of the last column of the table).
    On the other hand, to measure the power that the solar panel is providing to the circuit, why not measure intensity (you are already measuring voltage) and multiply intensity with voltage? Is an idea.
    Thanks for the information dude!

    1. xose Post author

      Hi Kike

      I’m measuring current at a given moment and that’s amperes. Maybe the word “consumption” is not right since it recalls “energy” and that means, as you say, amperes times time times voltage. Anyway the magnitude I want is the instantaneous current under certain circumstances because it allows me to calculate the theoretical life time of the cell: a 800mAh LiPo cell will power a 0.8mA device for about 1000 hours (not considering temperature, current bursts, cell life cycle,…).

      As for the measuring current also. Yes. That would be a very nice addon. Will has already pointed me to a nice IC that does just that. I will git it a try.

      Thank you very much.

  2. Raj

    Would you please explain a little bit about how the data from your weather station is interfaced to web. I didn’t see anything mentioned about it in your post.

    1. xose Post author

      Hi Raj

      In a previous post about my Home Monitoring System you can read about the way I’m passing MQTT messages in my home network and how I’m publishing them to several charting online services like Xively, TempoDB, Thingspeak or Open

      If you are interested in the actual implementation of the interface with those services you can check the code at my MQTT2Cloud python daemon at Github.

  3. Sebastian

    Hi XOSE (jose ??),

    I’m trying to run your code but I can not seem to operate the xbee.
    Why you are using pin 4 to control the Xbee instead of DTR pin?

    otherwise, I think in the line 105 should be digitalWrite instead of pinMode.

    finally, I had to create a. h with struct, to compile

    Thanks for your CODE


    1. xose Post author

      Hi Sebastian,
      sorry for the delay in the answer, I guess you have already moved to some other project by now…

      PIN4 is wired to the DTR line coming from the XBee, so I am actually using it.

      You were absolutely right about the bug in the xbeeSleep method. It looks like all the sleeping code is not working and even so the station has never gone down… sunny weather here 🙂

      I guess you had to create a header file with the struct definition because you are using the Arduino IDE and, if I’m not wrong, it injects the method definitions at the beginning of the .cpp file. Since some methods have parameters of type “measure”, which is defined only later, the compiler must have complained about it…

      Thank you for your comment.


  4. Pingback: NANO | Referências do projeto S.H.AS.T.

  5. Pingback: Ciseco XRF modules & LLAP Protocol | Tinkerman

  6. Pingback: Studying the effect of MAGEEC on real software | MAGEEC

  7. Pingback: » DSTH01; Digital Temperature Humidity Sensor Module.»robrico

  8. Pingback: RFM69 WIFI Gateway | Tinkerman

  9. Pingback: Low power weather station with BME280 and Moteino - Tinkerman

  10. Matt

    Hi Xose,

    Thanks for posting this. I’m trying to put something like this together. I’d like to better understand and learn how you calculated the mA(avg) in your table above. Could you show the math for how you calculated the mA(avg) for the “warm up” state as an example? I’m sure this is pretty simple math but a description would help with the learning as well as for future projects.

    Thanks for your help and patience.
    I hope you’re doing well.

    1. Xose Pérez Post author

      Taking the warm-up phase as an example.
      When in warm-up the board uses 10mA on average. You can get that reading with a multimeter and a uCurrent.
      The warm-up takes 2000ms every time it is executed (2 seconds) and it’s done every minute (60 times per hour), that’s 2000ms/event * 60events/h = 120000ms/h (2 minutes every hour). Since there are 3600000ms per hour that’s a ratio of 0.033 (or a 3.3% of the time is in the warm-up phase).
      10mA times 0.033 is 0.33mA. That’s the average consumption of the warmup phase. If you sum the average of every phase over a same period (1h) you get the average of the full project.
      In the table you can see that the warm-up phase and the DHT22 reading is what takes the most, basically because they take very long (I think you could almost get rid of the warm-up phase). But the XBee transmitting, even thou being more expensive it’s two orders of magnitude lower since it’s fast and I’m doing it every 5 minutes.

  11. Matt

    Thanks for your help Xose,

    I think you can tell I’m a bit new at this. Can you clarify what the purpose of the A0 and A1 pins are and what they are connected to in your fritzing diagram above? Why are there two sets of resistors here?

    Thanks again!

    1. Xose Pérez Post author

      Those are for battery and solar panel monitoring. Those sets of resistors are voltage dividers to get something useful into the analog pins of the Fio.

  12. Matt

    I can’t seem to get the DHT22 working. When attempting the “Example>Serial” file, I get “Requesting Data… sync Timeout” from the serial monitor. This has to do with the case “DHT_ERROR_DATA_TIMEOUT” applying, but I don’t know what this means. Anyone have a possible explanation and possible solution?

    Thanks for the help,

    1. Xose Pérez Post author

      Double check your wiring. Also try a different DHT22, those sensors are very prone to fail.

  13. Matt

    Hello Xose.

    This is a great project and quite the learning experience. I have a couple questions I was hoping someone would be willing to chime in on.

    1. The DHT22 sensor isn’t working with either of the codes referenced on this page.

    When I upload Ben Adams’ DHT22 library I get a “sync timeout” message. What does this mean? This is what I receive in the serial monitor:

    DHT22 Library Demo
    Requesting data…Polled to quick
    Requesting data…Sync Timeout
    Requesting data…Sync Timeout
    Requesting data…Sync Timeout

    When uploading the weatherstation.ino code it does not register the DHT22 sensor either and I get 0.00 returns for temp/humidity and “nan” for dew point. Below is an example or what I receive in the serial monitor.


    I have a feeling these are related problems but I don’t know how I should go about solving them. Any thoughts or suggestions?

    2. I’m looking at the different Xbee radios and the antenna connection types ( It seems like there are four antenna connection types available (wire, pcb, u.fl, or rpsma).

    What type of antenna connector did you use to connect to your fio? Did your weather box block the transmission of the data ever? It makes sense to me that an external antenna would work better than a wire antenna that is enclosed in the box, correct? What did you use and how has it been functioning?

    Thanks in advance for your help and thanks

    1. Xose Pérez Post author

      This a pretty old project (4 years already!). There are better DHT libraries now, and better sensors that the DHT22 which is very prone to failure. Most of the times I have faces a DHT failing it ws the sensors itself (I read somewhere is has an estimated lifetime of less than 2 years!). Sometimes it’s the wiring (double check the pins and the pull up from data to VCC).
      I am not using XBees anymore (too expensive and not very flexible). But the ones I have have ceramic or PCB antennae, except for the one I used as coordinator that had an SMA connector. The devices was in an “open” wooden box with vents all over the place and I never had problems with the signal.


Leave a Reply (all comments are moderated, be patient)

This site uses Akismet to reduce spam. Learn how your comment data is processed.