Sodaq One Power Consumption Deep Sleep

I am developing GPS tracker using the Sodaq One Version 3 Board. It requires the board to deep sleep for 1 hour, then take a GPS reading, and finally send the GPS coordinates via LoRa to a receiving Sodaq One receiving node in the field.

I tried using the Sodaq One “Low Power Sketch” without success.
https://learn.sodaq.com/Boards/One/Examples/low_power/

Then I came across a good example in the Sodaq Forum (just scroll down almost to the bottom of the forum to see example code posted by RogerRobbit. The code is actually for the Sodaq One Version 2.
Sodaq One Power Consumption

In the posting the author claims that the current draw is 30 microAmps (or 0.03mA). I ran this script and I can only get down to 0.4mA. This is actually enough for my application and should give approximately 1 year of life in the field using 19,000mAh battery SAFT or TADIRAN. I measure the current draw using a 3.7V LiIon battery connected to the Sodaq One (no serial connection) and connect a multimeter in series to measure current draw.

I then added the GPS code. The GPS code is from the example code provide at the URL.
GPS code example

The code seems to run fine. Initially I noted that the current draw during sleep was 0.4mA.

However after 20-30 cycles the current draw then goes up during sleep to 4.0mA. I don’t understand why?

I’ll post all of the code. Would appreciate any help. Thanks in advance.
Regards
Edmond

NB. Include and define statement have hash and greater and less than symbols removed to help with formatting.

The code below simply cycles through a sleep cycle approx 1 minute long, and also takes GPS readings between each sleep cycle.

include “Arduino.h”
include Sodaq_RN2483.h
include RTCZero.h
include Sodaq_UBlox_GPS.h

define MySerial SERIAL_PORT_MONITOR
define ARRAY_DIM(arr) (sizeof(arr) / sizeof(arr[0]))

RTCZero zerortc;

void initSleep()
{
// tell the LoRa-Module to sleep!
Serial1.begin(LoRaBee.getDefaultBaudRate());
Serial1.println(“sys sleep 60000”);
//Serial1.println(“sys sleep 30000”); // original code
delay(200);

// Set the sleep mode
SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
}

// do nothing just wake up
void alarmMatch(void){
MySerial.println(“alarmMatch”);
}

void resetAlarm(void) {
MySerial.println(“reset alarm function”);
// hours, minutes, seconds
zerortc.setTime(0, 0, 0);
// day, month, year
zerortc.setDate(1, 1, 1);

// alarmHours, alarmMinutes, alarmSeconds
zerortc.setAlarmTime(0, 1, 6);
//zerortc.setAlarmTime(0, 0, 36); // original code
zerortc.enableAlarm(zerortc.MATCH_HHMMSS);

MySerial.println(“RTC”);
MySerial.print(zerortc.getHours());
MySerial.print(":");
MySerial.print(zerortc.getMinutes());
MySerial.print(":");
MySerial.print(zerortc.getSeconds());

MySerial.println();
}

void setup() {
pinMode(GPS_ENABLE, OUTPUT);
digitalWrite(GPS_ENABLE, HIGH); // low=poweredoff, high=poweredon
sodaq_gps.init(GPS_ENABLE);

// inspired by…
// Sodaq One power consumption
MySerial.begin(57600);
pinMode(ENABLE_PIN_IO, OUTPUT);
digitalWrite(ENABLE_PIN_IO, HIGH);

// RGB LED:
initalizeLEDs();
lightBlueLED();
MySerial.println(“Start 10 second delay”);
delay(10000);

zerortc.begin(); // Set up clocks and such
resetAlarm(); // Set alarm
zerortc.attachInterrupt(alarmMatch); // Set up a handler for the alarm
MySerial.println(“Alarm interrupt set”);
delay(100);
lightNoLED();
}

void loop() {
lightRedLED();
//digitalWrite(GPS_ENABLE, HIGH); // code commented out - did not work
//sodaq_gps.init(GPS_ENABLE); // code commented out - did not work

delay(1000);
find_fix();
// lose GPS if code below enabled
//digitalWrite(GPS_ENABLE, LOW); // code commented out - did not work

delay(1000);
MySerial.println(“About to init sleep”);
initSleep();
MySerial.println(“call deep sleep”);
delay(100);
lightNoLED();
// call deep sleep and wait for interrupt which is never occurs
__WFI();

delay(200);
MySerial.println(“reset alarm”);
resetAlarm(); // Reset alarm before returning to sleep
MySerial.println(“end of loop”);
}

void find_fix()
{
MySerial.println(“Finding Fix”);
uint32_t start = millis();
//uint32_t timeout = 900L * 1000; // original
uint32_t timeout = 30L * 1000; // 30 second timeout
MySerial.println(String(“waiting for fix …, timeout=”) + timeout + String(“ms”));
if (sodaq_gps.scan(false, timeout)) {
MySerial.println(String(" time to find fix: “) + (millis() - start) + String(“ms”));
MySerial.println(String(” datetime = “) + sodaq_gps.getDateTimeString());
MySerial.println(String(” lat = “) + String(sodaq_gps.getLat(), 7));
MySerial.println(String(” lon = “) + String(sodaq_gps.getLon(), 7));
MySerial.println(String(” num sats = ") + String(sodaq_gps.getNumberOfSatellites()));
} else {
MySerial.println(“No Fix”);
}
}

void lightRedLED() {
digitalWrite(LED_RED, LOW);
digitalWrite(LED_GREEN, HIGH);
digitalWrite(LED_BLUE, HIGH);
}

void lightGreenLED() {
digitalWrite(LED_RED, HIGH);
digitalWrite(LED_GREEN, LOW);
digitalWrite(LED_BLUE, HIGH);
}

void lightBlueLED() {
digitalWrite(LED_RED, HIGH);
digitalWrite(LED_GREEN, HIGH);
digitalWrite(LED_BLUE, LOW);
}

void lightNoLED() {
digitalWrite(LED_RED, HIGH);
digitalWrite(LED_GREEN, HIGH);
digitalWrite(LED_BLUE, HIGH);
}

void initalizeLEDs()
{
pinMode(LED_RED, OUTPUT);
pinMode(LED_GREEN, OUTPUT);
pinMode(LED_BLUE, OUTPUT);
}

Have you had a look at the Universal Tracker?
It might be a better starting point for your application:

Hi Gabriel,

yes I did have a look at the Universal Tracker. It looks like a great product and will be easy to configure - however because I teach school students its important that I can teach coding, not just use an existing product.

I’ll try to copy some methods from the Universal Tracker and try them to see if they reduce energy consumption during sleep.

Regards

Edmond