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.

Hardware

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.

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.

Software

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() {
    ++interval;
    if (interval % MEASURE_EVERY == 0) {
        readAll();
        interval = 0;
        ++measures;
        if (measures % SEND_EVERY == 0) {
            sendAll();
            resetAll();
            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 Cosm.com.

11 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!

    Reply
    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.

      Reply
  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.

    Reply
    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 Sen.se.

      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.

      Reply
  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

    Regards

    Reply
    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.

      Xose

      Reply
  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

Leave a Reply