Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // LED-Staircase by Jannomag
- // Modified code, original made by Vinz68! Thanks for this!
- #include <Adafruit_NeoPixel.h> // Base library for LED controlling
- #include <WS2812FX.h> // Additional library for easy effects in "Partymode"
- #ifdef __AVR__
- #include <avr/power.h>
- #endif
- ///////////////////////////////////////////////////////////////////////////
- // Neopixel configuration
- #define PIN 9 // Pin used for the LEDs
- #define LEDSTRIPS 5 // Number of stairs
- #define LEDSPERSTAIR 2 // Number of leds per stair
- #define NUMPIXELS LEDSTRIPS*LEDSPERSTAIR // Calculate the total number of LEDs
- #define BRIGHTNESS 35 // Brightness of the LEDs
- ///////////////////////////////////////////////////////////////////////////
- // Additional input (switches)
- #define CLEANINGMODE 4 // Switch for turning all LEDs on
- #define PARTYMODE 5 // Switch for enabling fancy RGB party mode
- ///////////////////////////////////////////////////////////////////////////
- // Setup of NeoPixel and WS2812FX
- // I was using SK6812 RGBW LEDs. If using RGB-only LED strips like WS2812, change "NEO_GRBW" to "NEO_GRB"
- Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUMPIXELS, PIN, NEO_GRBW + NEO_KHZ800);
- WS2812FX ws2812fx = WS2812FX(NUMPIXELS, PIN, NEO_GRBW + NEO_KHZ800);
- ///////////////////////////////////////////////////////////////////////////
- // Configuration of PIR sensors
- int alarmPinTop = 2; // PIR at the top of the stairs
- int alarmPinBottom = 3; // PIR at the bottom of the stairs ; // 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
- ///////////////////////////////////////////////////////////////////////////
- // Configuration of the Light dependent resistor (LDR)
- bool useLDR = true; // flag, when true the program uses the LDR, set to "false" if you don't have a LDR sensor.
- int LDRSensor = A6; // Light dependent resistor, Analog Input line
- long LDRValue = 0; // Variable to hold the current measured LDR value
- long LDRThreshold = 600; // Only switch on LED's at night when LDR senses low light conditions - you may have to change this value for your circumstances!
- // Define the number of samples to keep track of. The higher the number, the more the readings will be smoothed, but the slower the output will respond to the input.
- // For our use case (determine the ammout of light) smoothing is good, so walk-by the LDR sensor or a sensor read spike is ingnored.
- const int numReadings = 100;
- int readings[numReadings]; // the readings from the analog input
- int readIndex = 0; // the index of the current reading
- long total = 0; // the running total
- long average = 0; // the average
- ///////////////////////////////////////////////////////////////////////////
- // configuration for fading, which, somehow doesn't work?
- int turnOnSpeed = 200; // speed to turn on next led-strip, in msec between next strip
- int turnOffSpeed = 100; // speed to turn off next led-strip, in msec between next strip
- int keepLedsOnTime = 5000; // keep leds on for at least .. msec.
- int keepLedsOffTime = 0; // keep leds off for at least .. msec.
- ///////////////////////////////////////////////////////////////////////////
- // constants won't change:
- const long LEDinterval = 300;
- // Set up Variables for the needed program logic (DO NOT TOUCH THESE!)
- unsigned long previousLEDMillis = 0; // will store last time LED was updated
- unsigned long timeOut = 0; // timestamp to remember when the PIR was triggered.
- unsigned long timeLoopStart = 0; // timestamp to remember when loop has started. used to determine the end-delay (keeps loop running in same intervals)
- unsigned long timeTemp = 0; // temp. var used in time calculations
- unsigned long timeDiff = 0; // temp. var used in time calculations
- bool readPIRInputs = true; // flag, when true, reads the PIR sensors. Disabled (false) by the program when LDR indicated that there is enough light.
- int downUp = 0; // main program mode, The possible values are:
- // 0 = Idle mode, waiting for PIR trigger to turn stairs on.
- // 1 = Going down, Turning stairs on (direction up to down)
- // 2 = Going up, Turnurning stairs on (direction down to up)
- // 3 = Turning leds off, from top to down
- // 4 = Turninf leds off, from bottom to up
- // 5 = All leds just turned off. After short time, automatically mode will be set to "0".
- ///////////////////////////////////////////////////////////////////////////
- //WS2812FX LED Effects fΓΌr Partymode
- #define DEFAULT_SPEED 1000 // Speed of the effects
- #define DEFAULT_BRIGHTNESS 50 // Brightness of the effects
- #define TIMER_MS 5000 // Defines the time in ms for each mode
- unsigned long last_change = 0; // Variable for looping
- unsigned long now = 0; // Variable for looping
- // Filter array for WS2812FX mode counters which should be disabled, not working atm.
- const int forbiddenModes[] = {0, 1, 2, 3, 24, 25, 26, 27, 28, 29, 34, 35, 45, 48, 50 };
- ///////////////////////////////////////////////////////////////////////////
- // Configuration of first steps variables
- int bottomStep[] = {0,1}; // Array of pixel numbers for the first step, count from 0 to the number on your first step at the bottom
- int topStep[] = {8,9}; // Array of pixel numbers for the first step, count backwards from your last pixel number
- int bFade = 0; // Fade state
- bool useFirstStepsAtDaylight = true; // flag, when true the program will use the firstStep function also during daylight (when useLDR=true)
- ///////////////////////////////////////////////////////////////////////////
- // Configuration of the cleaning light and partymode
- int cleaningModeActive = 0; // Variable for storing the state of the cleaning light
- int partyModeActive = 0; // Variable for storing the state of party mode
- int arduinoRunsLED = 12; // status LED, to show the Arduino is up and running
- int cleaningModeLED = 11; // status LED for cleaning mode
- int partyModeLED = 10; // status LED for party mode
- int arduinoRunsLEDState = LOW; // ledState used to set the running LED
- void setup() {
- // Initiate WS2812FX
- ws2812fx.init();
- ws2812fx.setBrightness(DEFAULT_BRIGHTNESS);
- ws2812fx.setSpeed(DEFAULT_SPEED);
- ws2812fx.setColor(0xFF000000); // only for RGBW! If using RGB, use 0x000000. FF000000 sets the color to the white LEDs
- ws2812fx.start();
- strip.begin(); // This initializes the NeoPixel library.
- strip.setBrightness(BRIGHTNESS); // Sets the brightness of the LEDs (change 'BRIGHTNESS' defined value when you need to change it)
- clearStrip(); // Initialize all pixels to 'off', and do strip.show()
- // Configure the used digital input & output
- 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
- pinMode(CLEANINGMODE, INPUT_PULLUP); // sets the internal pullup resistor for input. Connect the switches to the Arduino and Ground!
- pinMode(PARTYMODE, INPUT_PULLUP); // sets the internal pullup resistor for input. Connect the switches to the Arduino and Ground!
- pinMode(arduinoRunsLED, OUTPUT); // Sets the LED as output
- pinMode(cleaningModeLED, OUTPUT); // Sets the LED as output
- pinMode(partyModeLED, OUTPUT); // Sets the LED as output
- Serial.begin(9600); // only required for debugging. Output some settings in the Serial Monitor Window
- Serial.println("-------------------------------------------------");
- Serial.print("NeoPixel used on outout-pin [");
- Serial.print(PIN);
- Serial.print("] with ");
- Serial.print(NUMPIXELS);
- Serial.println(" Pixels");
- Serial.print("Number of LED-strips: ");
- Serial.println(LEDSTRIPS);
- Serial.print("Number of LEDs per strip: ");
- Serial.println(LEDSPERSTAIR);
- if (useLDR) {
- // initialize all the LDR-readings to current values...
- for (int thisReading = 0; thisReading < numReadings; thisReading++) {
- readings[thisReading] = analogRead(LDRSensor);
- total = total + readings[thisReading];
- }
- // ... and calculate the average value of [numReadings] samples.
- LDRValue = total / numReadings;
- Serial.print("LDR used on analog input pin [");
- Serial.print(LDRSensor);
- Serial.println("]");
- Serial.print("Determine number of samples for average value: ");
- Serial.println( numReadings );
- Serial.print("LDR average value = ");
- Serial.println( LDRValue );
- Serial.print("Stairs will work when LDR average value <= ");
- Serial.println(LDRThreshold);
- }
- Serial.println("-------------------------------------------------");
- delay (2000); // it takes the sensor 2 seconds to scan the area around it before it can detect infrared presence.
- digitalWrite(arduinoRunsLED, HIGH); // Turns on the Arduino-Runs LED after the setup is completed
- }
- void loop() {
- // While loop for cleaning and party modes
- while ( ( cleaningModeActive == 0 ) && ( partyModeActive == 0 ) ) { // While both modes are inactive...
- if ( digitalRead(CLEANINGMODE) == LOW ) { // if the switch for cleaning mode is ON (==LOW)...
- cleaningModeActive=1; // set the cleaningModeActive variable to 1
- digitalWrite(arduinoRunsLED, LOW); // and the running LED off
- }
- if ( digitalRead(PARTYMODE) == LOW ) { // if the switch for party mode is ON (==LOW)...
- partyModeActive=1; // set the cleaningModeActive variable to 1
- digitalWrite(arduinoRunsLED, LOW); // and the running LED off
- }
- // register the current time (in msec, for later use to optimize the execution loop)
- timeLoopStart=millis();
- // By default read the PIR inputs (unless LDR sensors are used and it is light enough...)
- readPIRInputs = true;
- if ( useLDR ) {
- // Read the (new) average value of the LDR (we use a sample array to filter out walk-by and sensor spikes)
- LDRValue = readAverageLDR();
- // For finetuning, show the LDR value, so the LDRThreshold can be determined ; once it works disable the next statement with '//'
- // Serial.println(LDRValue);
- // Check if LDR senses low light conditions ...
- if ( LDRValue >= LDRThreshold ) {
- // There is enough light, the stairs/ledstips will not be activated (readPIRInputs = false)
- readPIRInputs = false;
- unsigned long currentLEDMillis = millis();
- // let the running LED blink when the LDR detects light
- if ( currentLEDMillis - previousLEDMillis >= LEDinterval ) {
- // save the last time you blinked the LED
- previousLEDMillis = currentLEDMillis;
- // if the LED is off turn it on and vice-versa:
- if ( arduinoRunsLED == LOW ) {
- arduinoRunsLEDState = HIGH;
- } else {
- arduinoRunsLEDState = LOW;
- }
- // set the LED with the ledState of the variable:
- digitalWrite(arduinoRunsLED, arduinoRunsLEDState);
- }
- // Show that stair will not turn on / on PIR detection, due to LDR logic (daylight mode detected)
- // NOTE: These "Serial" statement can be deleted when everything works fine.
- // its here for finetuning the LDRThreshold value, which you should configure in the begin of this file.
- Serial.println("LDR detected Daylight according to LDRThreshold configuration.");
- Serial.print("LDR Average value = ");
- Serial.println(LDRValue);
- }
- else {
- // It is dark enough. The stairs/ledstips will be activated. (readPIRInputs = true)
- alarmValueTop = LOW;
- alarmValueBottom = LOW;
- digitalWrite(arduinoRunsLED, HIGH); // Turns on running LED
- }
- }
- // Read the PIR inputs ?
- if (readPIRInputs) {
- alarmValueTop = digitalRead(alarmPinTop); // Constantly poll the PIR at the top of the stairs
- alarmValueBottom = digitalRead(alarmPinBottom); // Constantly poll the PIR at the bottom of the stairs
- }
- // Check if PIR Top was triggered an leds must be turned on
- if ( (alarmValueTop == HIGH) && (downUp == 0) ) { // the 2nd term indicates that there is currently no activity (up or down)
- timeOut=millis(); // Timestamp when the PIR is triggered. The LED cycle wil then start.
- downUp = 1;
- colourWipeDown(strip.Color(0, 0, 0, 255), turnOnSpeed ); // Warm White,led-light from top to down. If using RGB-strips just use 3 color values like (255,255,255) for white
- }
- // Check if PIR Bottom was triggered an leds must be turned on
- if ( (alarmValueBottom == HIGH) && (downUp == 0)) { // the 2nd term indicates that there is currently no activity (up or down)
- timeOut=millis(); // Timestamp when the PIR is triggered. The LED cycle wil then start.
- downUp = 2;
- colourWipeUp(strip.Color(0, 0, 0, 255), turnOnSpeed); // Warm White,led-light from bottom to top. If using RGB-strips just use 3 color values like (255,255,255) for white
- }
- // Restart on-timer when a PIR sensor gets HIGH again while the lights are on
- if ( ( downUp != 0 ) && ( ( alarmValueTop == HIGH ) || ( alarmValueBottom == HIGH ) ) ) {
- timeOut=millis();
- }
- // Logic to turn the leds off (determines the turn-off direction)
- if ( (downUp!=0) && (timeOut+keepLedsOnTime < millis()) ) { //switch off LED's in the direction of travel.
- if (downUp == 1) {
- downUp = 3; // mode = turn off leds from top to down
- colourWipeDown(strip.Color(0, 0, 0, 0), turnOffSpeed); // Off
- downUp=5; // Stairs are just turned off
- }
- if (downUp == 2) {
- downUp = 4; // mode = turn off leds from bottom to top
- colourWipeUp(strip.Color(0, 0, 0, 0), turnOffSpeed); // Off
- downUp=5; // Stairs are just turned off
- }
- }
- // Enable firstSteps Effect when needed.
- if (downUp==0) { // Currently no activity on the stairs ? (in idle mode, not turned (or turning) on or off ?)
- // Check if PIRs are read (not when it is dark), or when breathe function must also work during the day
- if ( ( readPIRInputs==true ) && ( (readPIRInputs) || (useFirstStepsAtDaylight) ) ) {
- firstSteps(); // set fader for firstSteps to 0
- }
- else {
- bFade = 0;
- clearStrip(); // during daylight all leds turned off.
- }
- }
- else if (downUp==5) { // eventually the stairs led lights will be turned off again (mode=5)
- delay(keepLedsOffTime); // allow small delay/pause and then activate the stairs again with the breathe and motion detection function
- downUp=0; // set to 0 to allow breathe/motion detection (-1 for debugging one run)
- bFade = 0; // set fader for firstSteps to 0
- }
- }
- // while loops for cleaning and party mode. If the variables are ==1, run the voids.
- while ( cleaningModeActive == 1 ) {
- cleaningMode();
- }
- while ( partyModeActive == 1 ) {
- partyMode();
- }
- }
- long readAverageLDR() {
- // Subtract the last reading:
- total = total - readings[readIndex];
- // Read the current value of the Light Sensor, and store in samples array
- readings[readIndex] = analogRead(LDRSensor);
- // Add the reading to the total:
- total = total + readings[readIndex];
- // Advance to the next position in the array:
- readIndex = readIndex + 1;
- // If we're at the end of the array...
- if (readIndex >= numReadings) {
- // ...wrap around to the beginning:
- readIndex = 0;
- }
- // Calculate the average:
- average = total / numReadings;
- return (average);
- }
- void cleaningMode() {
- digitalWrite(cleaningModeLED, HIGH); // turns on the cleaning mode LED
- for (int l=0; l<NUMPIXELS; l++){ // for every LED
- strip.setBrightness(255); // set additional brightness
- strip.setPixelColor(l, strip.Color(0,0,0,255)); // set white as color, note RGB strips need three color values instead of four!
- }
- strip.show(); // This sends the updated pixel's to the hardware.
- if ( digitalRead(CLEANINGMODE) == HIGH ) { // if the cleaning mode switch is OFF
- digitalWrite(arduinoRunsLED, HIGH); // turn on the arduino runing LED
- digitalWrite(cleaningModeLED, LOW); // turn off the cleaning mode LED
- clearStrip(); // clear the strip
- downUp=5; // set the stairs variable to 5
- cleaningModeActive=0; // set the cleaning mode variable to 0
- strip.setBrightness(BRIGHTNESS); // set brightness to the value defined on top
- delay(100); // delay for debouncing the switch
- }
- }
- void partyMode() {
- digitalWrite(partyModeLED, HIGH); // turn the partyModeLED on
- now = millis(); // start millis()
- ws2812fx.service(); // initiate ws2812fx
- if(now - last_change > TIMER_MS) { // if the timer reaches TIMER_MS value (default 5000ms)
- uint8_t nextMode = ws2812fx.getMode() + 1; // add 1 to the mode counter
- // Filter for WS2812FX mode counters. Couldn't get the array from the top working
- // If the nextMode variable equals one of those numbers, set nextMode to the next number which is allowed
- if ( ( nextMode == 1 ) || ( nextMode == 2 ) || ( nextMode == 3 ) ) nextMode = 4;
- if ( ( nextMode == 24 ) || ( nextMode == 25 ) || ( nextMode == 26 ) || ( nextMode == 27 ) || ( nextMode == 28 ) || ( nextMode == 29 ) ) nextMode = 30;
- if ( ( nextMode == 34 ) || ( nextMode == 35 ) ) nextMode = 36;
- if ( ( nextMode == 45 ) ) nextMode = 46;
- if ( ( nextMode == 48 ) ) nextMode = 49;
- if ( ( nextMode == 50 ) ) nextMode = 51;
- // 2 tries for filter using the array...doesn't work, so commented out
- /*if ( nextMode == forbiddenModes[nextMode] ) {
- nextMode+1;
- } */
- /*if ( nextMode == forbiddenModes[nextMode] ) {
- nextMode = nextMode +1 ;
- }*/
- ws2812fx.setMode(nextMode % ws2812fx.getModeCount()); // let WS2812FX show the mode
- last_change = now; // set timer to 0
- }
- if ( digitalRead(PARTYMODE) == HIGH ) { // if the partymode switch is HIGH, means it's turned OFF!
- digitalWrite(arduinoRunsLED, HIGH); // turn on the arduino running LED
- digitalWrite(partyModeLED, LOW); // turn off the partymode led
- clearStrip(); // "clear" the strip by using the clearStrip() function
- downUp=5; // set the stair mode to 5
- partyModeActive=0; // set partyMode to 0
- delay(100); // delay for debouncing the switch
- }
- }
- // fades in the first steps, defined by bottomSteps and topSteps. bFade is the brightness of the white color
- void firstSteps() {
- for (bFade; bFade < 30; bFade++) {
- for (int i = 0; i < LEDSPERSTAIR; i++) {
- strip.setPixelColor(bottomStep[i], strip.Color(0,0,0,bFade));
- strip.setPixelColor(topStep[i], strip.Color(0,0,0,bFade));
- strip.show();
- delay(0);
- }
- delay(6);
- }
- }
- // Fade light each step strip
- void colourWipeDown(uint32_t c, uint16_t wait) {
- for (uint16_t k = 0; k < LEDSTRIPS; k++){
- int start = (NUMPIXELS/LEDSTRIPS) *k;
- for (uint16_t j = start; j < start + LEDSPERSTAIR; j++){
- strip.setPixelColor(j, c);
- delay(0);
- }
- strip.show();
- delay(wait);
- }
- }
- // Fade light each step strip
- void colourWipeUp(uint32_t c, uint16_t wait) {
- for (uint16_t k = LEDSTRIPS; k > 0; k--){
- int start = NUMPIXELS/LEDSTRIPS *k;
- int x = start;
- do
- {
- strip.setPixelColor(x-1, c); // white of RGBW
- x--;
- } while (x > start - LEDSPERSTAIR);
- strip.show();
- delay(wait);
- }
- }
- void clearStrip(){
- // All pixels off
- for (int l=0; l<NUMPIXELS; l++){
- strip.setPixelColor(l, strip.Color(0,0,0,0));
- }
- strip.show(); // This sends the updated pixel's to the hardware.
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement