Photon System.sleep() operation is troublesome

I have run into several issues with the System.sleep() function not working properly. I apologize if this has been addressed in other posts, but I did look for quite a while before creating a new one.

For example, with the following code, which should put the wifi to sleep for 10 seconds (after being powered on for 30), the Particle enters sleep mode after 30 seconds as it should (the RGB LED starts breathing white, not “flashing green” as the firmware documentation states), and never wakes up. The loop() code continues to execute as I can still see the “setupMillis” continuing to count up over a serial connection in ParticleDev, but it stays in that state indefinitely. The wifi never wakes up either.

int setupMillis;
bool boolHasSlept=0;

void setup() {
  pinMode(D7, OUTPUT);
  setupMillis = millis();
  Serial.begin(9600);
}

void loop() {

  Serial.print("Current Time: ");
  Serial.println(millis());
  Serial.println(WiFi.localIP());

  if (millis() - setupMillis > 30000 and boolHasSlept==0) {
    Serial.println("Sleeping for 10s...");
    boolHasSlept=1;
    System.sleep(10);
  }
  digitalWrite(D7, HIGH);
  delay(100);
  digitalWrite(D7, LOW);
  delay(2000);
}

Also, the following code should put the Particle into deep sleep for 10 seconds or until pin D2 goes high. This time though, the RGB LED turns off for an instant (more like 10 milliseconds), and then the loop() function appears to be executing (as indicated by the D7 LED continuing to flash), but there are no serial communications in Particle Dev anymore (the wifi does continue to ping though). Have tried with longer duration setpoints with no change in the amount of time the RGB LED “flashes” when the sleep command is executed.

int setupMillis;
bool boolHasSlept=0;

    void setup() {
      pinMode(D7, OUTPUT);
      setupMillis = millis();
      Serial.begin(9600);
    }
    
    void loop() {
    
      Serial.print("Current Time: ");
      Serial.println(millis());
      Serial.println(WiFi.localIP());
    
      if (millis() - setupMillis > 30000 and boolHasSlept==0) {
        Serial.println("Sleeping for 10s...");
        boolHasSlept=1;
        System.sleep(D2,RISING,100);
      }
      digitalWrite(D7, HIGH);
      delay(100);
      digitalWrite(D7, LOW);
      delay(2000);
    }

The third and final example is the Deep Sleep function. When this executes, the RGB LED starts flashing blue for very brief pulses (like 10 milliseconds every second) and the Particle is totally dead to the world - no code executing and need to start it in Safe Mode to re-flash it.

int setupMillis;
bool boolHasSlept=0;

void setup() {
  pinMode(D7, OUTPUT);
  setupMillis = millis();
  Serial.begin(9600);
}

void loop() {

  Serial.print("Current Time: ");
  Serial.println(millis());
  Serial.println(WiFi.localIP());

  if (millis() - setupMillis > 30000 and boolHasSlept==0) {
    Serial.println("Deeply sleeping for 10s...");
    boolHasSlept=1;
    System.sleep(SLEEP_MODE_DEEP,10);
  }
  digitalWrite(D7, HIGH);
  delay(100);
  digitalWrite(D7, LOW);
  delay(2000);
}

I’ve also had issues with the D0 and D1 pins not working when configured as discrete inputs, but that’s a topic for another day! Thanks in advance for any feedback!

Same here,

System.sleep(2) 
delay(2000);

Totally kills my WiFi connection, it even appears to kill it when the device is rebooted/power cycled (I have code that sends measurements first time around before the sleep is called).

Is there something I need to do different?

Side topic, my Photo’s WiFi is a nightmare to set-up so it’s a real pain to get it going again. Android doesn’t work, PC Serial doesn’t work and only the Laptop with manual settings can actually get the photon to accept the WiFi.

I struggled with the sleep function for awhile too, but here's some additional comments and some code that works for me:

@MrFixIt there was a bug with the old firmware where D0 and D1 would stop working that has been fixed in the latest stable

@TinamousSteve I think there was some improvements made to sleep and the connection to the cloud has been made slot more stable.

Instructions for update are here https://github.com/spark/firmware/releases/tag/0.4.3-rc2

One of the pivotal points to mention here is that (for the time being - or maybe already solved with 0.4.3 system :question: ) after wake from System.sleep() the WiFi and cloud connection won’t get reestablished automatically.
Just call WiFi.connect() or Spark.connect() explicitly like

  if (alreadyConnecting)
  {
    WiFi.connect();    // if you want WiFi only in SEMI_AUTOMATIC or MANUAL
    //Spark.connect(); // if you need cloud connection
    alreadyConnecting = true;
  }

For your serial issue there might be two reasons.
If you are on Windows when the port is kept open while your remote device disappears and reconnects Windows will not reconnect automatically. Close your connection during sleep and try to reopen after the Photon woke up.
If this is not the source of your problem, you might have to do Serial.begin(9600) afresh, just as with WiFi above.

This is exactly what I found to be the case (even after flashing to 0.4.3) - I had to explicitly tell the wifi to reconnect as @ScruffR mentioned in order to get it to come out of sleep (see modified code below). Thanks for the info! This is kind of a pain since additional logic is necessary to keep track of “disconnected” time for every sleep iteration so that it can be connected again (since the hard-coded “after 50 seconds” isn’t exactly ideal for long-term installations), but it’s possible nonetheless.

The Deep Sleep functionality does seem to be working now in f/w 0.4.3 now though, which is promising. (Thanks @Hootie81)

I did continue to have issues with the “discrete input or time” waking method though… as soon as the command executes (System.sleep(D2,RISING,10);), the breathing RGB LED turns off for about 200 ms and then comes back to a breathing state again - even though there is nothing connected to pin D2. The Photon does respond to a ping, and is connected to the cloud, but does not reconnect to serial even with “Serial.begin(9600);” in the loop routine. Not sure what else is possible to try there.

int setupMillis;
bool boolHasSlept=0;
bool boolWifiReconnected=0;

void setup() {
  pinMode(D7, OUTPUT);
  setupMillis = millis();
  Serial.begin(9600);

  Serial.println("");
  Serial.println("-------------- FRESH BOOT --------------");
}

void loop() {
  Serial.begin(9600);
  Serial.print("Time since boot and current IP address: ");
  Serial.print(millis()-setupMillis);
  Serial.print("; ");
  Serial.println(WiFi.localIP());

  if (millis() - setupMillis > 30000 and boolHasSlept==0) {
    Serial.println("Sleeping for 10s...");
    boolHasSlept=1;
    System.sleep(D2,RISING,10); //As soon as this executes, the breathing blue lights flashes off and back on (~200ms) and continues breathing again, but serial communication is lost.
    //System.sleep(10); //Does not work without the "WiFi.connect()" call being made later in the logic
    //System.sleep(SLEEP_MODE_DEEP,10); //Works now without any intervention to "wake" the Particle
  }

  if (millis() > 50000 and boolWifiReconnected==0)
  {
    Serial.println("Wifi Reconnecting");
    //WiFi.connect();  //Comment this line out to verify that the Particle does not wake up from "System.sleep" mode without it.
    boolWifiReconnected=1;
  }

  digitalWrite(D7, HIGH);
  delay(100);
  digitalWrite(D7, LOW);
  delay(2000);
}
1 Like

This should not be required, if you preset boolWiFiReconnected = 1; in setup().
You can also check for WiFi.connected().

About the premature wake, could you try if FALLING works better?
If not, try adding an external pull-down (pull-up for FALLING) resistor, in case the internal ones to not get attached automatically (as the should).
You should also set boolWiFiReconnected = 0 before you are sending the device to sleep for this mode, since variables are retained and without doing so, you'd tell the device is already reconnected.

BTW: You need to use && instead of and for boolean operations :wink:

I will test that out - thank you for the continued support!

I’m still getting used to this “wiring” language for sure, and haven’t used C/C++ in about 10 years - historically more of a VB kind of guy. Don’t laugh :smile:

I am going through a very weird problem when I am trying to connect to the cloud. My Sleep is working fine but not the connect();

When I run my code without the connect , my code works fine and sleep work 100% correctly with RISING.

Once i tried to connect to particle cloud the whole problem starts: Below is my code. PLease let me know what I am doing incorrect here:

#define Buzzer D7
#define WAKE_UP_PIN D3
#include "application.h"

SYSTEM_MODE(SEMI_AUTOMATIC);

int lastStateSwitchTime = 0;

void setup() {

        pinMode(WAKE_UP_PIN, INPUT);
        pinMode(Buzzer,OUTPUT);
                   
}

void loop()
{
       
        int sensorValue = digitalRead(WAKE_UP_PIN);

        if(sensorValue==1)
        {
                        digitalWrite(Buzzer, HIGH);
                        delay(5000);
                        digitalWrite(Buzzer, LOW);
                        Spark.connect();
                
                             
                        Spark.publish("touch", "on", 60, PRIVATE);
                        System.sleep(WAKE_UP_PIN, RISING);
        }
}

(ScruffR: I reformatted your code block - have a look how this works)

code block here

First of: Don’t double post!
I’ve removed the double post, since I had already answered here and then found the double - should I answer again or should the other stay unanswered? So don’t!


Now for my answer:

Before you’re able to publish your device has to be Spark.connected() (Spark.connect() is non-blocking in SEMI_AUTOMATIC)

It would help if you mentioned what kind of "problem starts"
I guess you’re getting a red SOS hard fault.

Possible solution to this is to add the following between connect and publish

  while(!Spark.connected())
  {
    Spark.process();
    delay(100);
  }
  Spark.process(); // one extra, just to be on the safe side

Hi !

I would like to apologize for double first here as It would have happened by mistake.

Here is my problem definition:
Whenever I am trying to wake the photon through wake up pin D3 it does not connect() or publish the events.

Here is the sequence:

1st Wake up - It shows the Breathing Cyan but does not publish
2nd wake up - It tries to connect to cloud but go to sleep in 2 seconds ( weird)
3rd Wake up – It connects and publish the event

then it works fine after then but in between again it fails after sometime.
I will try your suggestion and then I will let you know.

Thanks,
Satyen

1 Like

@MrFixIt, I'm also a MS VB(6) kind of guy, and I don't speak C/C++ too fluently. Sometimes, my biggest challenge is getting it to compile--if I can get it to compile, it'll usually work!
Anyway, just to clarify: there is a difference between && and & in C. I've been bit by this a number of times. Basically, && is a comparison operator, generally used in IF statements, etc. It doesn't care what either of the values are--it returns TRUE if both are nonzero, and FALSE otherwise. However, if you're looking to do a bit-wise AND operation, use &.
For example, you might end up bald when trying to debug code like this to mask for just the lower six bits of a variable:

myOut = dVal && 0x3F;

You'll get "true" or "false" (-1 or 0, I think), depending on whether dVal is nonzero. The proper operator to use in this case is:

myOut = dVal & 0x3F;

Oh yes, don't forget, the non-equality operator isn't <>...it's !=. Cheers!

:+1: Good sum-up of some of the stumbling points when transitioning from VB to C

That's also one that does bug me from time to time, that true is not -1 but +1 (at least in a lot of compilers and definetly on these devices).
For me -1 would make more sense, since booleans are stored in a byte and the one-complement of false (=0x00) shoule be 0xFF which would be -1 in a signed byte - but it's not.

BTW:
Just for the sake of nit-picking :wink:
&& (as other "active" boolean operators) is a boolean operator that combines two boolean operands (maybe via implicit casting) into one boolean result value, while comparison operators do compare two operands according to their own type (or the "exactest" castable type common to both) and have a boolean result.

why? does Particle's implementation of C++ not include the alternative tokens?

well, let's test it...

int a = 0;
int b = 1;

void setup()
{
  int result = -1;
  if (a and b)
  {
    result = 1;
  }
  else
  {
    result = 0;
  }
    char pushoverMessage[60] = "";
    sprintf(pushoverMessage, "the result was %s", (result? "True" : "False"));
    Spark.publish("pushover", pushoverMessage, 60, PRIVATE); // Spark WebHook!!!
}

void loop()
{
}

hey, it works!!!

2 Likes

Nice find :+1: I didn’t know that :blush:

That explaines why the original code built :wink:

@ScruffR: Wonder if we could save a couple bytes of firmware by removing alternative token support? :stuck_out_tongue:

…for those who think I’m serious, keep in mind that mnemonics and defines end up with the exact same end code. Couldn’t resist, though.

1 Like