Time functions without internet

Hi everyone.
I´m trying to solve an issue with my code and surely I´m missing somenthing because I cannot see
the problem.

I wrote a simple piece of code that measure a sensor every 10 seconds using:

 if(Time.second() == 0)  {...}
 if(Time.second() == 10)  {...}

and so on.
I’m adding safeguards to save locally the readings if no internet available.
The data is sent via Particle.Publish every hour. With internet everything goes great.

From the documentation I learned that once the handshake is done the time is keeped
locally. But when I cut internet, something (not my code) tries to re-connect and gets
a timeout.
I added some Serial.Print sentences in each measurement entry and this is what I get with internet:

Reading 00 sec
Reading 10 sec
Reading 20 sec
Reading 30 sec
Reading 40 sec
Reading 50 sec
Reading 00 sec

and so on. Without internet:

Reading 00 sec
Reading 30 sec
Reading 00 sec
Reading 30 sec
Reading 00 sec
Reading 30 sec

I tried with SYSTEM.MODE(MANUAL) as well without any change. I’m puzzled since I not
using any internet function in my code (except when 1 hour pass)…

Any help is appreciated.
Thank you!

@gavpret, firstly I need to point out the % modulo operator which could be used to simplify your 10 second logic:

if (Time.second() % 10 ==0) {...}

As for the “without internet” results, posting your code might help us better advise you.

1 Like

Thank you, @peekay123 for your reply.
A quick made sample code to reproduce the issue:
Please try with and without internet.

SYSTEM_MODE(MANUAL);

STARTUP(WiFi.selectAntenna(ANT_EXTERNAL));

void setup() {
}

void loop() {

  Particle.connect();
  waitUntil(Particle.connected);
  RGB.control(true);

  while (true)  {

    if(Time.second() == 0)  {
      RGB.color(255, 0, 0);
      RGB.brightness(255);
      delay(2000);
      RGB.brightness(0);
    }

    if(Time.second() == 10)  {
      RGB.color(0, 255, 0);
      RGB.brightness(255);
      delay(2000);
      RGB.brightness(0);
    }

    if(Time.second() == 20)  {
      RGB.color(0, 0, 255);
      RGB.brightness(255);
      delay(2000);
      RGB.brightness(0);
    }

    if(Time.second() == 30)  {
      RGB.color(255, 255, 0);
      RGB.brightness(255);
      delay(2000);
      RGB.brightness(0);
    }

    if(Time.second() == 40)  {
      RGB.color(0, 255, 255);
      RGB.brightness(255);
      delay(2000);
      RGB.brightness(0);
    }

    if(Time.second() == 50)  {
      RGB.color(255, 255, 255);
      RGB.brightness(255);
      delay(2000);
      RGB.brightness(0);
    }

  }
}

You should remove that while(true) and use loop() as it is intended.
And I guess your problem comes from the combination of equality checks and delay(2000).
If you have a delay stretch across the one second that fits your pattern, you’ll miss that branch.

BTW, when you got Particle.connect() you need the internet since you explicitly told the system it should communicate with the cloud and it will atempt to follow that order - regardless of SYSTEM_MODE(MANUAL)

Hi @ScruffR.
The code works perfectly with internet. Otherwise the delay routine takes lot more of time.
I’m presume that the system routines are trying to re connect, but I don’t know why since
I’m running in manual mode.

Is easy to see if you run the code above.

Seen my update?
You instructed the system to stay connected.

And just because a code is running doesn’t mean it’s running good.

1 Like

Well…even in MANUAL_MODE the system will try to reconnect and timeout forever?
How I suppose to run time critical code with that kind of behavior?

SYSTEM_MODE(MANUAL);

STARTUP(WiFi.selectAntenna(ANT_EXTERNAL));

unsigned long ledoffdelay;
bool ledoff = false;

void setup() {
  Particle.connect();
  waitUntil(Particle.connected);
  RGB.control(true);
}

void loop() {

    if(Time.second() % 10 == 0)  {
      RGB.color(255, 0, 0);
      RGB.brightness(255);
      ledoff = true;
      ledoffdelay = millis();
    }

    if (ledoff) {
      if (millis() - ledoffdelay >= 2000) {
            RGB.brightness(0);
            ledoff = false;
      }
    }
}

First, note that I removed the while(1) which prevents loop() from ending in order to allow the system firmware housekeeping to run. Adding SYSTEM_THREAD(ENABLED); at the top of the file would allow the system and user code to run in their own threads.

This code is “non blocking” allowing loop() to complete without delay. The ledoff added code creates the 2 second (2000ms) delay before the led is turned off. Incorporate this in your code and let me know how it goes. Do you have any other blocking delays in your loop()?

3 Likes

By checking you connection and not telling the system to stay connected without network e.g. via if (!WiFi.ready()) WiFi.off()
You can also use SYSTEM_THREAD(ENABLED) to decouple your app from the system tasks (as mentioned by @peekay123)

BTW, I'd slightly alter @peekay123's code

    if(Time.second() % 10 == 0 && !ledoff)  {
      RGB.color(255, 0, 0);
      RGB.brightness(255);
      ledoff = true;
      ledoffdelay = millis();
    }

to have that block only fire once in that 10th second

Thank you @peekay123 for your detailed explanation.
Is great to have some authorized help. Honestly most of the code that I use
in Particle is the result of experimentation since I had issues that I cannot figure out how to
solve.

I’m not using `SYSTEM_THREAD(ENABLED) and adding a 2 seconds delay only to prevent this:
OTA systematically crashes Photon - Easy to reproduce

What I trying to archieve with my code is the following:
A sensor is read every 10 seconds
The value is accumulated in one variable
Every hour, the accumulated value is divided by the number of reads effectively done
A webhook is hit with the resultant data

When sending the data to the webhook, if Particle.Publish() timeout, the system enter in
offline mode. It tries to reconnect, but it keeps reading and saving the data.
If still in emergency mode when a new hours begins, it saves the data to a local array
after checking if are memory available. If not if rotates the array and delete old values.
When the system connects again it dumps the array to the webhook.

Thank you @ScruffR for your help.
In my case I should do something like:

Wifi.on()
Particle.connect() and wait until connected
Particle.Publish()
Particle.disconnect()
Wifi.off()

Is OK to do this to hit a webhook?
No problem to have it disconnected from the cloud lot of time?

Thank you!

@gavpret, the while(1) code was killing the OTA and adding the 2 second delay allowed the system firmware to run a bit.

There are plenty of topics on all the things you want to do, including code. @ScruffR has great code for reconnecting wifi when a connection is lost. Do a Google search on “arduino circular buffer” which is exactly the type of buffer you need for storing offline data. There are also plenty of topics on running without a cloud connection.

That would be the way to do it.
And that’s also the scenario where System.updatesPending() would need to kick in to keep the connection open till a pending OTA update has been pulled in completely.