More elegant way to fractionate minutes

Hello, my first post. First project ever. Not a lot of programing background, I can read and write SQL and a tiny bit of JavaScript, pHp.

I’m using a controleverything.com NCD8Relay to building a controller to open a mechanical valve at a certain time of day, the valve is powered to open and also has to be powered to close. Rather than having the valve open at a certain point of time, I have decided that it is likely best to have it open between a certain amount of time say between 17:05 and 17:15. I also have decided that it might be best to convert the time over to a math function. 17:30 becomes 17.50

Saying this I don’t have any real programming background. So my question:

Does this make sense and is there a more elegant way to preform these functions?

unsigned long currentTime = rtc.now();
int mm = rtc.minute(currentTime);
float min_fraction = (float)mm / 60;

    void loop() {
unsigned long currentTime = rtc.now();
static unsigned long stopTime = 0;
int mm = rtc.minute(currentTime);
float min_fraction = (float)mm / 60;
float hh = rtc.hour(currentTime) + min_fraction;

if (hh >= 21.57 && hh <= 21.60) {
    relayController.turnOnRelay(6);
    Spark.publish("Relay 3", "ON, valve is open, powered on");
    delay(20000);
    relayController.turnOffRelay(6);
    Spark.publish("Relay 3", "OFF, valve is open, powered off");
}

}

Why bother with math when you’ve got built-in time functions? https://docs.particle.io/reference/firmware/photon/#time
You can use those to check if it’s within a certain range, and if so, execute the command.

I’ll try to come up with something, but (see below)
I’d rather go with the smallest unit (e.g. minute or even stick with sec) and adjust your bounds to that unit.

Meanwhile you could also check out the TimeAlarms library that would take all of that off you :wink: or provides a thorough insight in good coding practice with times.


There are plenty other ways to do it (e.g. with mktime() and the tm struct), but this should be fairly easy to understand

  // this only works for ranges NOT stretching over midnight, otherwise you need to incorporate the date too.
  int loBound = 21*3600 + 55*60;     // 21:55
  int hiBound = 22*3600              // 22:00
  int curTime = Time.now() % 86400;  // number of seconds today (drop date)
  if (loBound <= curTime && curTime <= hiBound)
    // now it is time to act

The time building could be put in a function too (e.g. makeTime(int hour, int min, int sec)) to make it a bit more readable.
This would actually be good to have as a static function in TimeClass.

2 Likes

Yes, using Unix timestamps makes evaluations easy... I did exactly that in a project of mine:

evaluate in loop()

  bool timerState = timerEvaluate();
  if (timerState != lastTimerState)
  {
    deviceState = timerState;
  }

evaluate like this:

bool timerEvaluate()  // comparing time here is easier with Unix timestamps...
{
  int on_time = tmConvert_t(Time.year(), Time.month(), Time.day(), deviceOnTime.theHour, deviceOnTime.theMinute, 0);
  int off_time = tmConvert_t(Time.year(), Time.month(), Time.day(), deviceOffTime.theHour, deviceOffTime.theMinute, 0);
  int now_time = tmConvert_t(Time.year(), Time.month(), Time.day(), Time.hour(), Time.minute(), Time.second());
  //
  if (on_time < off_time)
  {
    return (now_time > on_time && now_time < off_time);
  }
  else if (off_time < on_time)
  {
    return (now_time > on_time || now_time < off_time);
  }
  else // if both on and off are set to the same time, I'm confused... do nothing
  {
    return false;
  }

}

and makeTime:

time_t tmConvert_t(int YYYY, byte MM, byte DD, byte hh, byte mm, byte ss)
{
  struct tm t;
  t.tm_year = YYYY-1900;
  t.tm_mon = MM - 1;
  t.tm_mday = DD;
  t.tm_hour = hh;
  t.tm_min = mm;
  t.tm_sec = ss;
  t.tm_isdst = 0;
  time_t t_of_day = mktime(&t);
  return t_of_day;
}

keep your on and off times in a struct:

struct myTimer{
  int theHour, theMinute;
};

myTimer deviceOnTime = {6,30};
myTimer deviceOffTime = {18,00};

Agree!!

1 Like