// Define the digital pins for the PIR motion sensors
const int topSensorPin = 2; // PIR sensor at the top of the stairs
const int bottomSensorPin = 3; // PIR sensor at the bottom of the stairs
// Define the digital pins for the six LEDs
const int ledPins[] = {4, 5, 6, 7, 8, 9};
const int numLeds = 6;
// The time in milliseconds the light should stay on after motion is detected
const unsigned long lightOnTime = 5000; // 15 seconds
// The delay between lighting up each LED in milliseconds
const int stepDelay = 200; // Adjust this for a faster or slower sequence
// Variables for timing and state management
unsigned long lastMotionTime = 0;
bool lightsOn = false;
bool animating = false;
int currentStep = -1;
unsigned long lastStepTime = 0;
// New feature: fading variables
const int fadeSteps = 50; // Number of steps for fading
const int fadeDelay = 10; // Delay between each fade step (in milliseconds)
// New feature: detection timeout to avoid re-triggering immediately
const unsigned long detectionTimeout = 1000; // 2 seconds to ignore new motion after triggering
void setup() {
// Initialize the serial monitor for debugging
Serial.begin(9600);
// Set the sensor pins as INPUT
pinMode(topSensorPin, INPUT);
pinMode(bottomSensorPin, INPUT);
// Set the LED pins as OUTPUT and turn them all off initially
for (int i = 0; i < numLeds; i++) {
pinMode(ledPins[i], OUTPUT);
digitalWrite(ledPins[i], LOW);
}
}
void loop() {
// Read the state of the motion sensors
int topSensorState = digitalRead(topSensorPin);
int bottomSensorState = digitalRead(bottomSensorPin);
// Check for motion at the bottom AND if the lights are off or finished animating
// Also check if enough time has passed since the last detection
if (bottomSensorState == HIGH && !lightsOn && !animating && (millis() - lastMotionTime > detectionTimeout)) {
Serial.println("Motion detected at bottom. Starting forward animation.");
animating = true;
currentStep = 0;
lastStepTime = millis();
lastMotionTime = millis(); // Update last motion time
}
// Check for motion at the top AND if the lights are off or finished animating
// Also check if enough time has passed since the last detection
if (topSensorState == HIGH && !lightsOn && !animating && (millis() - lastMotionTime > detectionTimeout)) {
Serial.println("Motion detected at top. Starting reverse animation.");
animating = true;
currentStep = numLeds - 1;
lastStepTime = millis();
lastMotionTime = millis(); // Update last motion time
}
// Handle the sequential animation
if (animating) {
if (millis() - lastStepTime >= stepDelay) {
if (bottomSensorState == HIGH) { // Animate forward
if (currentStep < numLeds) {
digitalWrite(ledPins[currentStep], HIGH);
currentStep++;
} else {
animating = false;
lightsOn = true;
lastMotionTime = millis();
}
} else if (topSensorState == HIGH) { // Animate reverse
if (currentStep >= 0) {
digitalWrite(ledPins[currentStep], HIGH);
currentStep--;
} else {
animating = false;
lightsOn = true;
lastMotionTime = millis();
}
}
lastStepTime = millis();
}
}
// Turn off all LEDs with a fading effect if the lightOnTime has elapsed since the last motion detection
if (lightsOn && millis() - lastMotionTime >= lightOnTime) {
Serial.println("Duration expired. Turning off all lights with fade.");
fadeAllLeds(); // Call the fade function
lightsOn = false; // Reset the state
}
}
// Function to fade all LEDs out
void fadeAllLeds() {
for (int i = 0; i < numLeds; i++) {
// This is a simple on/off fade, more complex analogWrite would be needed for true fading
digitalWrite(ledPins[i], LOW);
}
}