/*setting up RTCLib*/
#include <Ds1302.h>
#include <RTClib.h>
#include <Wire.h>
RTC_DS1307 rtc;
const int ledPin = 9; //PWM pin for LED fading
const int pirPin = 2; //digital input
const unsigned long motionDelay = 1; //minutes the LEDs stay on if motion is detected
unsigned long currentMillis = 0; //used to store ms since system was turned on
unsigned long prevMillis = 0; //used to count elapsed time
bool ledState = false; //stores whether the LEDs are on or off
bool motionState = false, offState = true; //states used to change what activates the LEDs according to daily cycle
const int onHourAM = 5, onMinuteAM = 30, offHourAM = 7, offMinuteAM = 30; //morning time
const int onHourPM = 0, onMinutePM = 0, offHourPM = 0, offMinutePM = 53; //evening time
#ifdef pirActiveLow
bool pirSensSig = LOW;
#else
bool pirSensSig = HIGH;
#endif
void setup()
{
Serial.begin(9600);
pinMode(ledPin, OUTPUT);
pinMode(pirPin, INPUT);
if (!rtc.begin()) {
Serial.println("Couldn't find RTC");
while (1);
}
rtc.adjust(DateTime(F(__DATE__), F(__TIME__))); //if RTC hasn't started yet initalize time values from PC
//Used to set RTC with a give date and time. Used for debugging
//rtc.adjust(DateTime(2023, 5, 14, 3, 0, 0));
initOn(); //shows the system starting by fading and blinking LEDs
}
void loop()
{
DateTime now = rtc.now(); //read time of day from RTC
printTime(); //prints out the current time
if(((now.hour() == onHourAM) && (now.minute() >= onMinuteAM) && motionState) ||
(now.hour() == onHourPM) && (now.minute() >= onMinutePM) && offState) //if time is late in evening or early morning - fade on LEDs, switch off motionState and offState
{
Serial.println("On state");
ledState = fadeLED(HIGH);
motionState = false;
offState = false;
}
if((now.hour() == offHourPM) && (now.minute() >= offMinutePM) && !motionState) //if time is in the middle of the night - fade off LEDs, switch on motionState
{
ledState = fadeLED(LOW);
motionState = true;
Serial.println("Starting motion detect");
delay(500); //wait half a second after turning off LEDs before starting motion detection
motionRead();
DateTime now = rtc.now();
}
if((now.hour() >= offHourAM) && (now.minute() >= offMinuteAM) && (now.hour() < onHourPM) && !offState) //if time is in the middle of the day - fade off lights, switch off motionStaate, switch on offState
{
offState = true;
motionState = false;
Serial.println("Off state");
}
if(offState && ledState)
ledState = fadeLED(LOW);
delay(100);
}
bool fadeLED(bool posInc)
{
bool ledState;
int ledVal, incVal;
if(posInc)
{
ledVal = 0; //LEDs starts off and will fade on in for loop
incVal = 1; //used to increase brightness
ledState = true;
Serial.println("Fading on");
}
else
{
ledVal = 255; //LEDs starts on and will fade off in for loop
incVal = -1; //used to decrease brightness
ledState = false;
Serial.println("Fading off");
}
for(int i = 0; i <= 255; i++) //loop to fade LEDs on and off
{
analogWrite(ledPin, ledVal);
ledVal += incVal;
delay(30);
}
return ledState;
}
void motionRead()
{
while(motionState)
{
DateTime now = rtc.now();
printTime();
currentMillis = millis();
if((now.hour() == onHourAM) && (now.minute() == onMinuteAM))
{
Serial.println("No more motion state");
break;
}
if(digitalRead(pirPin) == pirSensSig)
{
prevMillis = currentMillis;
Serial.println("Detecting motion");
if(!ledState)
{
Serial.println("Detecting motion and turning on lights");
ledState = fadeLED(HIGH);
}
}
delay(200);
if(((currentMillis - prevMillis) >= (motionDelay*1000*60)) && ledState)
{
ledState = fadeLED(LOW);
Serial.println("No more motion");
}
Serial.println(currentMillis - prevMillis);
}
}
void printTime()
{
DateTime now = rtc.now();
Serial.print(now.hour(), DEC);
Serial.print(':');
Serial.print(now.minute(), DEC);
Serial.print(':');
Serial.println(now.second(), DEC);
}
void initOn()
{
ledState = fadeLED(HIGH);
delay(500);
digitalWrite(ledPin, LOW);
delay(500);
digitalWrite(ledPin, HIGH);
delay(500);
digitalWrite(ledPin, LOW);
delay(500);
digitalWrite(ledPin, HIGH);
delay(500);
ledState = fadeLED(LOW);
delay(500);
Serial.println("Bed leds initialized");
}