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.


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.


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.5x1.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

"Weather Station" was first posted on 14 May 2013 by Xose Pérez on under Learning, Projects and tagged arduino fio, bmp085, dht22, humidity, lipo battery, pressure, solar panel, temperature, weather.