Known issue: long delays or blocking code kills the connection to the Cloud

Why donā€™t you try this?

1 Like

Thanks, I missed that.

What is currently best practices with regard to delays in the Loop() function?

Currently I have a loop that has a delay(1); and inside it counts up till it reaches 10 seconds.
After 10 seconds there is a process that runs which includes a delay(1000).

Iā€™m considering removing the delay(1) in an effort to get faster samples from a microphone.
Thoughts?

Hi @seanreynoldscs,

During long delays (over 1 second), the core will automatically maintain the cloud connection. If youā€™re in manual mode you can use the Spark.process() calls to opportunistically put the connection maintenance wherever you want. Weā€™ll keep improving this, but you can find more details here: http://docs.spark.io/firmware/#advanced-system-modes

Thanks,
David

Bump. This needs to be better known and, sigh, documented.

@Dave
Okay so Spark.process() gets called after every loop iteration in automatic mode.
Are there any issues with calling it TOO frequently?

If I boot up a spark device and leave loop empty, will everything work?
It just seemed like things didnā€™t behave well when i took out delay(1) at the end of my loop() function, but I might have been fooling myself?

Hi @seanreynoldscs,

Hmm, I donā€™t think there should be any issues with calling it too frequently.

I think having a delay(10000) would be much easier on the connection than 10,000 delay(1)s

Thanks,
David

@syzygy Iā€™m not aware of any combo / key to get the core to a safe point with WiFi / Cloud to reflash over the IDE. You could build your code in the IDE, download a compiled version and flash locally. You can always put the core into DFU mode using the buttons on the core.

OK - WOW - that was a response to a very old post > 1yr.

@seanreynoldscs Why donā€™t you use the millis counter? You can set a variable to the next time you want to sample the microphone.

For example -

// global variable
int _next_time_to_sample = millis();

// inside your loop
if (millis() > _next_time_to_sample) {
  // do your sample
  _next_time_to_sample += 1000;
}

This way you let the rest of the Spark process what it needs outside of your loop and you wonā€™t have to block inside of your loop.

so, wait.

should we NOT use long delays, or are long delays ok, now?

both viewpoints seem to be in this thread and neither seem to recognize that the opposite is also recommended.

as a relatively new user to the spark core, I can tell you that iā€™m very confused about a lot of technical questions I have. The community is virtually useless because, apparently, things have changed so much and thereā€™s a whole bunch of old posts that arenā€™t taken down or annotated that they contain old information. there are also a lot of old posts that contain perfectly good information, so i canā€™t base my trust level on the age of the post.

the directions on how to compile for windows, for example, donā€™t really work. there are steps missing, and there seems to be a lot of guesswork involved in getting around the omissions to a working compile.

same with this. is delay(100000) ok? should I not block in the loop() method while waiting, but only check to see if my action time has come or not? What if thereā€™s blocking work in the loop that takes 30 seconds?

gaaah!

I love these little cores I have laying around, and I canā€™t wait for the photon, but come onā€¦ someone please document something somewhere. please?

@naikrovek, using delay() in your code will not block the cloud connection as the firmware will service the cloud connection during long delays. I prefer to use millis() based passive delays that allow the rest of my code to continue and consider this better programming practice. True blocking of the user loop() code for more than 10 seconds will cause the cloud connection to drop when running AUTOMATIC or SEMI_AUTOMATIC modes are used (MANUAL mode requires the user to manage the cloud connection via Spark.process()).

There are lots of code examples in the Community you can garner from. Your frustration with ā€œoutdatedā€ topics and instructions is warranted and I have pointed out to Spark the need for search results by date or other criteria. In the meantime, donā€™t get so frustrated - ask the Community for help!

1 Like

Chill out! Weā€™re happy to answer your questions. Not chill to call the community useless and then ask for help. Weā€™re people, you know.

In general with the Core you want to avoid delay()s that are long because blocking code doesnā€™t allow the connectivity stuff to run in the background. That said, we put in a fix so less people would run into this so that when you run a delay() thatā€™s long enough, weā€™ll run the connectivity code in the background. Itā€™s still not the recommended way - counting millis() is better practice - but you can do it. The thing to avoid now is code that is actually blocking (i.e. doesnā€™t call delay() but just takes a long time to process). For instance, if you added while(1) {} in your loop, it would kill the module.

hope that helps explain why we sometimes say itā€™s ok and sometimes say itā€™s not. The Photon will be multi-threaded, so none of this will be an issue any longer.

3 Likes

Sorry, I donā€™t mean the COMMUNITY is useless, I meant the community documentation, and useless isnā€™t the correct word. I misword things when I am upset or frustrated, and I apologize.

And you may notice that the two replies I got contradict each other, so Iā€™m no better informed than I was before.

Iā€™ll just loop and wait for my time to come around rather than using long delays, I guess. It seems the better of the two approaches.

@naikrovek, actually if you read carefully, both replies basically say the same thing! :smile:

Thatā€™s true, our answers said the same thing, although they were worded differently. Basically:

  1. Itā€™s ok to use long delay()s because in recent versions of the firmware, delay() calls a background task that services the Wi-Fi moduleā€™s connection to the cloud
  2. Passive delays by counting millis() is better practice
  3. Code that blocks without calling Sparkā€™s background task (like while(1){}) will still kill the connection

Does that help clear things up?

3 Likes

very clever solution...

I would underscore that the use of blocking code like delay( ) should be avoided, even if the processors (like the cool new Photon) are background processing. There are many ways to avoid it and certainly lots of folks here that can show someone how.

@naikrovek,

Regarding the documentation, I've a friend that is a veterinarian. With all that school and practicum, she knows everything about dogs, yet she could not tell me how to get dog poop out of my carpet... I had to ask around.

Try to post the question "How might I avoid blocking code or delays in this example?" and stand back and see how much help you will get.

i know this is a bit of an old topicā€¦butā€¦
i have a spark core ( i know they are particles now but this has been sitting around for over a year and it is an older spark core, not a particle photon or whatever they are now) and just dusted it off for a project.
after some updating of my cli i was able to factory reset and get it to connect. i was able to flash code to itsuccessfully and created a few webhooks that are working ( i see the data in the log on the particle dashboard).
howeverā€¦every few minutes the core seems to disconnect from the web, reconnect and then runs for a few minutes before repeating, there is a series or flashing white, blue, green, etc, that i didnā€™t document too closely because i was working on getting the code nailed down before i looked in to this, but i got the impression that the core was rebooting, reconnect after disconnect.

i DO have a rather long delay i put in there, just so i wasnā€™t slamming my endpoint with calls while i was writing the code and trouble shooting, etc.

i flashed my core using the web ide (last night, 5/23/16) and wondering if this should still be an issue?

any updates would be appreciated.

the delay is only temporary in my code now, but was wanting to know if you think this is what is causing the issue. the timeouts seem to be happening during the delay but may have been right when the delay was ending, not sure. the delay was set to 5 minutes.

i think i set the delay something like this (which reading now is horrible but you get the idea):

int minute = 60;
int second = 1000;
int delayTime = minute * second * 5;
delay(delaytime);

thanks,
jon

@b3ko, if you post your actual code it would help. If you want to delay without killing the cloud connection, you need to implement a non-blocking delay, something like this:

unsigned long myDelay = millis() + (60*5*1000);

while (millis() < myDelay) {
  Particle.process();
  delay(10);
}

This will appear like a blocking delay (where other code is not running and loop() is not looping). However, it will be calling Particle.process() which will keep the cloud connection active. :wink:

While the suggestion to write non-blocking code is good practice in any case, I'd say this delay() should not cause the disconnect, since in default "single" threaded mode delay() calls Particle.process() every 1000ms of accumulated waiting time.
So the question is what does?
Could it be that some connection times out during that delay and will cause the issue when touching it again?
Seeing your code would help there.

1 Like

thanks,
i havenā€™t had a chance to look at this again (kids) but should have some time tonight.
i am going to do some more testing (remove the delay, remove code until i figure out what is causing the drop) and if i canā€™t figure it out i will post some code.
i will also post what i find if i figure it out. thanks to both you and @peekay123 for the info.
-jon

1 Like