Electron: How to post-measurement data to Cloud for a set time period, plus save battery power?

Hi All,

I’m a newbie to the Particle community, and I need your help. :flushed:

I just got my Electron, and I’m keen to measure an analogue voltage once every ten minutes, post voltage results to Particle Cloud, and then put my Electron into deep sleep mode between measurements. That is, for my project I need to save solar + battery power, but also measure a voltage at a particular time i.e. once every ten-minutes. I’ve tried combining millis(10 * 60*1000) and System.sleep(SLEEP_MODE_DEEP,10), also polled the Particle Cloud for the time stamps too, but no success. See below for some example code. Can someone please suggest suitable code to do this? Also, does System.sleep() uses current millis? Lastly, can I use the 3G towers for accurate time stamps / event triggers? Any help would be greatly appreciated. Cheers! :grinning:

// For request time synchronisation from the Particle Cloud
#define ONE_DAY_MILLIS (24 * 60 * 60 * 1000)
unsigned long lastSync = millis();

// constants won't change. Used here to set a pin number :
const int ledPin =  7;      // the number of the LED pin 7
// Variables will change :
int ledState = LOW;             // ledState used to set the LED
// Generally, you should use "unsigned long" for variables that hold time
// The value will quickly become too large for an int to store
unsigned long previousMillis = 0;        // will store last time LED was updated
// constants won't change :
const long interval = 10 * 60 * 1000;           // interval at which to blink (milliseconds)

void setup() {
  // set the digital pin as output:
  pinMode(ledPin, OUTPUT);
}
    
void loop() {
    if (millis() - lastSync > ONE_DAY_MILLIS) {
    // Request time synchronization from the Particle Cloud
    Particle.syncTime();
    lastSync = millis();
  }
  
  // This is where I measure A0 voltage and post measurement on Particle Cloud
  Particle.publish("Voltage = ", "123.6 V"); // post analogue voltage here
  delay(5000); // Delay is to allow for FLASH OTA via 3G 
  System.sleep(SLEEP_MODE_DEEP,595); // Put Electron to sleep
    
  // Check to see if it's time to blink the LED; that is if the
  // difference between the current time and last time you blinked
  // the LED is bigger than the interval at which you want to
  // blink the LED.
  unsigned long currentMillis = millis();

  if (currentMillis - previousMillis >= interval) {
    // save the last time you blinked the LED
    previousMillis = currentMillis;

    // if the LED is off turn it on and vice-versa:
    if (ledState == LOW) {
      ledState = HIGH;
    } else {
      ledState = LOW;
    }

    // set the LED with the ledState of the variable:
    digitalWrite(ledPin, ledState);
  }
  // And repeat!
}

You should tell us what results your code gives you. Saying “no success” doesn’t help to diagnose your problem.

One obvious problem with your code is that code doesn’t run after you put the Electron into deep sleep, so nothing after you call System.sleep will ever be executed! When the device wakes up, it resets, and starts your code over form the beginning.

1 Like

This will only sleep 10sec, for 10min you'd need 600 instead.
To get a predictable, non-rolling wake time, you might want to replace constant 600 (or your 595) for the difference between Time.now() and your desired wake time.

The wake time is not retrieved via millis() as they won't be updated during sleep, but via an RTC interrupt.
The celltower time would usually only be few milli seconds better than the cloud time.
Particle.syncTime() does not need to be called that often. Every few hours would suffice, but with each wake from deep sleep in default AUTOMATIC mode, thus will be done anyhow - and millis() will be reset too.
The best time I'd say you'd get via GPS - but why the precission demand?

Thanks for the advice ScruffR. Do you have any example code that I may be able to work from? Ideally, my Electron would wake up from deep sleep every ten mins, measure A0 and then go back to sleep. Measured results would then be posted to the Particle Cloud. Thanks again for your help.

The problem with SLEEP_MODE_DEEP is the handshake which occurs for any interval, no matter how small. This doesn’t matter as much if it is a 24 hour interval. At 5-10 minutes this might get expensive.

1 Like

If this refers to the way to make the device wake at a particular time then you might want to have a look here
Have System.sleep SLEEP_MODE_DEEP wakeup at the same time everday - #7 by ScruffR

It's not exactly what you're looking for, but you should get the idea.

And for the code after deep sleep, with your code, you could just put everything into void setup() with System.sleep(SLEEP_MODE_DEEP, secsToWake); as last instruction and leave loop() empty - this way you won't forget, that deep sleep always wakes to run from the very beginning.
No variablies (unless explicitly marked retained) will carry over from one session to the next.


Update:
Just browsed over the linked thread and saw this final post by the ingenious Mat

void sleepUntil(time_t time) {
     time -= Time.local();
     System.sleep(SLEEP_MODE_DEEP, time); 
}

But reading through the thread will still be good for background and to figure how to build the time parameter :wink:

1 Like

I understand the handshake / key-exchange overhead will be significantly reduced in the next firmware release (0.5). @bdub had made mention of this but I cant find the original post.

Thanks all… I will have another hack, and post results :grinning: