Correctly turning off the Cellular?

I run my devices in Semi-Automatic mode + Threading. When my devices go to sleep, the following piece of code is run (based on an old post):

    Particle.connect()
    <connection attempt up to 3 minutes>
    Cellular.off();
    delay(2000);
    System.sleep(SLEEP_MODE_DEEP, sleepTime);

This normally appears to work, but in some cases a device may start to breathe blue, and it can take up to a few minutes until it finally enters Sleep. This particularly seems to happen when the Cellular was turned on previously in the code.

It was my understanding that this is the correct way of putting an Electron to sleep; any idea on what needs to change here? Is 2s not sufficient for the Cellular.off() command?

I use this, but in Manual Mode with Threading:
The Particle.disconnect() might help you ?
I’m guessing ScruffR recommended it to me.

  Particle.disconnect();
  for (uint32_t ms = millis(); millis() - ms < 1000; Particle.process());

  Cellular.off();
  for (uint32_t ms = millis(); millis() - ms < 1000; Particle.process());
 
  System.sleep(Door, FALLING, sleepTime );    

But from what I understand Particle.disconnect() is meant only to disconnect from the Cloud, not to disconnect a Cellular connection, or abort a connection attempt.

A very common situation I see with this problem is that a device will attempt a cellular connection (blink green), and after x time Cellular.off() tries to abort the attempt and put the device to sleep, after which it starts to breathe blue.

If you are OK with this 1-shot approach (wake up, try to connect, go to sleep, repeat), this works great for me. It’s Manual mode, un-related code removed. Give it a spin.

#include <Particle.h>
SYSTEM_MODE(MANUAL);
SYSTEM_THREAD(ENABLED);
int sleepTime = 4 * 3600       ;    // (# HOURS * 3600 seconds) 14,400 = 4 hours, 28800 = 8 hr, 21600 = 6hr ,
int connectionFail = 5 * 60000 ;    // (# of Minutes * 60,000 ms) Electron will Give-Up after this amount of time.

void setup()  {
}

void loop()   {
  // Wakes up Here

  Cellular.on();
  for (uint32_t ms = millis(); millis() - ms < 1000; Particle.process());
  
  Particle.connect();
  for (uint32_t ms = millis(); millis() - ms < 10000; Particle.process());

  if (waitFor(Particle.connected, connectionFail)) {  // Limit the Connection attempt      
      // do your sensor reading stuff here
      Particle.process();
      
      // Perform the Publish here, use NO_ACK flag or you may want to wait longer afterwards
        for (uint32_t ms = millis(); millis() - ms < 5000; Particle.process());
    }
 
  
  // Either the Cloud Connection was successful, or it wasn't.  It's time to go to sleep either way. 
  
  Particle.disconnect();
  for (uint32_t ms = millis(); millis() - ms < 1000; Particle.process());

  Cellular.off();
  for (uint32_t ms = millis(); millis() - ms < 1000; Particle.process());
  
  System.sleep(SLEEP_MODE_DEEP, sleepTime);  // Go to Sleep

} // End LOOP

1 Like

Your code works fine for me, but so does my own code (98% of the time). I’m just trying to wrap my head around what the real issue in my code is - it’s hard to troubleshoot as well as it happens very sporadically.

I don’t want to move to Manual mode for now (my code is much, much longer and it’d be an overkill solution) but I will add Particle.disconnect() and Cellular.disconnect() to my code and see if it improves things.

The reason I “reluctantly” moved to Manual mode was similar to your case.
I randomly had Electrons not completely going into Sleep.
This is the post were I got started down the trail. ScruffR’s comments there may help with your situation.

1 Like

With SYSTEM_THREAD(ENABLED) the impact on your code with SYSTEM_MODE(MANUAL) isn’t too breat.
While the docs mention that your code needs to explicitly call Particle.process() that’s only true if you are not running SYSTEM_THREAD(ENABLED) - AFAICT.

Since you are already running SEMI_AUTOMATIC all the necessary steps should be in place. One difference betweem SEMI_AUTOMATIC and MANUAL with SYSTEM_THREAD(ENABLED) is that some functions are non-blocking in MANUAL mode while they are (under some circumstances) in SEMI_AUTOMATIC mode.


(I see I’m repeating myself, I didn’t follow the link in @Rftop’s post before answering :blush:)

3 Likes

I generally prefer to go directly to Cellular.off(). Stepping down layer by layer (Particle.disconnect, Cellular.disconnect, Cellular.off) does not appear to have any advantage in my testing, however there very well could be cases where it is helpful that I did not test.

There are cases when Cellular.off() will breathe dark blue for a period of time before shutting off. In my experience it always eventually shuts off, but I haven’t investigated exactly what it’s doing and why it takes so long. However, it does not appears to be using much power while it’s doing it.

3 Likes

Good to know, thanks for the replies! I will just leave my devices the way they are then. If it’s a matter of a few minutes of low-power stalling without risk of remaining in that state for a prolonged period of time, it’s not too much of a worry to me.

1 Like