Created
July 29, 2020 16:58
-
-
Save balazsreho/53c48f5e327b8cb421d0579e36172a3a to your computer and use it in GitHub Desktop.
Arduino stair lightning (based on https://www.instructables.com/member/snikogos/ code)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Edit by Serge Niko June 2015 | |
#include <Adafruit_NeoPixel.h> | |
#define PIN 6 | |
// Parameter 1 = number of pixels in strip | |
// Parameter 2 = Arduino pin number (most are valid) | |
// Parameter 3 = pixel type flags, add together as needed: | |
// NEO_KHZ800 800 KHz bitstream (most NeoPixel products w/WS2812 LEDs) | |
// NEO_KHZ400 400 KHz (classic 'v1' (not v2) FLORA pixels, WS2811 drivers) | |
// NEO_GRB Pixels are wired for GRB bitstream (most NeoPixel products) | |
// NEO_RGB Pixels are wired for RGB bitstream (v1 FLORA pixels, not v2) | |
Adafruit_NeoPixel strip = Adafruit_NeoPixel(484, PIN, NEO_GRB + NEO_KHZ800); | |
// IMPORTANT: To reduce NeoPixel burnout risk, add 1000 uF capacitor across | |
// pixel power leads, add 300 - 510 Ohm resistor on first pixel's data input | |
// and minimize distance between Arduino and first pixel. Avoid connecting | |
// on a live circuit...if you must, connect GND first. | |
// Setup each step width. Setup each step's last value. | |
const int stepEnds[] = {29, 58, 87, 116, 145, 174, 203, 232, 261, 290, 319, 348, 377, 406, 431, 456, 483}; | |
// Set up Variables | |
const int stayOnDelay = 30000; // time stairs should stay lit in miliseconds | |
const int delayBetweenStepAnimations = 20; | |
const int stepDelay = 200; // delay between lighting up each stairs | |
// Day values | |
const uint8_t brightness = 100; | |
const uint8_t light_r = 247; // light of illuminated steps (R) | |
const uint8_t light_g = 244; // light of illuminated steps (G) | |
const uint8_t light_b = 243; // light of illuminated steps (B) | |
const uint8_t warnlight_r = 129; // light of illuminated steps (R) | |
const uint8_t warnlight_g = 195; // light of illuminated steps (G) | |
const uint8_t warnlight_b = 215; // light of illuminated steps (B) | |
// Night values | |
const uint8_t nbrightness = 50; | |
const uint8_t nlight_r = 243; // light of illuminated steps (R) | |
const uint8_t nlight_g = 102; // light of illuminated steps (G) | |
const uint8_t nlight_b = 20; // light of illuminated steps (B) | |
const uint8_t nwarnlight_r = 255; // light of illuminated steps (R) | |
const uint8_t nwarnlight_g = 0; // light of illuminated steps (G) | |
const uint8_t nwarnlight_b = 0; // light of illuminated steps (B) | |
const int numberOfSteps = sizeof(stepEnds) / sizeof(stepEnds[0]); // number of stairs | |
unsigned long timeOut = millis() - stayOnDelay; // timestamp to remember when the PIR was triggered. | |
int downUp = 0; // variable to rememer the direction of travel up or down the stairs | |
const int analogThreshold = 1000; | |
const int analogPin = A1; | |
int analogValue = 0; | |
bool nightMode = true; | |
bool canSwitchModes = true; | |
const int alarmPinTop = 10; // PIR at the top of the stairs | |
const int alarmPinBottom = 11; // PIR at the bottom of the stairs | |
int alarmValueTop = LOW; // Variable to hold the PIR status | |
int alarmValueBottom = LOW; // Variable to hold the PIR status | |
int ledPin = 13; // LED on the arduino board flashes when PIR activated | |
int LDRSensor = A0; // Light dependant resistor | |
int LDRValue = 0; // Variable to hold the LDR value | |
int colourArray[350]; // An array to hold RGB values | |
double change = 0.01; // used in 'breathing' the LED's | |
double breathe = 0.0; // used in 'breathing' the LED's | |
bool waitForAll = true; | |
void setup() { | |
strip.begin(); | |
strip.setBrightness(100); //adjust brightness here | |
strip.show(); // Initialize all pixels to 'off' | |
Serial.begin (9600); // only requred for debugging | |
pinMode(ledPin, OUTPUT); // initilise the onboard pin 13 LED as an indicator | |
pinMode(alarmPinTop, INPUT_PULLUP); // for PIR at top of stairs initialise the input pin and use the internal restistor | |
pinMode(alarmPinBottom, INPUT_PULLUP); // for PIR at bottom of stairs initialise the input pin and use the internal restistor | |
delay (2000); // it takes the sensor 2 seconds to scan the area around it before it can detect infrared presence. | |
Serial.print("number of steps: "); | |
Serial.println(numberOfSteps); | |
stripTest(); | |
} | |
void loop() { | |
analogValue = analogRead(analogPin); | |
if (canSwitchModes) { | |
if (analogValue > analogThreshold) { | |
nightMode = true; | |
strip.setBrightness(nbrightness); | |
} | |
else { | |
nightMode = false; | |
strip.setBrightness(brightness); | |
} | |
} | |
if (downUp == 0) { // idle state - 'breathe' the top and bottom LED to show program is looping | |
stepBreathe(); | |
} | |
alarmValueTop = digitalRead(alarmPinTop); // Constantly poll the PIR at the top of the stairs | |
// Serial.print("Top sensor: "); | |
// Serial.println(alarmValueTop); | |
alarmValueBottom = digitalRead(alarmPinBottom); // Constantly poll the PIR at the bottom of the stairs | |
// Serial.print("Bottom sensor: "); | |
// Serial.println(alarmValueBottom); | |
if (alarmValueTop == HIGH && downUp == 0 && !waitForAll) { // the 2nd term allows timeOut to be contantly reset if one lingers at the top of the stairs before decending but will not allow the bottom PIR to reset timeOut as you decend past it. | |
downUp = 1; | |
waitForAll = true; | |
canSwitchModes = false; | |
Serial.println("Starting from top"); | |
clearStrip(); | |
topdown(); // lights up the strip from top down | |
} | |
if (alarmValueBottom == HIGH && downUp == 0 && !waitForAll) { // the 2nd term allows timeOut to be contantly reset if one lingers at the bottom of the stairs before decending but will not allow the top PIR to reset timeOut as you decend past it. | |
downUp = 2; | |
waitForAll = true; | |
canSwitchModes = false; | |
Serial.println("Starting from bottom"); | |
clearStrip(); | |
bottomup(); // lights up the strip from bottom up | |
} | |
if (alarmValueBottom == HIGH || alarmValueTop == HIGH) { | |
timeOut = millis(); | |
} | |
if (downUp != 0 && timeOut+stayOnDelay < millis()) { //switch off LED's in the direction of travel. | |
if (downUp == 1) { | |
colourWipeDown(stepDelay, true); // Off | |
} | |
if (downUp == 2) { | |
Serial.println("Turning off"); | |
colourWipeUp(stepDelay, true); // Off | |
} | |
canSwitchModes = true; | |
downUp = 0; | |
breathe = 0.0; | |
} | |
if (alarmValueBottom == LOW && alarmValueTop == LOW && downUp == 0) { | |
waitForAll = false; | |
} | |
} | |
void stepBreathe() { | |
double easing = easeInOutQuad(breathe); | |
uint32_t color = 0; | |
if (nightMode) { | |
color = strip.Color(int(nwarnlight_r * easing), int(nwarnlight_g * easing), int(nwarnlight_b * easing)); | |
} | |
else { | |
color = strip.Color(int(warnlight_r * easing), int(warnlight_g * easing), int(warnlight_b * easing)); | |
} | |
breathe = breathe + change; | |
int lastStart = 0; | |
for (int i = 0; i <= numberOfSteps; i++) | |
{ | |
strip.setPixelColor(lastStart, color); | |
strip.setPixelColor(stepEnds[i], color); | |
lastStart = stepEnds[i] + 1; | |
} | |
strip.show(); | |
delay(10); | |
if ((breathe >= 1 && change > 0) || (breathe <= 0 && change < 0)) { | |
change = -change; | |
} | |
} | |
void stripTest() { | |
Serial.println("testing led strip"); | |
for (uint16_t i = 0; i < strip.numPixels(); i++) { | |
strip.setPixelColor(i, strip.Color(255, 0, 0)); | |
} | |
strip.show(); | |
delay(200); | |
for (uint16_t i = 0; i < strip.numPixels(); i++) { | |
strip.setPixelColor(i, strip.Color(0, 255, 0)); | |
} | |
strip.show(); | |
delay(200); | |
for (uint16_t i = 0; i < strip.numPixels(); i++) { | |
strip.setPixelColor(i, strip.Color(0, 0, 255)); | |
} | |
strip.show(); | |
delay(200); | |
for (uint16_t i = 0; i < strip.numPixels(); i++) { | |
strip.setPixelColor(i, strip.Color(255, 255, 255)); | |
} | |
strip.show(); | |
delay(500); | |
for (uint16_t i = 0; i < strip.numPixels(); i++) { | |
strip.setPixelColor(i, strip.Color(0, 0, 0)); | |
} | |
strip.show(); | |
Serial.println("testing done"); | |
} | |
void topdown() { | |
// Serial.println ("detected top"); // Helpful debug message | |
colourWipeDown(stepDelay, false); // Warm White | |
} | |
void bottomup() { | |
// Serial.println ("detected bottom"); // Helpful debug message | |
colourWipeUp(stepDelay, false); // Warm White | |
} | |
// Fade light each step strip | |
void colourWipeDown(uint16_t wait, bool is_turn_off) { | |
Serial.print("NIGHT?: "); | |
Serial.println(nightMode); | |
uint16_t animationSteps = wait / 10 - 2; | |
// Starting from 0 (1st step) to the last. | |
int lastStart = 0; | |
for (uint32_t currentStep = 0; currentStep <= numberOfSteps; currentStep++) { | |
// Serial.print("wipe down step: "); | |
// Serial.println(currentStep); | |
for (uint16_t j = 0; j <= animationSteps; j++) { | |
double easing = easeOutQuad(1.0 * j / animationSteps); | |
if (is_turn_off) { | |
easing = 1 - easing; | |
} | |
uint32_t c = 0; | |
if (!nightMode){ | |
c = strip.Color(int(light_r * easing), int(light_g * easing), int(light_b * easing)); | |
} | |
else { | |
c = strip.Color(int(nlight_r * easing), int(nlight_g * easing), int(nlight_b * easing)); | |
} | |
for (uint32_t i = lastStart; i <= stepEnds[currentStep]; i++) { | |
strip.setPixelColor(i, c); | |
} | |
strip.show(); | |
delay(10); | |
} | |
lastStart = stepEnds[currentStep] + 1; | |
delay(delayBetweenStepAnimations); | |
} | |
} | |
// Fade light each step strip | |
void colourWipeUp(uint16_t wait, bool is_turn_off) { | |
uint16_t animationSteps = wait / 10 - 2; | |
// Starting from the last to the first. | |
int nextStart = 0; | |
for (int32_t currentStep = numberOfSteps; currentStep >= 0; currentStep--) { | |
// Serial.print("wipe down: "); | |
// Serial.println(currentStep); | |
if (currentStep != 0) { | |
nextStart = stepEnds[currentStep - 1] + 1; | |
} | |
else { | |
nextStart = 0; | |
} | |
for (uint16_t j = 0; j <= animationSteps; j++) { | |
for (uint32_t i = nextStart; i <= stepEnds[currentStep]; i++) { | |
double easing = easeOutQuad(1.0 * j / animationSteps); | |
if (is_turn_off) { | |
easing = 1 - easing; | |
} | |
uint32_t c = 0; | |
if (!nightMode){ | |
c = strip.Color(int(light_r * easing), int(light_g * easing), int(light_b * easing)); | |
} | |
else { | |
c = strip.Color(int(nlight_r * easing), int(nlight_g * easing), int(nlight_b * easing)); | |
} | |
strip.setPixelColor(i, c); | |
} | |
strip.show(); | |
delay(10); | |
} | |
delay(delayBetweenStepAnimations); | |
// Serial.println(nextStart); | |
// Serial.println(stepEnds[currentStep]); | |
} | |
} | |
void clearStrip() { | |
for (int l = 0; l < strip.numPixels(); l++) { | |
strip.setPixelColor(l, (0, 0, 0)); | |
} | |
} | |
double easeInOutQuad(double x) { | |
return x < 0.5 ? 2 * x * x : 1 - pow(-2 * x + 2, 2) / 2; | |
} | |
double easeOutQuad(double x) { | |
return 1 - (1 - x) * (1 - x); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment