20161009_021036s

Low power weather station with BME280 and Moteino

A few weeks ago I wrote about my new door monitor. It was the first step towards migrating my XBee based wireless sensors network to RFM69 radios using Moteino platform by LowPowerLab. I was truly impressed by the low power consumption so I committed myself to keep on working with them.

Coincidentally Felix Russo, the guy behind LowPowerLab, released the new version of it’s Weather Shield for Moteino. So it was time to update (or completely revamp) my trusty Arduino FIO based weather station… and last week I received a parcel from LowPowerLab with a pair of shields to play with: the new WeatherShield R2 and the PowerShield R3. They are both compatible with the Moteino (off course).

Moteino PowerShield and WeatherShield

From left to right: PowerShield R3, Moteino and the new WeatherShield R2

WeatherShield R2 for Moteino

20161008_151733s

The Moteino WeatherShield R2 uses the new Bosch BME280 sensor, the heir of the BMP085, BMP180 and BMP183 dynasty. It provides temperature, humidity and pressure measurement in a very small package, with improved accuracy and really fast acquisition times. It’s that tiny silver square on the bottom left of the picture above. But, if the sensor is so small: what do you need the rest of the shield for?

Well, you basically have a solder jumper for the on-board pull-ups for the I2C buses (they are connected by default), a voltage divider to monitor battery status on pin A7 (also with a solder jumper connected by default) and a SI7021 footprint as a cheaper alternative (USD 3-3.5 against the USD11 of the BME280 when bought in units). The rest of the board is a prototyping zone for your own addons.

You may have noticed an angled resistor in the pic above. Originally Felix designed the board to use a mosfet to “enable” the battery reading feature hence saving some microamps. But on the final board it has been removed and bypassed with a 27Ohm resistor (the angled one). The pads are still there so anyone can add the mosfet and the resistors to A3. Bad news is that this voltage divider actually evaporates a few mW…

Code for this project is released as free open software and can be checked out at my Moteino Weather Station repository on Bitbucket.

Good night Moteino, sleep tight

I like to start programming with a minimum working program and add features on top of it. So the first sketch I uploaded to the Moteino was just initializing the radio and sleep it immediately and then do the same with the controller using RocketScream LowPower library.

I then grabbed my multimeter and the uCurrent Gold and checked the consumption: 1.9mA. What? I was expecting something around the 15uA. There was something wrong. Mind that I didn’t have anything plugged to the board yet. There was only the ATmega, the RFM69 radio and the SPI Flash IC… wait!

OK, it’s not the first time that this happens to me so I better write it down so I don’t forget next time:

Put the flash IC to sleep too!!

I then added this code to the initialization routine:

if (flash.initialize()) {
    flash.sleep();
}

And read my multimeter again: 14.3uA. Much better!

Setting the BME280 to sleep

Next I moved to the WeatherShield. I had no experience with the BME280 sensor but it’s specs looked awesome. I relied on the PlatformIO library manager to check for available libraries:

$ pio lib search BME280
Found 3 libraries:

[ ID  ] Name             Compatibility         "Authors": Description
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
[ 901 ] BME280           arduino, atmelavr, atmelsam, espressif8266, intel_arc32, microchippic32, nordicnrf51, teensy, timsp430 "Tyler Glenn": Provides a library for reading and interpreting Bosch BME280 environmental sensor data over I2C.
[ 166 ] Adafruit BME280 Library arduino, atmelavr     "Adafruit Industries": Arduino library for BME280 humidity and pressure sensors
[ 684 ] SparkFun BME280  arduino, atmelavr, atmelsam, espressif8266, intel_arc32, microchippic32, nordicnrf51, teensy, timsp430 "Marshall Taylor, SparkFun Electronics": A library to drive the Bosch BME280 Altimeter and Pressure sensor

I had pretty good experiences with Adafruit’s libraries in the past so I installed it first. Loaded the sample sketch and it worked right away without modifications. Good. I then merged the sketch to my original one and checked power consumption again with controller, radio and flash in sleep mode: 714uA. Well, it’s not bad but I expected something better. The BME280 can work down to 100nA so there was room for improvement here.

Reading the BME280 datasheet I found out that the sensor has 3 working modes: sleep, forced and normal. In “sleep” mode the sensor does not perform any measurements but the registers are available for reading. In “forced” mode the sensor is forced to perform one reading and then goes back to sleep. And in “normal” mode the sensor performs a reading and then stays in stand by for a certain amount of time before reading again.

It looked like I needed to set my sensor in “forced” mode to control when I wanted it to wake, read the temperature, pressure and humidity, store the values in it’s registers and go back to sleep. But the Adafruit library does not provide a method to do that, neither the one by Tyler Glenn. But, even thou the SparkFun library doesn’t let you change the mode in-the-fly either, it does expose a method to write to the IC registers directly. So I can do what I want without having to modify a third party library:

void bmeForceRead() {

    // We set the sensor in "forced mode" to force a reading.
    // After the reading the sensor will go back to sleep mode.
    uint8_t value = bme.readRegister(BME280_CTRL_MEAS_REG);
    value = (value & 0xFC) + 0x01;
    bme.writeRegister(BME280_CTRL_MEAS_REG, value);

    // Measurement Time (as per BME280 datasheet section 9.1)
    // T_max(ms) = 1.25
    //  + (2.3 * T_oversampling)
    //  + (2.3 * P_oversampling + 0.575)
    //  + (2.4 * H_oversampling + 0.575)
    //  ~ 9.3ms for current settings
    delay(10);

}

So I just had to call my bmeForceRead method before reading the sensor registers. It sets the sensor in forced mode and waits for the readings to take effect. Timing is calculated based on BME280 datasheet.

Grabbed my uCurrent and multimeter and… 242uA! Good! But it can be better…

Modifying the WeatherShield

So back to the first section in this post I was talking about the missing mosfet and the voltage divider. Do you know how much current flows through a 14k7 voltage divider at 3.3V? Around 224uA.

Grabbed the solder iron and removed the 27Ohm resistor in the WeatherShield (the angled one). And since I was not going to use the battery monitor circuit in the shield I cut the solder jumper left to the A7 silkscreen label.

And now…. 13.9uA!! Bingo! Mind that I’m close to the uCurrent error level so 2-3 uA up or down don’t really mean anything.

Modified Moteino WeatherShield

The Moteino WeatherShield R2 without the angled resistor. The solder jumper to A7 has been cut as well

Next I plugged my DSO Nano as I had done with the Door Monitor and captured some screenshots with sending power patterns.

The DSO Nano connected to the uCurrent Gold monitoring power consumption while sending packets

The DSO Nano connected to the uCurrent Gold monitoring power consumption while sending packets

Capture from the DSO Nano

A sample capture. There is a delay at the beginning when the sensor is reading. Then you can see 3 packets, the second and third ones with a repeat 40ms after the first try.

Adding the PowerShield

Last I added the Moteino PowerShield R3 and a small LiPo I had around. The Moteino Sandwich is ready. I also took some measurements with the whole set in sleep mode and it threw 12.2uA. Amazing. I expected a higher value due to the powershield boosting the ~4V of the LiPo to 5V to power the Moteino throught the VIN pin but I guess error in the measures is even higher than that.

Moteino Sandwich

Moteino Sandwich: add a PowerShield, a WeatherShield, a Moteino and spice it all with a cute small LiPo

Weather Station power measurement

12.2uA!

I have to say I’m a bit confused about the PowerShield. It’s something in between a LiPo charger and a power supply but it’s neither of both. It provides a way to monitor battery voltage through a voltage divider tied to A7 (again). This time thou the resistors are quite heavier and the power drainage is negligible. But it lacks options for power harvesting. I would like to connect a solar panel for instance. I think that’s something I’ll try to add at some point since my previous weather station had one and has been working flawlessly for 4 years…

Some maths to end with

I like maths.

So very roughly:

Stage mA ms/event events/5minute mA*ms/5minute
Reading data 8 12 1 96
Sending burst 60 4 3 720
Waiting ACK 23 40 3 2760
Blinking LED 8 5 1 40
Rest of the 5 minutes 0.014 300000-12-4*3-40*3-5 ~4200
Total over 5 minutes ~7814

That’s 26uA average (7814mA*ms/5minute / 5 / 60000 ms/minute). The little 100mAh LiPo battery would last 5 months!! Add a bulkier 3000mAh and you can forget about it for years. And these numbers are really conservative: ATC would lower burst spikes as the radio adjust the transmitting power to match the expected RSSI and ACK should come faster…

Now I have my new weather station side by side with the old one. Getting to know each other for some days while I think about the solar panel or maybe a couple more sensors and a proper enclosure…

Code for this project is released as free open software and can be checked out at my Moteino Weather Station repository on Bitbucket.

CC BY-SA 4.0 Low power weather station with BME280 and Moteino by Tinkerman is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License.

10 thoughts on “Low power weather station with BME280 and Moteino

  1. Stevo

    I work on similar project with BME280 and memory display powered by solar cell and super-capacitors. I use forced mode too, but only ONE in initialization. Now I see, why I have same data on LCD every time. I did not read the datasheet before in detail. Thanks for forceRead function explaination.

    Reply
      1. Stevo

        Hi.
        Actually not now, but connection is simply: small solar cell (6-9V) and low drop 5V LDO to charge 2 small and parallel 4,7F/2,5V capacitor. Than 3V3 low drop LDO to power arduino mini (without internal LDO and power led), SHARP memory display and BME280. Every minute processor measure data and write to LCD and going to sleep. Power consumption in power sleep is les than 10uA. Now actualy works some months without problems. Somtimes if was a week without more sunny days cappacitors lost power and dont work (winter time). If You want to see some pictire wtite mi a mail and I send You some =).

        Reply
  2. Jrbenito

    Hi Xose,

    Thanks for sharing. I am revamping my very old weather station to wireless transmit data to inside home and will base my project on this shield and your path.

    BR

    Reply
  3. sdfdsfsdfds

    Why not use the power board’s ability to power off a AA, drop in a NiMH cell, and an appropriately sized solar panel with minimal components?

    Reply
    1. Xose Pérez Post author

      It has been a while… My understanding of how it works (according to the datasheet) is that once you perform a reading in Force Mode it returns to sleep mode, so if you want to do another reading you have to set the sensor in force mode again, that’s what my bcmForceRead method does.

      Reply

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