[Photon] SLEEP_MODE_DEEP waking problems [Solved]

int and long are the same on this 32bit µC - both 32bit long.

You are also monitoring if the device wakes in between (e.g. due to power cut)?
I saw in your code that you have an “immediate” send to sleep in that case - could that be happening with some off time?

BTW, what system version are you on?
There were several issues in connection with the different sleep modes and most of them got addressed over time, so you might want to give v0.6.0-rc.1 pre-release a try.

And you desperately need to get rid of all these recursions. The more I see it in your code the worse it seems.

e.g. in SleepCalculator()

void SleepCalculator()
{
  ...  
  if(sleepTime > 259200){
    sleepCalculator();
  }
}

If that condition is true after the first run of that function it will be on all subsequent runs too (at least for the few milliseconds you have before a stackoverflow).
Just don’t do that - ever!

Currently updating it to 0.5.2 with the Particle Device Updater.

How can I update it to that pre-release?

Here you can find the instructions

1 Like

Alright, thank you.

Gonna try it on 0.5.2, if that doesn’t fix it I’ll try the pre-release.

About the recursions, I hadn’t thought if it that way so going to get rid of those :wink:

Again, I have had no luck with the sleep time. It should sleep for 13.5 hours, but it hasn’t woken up all weekend. This is on 0.5.2. I just installed the pre-release. If that still gives a problem, I’m going to hard code the sleep time. If that solves it, I’m clearly doing something wrong wit the calculations.

1 Like

@ScruffR

Yesterday and last night I tested my code for the sleeptime calculation. In both cases the Photon didn’t wake up. One sleeptime was only 1.5 hours, but during the night it was 13.5. I know the sleeptime works when I hardcode the sleeptime, but with calculating it, it simply won’t work. The Photon publishes the right time, but for some reason this is not used as the final sleeptime. It could be that the unsigned long ‘glitches’ out and starts at the end (giving it a huge value that is about 149 years of sleeptime).

Could you take a look at it? Also, I’m currently on the pre-release version.

//Calculates the total time to sleep until the next wakeup.
void sleepCalculator(){
  //Detect if its currently after sleepHour/Minute but before midnight or before wakeupHour/Minute and after midnight.
  //Based on that, calculate the calcEvening and calcNight values.
  if(tHour == sleepHour && tMinute >= sleepMinute){
    calcEvening = (((24 - tHour) * 60) - tMinute) * 60;
    calcNight   = (wakeupHour * 60 + wakeupMinute) * 60;
  }
  else if(tHour > sleepHour){
    calcEvening = (((24 - tHour) * 60) - tMinute) * 60;
    calcNight   = (wakeupHour * 60 + wakeupMinute) * 60;
  }
  else if(tHour < wakeupHour){
    calcEvening = 0;
    calcNight   = ((wakeupHour - tHour) * 60 - tMinute + wakeupMinute) * 60;
  }
  else if(tHour == wakeupHour && tMinute < wakeupMinute){
    calcEvening = 0;
    calcNight = (wakeupMinute - tMinute) * 60;
  }

  //Based on the day, add extra time for weekend sleep.
  if(tDay == 6){
    if(tHour == sleepHour && tMinute >= sleepMinute){
      calcWeekend = 172800;
    }
    if(tHour > sleepHour){
      calcWeekend = 172800;
    }
    if(tHour < wakeupHour){
      calcWeekend = 0;
    }
    if(tHour == wakeupHour && tMinute >= sleepMinute){
      calcWeekend = 0;
    }
  }
  else if(tDay == 7){
    calcWeekend = 86400;
  }
  else{
    calcWeekend = 0;
  }

  sleepTime = long(calcEvening + calcNight + calcWeekend);
}

Below is the declaration of all the variables.

//At what time the device should go to sleep.
const int sleepHour = 18;
const int sleepMinute = 0;

//At what time the device should wake up.
const int wakeupHour = 7;
const int wakeupMinute = 30;

//Time calculation related variables.
unsigned long sleepTime = 0;//Explicitely 0 to ensure that even if the calculation fails for some reason, the device boots uip immediately.
int calcEvening;            //Values used for sleepTime calculation
int calcNight;              //So above.
int calcWeekend = 0;        //This one needs to start at 0, since this one isn't always filled.

Before the Photon goes to sleep, it runs my debug() function and sends the value of sleepTime. This is done after sleepTime has been calculated.

I suspect that I’ve declared a variable in a wrong way, in a way that System.sleep() cannot interpret properly. Am I doing something wrong?

I can have a look.

Thanks, I suspect there’s something going on with sleepTime = long(calcEvening + calcNight + calcWeekend);. Maybe my way of making it a long is wrong, maybe I need to first make it a single integer (so calculate before long conversion). But I’m a bit at a loss :disappointed:

int and long are the same on this system, but when mixing signed and unsigned data types you may need to be careful.

Alright, going to look into it. Thanks.

@ScruffR

About the prerelease, my serial communication with the computer isn’t working. I can connect/open the connection to the Photon, but there’s no data coming in (I am sending data using Serial.print()). So, I think that might be bugged in that version. Currently downgrading so I can read out the Photon directly.

I haven’t Now I have tested this and I would actually do the sleep time calculation like this

//At what time the device should wake up.
const int wakeupHour = 7;
const int wakeupMinute = 30;
// have a nice and easily computable and system compatible representation (seconds since midnight)
const uint32_t wakeTime  = wakeupHour * 3600 + wakeupMinute * 60;

//At what time the device should go to sleep.
const int sleepHour = 18;
const int sleepMinute = 0;
// have a nice and easily computable and system compatible representation (seconds since midnight)
const uint32_t sleepTime = sleepHour  * 3600 + sleepMinute  * 60; 

/*************************** don't need them anymore ******************************
// having them global although only used in one function is no good practice anyway
//Time calculation related variables.
unsigned long sleepTime = 0;//Explicitely 0 to ensure that even if the calculation fails for some reason, the device boots uip immediately.
int calcEvening;            //Values used for sleepTime calculation
int calcNight;              //So above.
int calcWeekend = 0;        //This one needs to start at 0, since this one isn't always filled
**********************************************************************************/

//Calculates the total time to sleep until the next wakeup.
// returns the seconds to sleep and rids us from the need for a global variable (0 indicates not sleeping at work!)
uint32_t sleepCalculator() {
  uint32_t currTime  = Time.local() % 86400;    // this will give you seconds since midnight when Time.zone() is set right (including DST)
  uint32_t deltaTime = 0;

  // when current time between wake and sleep time and the day between Sunday (1) and Saturday (7), then don't sleep, we're working
  // you might want to consider what to do with bank holidays
  if (wakeTime <= currTime && currTime <= sleepTime && 1 < Time.weekday() && Time.weekday() < 7) return 0;

  // so, now we are outside of the times where the device should be awake (or it should rather sleep)
  // calculate how long till the next wake periode
  deltaTime = (wakeTime + 86400) - currTime;

  switch(Time.weekday())
  {
    case 6: // on Fridays 
      deltaTime += 2*86400; // skip Saturday and Sunday
      break;
    case 7: // on Saturdays
      deltaTime += 86400; // skip Sunday
      break;
    default:
      // don't skip tomorrow we need to wake again :-(
      break;
  }

  return deltaTime;
}

About your serial problem, you might need to reinstall the most recent serial drivers, since 0.6.0 will be bringing a second USB COM port for better debugging.

1 Like

All right, thanks again for your effort. I’ll implement it in my code!

About the drivers: just used the drivers from this page, but they are from September '15. Installed them, but as expected there’s no difference. Where can I find the right drivers for the pre-release?

That is rather odd, since I’m running 0.6.0-rc.1 and see serial output just fine with these drivers.
Can you see the device in Device Manager?
Are you using the correct COM port? That was the only thing that I had to change after the update, since the device was recognized as a new COM and hence got a new port number assigned.

Yep, the Photon is connected to COM6. I can connect to it, but no data is shown. I have initiated the serial communication in the code, I’m using the correct baud rate. I rebooted my computer. The Photon is detected properly, no device errors are shown, but nothing is received.

Have you reflashed your code after updating?
Can you put your device into Listening Mode and press “i” and see if you get anything that way?
Could your USB cable got damaged?
Can you flash a very simple test program that only prints the time or something every few seconds?

That hasn’t got anything to do with 0.6.0-rc.1, other than what I’ve said above.

BTW, for USB serial the baudrate is completely irrelevant - it’s always USB speed.

Have you reflashed your code after updating?

Yes.

Can you put your device into Listening Mode and press "i" and see if you get anything that way?

Yes, this give me my device id.

Could your USB cable got damaged?

Well, that doesn't seem the case :wink:

Can you flash a very simple test program that only prints the time or something every few seconds?

Yep, and it does work. Going back to my original program.

Conclusion: something's going wrong in my original program. Interesting. Thanks for the debugging.

Kind of weird because I haven't done anything to the communications-part in my code, it's been the same for the last few weeks.

I've added a Serial.print("test") in the loop() and there's nothing. This is pretty weird because I open it just normally with Serial.begin(9600). The print is even at the start of the loop before anything else is done...

I simply cannot deduct what is causing this error. There’s clearly nothing wrong with the device, not with the cable, but as soon as I run my program the communications stay empty.

What is even more weird is that older versions of my program, the ones where I started printing and of which I 100% know they work, aren’t working anymore either. These are versions of my programs where I was using the serial communication constantly to read out values.

However, these were written on 0.4.6 and I’m currently back to default 0.5.2, has something changed in the meantime?

can you post your current code again?

Current code:

//BEFORE DEPLOYMENT CHANGE THE FOLLOWING VALUES TO THAT OF THE LOCATION!!!
//Location's WiFi information
const char* SSID_Location = "XXXXXXXX";  //WiFi network name
const char* PASS_Location = "XXXXXXXX";   //Password of the network.

//The location in our database, don't forget: create location in database.
const int location = 4; //this is a predefined location found in the database.

//At what time the device should go to sleep.
const int sleepHour = 17;
const int sleepMinute = 30;

//At what time the device should wake up.
const int wakeupHour = 7;
const int wakeupMinute = 45;

//MAKE SURE ALL THESE VARIABLES ARE SET PROPERLY BEFORE DEPLOYING THE DEVICE AT THE LOCATION.







//  #     #  ###  #######  ###
//  #  #  #   #   #         #
//  #  #  #   #   #         #
//  #  #  #   #   #####     #
//  #  #  #   #   #         #
//  #  #  #   #   #         #
//   ## ##   ###  #        ###

//WIFI CREDENTIALS for development
/*DO NOT CHANGE*/ const char* SSID = "XXXXXXXX";
/*DO NOT CHANGE*/ const char* PASS = "XXXXXXXX";







//  #        ###  ######   ######      #     ######   ###  #######   #####
//  #         #   #     #  #     #    # #    #     #   #   #        #     #
//  #         #   #     #  #     #   #   #   #     #   #   #        #
//  #         #   ######   ######   #     #  ######    #   #####     #####
//  #         #   #     #  #   #    #######  #   #     #   #              #
//  #         #   #     #  #    #   #     #  #    #    #   #        #     #
//  #######  ###  ######   #     #  #     #  #     #  ###  #######   #####

#include <RunningMedian.h>  //Averages the sensorValues to prevent false positives.
//Library by Rob Tillaart, https://github.com/RobTillaart







//  #     #     #     ######   ###     #     ######   #        #######   #####
//  #     #    # #    #     #   #     # #    #     #  #        #        #     #
//  #     #   #   #   #     #   #    #   #   #     #  #        #        #
//  #     #  #     #  ######    #   #     #  ######   #        #####     #####
//   #   #   #######  #   #     #   #######  #     #  #        #              #
//    # #    #     #  #    #    #   #     #  #     #  #        #        #     #
//     #     #     #  #     #  ###  #     #  ######   #######  #######   #####


//TIME RELATED MEASUREMENTS / TIMED ACTIVITIES
int tHour;                  //stores the hours
int hourOffset = 2;         //Offset from server time to our time, also used to emulate night times.
int tMinute;                //stores the minutes
int mMinute = 60;           //used as a modulo to dictate time intervals (modulo is not necessary if you push only once per hour).
int tDay;                   //Used to know when it's weekend. 5, 6, 7 = Friday, Saturday, Sunday
int tSecond;                //stores the seconds
int cooldown = 750;         //Cooldown periods ensuring certain functions are done properly.

//Moment for debugging, make sure this falls within the active / non sleep periods.
int debugStartHour = 9;     //Starting hour of the debug interval
int debugStartMinute = 0;   //Starting minute of the debug interval
int debugEndHour = 9;       //Ending hour of the debug interval
int debugEndMinute = 30;    //Ending minute (exclusive) of the debug interval (if full hour, debugEndMinute should be 60, not 0)
bool debugState = false;    //Used for other functions to detect if the device is in debug mode.
unsigned long printTimer;   //Used to make the printing happen less often (once every interval)
int prInterval = 1000;      //Print interval

//Based on what time the device should go to sleep and wake up, the sleep time in seconds is calculated.
int sleepTime = 0;    //Explicitely 0 to ensure that even if the calculation fails for some reason, the device boots uip immediately.
bool sleepState = false;        //Used to indicate if the device should go to sleep.
int calcEvening;       //Values used for sleepTime calculation
int calcNight;         //So above.
int calcWeekend = 0;   //This one needs to start at 0, since this one isn't always filled.

//PUBLISHSTRING used to Publish the location and value to the Particle Cloud.
char publishString[40];

//TRANSMISSION CONFIRMATIONS
int wifiState = 0;              //Used to know if WiFi is on, working, connected and if a dataPublish is possible.
unsigned long stateTimer;       //Used to make sure the wifiState has enough 'delay' to process all commands.

//DISTANCE SENSOR
int sensorPin = (A0);           //Pin that reads out the values of the distence sensor
int sensorValue;                //Raw sensor values
bool sensorState = false;       //Used to know if sensor is low, high or recently low, prevents multiple data additions to value. Range is 0, 1, 2.
uint16_t value = 0;             //Amount of people that walked by.
int statePin = D5;              //The pin which turns the sensor on or off (connected to low-end transistor)
int nulValue = 4098;            //nulValue is the lowest value of the distance sensor (in rest), all calculations are done based on this lowest value. This value starts high, to ensure the first readings are lower.
const int oST = 200;            //Original sensorThreshhold
int sensorThreshold = oST;      //Threshold of the sensor (above this value and somebody walked by).
const int sensorOffset = 100;   //When threshold is met, apply filter to ensure no flickering readings.
int sensorMedian;               //The actual average that's getting output from the value sensorValues RunningMedian.
int sampleSize = 100;           //The size of the samples to be used in the RunningMedian
RunningMedian sensorValues = RunningMedian(sampleSize);  //Creates an array to average the data which then gets stored in value.
unsigned long sensorTimer;      //Used to make sure there are not constant readings or value additions from the sensor.
int sensorTimeOffset = 500;     //The amount of time that has to pass between high and low reading of the sensor.
unsigned long correctionTimer;  //Timer used to correct the nulValue if the sensor is moved or doesn't detect values within a certain range anymore.
int correctionOffset = 10000;   //If the sensor isn't in the range of the nulValue for this amount of time, then the nulValue is increased.
int nulValueRange = 10;         //Sensor value has to be in this range the majority of time.
bool timerSet = false;          //Used to know if a timer has been set for correction

//FIRST RUN & EEPROM DATA
bool firstRun = true;           //Used to activate several parts of the Photon before continuing.
int eepromAddress[] = {0, 2};   //Address of the stored values in EEPROM (uint16_t = 2 bytes)
int eepromUnwritten = 65535;    //Value of eeprom for uint16_t when unwritten.
uint16_t eepromValue1;          //Value 1, compared to value 2.
uint16_t eepromValue2;          //Value 2, compared to value 1.
//Two values are used to ensure that there's *always* a backup value.
//If one fails, the other one can still be used (due to i.e. a power cut)

//ACTIVITY LED
int ledVal = 255;           //Strength of the LED.
unsigned long bleepTimer;   //Timer for when to bleep.
int bleepInterval = 1000;   //At what time to bleep the LED.
int bleepDuration = 100;    //How long the LED will bleep.

//MISCELLANEOUS
SYSTEM_MODE(SEMI_AUTOMATIC);






//   #####   #######  #######  #     #  ######
//  #     #  #           #     #     #  #     #
//  #        #           #     #     #  #     #
//   #####   #####       #     #     #  ######
//        #  #           #     #     #  #
//  #     #  #           #     #     #  #
//   #####   #######     #      #####   #

void setup(){
  //Initiates a serial communication.
  Serial.begin(9600);

  //Setting up the credentials for WiFi
  //Multiple credentials for the deploy location and development location
  WiFi.setCredentials(SSID, PASS);
  WiFi.setCredentials(SSID_Location, PASS_Location);

  //Initiates the statePin as an output pin, to turn the sensor on or off.
  pinMode(statePin, OUTPUT);

  WiFi.on();
  Particle.connect();

}







//  #        #######  #######  ######
//  #        #     #  #     #  #     #
//  #        #     #  #     #  #     #
//  #        #     #  #     #  ######
//  #        #     #  #     #  #
//  #        #     #  #     #  #
//  #######  #######  #######  #

void loop(){
  //This is executed when Photon turns on (this includes after a deep sleep)
  while(firstRun == true){
    photonWakeUp();
  }

  //Functions used to gather data.
  detectTime();       //Detects time
  readSensor();       //Reads the distance sensor to detect passersby.

  //Functions that are based on time (hours/minutes, etc).
  timedActivities();  //Ensures time related activities are being executed, including dataPublish.

  //Based on the interal timer (millis), make a led blink to show activity.
  //Green is normal activity, blue is with WiFi on.
  ledBleep();

  //Function to debug based on the gathered data.
  serialPrint();      //Used to communicate data to a serial monitor, i.e. the computer.
}







//  #######  ###  #     #  #######  #####_
//     #      #   ##   ##  #        #     #
//     #      #   # # # #  #        #     #
//     #      #   #  #  #  #####    #     #
//     #      #   #     #  #        #     #
//     #      #   #     #  #        #     #
//     #     ###  #     #  #######  #####`

//     #      #####   #######  ###  #     #  ###  #######  ###  #######   #####
//    # #    #     #     #      #   #     #   #      #      #   #        #     #
//   #   #   #           #      #   #     #   #      #      #   #        #
//  #     #  #           #      #   #     #   #      #      #   #####     #####
//  #######  #           #      #    #   #    #      #      #   #              #
//  #     #  #     #     #      #     # #     #      #      #   #        #     #
//  #     #   #####      #     ###     #     ###     #     ###  #######   #####


//All activities related to timing and specific moments of when they need to be executed.
//Including the intervalled dataPublish.
void timedActivities(){
  //=========================================================================//
  //DEBUG WINDOW
  //The Photon is turned on to make it possible to debug, upload new code and so on.
  if(tHour >= debugStartHour && tHour <= debugEndHour && tMinute >= debugStartMinute && tMinute < debugEndMinute){
    if(WiFi.ready()){
      if(Particle.connected()){
        debugState = true;
      }
    }
    else{
      WiFi.on();
      WiFi.connect();
    }
  }
  else{
    debugState = false;
  }
  //=========================================================================//

  //=========================================================================//
  //SLEEPMODE
  //Checks if the device needs to go in sleep mode.
  //Before going to sleep, it first publishes the final data.
  if(tHour == sleepHour && tMinute >= sleepMinute){
    sleepState = true;
  }
  //After the hour of sleep.
  if(tHour > sleepHour){
    sleepState = true;
  }
  //Before the hour of wakeup.
  if(tHour < wakeupHour){
    sleepState = true;
  }
  //In the hour of wakeup, at the minute or before the minute - offset of wakeup.
  if(tHour == wakeupHour && tMinute < (wakeupMinute)){
    sleepState = true;
  }

  //If the day is Saturday (7) or Sunday (1).
  if(tDay == 1 || tDay == 7){
    sleepState = true;
  }

  //When in sleepState, publish the data, then go into sleepmode.
  //Makes sure the device isn't in debugState.
  if(sleepState == true && debugState == false){
    if(value != 0){
      tMinute = mMinute;
    }
    else{
      photonSleep();
    }
  }
  //=========================================================================//

  //=========================================================================//
  //DATAPUBLISH
  //At a specified interval a data transfer will be initiated.
  if(tMinute % mMinute == 0){
    switch (wifiState){
      case 0:
      if(debugState == false){
        WiFi.on();
        Particle.connect();
      }
      wifiState++;
      break;

      case 1:
      if(WiFi.ready()){
        wifiState++;
        stateTimer = millis();
      }
      break;

      case 2:
      if(millis() > stateTimer + cooldown){
        Particle.process();
        wifiState++;
        stateTimer = millis();
      }
      break;

      case 3:
      if(millis() > stateTimer + cooldown){
        if(Particle.connected()){
          wifiState++;
          stateTimer = millis();
        }
      }
      break;

      case 4:
      if(millis() > stateTimer + cooldown){
        dataPublish();
        wifiState++;
      }
      break;

      case 5:
      if(debugState == false){
//        WiFi.off();
      }
      break;
    }
  }
  else {
    wifiState = 0;
    if(debugState == false){
//      WiFi.off();
    }
  }
  //=========================================================================//
}







//   #####   #######  #     #  #######  ######
//  #     #     #     #     #  #        #     #
//  #     #     #     #     #  #        #     #
//  #     #     #     #######  #####    ######
//  #     #     #     #     #  #        #   #
//  #     #     #     #     #  #        #    #
//   #####      #     #     #  #######  #     #

//  #######  #     #  #     #   #####   #######  ###  #######  #     #   #####
//  #        #     #  ##    #  #     #     #      #   #     #  ##    #  #     #
//  #        #     #  # #   #  #           #      #   #     #  # #   #  #
//  #####    #     #  #  #  #  #           #      #   #     #  #  #  #   #####
//  #        #     #  #   # #  #           #      #   #     #  #   # #        #
//  #        #     #  #    ##  #     #     #      #   #     #  #    ##  #     #
//  #         #####   #     #   #####      #     ###  #######  #     #   #####

//Publishes the location and the value to the Particle Cloud.
//The Particle Cloud uses a webhook to store this information in the database.
void dataPublish(){
  //Converts the location and value into a string with identifiers (var1, var2)
  sprintf(publishString, "{\"var1\": %u, \"var2\": %u}", location, value);
  //The string is published under the identifier "trap"
  //The Trapteller webhook is triggered by this identifier.
  Particle.publish("trap", publishString);
  //To make sure the publish is done properly, a cooldown is added.
  //When not using if/for/switch functions, make sure this cooldown is 1 second.
  delay(cooldown);
  value = 0;    //Resets the value after it has been sent.
  eepromPut();  //Resets the values of the eeprom.
}

//=========================================================================//

void debug(){
  sprintf(publishString, "{Dag: %u / Tijd: %u:%u:%u / Sleeptime: %u / Value: %u}", tDay, tHour, tMinute, tSecond, sleepTime, value);
  Particle.publish("debug", publishString);
  delay(cooldown);
  serialPrint();
}

//=========================================================================//

//Time is synced with the Particle cloud and the values are stored
void detectTime(){
  //Time correction because Particle Cloud is in another timezone than the Photon.
  tHour = Time.hour() + hourOffset;
  if(tHour > 24){
    tHour - 24;
  }
  tMinute = Time.minute();
  tSecond = Time.second();
  tDay = Time.weekday();
}

//=========================================================================//

//Getting previously stored values from the EEPROM.
//Used to check if there's still data from previous session.
//If this is the case, this data is placed in value so it gets published.
void eepromGet(){
  //Reads EEPROM from specific address.
  EEPROM.get(eepromAddress[0], eepromValue1);
  EEPROM.get(eepromAddress[1], eepromValue2);

  //Checks if the data received is from an empty EEPROM.
  //If this is the case, changes these values to 0.
  if(eepromValue1 == eepromUnwritten){
    eepromValue1 = 0;
  }
  if(eepromValue2 == eepromUnwritten){
    eepromValue2 = 0;
  }

  //Checks if both values are the same. If this is not the case, takes the highest value.
  //This is done because the device could have crashed while writing was still going on.
  if(eepromValue1 != eepromValue2){
    if(eepromValue1 > eepromValue2){
      eepromValue2 = eepromValue1;
    }
    if(eepromValue2 > eepromValue1){
      eepromValue1 = eepromValue2;
    }
  }

  value = eepromValue1;
}

//=========================================================================//

//Puts the current data of value into the correct EEPROM address.
void eepromPut(){
  for(int i = 0; i < 2; i++){
    EEPROM.put(eepromAddress[i], value);
  }
}

//=========================================================================//


//ledBleep is used to indicate some activity on the device.
//Photon's original LED breathing/signals are turned off to save power.
//When deployed, this code CAN be disabled.
//LED color explanation: RED = debug / BLUE = WiFi ready (outside debug) / GREEN = active, no wifi or debug
void ledBleep(){
  if(millis() >= bleepTimer + bleepDuration && millis() < bleepTimer + bleepInterval){
    RGB.color(0, 0, 0);
  }

  if(millis() >= bleepTimer + bleepInterval){
    if(debugState == true){
      RGB.color(ledVal, 0, 0);
    }
    else if(WiFi.ready()){
      RGB.color(0, 0, ledVal);
    }
    else{
      RGB.color(0, ledVal, 0);
    }
    bleepTimer = millis();
  }
}

//=========================================================================//

//Used during the night, ensures the Photon goes to sleep to preserve power.
//Automatically detects if its weekend or not.
void photonSleep(){
  digitalWrite(statePin, LOW);                //Turn off the distance sensor.
  sleepCalculator();                          //Calculate the total sleep time.

  if(WiFi.ready()){                             //Turns on the WiFi if it's currently not on.
    WiFi.on();
  }

  Particle.connect();                         //Connects the device to the internet.

  waitUntil(Particle.connected);            //Waits until the device is actually connected.

  debug();                                    //Runs the debug function.

  firstRun == true;                           //Resetting firstRun for the wakeup, not sure if this gets reset on its own.

  System.sleep(SLEEP_MODE_DEEP, sleepTime);   //Going in to deep sleep.
}

//=========================================================================//

//Initiated after the Photon wakes up.
//Initializes all the functions of the Photon for it to work.
void photonWakeUp(){
  printTimer = millis();        //giving a value to the printTimer
  digitalWrite(statePin, HIGH); //Turning the distance sensor on.
  WiFi.on();                    //Turning WiFi on...
  Particle.connect();           //Making it connect...

  waitUntil(Particle.connected);

  detectTime();               //detect time
  eepromGet();                //get data from the EEPROM
//    RGBcontrol();               //get control of the RGB, as it uses quite some power.
  debug();
  bleepTimer = millis();      //starting the timer for the LED bleeps.
  firstRun = false;           //and to exit the firstRun.
}

//=========================================================================//

//Reads the distance sensor to detect someone passing by.
//Applying a filter to ensure that jittering values don't go above or under the threshold rapidly.
void readSensor(){
  //Reading the sensor and adding it to the sensorMedian.
  sensorValue = analogRead(sensorPin);
  sensorValues.add(sensorValue);
  sensorMedian = int(sensorValues.getMedian());

  //Detects if the current sensorMedian is lower than the lowest value (this is the point where offSet should start)
  //Removes the nulValue from the sensorMedian, ensuring all the readings have a baseline of nulValue.
  if(sensorMedian < nulValue){
    nulValue = sensorMedian;
  }
  sensorMedian -= nulValue;

  if(sensorMedian > nulValueRange){
    if(timerSet == false){
      correctionTimer = millis();
      timerSet = true;
    }
    if(timerSet == true){
      if(millis() > correctionTimer + correctionOffset){
        nulValue++;
      }
    }
  }
  else{
    timerSet = false;
  }

  //Detects if the average of the sensorValue is over the threshold while the sensorState was false.
  //If this is the case, the threshold is lowered (to ensure a better reading and no flickering)
  //And value is increased by one (since one person passed by), at this point the sensorState is true, because someone is passing by.
  if(sensorMedian > sensorThreshold && sensorState == false){
    sensorThreshold -= sensorOffset;
    value++;
    eepromPut();
    sensorState = true;
    sensorTimer = millis();
  }

  //Prevents too many data inputs (i.e. by swaying someone's hands in front of it)
  if(sensorMedian > sensorThreshold && sensorState == true && (millis() < (sensorTimer + sensorTimeOffset))){
    sensorTimer = millis();
  }

  //Since the threshold has been lowered, the sensorValue first has to drop
  //Then, if this happens and a short timer has passed, the sensorState is put to false indicating someone has passed.
  if(sensorMedian < sensorThreshold && sensorState == true && (millis() > (sensorTimer + sensorTimeOffset))){
    sensorThreshold = oST;
    sensorState = false;
  }
}

//=========================================================================//

//Get control of the Photon RGB LED, turning it off to preserve power.
void RGBcontrol(){
  RGB.control(true);
  RGB.color(0,0,0);
}

//=========================================================================//

//Prints desired data to the console for debugging.
void serialPrint(){
  //Wait for interval to pass.
  if(millis() > printTimer + prInterval){
    //Print time
    if(tHour < 10){
      Serial.print("0");
    }
    Serial.print(tHour);
    Serial.print(":");
    if(tMinute < 10){
      Serial.print("0");
    }
    Serial.print(tMinute);
    Serial.print(":");
    if(tSecond < 10){
      Serial.print("0");
    }
    Serial.print(tSecond);

    //Print other desired values
    Serial.print("sleepTime");
    Serial.print("\t");
    Serial.print(sleepTime);

    //Line Break
    Serial.println();

    //Resetting the printTimer.
    printTimer = millis();
  }
}

//=========================================================================//

//Calculates the total time to sleep until the next wakeup.
void sleepCalculator(){
  //Detect if its currently after sleepHour/Minute but before midnight or before wakeupHour/Minute and after midnight.
  //Based on that, calculate the calcEvening and calcNight values.
  if(tHour == sleepHour && tMinute >= sleepMinute){
    calcEvening = (((24 - tHour) * 60) - tMinute) * 60;
    calcNight   = (wakeupHour * 60 + wakeupMinute) * 60;
  }
  else if(tHour > sleepHour){
    calcEvening = (((24 - tHour) * 60) - tMinute) * 60;
    calcNight   = (wakeupHour * 60 + wakeupMinute) * 60;
  }
  else if(tHour < wakeupHour){
    calcEvening = 0;
    calcNight   = ((wakeupHour - tHour) * 60 - tMinute + wakeupMinute) * 60;
  }
  else if(tHour == wakeupHour && tMinute < wakeupMinute){
    calcEvening = 0;
    calcNight = (wakeupMinute - tMinute) * 60;
  }

  //Based on the day, add extra time for weekend sleep.
  if(tDay == 6){
    if(tHour == sleepHour && tMinute >= sleepMinute){
      calcWeekend = 172800;
    }
    if(tHour > sleepHour){
      calcWeekend = 172800;
    }
    if(tHour < wakeupHour){
      calcWeekend = 0;
    }
    if(tHour == wakeupHour && tMinute >= sleepMinute){
      calcWeekend = 0;
    }
  }
  else if(tDay == 7){
    calcWeekend = 86400;
  }
  else{
    calcWeekend = 0;
  }

  sleepTime = calcEvening + calcNight + calcWeekend - 86400;

  if(sleepTime < 0){
    sleepTime = 0;
  }
}