Trouble reconnecting after spark.sleep(SLEEP_MODE_DEEP, time)

I’m working on a project that needs to wake up and take a measurement every 15 minutes, then go back to sleep to conserve power. The problem I have run into is that after a few times sleeping, the core will fail to reconnect on wakeup. On startup it will go from the starting cyan into a few red flashes, then rapidly flashing cyan that goes on forever. sometimes it will also blink green a few times before going into rapid cyan. This happens seemingly no matter what code I use. It even happens with this simple program.

void setup() {}

void loop() {
 while(millis()<20000){}

Spark.sleep(SLEEP_MODE_DEEP,20);     
}

I’ve read through a lot of other topics, especially concerning the blinking cyan LED, but none of them have fixes that I found that I could apply when using the spark.sleep function, or they are old and firmware probably fixed all the issues. I can’t be doing a hard reset every 5-1- minutes when it fails.

If anyone knows what I’m doing wrong here or what fix I could possibly implement, I’d really like to get this resolved.

Is this a Particle Core?

If so, then your while() does prevent the Core from doing its cloud-keeping which has to be done at least once every 10sec.

Try this instead

  while (millis() < 20000)
    SPARK_WLAN_Loop();

Would if() statements or a long setup also prevent it from cloud-keeping because the actual program I’m using doesn’t use a while loop?

It depends on your code. If any of your code is running for a prolonged period of time and does not call SPARK_WLAN_Loop() or Spark.process() the cloud-keeping gets messed up, which will result in several reconnection attempts and finally in red flashes.

For this particular issue you could have a look into SYSTEM_MODE(SEMI_AUTOMATIC) and SYSTEM_MODE(MANUAL) which give you more control over the cloud activity.

But if you tried my suggested workaround, do you still get the original sleep issue?

I don’t get the same issue with the simple program using that workaround. Now I’m wondering what it is in my bigger program that is causing the issue. Again, the problem occurs before it even jumps into the loop for me so that is partly why I question if it has anything to do with code in my loop.

I’ll have to revise that last statement. The core had an issue just 8 minutes in and got disconnected using the workaround.

Disconnects as such are don’t neccessarily mean there is something wrong, they may occure any time - not neccessarily in connection with sleep.
But does it show the red flashing again?

If you are doing a lot of wake-reconnect-sleep cycles in a short period of time, your WiFi router might run out of DHCP addresses to hand out.
To confirm or confute this theory you could write a little sketch that just publishes its IP address.
If it changes, your router might eventually run out of new ones to hand out. Then you could try to increase the IP range for your subnet on your router and see if the time before it fails changes.
If the IP stays the same, your router recoginizes the returning device and this was not the cause of your problem.


I’ve tested my own Core with this sketch and it does do what it should for at least 15 min.

IPAddress ip;
char szIP[16];

uint32_t ms;
void setup()
{
}

void loop()
{
    SPARK_WLAN_Loop();
    ms = millis();
    
    ip = WiFi.localIP();    
    sprintf(szIP, "%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]);    
    Spark.publish("SleepTest", szIP);
    
    while(millis() - ms < 10000)
        SPARK_WLAN_Loop();

    Spark.sleep(SLEEP_MODE_DEEP, 5);
}

My router keeps handing out two different IPs alternately. Obviously it only holds on to an IP for about half a minute before it gets reused.

It looks like my core is getting issued the same IP address each time it reboots so that isn’t the problem. Just running that program it failed on the 8th reboot. I’m wondering if this isn’t a problem with my access point. I’ll try another network point and see if that works.

Trying a different network is a good way to pin down some issues.

Maybe there is a setting in your AP to lock out “misbehaving” clients. If a device keeps comming and going too often/quickly, your AP might consider it harmful and lock it out for safety reasons.
Just try out if it always/mostly is after the 8th attempt (with longer absence after a fail, to let the AP calm down ;-))

I tried the above code with my local WiFi and my Android phone as AP - both worked fine.

Tried it with another AP and had the same issue. I looked through the admin settings for the router but couldn’t find anything that would kick off a device.

Interestingly I tried a program implementing spark.sleep without deep sleep mode and the re-connection works fine for an indefinite amount of time. I’m not sure if this makes a difference or gives insight into what ay be causing the issue. From what I’ve read, spark.sleep just cuts off wi-fi and then reconnects on wakeup, so if it were a wifi issue it should be happening in either mode correct?

One thing I just remembered doing ages ago was to update the bootloader.
There was a thread about wake on pin where this came up as a possible solution - I can’t remember where this was, but maybe @Dave or @kennethlimcp can.

I’ll look for it or one of them geniouses can remember it :wink:

1 Like

Ok, I’m not quite sure how to do the update for bootloader if that could give the fix.

Have a read through this thread :wink:

Here is something I found in the thread that seems to have worked for me:

" I think you need this code after your sleep code but only when STOP is done:"

  /* Enable HSE, PLL and select PLL as system clock source after wake-up from STOP */
    
  /* Enable HSE */
  RCC_HSEConfig(RCC_HSE_ON);

  /* Wait till HSE is ready */
  if(RCC_WaitForHSEStartUp() != SUCCESS)
  {
    /* If HSE startup fails try to recover by system reset */
    NVIC_SystemReset();
  }

  /* Enable PLL */
  RCC_PLLCmd(ENABLE);

  /* Wait till PLL is ready */
  while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);

  /* Select PLL as system clock source */
  RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);

  /* Wait till PLL is used as system clock source */
  while(RCC_GetSYSCLKSource() != 0x08);
}

I’m not sure exactly what it does but I though I’d give it a try. Now, whenever my core has a problem reconnecting it just retries until it gets it instead of looping the flashing cyan.

If you understand what’s going on or have any explanation that would be great because I hate to have too much code that I don’t understand.

@mwbrady, when the STM32 goes into STOP mode, it shuts off some of the key system clocks in order to reduce power consumption. The code above restarts those clocks so the user code and continue correctly after a STOP mode sleep. :smile:

Awesome. Any reason why the deep sleep mode may have been working a few times then stopped? It seems like if there is something causing a problem that needs to be reset, then it should cause the problem every time deep sleep mode is called, not a few cycles in.

@mwbrady, I have not looked deep into topic and have not played with sleep modes in a while. This is definitely on my radar, especially with the Photon. All this to say I don’t really have an answer right now :flushed:

No problem. At least I have the problem fixed so it’s not a major concern for me anymore. I’ll be tinkering with the photon here soon also so hopefully I’ll have less issues there.

2 Likes