Timing while asleep

Hey all,
I’m still very new to coding and would love some help with a project I’m working on.

I’m making an automatic timer that tracks how long a switch is flipped and publishes that to the cloud. Its battery operated so I’m trying to maximize battery life whenever possible.

My thought is to wakeup when the switch is on and pulls D1 low, get the current time, and go back to sleep (all without ever connecting to the internet)
Then, when the switch is off (pullup brings D1 high), I’d wake up again, get the current time, see the difference, connect to the internet, publish the total time, and return to sleep.

A few questions based on this.

  1. Is this a smart approach? Is there a better approach?
  2. Does Time.now() require a cloud connection? If yes, is there a regular timer I can start and end instead that will still run while the particle is asleep?
  3. Does this code make sense for what I’ve described?
  4. This will be run on an electron. Does that change anything? (no wi-fi where its running)
    Thanks so much, and looking forward to your help.
    Best,
    Brett
SYSTEM_MODE(SEMI_AUTOMATIC);


int sensor=D1;
int startTime=0;
int endTime=0;
int totalTime=0;
void setup() {
    
pinMode(D1, INPUT_PULLUP);

}

void loop() {
    if ( digitalRead(sensor)==LOW)
    {
        startTime=Time.now();
        System.sleep(D1, CHANGE);
        
    }
    else {
        endTime=Time.now();
        totalTime=endTime-startTime;
        
        Spark.connect();
        Spark.publish("totalTime", String(totalTime), 60, PRIVATE);
        delay(10000);
       System.sleep(D1, CHANGE);
    }
}

I’d keep track of the prevous button state and you should apply an external pull resistor since AFAIK System.sleep() tends to override your pinMode() setting the mode to INPUT on CHANGE trigger.
Your time variables should be unsigned int.

And nowadays Spark.xxx() functions would actually be called Particle.xxx() :wink:

You might also want a waitUntil(Particle.connected); before your publish and a Particle.disconnect() before System.sleep().

Hey ScuffR,
Thanks so much. I’ll give this a shot when I’m back home tonight and keep you posted.

Hey ScruffR,
I gave it a shot and I’m getting closer, but still not 100% there. Any thoughts would be awesome.
For some reason the electron seems to wake up and try connecting to cellular rather than waiting until it hits particle.connect.
Things I’ve done:

  • Moved to a 220 ohm pull up resistor (I know this is a low value but I figure that will only help not hurt while debugging)
  • switched spark.xxx to particle.xxx
  • added waitUntil() and Particle.disconnect

Things I haven’t yet done (but wouldn’t think are causing this particular issue?):

  • keeping track of the button state
    Partly because I wasn’t certain a smart way to do it and partly because I work on this outside of my actual job and didn’t have a ton of time to work today.

Code:

    SYSTEM_MODE(SEMI_AUTOMATIC);


int sensor=D1;
unsigned int startTime=0;
unsigned int endTime=0;
unsigned int totalTime=0;
void setup() {

pinMode(D1, INPUT_PULLUP);
pinMode(D7, OUTPUT);

}

void loop() {
if ( digitalRead(sensor)==LOW)
{
    startTime=Time.now();
    digitalWrite(D7, HIGH);
    delay(500);
    digitalWrite(D7, LOW);
    System.sleep(D1, CHANGE);
    
}
else {
    endTime=Time.now();
    totalTime=endTime-startTime;
     digitalWrite(D7, HIGH);
    delay(500);
    digitalWrite(D7, LOW); 
    delay(500);
    digitalWrite(D7, HIGH);
    delay(500);
    digitalWrite(D7, LOW);
Particle.connect();

   waitUntil(Particle.connected);
   delay(2000);
    Particle.publish("totalTime", String(totalTime), 60, PRIVATE);

     digitalWrite(D7, HIGH);
    delay(200);
    digitalWrite(D7, LOW); 
    delay(200);
    digitalWrite(D7, HIGH);
    delay(200);
    digitalWrite(D7, LOW);
    delay(200);
    digitalWrite(D7, HIGH);
    delay(200);
    digitalWrite(D7, LOW);
     delay(20000);

    Particle.disconnect();
    waitUntil(Particle.disconnected);
   System.sleep(D1, CHANGE);
}
}

I also threw in a few blink patterns so I could figure out where the electron was in running the code at any moment which is what the random high low delays are. I’m assuming there’s a smarter/more conventional way to do this but I don’t know it so this seemed to works.

Thanks again for all your help, I really appreciate it.
-Brett

If you don’t want the cellular connection to be established after wake, you’d need to use Cellular.disconnect() before going to sleep.
But it would actually be better to stay connected to the cell towers while asleep, since each reconnect will consume up to 6K of your monthly data allowence.

So instead of disconnecting and reconnecting on wake, use this instead

  System.sleep(D1, CHANGE, SLEEP_NETWORK_STANDBY);

This keeps the cell connection open for up to 23 minutes and will hence be much quicker to start running your code. But if you sleep longer than 23 minutes you will still see the data consumption. So you might want to wake on timeout as well to keep the connection alive.

Another thing to get going faster is SYSTEM_THREAD(ENABLED)

Hey ScruffR,
Really delayed reply but wanted to thank you for the help. took me a bit longer than expected but I got everything up and running from a code perspective (for now at least!) Now I’m onto fun with hardware and batteries
Thanks again,
Brett

2 Likes