#include <Adafruit_NeoPixel.h>
#define LED_PIN 6 // Pin where your WS2812B LED strip is connected
#define NUM_LEDS 96 // Total number of LEDs in the strip (16 LEDs per stair * 6 stairs)
#define LEDS_PER_STAIR 16 // Number of LEDs per stair
#define TRIG_PIN_BOTTOM 9 // Trigger pin for the bottom HC-SR04
#define ECHO_PIN_BOTTOM 10 // Echo pin for the bottom HC-SR04
#define TRIG_PIN_TOP 7 // Trigger pin for the top HC-SR04
#define ECHO_PIN_TOP 8 // Echo pin for the top HC-SR04
#define SOUND_SPEED 0.034 // Speed of sound in cm/us
#define MAX_DISTANCE 100 // Maximum distance to detect motion (in cm)
#define STAIR_DELAY 200 // Delay between each stair lighting up (in ms)
#define FADE_SPEED 20 // Speed of the fill effect (in ms)
#define HOLD_TIME 5000 // Time to keep the lights on before fading out (in ms)
Adafruit_NeoPixel strip(NUM_LEDS, LED_PIN, NEO_GRB + NEO_KHZ800);
unsigned long illuminationStartTime = 0;
bool isIlluminated = false;
bool motionDetected = false;
enum Direction {UP, DOWN};
Direction motionDirection;
void setup() {
pinMode(TRIG_PIN_BOTTOM, OUTPUT);
pinMode(ECHO_PIN_BOTTOM, INPUT);
pinMode(TRIG_PIN_TOP, OUTPUT);
pinMode(ECHO_PIN_TOP, INPUT);
strip.begin();
strip.show(); // Initialize all pixels to 'off'
Serial.begin(9600);
}
void loop() {
detectMotion();
if (motionDetected && !isIlluminated) {
if (motionDirection == UP) {
illuminateStairs(UP);
} else if (motionDirection == DOWN) {
illuminateStairs(DOWN);
}
illuminationStartTime = millis();
isIlluminated = true;
motionDetected = false;
}
if (isIlluminated) {
// Reset timer if motion is detected again during illumination or hold time
if (detectMotionDuringIllumination()) {
illuminationStartTime = millis();
}
// Check if hold time has elapsed to start fade out
if (millis() - illuminationStartTime >= HOLD_TIME) {
if (motionDirection == UP) {
fadeOutStairs(DOWN);
} else if (motionDirection == DOWN) {
fadeOutStairs(UP);
}
isIlluminated = false;
}
}
delay(50); // Small delay to prevent excessive CPU usage
}
void detectMotion() {
float distanceBottom = measureDistance(TRIG_PIN_BOTTOM, ECHO_PIN_BOTTOM);
float distanceTop = measureDistance(TRIG_PIN_TOP, ECHO_PIN_TOP);
if (distanceBottom > 0 && distanceBottom < MAX_DISTANCE) {
motionDetected = true;
motionDirection = UP;
Serial.println("Motion detected at bottom sensor.");
} else if (distanceTop > 0 && distanceTop < MAX_DISTANCE) {
motionDetected = true;
motionDirection = DOWN;
Serial.println("Motion detected at top sensor.");
}
}
bool detectMotionDuringIllumination() {
float distanceBottom = measureDistance(TRIG_PIN_BOTTOM, ECHO_PIN_BOTTOM);
float distanceTop = measureDistance(TRIG_PIN_TOP, ECHO_PIN_TOP);
if ((distanceBottom > 0 && distanceBottom < MAX_DISTANCE) || (distanceTop > 0 && distanceTop < MAX_DISTANCE)) {
Serial.println("Motion detected during illumination. Resetting timer.");
return true;
}
return false;
}
float measureDistance(int trigPin, int echoPin) {
digitalWrite(trigPin, LOW);
delayMicroseconds(2);
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);
long duration = pulseIn(echoPin, HIGH, 30000); // Timeout after 30ms (max distance ~500cm)
float distance = (duration * SOUND_SPEED) / 2;
return distance;
}
void illuminateStairs(Direction dir) {
if (dir == UP) {
for (int i = 0; i < NUM_LEDS; i += LEDS_PER_STAIR) {
fillFromCenter(i, true);
delay(STAIR_DELAY);
}
} else if (dir == DOWN) {
for (int i = NUM_LEDS - LEDS_PER_STAIR; i >= 0; i -= LEDS_PER_STAIR) {
fillFromCenter(i, true);
delay(STAIR_DELAY);
}
}
}
void fadeOutStairs(Direction dir) {
if (dir == UP) {
for (int i = NUM_LEDS - LEDS_PER_STAIR; i >= 0; i -= LEDS_PER_STAIR) {
fillFromCenter(i, false);
delay(STAIR_DELAY);
}
} else if (dir == DOWN) {
for (int i = 0; i < NUM_LEDS; i += LEDS_PER_STAIR) {
fillFromCenter(i, false);
delay(STAIR_DELAY);
}
}
}
void fillFromCenter(int startIndex, bool turnOn) {
int center = LEDS_PER_STAIR / 2;
int step = 15; // Adjust brightness increment
if (!turnOn) step = -15;
int startBrightness = turnOn ? 0 : 255;
int endBrightness = turnOn ? 255 : 0;
for (int brightness = startBrightness; (turnOn ? brightness <= endBrightness : brightness >= endBrightness); brightness += step) {
uint32_t color = strip.Color(brightness, brightness, brightness); // Adjust color as needed
for (int j = 0; j <= center; j++) {
int leftIndex = startIndex + center - j;
int rightIndex = startIndex + center + j - 1;
if (leftIndex >= startIndex && leftIndex < startIndex + LEDS_PER_STAIR) {
strip.setPixelColor(leftIndex, color);
}
if (rightIndex >= startIndex && rightIndex < startIndex + LEDS_PER_STAIR) {
strip.setPixelColor(rightIndex, color);
}
}
strip.show();
delay(FADE_SPEED);
}
}