Power Consumption facts with SLEEP_NETWORK_STANDY

I was searching to forum to get some information on power consumption during sleep with SLEEP_NETWORK_STANDY and stumbled over this post:

Is this really the case? How much power does the cellular module consume when SLEEP_NETWORK_STANDY is set? Is it different from normal operation? Is there a Standby mode for the uBlox module?

I am coming up to this because I have to wake up the device from sleep every 2 - 5 minutes and with using deep sleep it sometimes comes to 60s+ Reconnection-Time. Which is unfortunately not good. Are there any workarounds?

Same here when Particle Publishing every 2 mins using an Electron and the same sleep code.

If you push the data to Ubidots using their library which is what I do, then the wake-up, send data, and back to sleep times are only a few seconds. If you blink you will miss it most of the time.

Just my experience.

Yes, since the ublox module will still hold the connection while being in standby mode and can just use the still open connection instead of going through the whole time and power consuming reconnection process - hence that’s the way to go with sleep periodes less than keep alive timeout for the SIM and hence now workaround should be required.

I cannot confirm this - at least in my own case. I have been writing a small piece of code that puts the electron into deep sleep and wakes it after four minutes, reconnects to the cellular network and cloud, sends current fuel status and goes back into sleep.

After some optimisation, reconnecting and sending just takes an average of just 6 seconds! So happy with how it works now!

Here’s the code:


SYSTEM_THREAD(ENABLED);
SYSTEM_MODE(SEMI_AUTOMATIC);

FuelGauge fuel;
PMIC pmic; 

long lastPublish = 0;
long lastCurrentLimitSet = 0;

void setup() {
    
    // Set PMIC to charge at higher power
    pmic.begin();
    pmic.setChargeCurrent(0,0,1,0,0,0); //Set charging current to 1024mA (512 + 512 offset)
    pmic.setInputCurrentLimit(1500);
    
    Cellular.on();
    Cellular.connect();
    waitUntil(Cellular.ready);
    
    Particle.connect();
    waitUntil(Particle.connected);
    
    Particle.publish("B",
        "v:" + String::format("%.2f",fuel.getVCell()) +
        ",c:" + String::format("%.2f",fuel.getSoC()),
        60, PRIVATE
    );    

    // Todo: Do I have to set charging register again? 
    delay(1000);   
    System.sleep(SLEEP_MODE_DEEP, 240);
}

// loop() runs continuously
void loop() {
}

EDIT:

What I mean with “cannot confirm this” is that there is a huge difference between Deep Sleep and Network Standby:

Deep Sleep just consumes about 10% of a 2000mAh Battery during a time of 8 hours.
Network Standby almost consumes 100% in the same time - of same battery.

So Network Standby still consumes a lot of battery since uBlox is still online and holding connection. Also reconnection (after optimising code) just takes about 6 seconds in my case - so Network Standby is not an option to save battery. That’s what I found out!

You mean you checked this code with

    System.sleep(SLEEP_MODE_DEEP, 240);

and also

    System.sleep(SLEEP_MODE_DEEP, 240, SLEEP_NETWORK_STANDBY);

and you didn’t see any difference in behaviour?
I can’t quite imagine that - although I haven’t used the former version since SLEEP_NETWORK_STANDBY was first introduced and the difference was massive. Maybe some recent system enhancement has taken the edge off the bare version too.

I’d also add millis() to your publish to see the difference in reconnection time.

BTW, Particle.connect() does all the things required, so you can just drop these lines too

    Cellular.on();
    Cellular.connect();
    waitUntil(Cellular.ready);

Oh I am sorry I did send the answer way to early because I was interrupted … :smiley: See my edit above …

Ah! Ok. Will change that later on - Just not clear from the documentation so I used both and it worked!

I’d also remove the delay(1000) as this diminishes the effect of SLEEP_NETWORK_STANDBY and it’s not required on Electrons the ensure event delivery for a few system versions now.

I am experiencing a something else:

The documentation says:

From 0.6.0, the device determines that a full reinitialization isn’t needed and reuses the existing session, after validating that the local state matches what was last communicated to the cloud. Connecting to the cloud after reset or wake-up sends just a reconnect message, using 135 bytes of data.

But my Data consumption for one hour is 7,3 KiB. During one hour I am sending 12 times which make an average of about 600 bytes per wake-up. I am just curious to know where this data is coming from. I remember that a single publish with no payload will consume a total of about 60 bytes (that’s what the docs say, right?)

So 60 bytes + 135 bytes during reconnection is not 600 !? Any Idea @ScruffR

Can you post a link to that quote to see the context of that statement too?
Since I’d expect an implicit (w/o SLEEP_NETWORK_STANDBY) power down of the cellular modem will also tear down the cellular and cloud connection I’m not sure how the same session could be reused, hence the full handshake and the extra data cost (and battery too).

I’d need to do my own test in order to brush up my own experience with the devices with most recent system versions tho’

I was just quoting the official documentation - it says:

Prior to 0.6.0, when the device was reset or woken from deep sleep, the cloud connection would be fully reinitialized, which meant resending the 4400 bytes of data.

but …

From 0.6.0, the device determines that a full reinitialization isn’t needed and reuses the existing session, after validating that the local state matches what was last communicated to the cloud. Connecting to the cloud after reset or wake-up sends just a reconnect message, using 135 bytes of data. A key requirement for the device to be able to determine that the existing session can be reused is that the functions, variables and subscriptions are registered BEFORE connecting to the cloud.

so if there would be a reconnection every time the device will be waken up it would be far more than just 7,3 KiB (5x4400 bytes)

Here’s the link:

https://docs.particle.io/reference/firmware/electron/#optimizing-cellular-data-use-with-cloud-connectivity-on-the-electron

Did you have your device running a while before “measuring” the data consumption?
Otherwise with the initial 4.400B plus your 6x 195B and considering the minimal chunk size the cellular provider uses for billing, you might not be too far off your 7.3KB.

Yes I have been running it for two days now and when taking a look at it’s hourly data consumption - it’s constantly in the range of 7,3KiB / hour …

However I am currently using a third party SIM Card so this might have impact as well - I am going to replace it by using Particle SIM to see wether this has impact or not.

I can post battery voltage and SOC levels every 2 mins using a Particle SIM and the standard 2000mAh battery along with a 3w solar panel and stay online almost perpetually.

I’m using just over 1Mb per month during this test of posting every 2 mins.

I can get a fully charged battery with no solar input to run for at least 24 (maybe longer, can’t remember exact battery only run times but I know it was at least 24 hours), hours before getting down to 20%. The code then puts the Electron info deep sleep mode and wakes up every hour to see if the solar panel has charged the battery back up past 2o% before going back to the main loop of sending data. The battery at 20% is enough energy to keep it in deep sleep mode for at least 1 week while waking up every hour.

I’m sending data to Ubidots which is quicker than the Particle Publish method.

Just wanted to post this as an example that may or may not help you. It’s what I ended up with after months of testing.


SYSTEM_MODE(SEMI_AUTOMATIC);
//SYSTEM_THREAD(ENABLED);
// This #include statement was automatically added by the Particle IDE.
#include "Ubidots/Ubidots.h"

#define TOKEN "YourTokenHere"  // Put here your Ubidots TOKEN
#define DATA_SOURCE_NAME "ElectronSleepNew"

SerialLogHandler logHandler(LOG_LEVEL_ALL);  //This serial prints system process via USB incase you need to debug any problems you may be having with the system.

Ubidots ubidots(TOKEN); // A data source with particle name will be created in your Ubidots account.


int button = D0;         // Connect a Button to Pin D0 to Wake the Electron when in System Sleep mode. 
int ledPin = D7;         // LED connected to D1
int sleepInterval = 60;  // This is used below for sleep times and is equal to 60 seconds of time. 

ApplicationWatchdog wd(660000, System.reset); //This Watchdog code will reset the processor if the dog is not kicked every 11 mins which gives time for 2 modem reset's. 

void setup() {
 //Serial.begin(115200);
 pinMode(button, INPUT_PULLDOWN);  // Sets pin as input
 pinMode(ledPin, OUTPUT);          // Sets pin as output

 ubidots.setDatasourceName(DATA_SOURCE_NAME); //This name will automatically show up in Ubidots the first time you post data. 
 
 PMIC pmic; //Initalize the PMIC class so you can call the Power Management functions below. 
 pmic.setChargeCurrent(0,0,1,0,0,0); //Set charging current to 1024mA (512 + 512 offset)
 pmic.setInputVoltageLimit(4840);   //Set the lowest input voltage to 4.84 volts. This keeps my 5v solar panel from operating below 4.84 volts.  
}

void loop() {
    
FuelGauge fuel; // Initalize the Fuel Gauge so we can call the fuel gauge functions below. 
 
    
if(fuel.getSoC() > 20) // If the battery SOC is above 20% then we will turn on the modem and then send the sensor data. 
  {
   
   float value1 = fuel.getVCell();
   float value2 = fuel.getSoC();
   
  ubidots.add("Volts", value1);  // Change for your variable name
  ubidots.add("SOC", value2);    

  Cellular.connect();  // This command turns on the Cellular Modem and tells it to connect to the cellular network. 
  
   if (!waitFor(Cellular.ready, 600000)) { //If the cellular modem does not successfuly connect to the cellular network in 10 mins then go back to sleep via the sleep command below. After 5 mins of not successfuly connecting the modem will reset.  
    
    System.sleep(D0, RISING,sleepInterval * 2, SLEEP_NETWORK_STANDBY); //Put the Electron into Sleep Mode for 2 Mins + leave the Modem in Sleep Standby mode so when you wake up the modem is ready to send data vs a full reconnection process.  
    
}  
  
     ubidots.sendAll(); // Send fuel gauge data to your Ubidots account. 

     digitalWrite(ledPin, HIGH);   // Sets the LED on
     delay(250);                   // waits for a second
     digitalWrite(ledPin, LOW);    // Sets the LED off
     delay(250);                   // waits for a second
     digitalWrite(ledPin, HIGH);   // Sets the LED on
     delay(250);                   // waits for a second
     digitalWrite(ledPin, LOW);    // Sets the LED off
  
     System.sleep(D0, RISING,sleepInterval * 2, SLEEP_NETWORK_STANDBY); //Put the Electron into Sleep Mode for 2 Mins + leave the Modem in Sleep Standby mode so when you wake up the modem is ready to send data vs a full reconnection process.  
    
  }
  else //If the battery SOC is below 20% then we will flash the LED 4 times so we know. Then put the device into deep sleep for 1 hour and check SOC again. 
  {
      
  //The 6 lines of code below are needed to turn off the Modem before sleeping if your using SYSTEM_THREAD(ENABLED); with the current 0.6.0 firmware. It's a AT Command problem currently. 
  //Cellular.on();
  //delay(10000);
  //Cellular.command("AT+CPWROFF\r\n");
  //delay(2000);
  //FuelGauge().sleep();
  //delay(2000);
  
  
  digitalWrite(ledPin, HIGH);   // Sets the LED on
  delay(150);                   // Waits for a second
  digitalWrite(ledPin, LOW);    // Sets the LED off
  delay(150);                   // Waits for a second
  digitalWrite(ledPin, HIGH);   // Sets the LED on
  delay(150);                   // Waits for a second
  digitalWrite(ledPin, LOW);    // Sets the LED off
  delay(150);                   // Waits for a second
  digitalWrite(ledPin, HIGH);   // Sets the LED on
  delay(150);                   // Waits for a second
  digitalWrite(ledPin, LOW);    // Sets the LED off
  delay(150);                   // Waits for a second
  digitalWrite(ledPin, HIGH);   // Sets the LED on
  delay(150);                   // Waits for a second
  digitalWrite(ledPin, LOW);    // Sets the LED off
  
  System.sleep(SLEEP_MODE_DEEP, 3600);  //Put the Electron into Deep Sleep for 1 Hour. 
  
  }
}    

Due to parallel discussion about the same code I’ll lock this to keep things from branching too much