Why is the code in this if block executed?

I want my photon to enter sleep mode during the evening. I also want the photon to stay awake for at least two hours after I have pushed the reset button. I have created a boolean function for evaluating if the current time is in between the go-to-sleep and wakeup time (which is different on thursdays than on other days) and a boolean function that evaluates if it has been more than 2 hours since setup ran.
In the main loop I use an if to check if these two booleans are true, and then put the photon to sleep until wakeup time.
I have however not yet gotten this to work, mainly because the main if block in loop always evaluates to true. So sleep automatically enables even though the twoHoursSinceStartup function should not evaluate to true. What am I doing wrong?

//When in sleep mode, reactivate by pressing the reset button, in which case it will stay on for at least two hours

unsigned long resetTime;

//Sleeping times, immediately correcting for notation in Unix Time instead of my own GMT+1 timezone:
int sleepingHourUsual = 22 - 1;                 //o'clock in the evening
int sleepingHourFriday = 4 - 1;                 //o'clock on fridaymorning. This is Thursday's sleepcycle starting on friday, currently only works for am
int wakingHourUsual = 9 - 1;



void setup() {
    resetTime = millis();
    
}


void loop() {
    if (sleepingTime(Time.weekday()) && twoHoursSinceStartup) { 
        if (Time.hour() > wakingHourUsual)      //if sleeping starts at pm
        {                                     
            System.sleep(((wakingHourUsual + (24 - Time.hour())) * 3600));
        } 
        else                                    //if sleeping starts at am
        {                                      
            System.sleep(((wakingHourUsual - Time.hour()) * 3600));
        }
        

    }
    digitalWrite(D7,HIGH);
    delay(1000);
    digitalWrite(D7,LOW);
    delay(1000);
}

bool twoHoursSinceStartup() {
    bool twoHoursPassed = ((millis() - resetTime) >= 7200000);
    return twoHoursPassed;
}


//returns if photon should sleep based on the weekday and current hour. Different sleep cycle for Thursday night/Friday morning
bool sleepingTime(int weekday) {
    bool sleepDuringCurrentHour;
    if (!(weekday == (5 || 6)))  {         //if not Thursday or Friday. This works for both pm and am as starting sleeptime
    
        //if time(am) inbetween am sleepstart and am sleepend || if time(pm) inbetween pm sleepstart and am sleepend || if time(am) inbetween pm sleepstart and am sleepend 
        sleepDuringCurrentHour = (Time.hour() < wakingHourUsual && Time.hour() >= sleepingHourUsual) ||
        (Time.hour() >= sleepingHourUsual  && sleepingHourUsual > wakingHourUsual) ||
        (Time.hour() < wakingHourUsual && sleepingHourUsual > wakingHourUsual);    
    
    } else if (weekday == 5) {          //if Thursday.
        
        //if time(am) inbetween am sleepstart and am sleepend || if time(pm) inbetween pm sleepstart and am sleepend || if time(am) inbetween pm sleepstart and am sleepend
        sleepDuringCurrentHour = (Time.hour() < wakingHourUsual && Time.hour() >= sleepingHourUsual) ||
        (Time.hour() < wakingHourUsual && sleepingHourUsual > wakingHourUsual);
        
    } else if (weekday == 6) {           //if Friday, since thursdays sleep cycle is started on fridaymorning. This works for am as starting sleeptime
    
        //if time(am) inbetween am sleepstart and am sleepend || if time(pm) after friday pm sleepstart
        sleepDuringCurrentHour = (Time.hour() < wakingHourUsual && Time.hour() >= sleepingHourFriday) ||
        (Time.hour() >= sleepingHourUsual && sleepingHourUsual > wakingHourUsual);

    }
    return sleepDuringCurrentHour;
}

@Nedervino

I built a class to create daily timers. you can enter StartTime and StopTime and use member functions to determine if the timer is active or if you cross a boundary… an example for you to try:

#include "StateTimer.h"

StateTimer dailyTimer, thursdayTimer;

int timerState = 0;

void setup()
{
  Time.zone(1);
  Particle.variable("timerState", timerState);
  dailyTimer.begin(23,0,0,4,0,0); //starts 23:00:00 ends 04:00:00
  thursdayTimer.begin(18,0,0,4,0,0);  //starts 18:00:00 ends 04:00:00
}

void loop()
{
  int thisDay = Time.weekday();
  if (thisDay == 5)
  {
    if(thursdayTimer.timerON())  //timerON() returns true when current time crosses start time boundry
    {
      //Sleep
    }
  }
  else
  {
    if(dailyTimer.timerON())
    {
      //Sleep
    }
  }
  timerState = ((thisDay == 5 && thursdayTimer.isActive()) || (thisDay != 5 && dailyTimer.isActive()))? 1 : 0;  //isActive() returns true when time is between startTime and StopTime
}

header:

#ifndef StateTimer_h
#define StateTimer_h

#include "application.h"

class StateTimer{

  public:

    StateTimer() {};
    StateTimer(uint8_t onHour, uint8_t onMinute, uint8_t onSecond, uint8_t offHour, uint8_t offMinute, uint8_t offSecond);

    void
      begin(void),
      begin(uint8_t onHour, uint8_t onMinute, uint8_t onSecond, uint8_t offHour, uint8_t offMinute, uint8_t offSecond),
      setStartTime(uint8_t onHour, uint8_t onMinute = 0, uint8_t onSecond = 0),
      setStopTime(uint8_t offHour, uint8_t offMinute = 0, uint8_t offSecond = 0);

    bool
      timerON(void),
      timerOFF(void),
      isActive(void),
      isActive(uint32_t nowTime),
      isInactive(void),
      isInactive(uint32_t nowTime);

    uint32_t
      getLocalEpoch(void),
      getStartTime(void),
      getStopTime(void);

  private:

    uint8_t
      _onHour,
      _onMinute,
      _onSecond,
      _offHour,
      _offMinute,
      _offSecond;

    uint32_t
      _startTime,
      _stopTime,
      _lastTime;

    bool
      _oldState = false;

    time_t
      _tmConvert_t(uint16_t YYYY, uint8_t MM, uint8_t DD, uint8_t hh, uint8_t mm, uint8_t ss);

    uint32_t _getTime(void);
};

#endif

implementation:


#include "StateTimer.h"


StateTimer::StateTimer(uint8_t onHour = 23, uint8_t onMinute = 59, uint8_t onSecond = 59, uint8_t offHour = 0, uint8_t offMinute = 0, uint8_t offSecond = 0)
{
  _startTime = _tmConvert_t(Time.year(), Time.month(), Time.day(), onHour, onMinute, onSecond);
  _stopTime = _tmConvert_t(Time.year(), Time.month(), Time.day(), offHour, offMinute, offSecond);
}

void StateTimer::begin(void)
{
  this-> begin(0,0,0,0,0,0);
}

void StateTimer::begin(uint8_t onHour, uint8_t onMinute, uint8_t onSecond, uint8_t offHour, uint8_t offMinute, uint8_t offSecond)
{
  _startTime = _tmConvert_t(Time.year(), Time.month(), Time.day(), onHour, onMinute, onSecond);
  _stopTime = _tmConvert_t(Time.year(), Time.month(), Time.day(), offHour, offMinute, offSecond);
}

bool StateTimer::timerON(void)
{
  bool newState = this-> isActive();
  if(newState == true && _oldState == false)
  {
    _oldState = true;
    return true;
  }
  else
  {
    return false;
  }
}

bool StateTimer::timerOFF(void)
{
  bool newState = this-> isActive();
  if(newState == false && _oldState == true)
  {
    _oldState = false;
    return true;
  }
  else
  {
    return false;
  }
}

bool StateTimer::isActive(void)
{
  return this-> isActive(this-> _getTime());
}

bool StateTimer::isActive(uint32_t nowTime)
{
  _lastTime = nowTime;
  if (_startTime < _stopTime)
  {
    return (_startTime < nowTime && nowTime < _stopTime);
  }
  else if (_startTime > _stopTime)
  {
    return (nowTime > _startTime || nowTime < _stopTime);
  }
  else
  {
    return false;
  }
}

bool StateTimer::isInactive(void)
{
  return ~ (this-> isActive());
}

bool StateTimer::isInactive(uint32_t nowTime)
{
  return ~ (this-> isActive(nowTime));
}

void StateTimer::setStartTime(uint8_t onHour, uint8_t onMinute, uint8_t onSecond)
{
  _startTime = _tmConvert_t(Time.year(), Time.month(), Time.day(), onHour, onMinute, onSecond);
}

void StateTimer::setStopTime(uint8_t offHour, uint8_t offMinute, uint8_t offSecond)
{
  _stopTime = _tmConvert_t(Time.year(), Time.month(), Time.day(), offHour, offMinute, offSecond);
}

time_t  StateTimer::_tmConvert_t(uint16_t YYYY, uint8_t MM, uint8_t DD, uint8_t hh, uint8_t mm, uint8_t 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;
}

uint32_t StateTimer::_getTime(void)
{
  return this-> _tmConvert_t(Time.year(), Time.month(), Time.day(), Time.hour(), Time.minute(), Time.second());
}

uint32_t StateTimer::getLocalEpoch(void)
{
  return this-> _getTime();
}

uint32_t StateTimer::getStartTime(void)
{
  return this-> _tmConvert_t(Time.year(), Time.month(), Time.day(), _onHour, _onMinute, _onSecond);
}
uint32_t StateTimer::getStopTime(void)
{
  return this-> _tmConvert_t(Time.year(), Time.month(), Time.day(), _offHour, _offMinute, _offSecond);
}

not perfect for your application but you may want to try it…

To answer this question:

You are missing the function parameter parentheses and are ending the if clause parentheses too early. It should be

if (sleepingTime(Time.weekday() && twoHoursSinceStartup())

I'm surprised your code even built. I suspect that this will give you a warning (try to add a proper error to see the warnings :wink: ).

1 Like

What a mistake to make…Thanks for the help! Working until deep in the night obviously does not benefit my analytical skills