#include <Arduino.h>
// #include "DYPlayerArduino.h"
// #include <SoftwareSerial.h>
#define PIR_PIN 3 // PIR sensor input pin
#define BULB_PIN 5 // PWM pin for MOSFET/bulb control
#define MP3_RX 10 // SoftwareSerial RX for MP3
#define MP3_TX 11 // SoftwareSerial TX for MP3
// Initialise on software serial port.
// SoftwareSerial mySerial(MP3_RX, MP3_TX); // RX, TX
// DY::Player player(&mySerial);
// =========== INIT Conditions ================
const unsigned long INIT_DURATION = 10 * 1000UL; // 60 seconds
const int INIT_BRIGHTNESS = 25; // PIR Init Brightness 10% (255 * 0.1)
int INIT_LED_ON_TIME = 500; // LED On time (in milliseconds) during flashing at INIT state
int INIT_LED_OFF_TIME = 3000; // LED Off time (in milliseconds) during flashing at INIT state
const int FLASH_BRIGHTNESS = 128; // 50% (255 * 0.5) flashing brightness
const int READY_BRIGHTNESS = 77; // 30% (255 * 0.3)
unsigned long flashInterval = 10 * 1000UL; // LED Flash Interval during Ready state
const int readyLedOnTime = 500; // For how long the led needs to be on during Ready flashing
unsigned long lastLedToggleTime = millis() - INIT_LED_OFF_TIME - 20; // note last time led has toggled
const unsigned long COOLDOWN_DURATION = 30 * 1000UL; // 2 minutes
unsigned long TRIGGER_LED_ON_TIME = 20 * 1000UL; // LED On time when PIR triggered
const int MAX_BRIGHTNESS = 255; // PWM max
const int PULSE_MAX = 64; // 25% (255 * 0.25)
const int volume = 25; // Set mp3 volume from 1-30
enum State { INIT,
READY,
TRIGGERED }; // System states
State currentState = INIT; // Start in INIT
unsigned long initStartTime; // Timestamp for init start
unsigned long fadeStartTime; // Timestamp for fade start
unsigned long cooldownEndTime; // Timestamp for cooldown end
bool triggerLedOff = false; // flag to turn off led when pir triggered after the specified time pass
const unsigned long FADE_DURATION = 2000UL; // 2 seconds
const unsigned long PULSE_PERIOD = 2000UL; // Pulse cycle time (ms)
const float PI_TWO = 2.0 * 3.1415926535; // For sine calculation
bool fullBrightness = false; // flag to check if light is on full brightness
int brightness = 0;
void setup() {
// player.begin();
// Also initiate the hardware serial port so we can use it for debug printing
// to the console..
Serial.begin(9600);
// player.setVolume(volume); // 50% Volume Set volume from 0-30
pinMode(PIR_PIN, INPUT_PULLUP); // PIR as input
pinMode(BULB_PIN, OUTPUT); // Bulb PWM as output
analogWrite(BULB_PIN, 0); // Start bulb off
initStartTime = millis(); // Record init start time
Serial.println("Perform Initialization");
}
void loop() {
switch (currentState) {
case INIT:
// Soft pulsing at ~25% average (sine from 0 to 64)
{
doInitSequence();
}
break;
case READY:
// Steady 50%, wait for PIR trigger
if (digitalRead(PIR_PIN) == HIGH) {
currentState = TRIGGERED;
fadeStartTime = millis(); // Start fade timer
cooldownEndTime = millis() + COOLDOWN_DURATION; // Initial cooldown
// player.playSpecified(1); //Play specified file
Serial.println("Play Mp3");
}
// Indicate led is in ready mode
if ((millis() - lastLedToggleTime) > flashInterval) {
Serial.println("flash led once to indicate Redy mode");
lastLedToggleTime = millis(); //Note current time
analogWrite(BULB_PIN, READY_BRIGHTNESS);
delay(readyLedOnTime);
analogWrite(BULB_PIN, 0); // Turn off led
}
break;
case TRIGGERED:
// Handle fade from 0% to 100% over 2 seconds
{
if (fullBrightness == false) {
Serial.println("Set brightness to FULL");
for (brightness = 0; brightness <= MAX_BRIGHTNESS; brightness++) {
analogWrite(BULB_PIN, brightness);
Serial.print("Brightness:");
Serial.println(brightness);
delay(16); // Wait for 16 milliseconds
}
Serial.print("Full Brightness:");
Serial.println(brightness);
fullBrightness = true;
triggerLedOff = false; // Flag to be checked to turn off led after the time finish
}
}
if (!triggerLedOff && (millis() - fadeStartTime) > TRIGGER_LED_ON_TIME) {
for (brightness = MAX_BRIGHTNESS; brightness >= 0; brightness--) {
Serial.print("Brightness:");
Serial.println(brightness);
analogWrite(BULB_PIN, brightness);
delay(16); // Wait for 16 milliseconds
}
// analogWrite(BULB_PIN, 0); // Turn off led
triggerLedOff = true; // Set the flag to indicate led is now off
}
// Check if cooldown expired (2 min since last movement)
if (millis() >= cooldownEndTime) {
// Flash once: Brief off (200ms)
Serial.println("Cooldown Expired get back to ready state");
flashBulb(); // Flash bulb
analogWrite(BULB_PIN, 0);
Serial.println("Get back to Ready State");
fullBrightness = false;
currentState = READY; // Back to READY
}
break;
}
}
void flashBulb() {
// Flash bulb 2 times at 50% brightness
Serial.println("Flash led 2 times");
for (int i = 0; i < 2; i++) {
analogWrite(BULB_PIN, FLASH_BRIGHTNESS); // Set to READY Brightness
delay(300); // Turn on bulb for 300ms
analogWrite(BULB_PIN, 0); // Turn off bulb
delay(500); // Keep bulb off for 500ms
}
lastLedToggleTime = millis(); // Note current time when led has been toggled
}
void doInitSequence() {
unsigned long elapsed = millis() - initStartTime;
bool ledState = false; //Hold led state
while (elapsed < INIT_DURATION) {
elapsed = millis() - initStartTime;
if (elapsed >= INIT_DURATION) {
currentState = READY;
Serial.println("Init Complete");
analogWrite(BULB_PIN, 0); // Turn off bulb
delay(500); // wait for 500 milliseconds
//Flash Bulb 2 times
flashBulb();
break;
}
if (ledState && (millis() - lastLedToggleTime) > INIT_LED_ON_TIME) {
Serial.println("turn off led init");
ledState = false; // Reset led state
lastLedToggleTime = millis(); // Note current time
analogWrite(BULB_PIN, 0); // Turn off led
} else if (!ledState && (millis() - lastLedToggleTime) > INIT_LED_OFF_TIME) {
Serial.println("turn on led init");
ledState = true; // set led state
lastLedToggleTime = millis(); // Note current time
analogWrite(BULB_PIN, INIT_BRIGHTNESS); // Set led state at INIT Brightness
}
delay(10); // wait for small duration
}
}