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
}
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.
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)
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.
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?
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()
}
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!".
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?
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