Electron strange behavior with sleeping

Hi, I have a small application spending most of the time sleeping. It wakes up, does a quick gauge measurement, publishes the data, and continues sleeping while putting the network into standby. I turn on the D7 led while the Electron is awake to have a visual feedback, but I dont really understand what I see.

This is a beta Electron 2G running 0.6.0-rc2, I have a 3G version as well, but it behaves the same way. Battery was full.

Here is a short video clip what I have:

Here is some explanation:

  1. (00:01) Reset the Electron.
  2. (00:05) Connected to Cloud, published data, start sleeping. - OK
  3. (00:36) Device woke up, published data, keeps on breathing cyan… - Why?
  4. (01:37) Stopped breathing cyan. - What happened here for 1 min??? D7 led doesn’t turn on.
  5. (02:07) Device woke up, published data, start sleeping 10 sec later. - Strange
  6. (02:45) Device woke up, reconnecting to Cloud. I get device came online on Console, published data, start sleeping. - Renegotiating with the Cloud?
  7. Maybe does one more cycle, then continues from state 3, so it is reproducible.

Questions:

  1. After 00:36 why does the Electron keep on breathing cyan?
  2. What happens between 00:36 and 01:37? D7 led is off, so the Electron should be sleeping.
  3. Sometimes the Electron goes back sleeping much later ~10 seconds. Why does it need some much time?
  4. Why does it need to renegotiate with the Cloud just after such a short time? (It was running the same app before the video, so 23 mins didn’t expired.)
  5. Why is this behavior periodic?

Here is the whole code:

SYSTEM_THREAD(ENABLED);

char str[64];
FuelGauge fuel;

void setup()
{
   pinMode(D7, OUTPUT);
   digitalWrite(D7, LOW);
}

void loop()
{
    digitalWrite(D7,HIGH);
    waitUntil(Particle.connected);
    sprintf(str, "%02.2f %03.2f", fuel.getVCell(), fuel.getSoC());
    Particle.publish("data", str, 60, PRIVATE);
    digitalWrite(D7,LOW);
    
    System.sleep(D0, RISING, 30, SLEEP_NETWORK_STANDBY);
}

Let me know if you have any suggestions. Thank you.

I can confirm that my 3G Electron also behaves odd with that code.
The first few rounds before it starts doing what one would expect.

@BDub, any idea what’s up there?


Update:
Some more experiments seem to indicate that the state of connection established fully or just not quite but enough to publish (but not really - see bellow) immediately before sleep impacts the way how the device will behave after wake.
And that also reminded me of the fact that you have to allow for about 5sec for a publish to fully execute before you cut the cloud connection (e.g. via sleep()).
Since that’s not there the previous publish might “hang around” till next wake, impacting the behaviour.

That’s a theory that seems plausible for me, maybe @BDub has a better one :blush:

Till then try adding this between publish() and sleep()

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

Thank you @ScruffR for looking into it. I really appreciate it.

Yes, the 5sec delay seems to be a working workaround for this issue. The interesting things is that, whenever I saw the D7 led blink with my previous code, the publish was successful, and I could see it in the Console log. So I didn’t suspect that the publish function call wasn’t completely processed.

Is there a flag indicating that the publish() finished completely? Hopefully, there is a way to make it a bit more efficient.
What is the reason for calling Particle.process() for 5sec, instead of using a simple delay()? At first glance the delay() also seems to do the trick.

I'm currently in contact with Brett and he's confirmed that in 0.6.0-rc.2 already is a fix that takes care of finishing pending publishes (and other unfinished UDP actions). So that's not an issue anymore.
But the observed periodicity of the funky blinks suggests to me that there might still be some systematic cause which needs further investigation (what he's already on to).

delay(5000) only calls the background thread 5 times (once per sec - in non-SYSTEM_THREAD(ENABLED) mode) while my code calls it about 5000 times giving it a lot more chance to finish other pending actions too.

Also OTA flashing can get flaky with long delay()s, but my code is "OTA-friendly"

2 Likes

I did some testing on this yesterday and confirmed there is something odd happening that’s unexpected here. I created an issue in github here if you’d like to follow along or contribute to the solution :smile:

2 Likes

@Bdub @ScruffR I have seen this happen many times with a sleeping Electron that I have been testing where it would not go back to sleep after publishing data to Ubidots.

It would work just fine for days and then it would just not go back to sleep and stay breating cyan until the battery died.

Here is the code I was using on the Electron. I’m not worried about the token, use it if you want and it should publish fine. :

    // This #include statement was automatically added by the Particle IDE.
    #include "Ubidots/Ubidots.h"
    
    #define TOKEN "TGiZfnCx9eWGlLCySOiVi7kc3SeAeD"  // Put here your Ubidots TOKEN
    
    Ubidots ubidots(TOKEN); // A data source with particle name will be created in your Ubidots account
    
    int button = D0; 
    int ledPin = D7;              // LED connected to D1
    int sleepInterval = 60;
    
    
    void setup(){
        pinMode(button, INPUT_PULLDOWN);    // sets pin as input
        pinMode(ledPin, OUTPUT);    // sets pin as output
        //Serial.begin(115200);
        ubidots.setDatasourceName("PinWakeTestCode2"); // Uncomment this line to change the data source Name.
        
    }
    
    void loop(){
        
        FuelGauge fuel;
        
        float value1 = fuel.getVCell();
        float value2 = fuel.getSoC();
       
        ubidots.add("Volts", value1);  // Change for your variable name
        ubidots.add("SOC", value2);
        ubidots.sendAll();
        
      digitalWrite(ledPin, HIGH);   // sets the LED on
      delay(500);                  // waits for a second
      digitalWrite(ledPin, LOW);    // sets the LED off
      delay(500);                  // waits for a second
      digitalWrite(ledPin, HIGH);   // sets the LED on
      delay(500);                  // waits for a second
      digitalWrite(ledPin, LOW);    // sets the LED off
      delay(500);                  // waits for a second
      digitalWrite(ledPin, HIGH);   // sets the LED on
      delay(500);                  // waits for a second
      digitalWrite(ledPin, LOW);    // sets the LED off
      delay(500);                  // waits for a second
    
      
      System.sleep(D0, RISING, sleepInterval * 60, SLEEP_NETWORK_STANDBY);
        
    }

@RWB after briefly looking at that code I have a suspicion. I don’t like to point fingers, but my hunch is that there may be a busy wait loop in the ubidots library that could get stuck forever if the electron is not able to send data for a moment. The electron should recover, but it’s unclear what the library may do.

You also might want to add waitUntil(Particle.connected); at the beginning of your loop, since you are going to sleep and then waking up again.

Also it looks like you are sleeping for 1 hour. This is most likely the catalyst of being disconnected. After 1 hour of sleeping, the PDP context may not be active anymore. In fact it should be deactivated ahead of time if you know you’re going to sleep for more than 23 minutes. After sleeping for 23 minutes though, the network connection will timeout between the server to device path. I would recommend not using SLEEP_NETWORK_STANDBY in this case to turn the modem off while you sleep for 1 hour. And the waitUntil(Particle.connected); will then be critical to include.

2 Likes

Thank you @BDub for confirming and escalating this issue.

@aguspg @Metavix Hey, Guys!

I have been trying to use my Electron along with some solar panels to do some testing with charging directly from some 5v solar panels.

I’m attempting to use some code from that past where I was successfully pushing the Electrons Voltage and SOC readings to Ubidots to graph out over time but this now always causes the Electron to hang and never got back to sleep after it wakes up.

I know you guys have updated your library lately and added UDP communication for lowering Electron data usage which is good. I wanted to reach out and see if you guys could look at my code that used to work and see if maybe there is a reason why it now causes the Electron never to go back to sleep.

The 2nd post above this is from Bdub thinking it maybe something in the SendAll function in your library causing this but I added the "waitUnti(Particle.connected); before the SendAll function but it did not make any difference, and the Electron would still hang rather quickly.

Here is the code:

    // This #include statement was automatically added by the Particle IDE.
    #include "Ubidots/Ubidots.h"
    
    #define TOKEN "TGiZfnCx9eWGlLCySOiVi7kc3SeAeD"  // Put here your Ubidots TOKEN
    
    Ubidots ubidots(TOKEN); // A data source with particle name will be created in your Ubidots account
    
    int button = D0; 
    int ledPin = D7;              // LED connected to D1
    int sleepInterval = 60;
    
    
    void setup(){
        pinMode(button, INPUT_PULLDOWN);    // sets pin as input
        pinMode(ledPin, OUTPUT);    // sets pin as output
        //Serial.begin(115200);
        ubidots.setDatasourceName("PinWakeTestCode2"); // Uncomment this line to change the data source Name.
        
    }
    
    void loop(){
        
        FuelGauge fuel;
        
        float value1 = fuel.getVCell();
        float value2 = fuel.getSoC();
       
        ubidots.add("Volts", value1);  // Change for your variable name
        ubidots.add("SOC", value2);
        ubidots.sendAll();
        
      digitalWrite(ledPin, HIGH);   // sets the LED on
      delay(500);                  // waits for a second
      digitalWrite(ledPin, LOW);    // sets the LED off
      delay(500);                  // waits for a second
      digitalWrite(ledPin, HIGH);   // sets the LED on
      delay(500);                  // waits for a second
      digitalWrite(ledPin, LOW);    // sets the LED off
      delay(500);                  // waits for a second
      digitalWrite(ledPin, HIGH);   // sets the LED on
      delay(500);                  // waits for a second
      digitalWrite(ledPin, LOW);    // sets the LED off
      delay(500);                  // waits for a second
    
      
      System.sleep(D0, RISING, sleepInterval * 2, SLEEP_NETWORK_STANDBY);
        
    }
1 Like

@RWB, you might want to add which version of system firmware and Ubidots library you tested with :wink:

@peekay123 First I tried this on Electron Firmware 0.5.3 and then I upgraded to 0.6.2-rc.2

It felt like the code would hang quicker on the 0.6.2-rc.2 firmware for some reason. The Electron would go to sleep only a couple times before waking up and then never going back to sleep, even if I put the wait.Particle connected before attempting to call the send all function.

Then I removed the sleep code and just send data every two mins, but it would stop sending data after only a couple successful attempts.

I think the old code is conflicting with the new library they have uploaded somehow. I’ll just wait for a recommended example using UDP from them before I spend to much time trying to dig into the library code.

@RWB, did you test with threading enabled?

No but I will try that and report back.

1 Like

@peekay123 I tried adding the Threading Enabled to the code and it didn’t keep the code from hanging eventually with a breathing cyan LED instead of going back to sleep.

I use the UDP example from their latest library and when it works the Wake > Publish > Sleep code works super quick but it also eventually hangs. I’ve tried adding wait until particle connected and different variations of that but always eventually the code hangs and never goes back to sleep.

I do not see any Particle Wait being used in the code for the Send.All function so now sure what’s going on.

I’ve just switched back to sending data to Azure which still hangs before going to sleep for 5-30 seconds for some reason but it always does goes to sleep.

    char Org[] = "My_ORGANIZATION";
    char Disp[] = "Particle Photon";
    char Locn[] = "Fishers, IN";
    
    int button = D0; 
    int ledPin = D7;              // LED connected to D1
    int sleepInterval = 60;
    
    void setup()
    
    {
    
     //Serial.begin(9600);
     pinMode(button, INPUT_PULLDOWN);    // sets pin as input
     pinMode(ledPin, OUTPUT);    // sets pin as output
    	
      delay(1000);
    }
    
    void loop()
    
    {
      
     
     
     // Measure Relative Humidity from the HTU21D or Si7021
     float h = 50.0;
    
     // Measure Temperature from the HTU21D or Si7021
     float f = 100.5;
     // Temperature is measured every time RH is requested.
     // It is faster, therefore, to read it from previous RH
     // measurement with getTemp() instead with readTemp()
    
     char payload[255]; 
    
     if (waitFor(Particle.connected, 60000)) {
            
     snprintf(payload, sizeof(payload), "{ \"s\":\"wthr\", \"u\":\"F\",\"l\":\"%s\",\"m\":\"Temperature\",\"o\":\"%s\",\"v\": %f,\"d\":\"%s\" }", Locn, Org, f, Disp);
     //Serial.println(payload);
     Spark.publish("AzureElectron", payload, NO_ACK);   //The NO_ACK is currently only working with RC 0.6.0 rc1 firmware. This is just a test. For Electron
     //Particle.publish("ConnectTheDots", payload); 
     //Particle.publish("GoogleCloudTest", payload); 
     
    
     snprintf(payload, sizeof(payload), "{ \"s\":\"wthr\", \"u\":\"%%\",\"l\":\"%s\",\"m\":\"Humidity\",\"o\":\"%s\",\"v\": %f,\"d\":\"%s\" }", Locn, Org, h, Disp);
    //Serial.println(payload);
     Spark.publish("AzureElectron", payload, NO_ACK);   //The NO_ACK is currently only working with RC 0.6.0 rc1 firmware. This is just a test. For Electron
     //Particle.publish("ConnectTheDots", payload);
     //Particle.publish("GoogleCloudTest", payload);
     
      digitalWrite(ledPin, HIGH);   // sets the LED on
      delay(250);                  // waits for a second
      digitalWrite(ledPin, LOW);    // sets the LED off
      delay(250);                  // waits for a second
      digitalWrite(ledPin, HIGH);   // sets the LED on
      delay(250);                  // waits for a second
      digitalWrite(ledPin, LOW);    // sets the LED off
      delay(250);  
      
      
      }
    
    
      
      System.sleep(D0, RISING,sleepInterval * 2, SLEEP_NETWORK_STANDBY);
     
    
    }

@RWB, I can’t vouch for the Ubidots issue but I wonder if doing a two Particle.publish() burst is causing the delays you are seeing before sleep. I am going to look at the Ubidots stuff to see if I can replicate the error.

@peekay123 When sending 2 Particle Publish events to Azure using the code above your post the Electron will most of the time wake up, send both publish events back to back, flash the LED and then go right to sleep.

Then sometimes it will stay breathing cyan after the LED flashing indicating both Particle publish events have happened. Sometimes it will breath cyan for up to like 30 seconds before going back to sleep.

I’ll add a 5-second delay between publishers and see if it makes a difference.

@RWB, the point is that the publish limit is one per second. The cloud may impose a delay if you do two back-to-back even though there is an allowable burst of 4 in one second. I’ll have to check with @Dave.

@peekay123 I did put a 5-second delay between publish events, but I’m still seeing cases of prolonged cyan led breathing after the led flashing indicating both publish events have happened.

Not sure what it could be waiting on before sleeping but it doesn’t happen every time. It always does end up going to sleep though. :grinning: