Close

Version Two: Stop eating batteries!

A project log for Sea Temperature Sensor using GSM

A template for battery powered sensors using GSM

mike-cochraneMike Cochrane 06/15/2015 at 09:401 Comment

After a successful first deployment it's time to work on the battery life.

I already had some ideas for how to reduce the power usage, so time to start working on them:

New Sim800l breakout board

The previous breakout board I was using was the only one I could get easily in New Zealand. It broke out pover, ground, Tx, Rx, and Reset. Turns out the Power Key pin is tied to ground forcing the module to stay power on.

After much searching I found an equally simple break out board from AND Technology on AliExpress that gives me the Power Key (PWRKEY) instead of Reset. I ordered three and handed over the extra cash to get the DHL'd (8 days) instead of snail mailed (probably a month).

A welcome surprise I got email diagrams and documentation for the break out board in perfect english. It contained one critical piece of information about the PWRKEY pin "Shorted with GND via R104 by default". So I knew I had to remove R104 so I could use the PWRKEY, guess which is the only resistor not labeled on the diagram:

So it's the unlabled one top left, by the 2.8v test point. So that got wiped off with the soldering iron and a 100R resistor from that to a I/O pin on the Teensy.
// Pull PWRKEY low
pinMode(2, OUTPUT);
digitalWrite(2, LOW);

// For at least one second
delay(1100);

// Then let it go high again
pinMode(2, INPUT);
Hibernate the Teensy

The Freescale MK20DX128VLH5 on the Teensy 3.0 has some awesome low power / hibernate modes available. Thankfully [duff2013] is more patient than I and has created an awesome Snooze library for the Teensy.

I added a watch crystal to the Teensy so I could use the RTC, not for the clock but for waking from hibernate.

So

for (int i = 0; i <= 9; i++) {
    delay(60000);
}
Changed to the way more accurate and low power

// Update Every 15 mins
#define UpdateTime 15

// Sleep
#include <Snooze.h>
SnoozeBlock config;

// Timing
elapsedMillis sinceWake;

...

void setup() {
    ...
}

void loop() {
    // Reset ms since wake up timer
    sinceWake = 0;

    ... do the useful stuff ...
    	
    // Sleep until next reading
    uint8_t sleepTime = 60 - sinceWake/1000; // number of seconds
    config.setAlarm(0, UpdateTime - 1, sleepTime); // how long to sleep for
    Snooze.deepSleep(config); // go to sleep
}

This now gave me very reliable 900 seconds between receiving readings, ever if the sim800l was a bit inconsistent with its response time.


Reduce the time things take

A lot of the code for the first version was about getting it working, so instead of waiting for an expected result from the Sim800L there was just a "wait 4 seconds". So time to get some real code in here:

/**
 * Wait for a define length of time for a 
 * particular response from the Sim800l
 */
elapsedMillis waitTime;
bool waitFor(String searchString, int waitTimeMS) {
    waitTime = 0;
    String foundText;
    while (waitTime < waitTimeMS) {
        if (!HWSERIAL.available()) {
            // Nothing in the buffer, wait a bit
            delay(5);
            continue;
        }
        
        // Get the next character in the buffer
        incomingByte = HWSERIAL.read();
        if (incomingByte == 0) {
            // Ignore NULL character
            continue;
        }
        foundText += incomingByte;
        
        if (foundText.lastIndexOf(searchString) != -1) {
            // Found the search string
            return true;
        }
    }
    
    // Timed out before finding it
    return false;
}

/**
 * Wait for "OK" from the Sim800l
 */
bool waitForOK() {
    return waitFor("\nOK\r\n", 4000);
}
Now instead of delay(4000), I've got waitForOK(). Turns out some of the responses were coming back in 23ms where I was waiting 4000!

With smart waits in place from Sim800l is now turned on for a little over 30 seconds where it was previously on for nearly 90 seconds. This saves a lot of power (the Sim800l can peak at 2A power usage).

Kill the Blinky LED

All the breakout boards have status LEDs on them, they flash at different rates depending on the status of the module. Really handy during testing, not so handy for conserving battery. So the three component top right of the board had to go too. I'm not sure how much this saves, but it seemed worth it.

That's it for power saving changes in this version. Full code is in the GitHub repo.

Discussions

Charles wrote 01/14/2016 at 17:47 point

Mike, it's really a great project! How did you managed to kill the leds? For status led there is an AT command to disable it, but for power led I couldn't find any. Or you just unsolder them?

  Are you sure? yes | no