Argon- System Mode Manual- Infrequent publishes

I am using Argon in a solar powered application. Using System Mode MANUAL. It enables WiFi periodically, do one publish and disable it. If I publish every 10 minutes, it works fine. If I increase the time to say 60 minutes, Particle publishes do not go through. Following is the section of relevant code. Is there any way around it?

void loop() {
  if (publish_count==PUBLISH_INTERVAL){
    WiFi.on();
    WiFi.connect(); 
    i=0;
    while(i< (30000/BLINK_INTERVAL) && !WiFi.ready()) { // total 30 seconds timeout waiting for Wifi connect
      Particle.process();
      i++;
    } 
    Particle.connect();
    i=0;
    while(i< (30000/BLINK_INTERVAL) && !Particle.connected()){ // total 30 seconds timeout waiting for Particle connect
      Particle.process();
      i++;
    }
    delay(100); //additional wait for safety 
    succ =Particle.connected();
    //waitFor(Particle.connected,1000);
    if (succ)  Particle.publish(eventName,mystring1);
    delay(1000); // wait for all active publishes to complete
    Particle.disconnect();
    WiFi.disconnect();
    WiFi.off();  
    publish_count=0;
  } 
  publish_count++;
  delay(2000);
}

Without seeing your definitions, setup() or knowing your os version - I would try changing the Particle.publish() statement:

You might try using the following and examine the bool result:

if (succ) {
  bool pubSuccess;
  pubSuccess = Particle.publish(eventName, myString1, PRIVATE, WITH_ACK);
  if (! pubSuccess) {
    // get here if event publish did not work
  }
  delay(5000);   // increase the delay a bit
}

Here is a docs reference:
https://docs.particle.io/reference/device-os/firmware/argon/#particle-publish-

Thanks Rob. Will add code to retry if the first publish fails.

There seems to be something unique about MANUAL mode where if the interval > 10minutes, the success rate drops drastically and consistently.

I’m sorry. I wasn’t being clear in my last post. This if statement:

is where you would find out, immediately, the publish failed - not retry. A Particle.publish() statement should just work. Without seeing your actual code we can only guess what is truly going on. I understand, though, if you can’t post it.

Take a look at this modified Particle.publish() statement from your original post:

The last parameter, WITH_ACK, might help you get a successful result. Also, a longer delay() statement following your publish statement before your Particle.disconnect() might help. Right now I am cringing from this last bit of advice (make a blocking statement LONGER??!!). Let me explain, each delay(1000) statement will invoke only one call to Particle.process(). So, offer 4 more of these invoked calls before disconnection with each delay increase of 1000ms. Better yet, instead, do what you have been doing earlier in your code: finish with a while loop allowing a boat load of Particle.process() statements before disconnecting. Replace this line:

with this new but similar while loop.

This may give the system plenty of time, in background, to do all the necessary housekeeping before killing the connection. I hope this is helpful to you. :wink:

1 Like

Instead of all these while() loops you should rather use the dedicated functions waitFor() and waitUntil().

Also your i < (30000/BLINK_INTERVAL) check will not give you 30 seconds but an arbitrary time as the runtime for Particle.process() is non-deterministic. You will call it 30000 times and however long each individual call will take will be your timeout.
Particularly on cellular devices the process time will be considerably more than on WiFi devices.

The same applies to your publish_count “timing” scheme.

If you want some timed stuff use the time based tools (millis(), micros() and the Time object) :wink:

If you want a delay with maximum cloud performance while waiting you can use this

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

BTW, you are checking for WiFi.ready() but still carry on with the rest of your logic even if that would time and consequently all subsequent steps will be futile - not best practice IMO.

3 Likes

Thanks @robc for your detailed comments.

Just to clarify, every delay() implicitly calls the Particle.process()? Also, how often do I need to call Particle_process() in the MANUAL mode to have a reliable connection?

Thanks @ScruffRfor your comments.

  • if using waitFor() with a timeout, does it ensure that the Particle.process() is called periodically while it’s waiting?
  • For millis(): Do I need to take into account the millis overflow/wrap-around when calculating time difference? Is there any example code?

@sunder

Yes

No, that is handled by the DeviceOS

2 Likes

No. In general terms, a delay() statement will invoke Particle.process() when a background cumulative counter of delay ms = 1000ms. Example: with no previous delay() statements called - If I call delay(800) four times, by the end of that sequence Particle.process() will have been invoked twice.

Quite often. For starters, I would modify your code from

to

  publish_count++;
  delay(2000);
  Particle.process();   //  New line  -  last statement within loop()
}
1 Like

Oops! That is not right, sorry. The answer to the above should be three calls of Particle.process(). Another example: If I call delay(800) six times, by the end of that sequence Particle.process() will have been invoked four times. Oye, I thought about what I posted earlier and thought, “that can’t be right!”.

As stated above I’d rather use this

  for(uint32_t _ms = millis(); millis() - _ms < 2000; Particle.process());

for a 2 second delay when maximum cloud performance is wanted.

1 Like

I am still a bit confused what happens when millis() overflows and goes to 0. From reference:

when millis() is 2 seconds short of 0xfffff…and 2 seconds later overflows (or wraps around) to 0, the for loop above will be stuck for ever? How is this handled by the DeviceOS?

Nope, it won’t.

As long you use unsigned long for all your calculations nothing bad will happen.
When you happen to subtract a bigger number from a smaller number (which would result in a negative value normally) with unsigned datatypes the result would require more bits than you have but what fits into the given bits is still the correct difference :wink:

Binary arithmetic is something worth looking into :sunglasses:

2 Likes

In addition, check this tutorial out:

1 Like

Thank you! I should’ve paid more attention during the unsigned binary arithmetic class :wink: