Putting an Electron to Sleep until a condition is met

Heelo,

I understand from the documentation that an Electron can be put to sleep for a particular amount of time or made to wake up when an event (RISING, FALLING, CHANGE edge) is detected on a particular pin. I was wondering if there was a way to wake up the Electron when a particular condition was met instead.

For example, I want to read 3 sensors and wake the electron up from deep sleep only when the sensor values exceed a set threshold. The electron should sleep when this condition is not met, but must periodically check the sensor values in the background.

Pseudo code:

void loop()
{ 
    a = analogRead(A0);
    b = analogRead(B5);
    c = digitalRead(D0);
 
   //Condition to wake up : if the sensor have values above set thresholds
    if(a > 10 && b > 20 && c){
                        //do something
    }
    else
           System.sleep(SLEEP_MODE_DEEP, 30, SLEEP_NETWORK_STANDBY);   // else sleep (for 30 seconds??) 
    }

The above code would force the electron to sleep for 30 seconds every time the wakeup condition is not met. If the sensors do exceed the thresholds during the sleep state, I will end up losing the instances and frequency of such occurrences.

Any idea if such a conditional sleep mode is possible on an Electron?

Thanks for the help. Cheers!

Posts already referred:

there are different kinds of sleep but in deep sleep, you cannot read a sensor

you can use deep sleep to power down and wake on a timer. check the values and then power up the Cellular radio.

look at the docs for sleep modes

As @BulldogLowell already pointed out not in deep sleep. But also not in Standby Sleep.
All due to the fact that there is no code running while sleeping that way.

But since you seem to be dealing with analog sensors you can factor a wake or block signal electronically.

There might be other low power - but not sleep - modes that conserve more power while still running code (e.g. reduced clock speed), but these are not incorporated in the system (yet) and may have other side effects (e.g. most time critical tasks will be off).

Thank you, @BulldogLowell.

@ScruffR Could you elaborate what you mean by this?

Also, would I end up consuming more power if I were to put my electron to sleep (deep sleep with network standby) and waking it up (to check sensor values) every 10 seconds?

I am trying to implement a system which wakes up the Electron everytime the temperature exceeds 75 F. Which means, the electron will be awake and NOT fall asleep the whole time temp is above the threshold.

Hereā€™s my code: (D0 and D7 have been connected to each other)

#include <SHT1x.h>
SYSTEM_THREAD(ENABLED);
SYSTEM_MODE(AUTOMATIC);

const int wkpin = D0;   //D0 and D7 are shorted. So I can control the wake up trigger at D0
const int trig = D7;

#define dataPin  D5 
#define clockPin D4 
SHT1x sht1x(dataPin, clockPin);

double temp_f, humidity;

void setup() {
    pinMode(wkpin, INPUT);
    pinMode(trig, OUTPUT);
    Serial.begin(9600);
}

int state = 1;

void loop() {
  temp_f = sht1x.readTemperatureF();
  humidity = sht1x.readHumidity();
  
  if((temp_f > 75)){
      digitalWrite(trig, state);
      state = !state;     //Everytime the temp exceeds 75, the state of D7, hence D0, is toggled. Else, the previous state of D0 prevails.
  } 
       
  Particle.publish("** 1 **", "before sleep");
  System.sleep(wkpin,CHANGE, SLEEP_NETWORK_STANDBY, 30);
  Serial.println("************************************");
  Particle.publish("** 2 **", "after waking up");
      
  delay(1000);
  Particle.process();
  
}

I get a periodic output every 30 seconds even if the LED (D7) indicating that the temperature has exceeded 75 turns on while the ELectron is sleeping (ie, the electron continues to sleep despite the temperature exceeding the set threshold). The sleep DOESNā€™T SEEM TO BE INTERRUPTED by the temperature.

Am I missing something?

I said

due to your previous example using analogRead(A0) which would open the direct signal translation from an analog value to a digital wake signal.
But now you are using a "smart" sensor which needs to be read by the ĀµC which requires it to be awake to actively do that and - as said before - that's not possible.

On the other hand if you want to keep the device from going to sleep, why not just put the sleep block into an else branch of your if (temp_f > 75)?

BTW, this doesn't really make sense

An implementation that wakes the device when the temperature exceeds the threshold does not mean it won't fall asleep again.
The not-falling asleep is a totally different thing than waking from sleep.
The former means *not to call the System.sleep() function while the latter implies that System.sleep() definetly was called before.

Any change in state between wake and sleep does not prevent System.sleep() to actually send the device to sleep.

1 Like

Thanks @ScruffR. This is exactly what I ended up doing shortly after I posted the question. I am getting the workflow I hoped for :slight_smile: I was going to post it as an answer so others could benefit from it..

I have one final question about Sleep-wake up. Can the frequency of wake up increase the power consumption more than the power that would otherwise be consumed if the device never fell asleep?

For example, I have a system that reads about 8 sensors and publishes a message every time there's a change in any of the sensor values. Will more power be consumed if the device was to wake up, say, every 10 seconds (in System.sleep(intPin, mode, sleepForSeconds, SLEEP_NETWORK_STANDBY); mode) and run a check for change than it would if it never went to sleep?

Thanks again..

As long as the temperature is above the threshold, the else {System.sleep()...} loop doesn't get executed. So I am able to keep the device "awake" till the temp > 75 condition is met. When that fails, the device sleeps for x seconds and picks up where it left off upon wake.

It took me some experimenting to realize that, as you rightly said, reading the values from a "smart" sensor will not happen while the device is sleeping (this is different from analogRead(A0) since that can be translated as an EDGE to trigger a wake up).

This part of the documentation confuses me:

// Turn off cellular for seconds.
// Keep application running.
// Low power usage.
System.sleep(seconds);

And then it says:

System.sleep(long seconds) does NOT stop the execution of application code (non-blocking call). Application code will continue running while the cellular module is in standby mode.

So when I use System.sleep(0); , the microcontroller goes into a sleep state while still running the application in the background and checking for an interrupt at WKP. What happens to the cellular during sleepy time? Is it turned off or on standby?

System.sleep(timeout) is some other sleep mode than System.sleep(pin, edge, timeout) just as System.sleep(SLEEP_MODE_DEEP, timeout) is some third sleep mode again.
BTW, I'd not call the first in the list "sleep mode" at all, since it only switches off the radio module and switches it back on after timeout.
And I see no use in this statement System.sleep(0). This will "sleep" the radio for 0 seconds.

This can happen but is rather unlikely. If you choose the sleep time (without SLEEP_NETWORK_STANDBY) just long enough for the remote side to cut the connection but so short that the wake happens very often, then the reconnection process might consume more energy than staying awake. But with a good choice of sleep timeout you'll definetly preserve power in comparison to staying awake all the time.

1 Like

Thanks, @ScruffR :slight_smile:

1 Like

Hello,

Bringing back up an old topic ā€“ I have a case where I want a non-blocking sleep command, and there is a condition that would need to wake the Particle from sleep (not like choosing whether it should go to sleep or not, as this thread discusses). Would a Particle.connect() call be enough?

And will the Boron show similar behaviors to this?

Thanks!

What is a "non-blocking sleep command"? :confused:

When the device sleeps (and System.sleep(timeout) is a misnomer, because it doesn't really sleep the system but only the radio module) you can't call anything in code.
If you want to turn off the radio module then do that via Cellular.off() and switch it back on whenever you want - that (IMO silly) System.sleep(timeout) should never have been called that way - something like Cellular.pause(timeout) or similar would have been much more fitting/clear IMO.

1 Like

You can follow this thread for firmware updates on gen 3 hardware.

Thank you! Actually, is there a command like Cellular.pause? Or a command that doesnā€™t force the user to have to do a full-on reconnect to the network?

What do you mean?
Do you want to reconnect or not?
How would a not "full-on" connection look like for your?

I want to have code constantly running and connect to the cellular network every 15 minutes. Iā€™m hoping that I can turn off cellular every 15 minutes and reconnect. I read that Cellular.off forces a full reconnect, while System.sleep puts cellular in standby mode, so that it takes less energy to reconnect. Thatā€™s where Iā€™m at!

I see you opened a new thread for this, so I'll lock this thread to avoid scattering replies over multiple threads.
The discussion should be continued in the new thread