Schedule event every day at 6 PM


#1

Hi there,

I want to schedule an event ( put high a pin ) every day at 6:00 PM

To do this I made this code:

void loop()
{
  /* Send sensors data  */
  if( (Time.minute() % 5 == 0) && (Time.second() == 0) )
  {
      readSensorBMP180();
  }
  
  /* Start Irrigation System */
  if( (Time.hour() == 18) && (Time.minute() == 14) && (Time.second() == 0) )
  {
      Particle.publish( "IrrigationSystemStatus", "started", 60, PRIVATE );
  }
  
  /* Request time synchronization from the Particle Cloud */
  if( (Time.hour() == 0) && (Time.minute() == 0) && (Time.second() == 0) )
  {
    Particle.syncTime();
  }
  
  delay(200);
}

Every thing works, but thus is the problem each evet is sent 4 times because when 18:00:00 comes, the second if is true for an entire second and with the delay of 200 ms the code inside this loop is executed 4 times.

I set 1 seconds as delay, but there is the risk that the code won’t executed.

I think to use a flag variable but I need to this a mechanism to reset this variable.

The mills function should be fine for the first IF, but to schedule an event at 6:00:00 is not a precise.

Any advice?

Thanks!


#2

First I’d not test for multiple fields when checking for a time but for the combined time - easiest would be seconds as this is what Time.local() gives you back already.
Next I would not check for equality but always for greater or equal in conjunction with a “once per day” flag, otherwise you may miss a whole day when you miss the particular second.

So I’d go with something like this

const int timeAction = 18*3600 + 14*60 + 00; // hh+mm+ss
int previousDay = 0;

void setup() {
  Time.zone(yourUTCOffset);
  ...
}
void loop() {
  if (previousDay != Time.day() &&  Time.local() % 86400 >= timeAction) {
    previousDay = Time.day();
    doWhatever();
  }
} 

Help on a time-based code
#3

Hi ScruffR,

thnaks for the example! Very usefull!

I have another two questions:

  • How to trigger an event every 5 minutes? Time.local() % 300 may be invalid is the loop delay is 200 ms. In this case I need a flag variable.

    ‘if( (Time.local() % 300) == 0 )
    {
    readSensorBMP180();
    }’

  • Is it necessary to update the system time with Particle.syncTime once a day?

    if( (Time.hour() == 0) && (Time.minute() == 0) && (Time.second() == 0) )
    {
    Particle.syncTime();
    }

Thanks for your time!


#4

Depending on your needs for precission you may want to resync once a day or once a week or month.
But whenever a new cloud connection is established an implicit resync will happen anyway.
If you decide to stick with once a day I’d just stuff it into the 18:14:00 block - that’s done once a day too.

For the 5 minute task, it’s just the same: Don’t check for equality.
And in this case you don’t just want to store the day you last performed this, but the actual time.

int previousTime = 0;

...
  if (Time.local() - previousTime >= 300) {
    previousTime = Time.local();
    previousTime -= (previousTime % 300); // optional to act on 5min boundary
    doWhatever();
  }

If you don’t care about the 5min bounds but just round about every five minutes, I’d go with the commonly used millis() timing or use a Software Timer.


#5

Thanks.

I prefer to use the unix time because I want to send data every 5 min.
And in this way I can set a loop delay equal to 1000.

Have a nice day!


#6

The best practice would be to not use any delay but have your loop() run completely free.
And the two alternatives I mentioned will allow 5 minute intervals just the same, so I don’t quite understand your argument