Advertisement
Guest User

Untitled

a guest
Oct 19th, 2021
75
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 22.24 KB | None | 0 0
  1. // LED-Staircase by Jannomag
  2. // Modified code, original made by Vinz68! Thanks for this!
  3.  
  4.  
  5. #include <Adafruit_NeoPixel.h> // Base library for LED controlling
  6. #include <WS2812FX.h> // Additional library for easy effects in "Partymode"
  7.  
  8. #ifdef __AVR__
  9. #include <avr/power.h>
  10. #endif
  11.  
  12. ///////////////////////////////////////////////////////////////////////////
  13. // Neopixel configuration
  14. #define PIN           9   // Pin used for the LEDs
  15. #define LEDSTRIPS     5   // Number of stairs
  16. #define LEDSPERSTAIR  2   // Number of leds per stair
  17. #define NUMPIXELS     LEDSTRIPS*LEDSPERSTAIR   // Calculate the total number of LEDs
  18. #define BRIGHTNESS    35  // Brightness of the LEDs
  19.  
  20. ///////////////////////////////////////////////////////////////////////////
  21. // Additional input (switches)
  22. #define CLEANINGMODE  4   // Switch for turning all LEDs on
  23. #define PARTYMODE     5   // Switch for enabling fancy RGB party mode
  24.  
  25. ///////////////////////////////////////////////////////////////////////////
  26. // Setup of NeoPixel and WS2812FX
  27. // I was using SK6812 RGBW LEDs. If using RGB-only LED strips like WS2812, change "NEO_GRBW" to "NEO_GRB"
  28. Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUMPIXELS, PIN, NEO_GRBW + NEO_KHZ800);
  29. WS2812FX ws2812fx = WS2812FX(NUMPIXELS, PIN, NEO_GRBW + NEO_KHZ800);
  30.  
  31.  
  32. ///////////////////////////////////////////////////////////////////////////
  33. // Configuration of PIR sensors
  34. int alarmPinTop = 2;              // PIR at the top of the stairs
  35. int alarmPinBottom = 3;           // PIR at the bottom of the stairs                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     ;          // PIR at the bottom of the stairs
  36. int alarmValueTop = LOW;          // Variable to hold the PIR status
  37. int alarmValueBottom = LOW;       // Variable to hold the PIR status
  38.  
  39. ///////////////////////////////////////////////////////////////////////////
  40. // Configuration of the Light dependent resistor (LDR)
  41. bool useLDR = true;               // flag, when true the program uses the LDR, set to "false" if you don't have a LDR sensor.
  42. int LDRSensor = A6;               // Light dependent resistor, Analog Input line
  43. long LDRValue = 0;                // Variable to hold the current measured LDR value
  44. 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!
  45. // 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.
  46. // 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.
  47. const int numReadings = 100;
  48. int readings[numReadings];        // the readings from the analog input
  49. int readIndex = 0;                // the index of the current reading
  50. long total = 0;                   // the running total
  51. long average = 0;                 // the average
  52.  
  53. ///////////////////////////////////////////////////////////////////////////
  54. // configuration for fading, which, somehow doesn't work?
  55. int turnOnSpeed = 200;                // speed to turn on next led-strip, in msec between next strip
  56. int turnOffSpeed = 100;               // speed to turn off next led-strip, in msec between next strip
  57. int keepLedsOnTime = 5000;            // keep leds on for at least .. msec.
  58. int keepLedsOffTime = 0;              // keep leds off for at least .. msec.
  59.  
  60. ///////////////////////////////////////////////////////////////////////////
  61. // constants won't change:
  62. const long LEDinterval = 300;
  63. // Set up Variables for the needed program logic (DO NOT TOUCH THESE!)
  64. unsigned long previousLEDMillis = 0;        // will store last time LED was updated
  65. unsigned long timeOut = 0;        // timestamp to remember when the PIR was triggered.
  66. unsigned long timeLoopStart = 0;  // timestamp to remember when loop has started. used to determine the end-delay (keeps loop running in same intervals)
  67. unsigned long timeTemp = 0;       // temp. var used in time calculations
  68. unsigned long timeDiff = 0;       // temp. var used in time calculations
  69. bool readPIRInputs = true;        // flag, when true, reads the PIR sensors. Disabled (false) by the program when LDR indicated that there is enough light.
  70. int downUp = 0;                   // main program mode, The possible values are:
  71.                                   //  0   =   Idle mode, waiting for PIR trigger to turn stairs on.
  72.                                   //  1   =   Going down, Turning stairs on (direction up to down)
  73.                                   //  2   =   Going up, Turnurning stairs on (direction down to up)
  74.                                   //  3   =   Turning leds off, from top to down
  75.                                   //  4   =   Turninf leds off, from bottom to up
  76.                                   //  5   =   All leds just turned off. After short time, automatically mode will be set to "0".
  77.                                  
  78. ///////////////////////////////////////////////////////////////////////////
  79. //WS2812FX LED Effects fΓΌr Partymode
  80. #define DEFAULT_SPEED         1000  // Speed of the effects
  81. #define DEFAULT_BRIGHTNESS    50    // Brightness of the effects
  82. #define TIMER_MS              5000  // Defines the time in ms for each mode
  83. unsigned long last_change = 0;      // Variable for looping
  84. unsigned long now = 0;              // Variable for looping              
  85. // Filter array for WS2812FX mode counters which should be disabled, not working atm.
  86. const int forbiddenModes[] = {0, 1, 2, 3, 24, 25, 26, 27, 28, 29, 34, 35, 45, 48, 50 };
  87.  
  88. ///////////////////////////////////////////////////////////////////////////
  89. // Configuration of first steps variables
  90. 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
  91. int topStep[] = {8,9};      // Array of pixel numbers for the first step, count backwards from your last pixel number
  92. int bFade = 0;              // Fade state
  93. bool useFirstStepsAtDaylight = true;  // flag, when true the program will use the firstStep function also during daylight (when useLDR=true)
  94.  
  95.  
  96. ///////////////////////////////////////////////////////////////////////////
  97. // Configuration of the cleaning light and partymode
  98. int cleaningModeActive = 0;       // Variable for storing the state of the cleaning light
  99. int partyModeActive = 0;          // Variable for storing the state of party mode
  100. int arduinoRunsLED = 12;          // status LED, to show the Arduino is up and running
  101. int cleaningModeLED = 11;         // status LED for cleaning mode
  102. int partyModeLED = 10;            // status LED for party mode
  103. int arduinoRunsLEDState = LOW;  // ledState used to set the running LED
  104.  
  105.  
  106. void setup() {
  107.   // Initiate WS2812FX
  108.   ws2812fx.init();
  109.   ws2812fx.setBrightness(DEFAULT_BRIGHTNESS);
  110.   ws2812fx.setSpeed(DEFAULT_SPEED);
  111.   ws2812fx.setColor(0xFF000000); // only for RGBW! If using RGB, use 0x000000. FF000000 sets the color to the white LEDs
  112.   ws2812fx.start();
  113.  
  114.   strip.begin();                    // This initializes the NeoPixel library.
  115.  
  116.   strip.setBrightness(BRIGHTNESS);  // Sets the brightness of the LEDs (change 'BRIGHTNESS' defined value when you need to change it)
  117.   clearStrip();                     // Initialize all pixels to 'off', and do strip.show()
  118.  
  119.   // Configure the used digital input & output
  120.   pinMode(alarmPinTop, INPUT_PULLUP);     // for PIR at top of stairs initialise the input pin and use the internal restistor
  121.   pinMode(alarmPinBottom, INPUT_PULLUP);  // for PIR at bottom of stairs initialise the input pin and use the internal restistor
  122.  
  123.   pinMode(CLEANINGMODE, INPUT_PULLUP);    // sets the internal pullup resistor for input. Connect the switches to the Arduino and Ground!
  124.   pinMode(PARTYMODE, INPUT_PULLUP);       // sets the internal pullup resistor for input. Connect the switches to the Arduino and Ground!
  125.  
  126.   pinMode(arduinoRunsLED, OUTPUT);        // Sets the LED as output
  127.   pinMode(cleaningModeLED, OUTPUT);       // Sets the LED as output
  128.   pinMode(partyModeLED, OUTPUT);          // Sets the LED as output
  129.                                                                            
  130.   Serial.begin(9600);      // only required for debugging. Output some settings in the Serial Monitor Window
  131.   Serial.println("-------------------------------------------------");
  132.   Serial.print("NeoPixel used on outout-pin [");  
  133.   Serial.print(PIN);
  134.   Serial.print("] with ");  
  135.   Serial.print(NUMPIXELS);
  136.   Serial.println(" Pixels");
  137.   Serial.print("Number of LED-strips: ");
  138.   Serial.println(LEDSTRIPS);
  139.   Serial.print("Number of LEDs per strip: ");
  140.   Serial.println(LEDSPERSTAIR);
  141.  
  142.   if (useLDR) {
  143.     // initialize all the LDR-readings to current values...
  144.     for (int thisReading = 0; thisReading < numReadings; thisReading++) {
  145.       readings[thisReading] = analogRead(LDRSensor);
  146.       total = total + readings[thisReading];
  147.     }
  148.     // ... and calculate the average value of [numReadings] samples.
  149.     LDRValue = total / numReadings;
  150.  
  151.     Serial.print("LDR used on analog input pin [");
  152.     Serial.print(LDRSensor);
  153.     Serial.println("]");
  154.     Serial.print("Determine number of samples for average value: ");
  155.     Serial.println( numReadings );
  156.     Serial.print("LDR average value = ");
  157.     Serial.println( LDRValue );
  158.     Serial.print("Stairs will work when LDR average value <= ");
  159.     Serial.println(LDRThreshold);
  160.   }
  161.   Serial.println("-------------------------------------------------");
  162.  
  163.  
  164.   delay (2000); // it takes the sensor 2 seconds to scan the area around it before it can detect infrared presence.
  165.   digitalWrite(arduinoRunsLED, HIGH); // Turns on the Arduino-Runs LED after the setup is completed
  166.  
  167. }
  168.  
  169. void loop() {
  170.  
  171.   // While loop for cleaning and party modes
  172.   while ( ( cleaningModeActive == 0 ) && ( partyModeActive == 0 ) ) {    // While both modes are inactive...
  173.     if ( digitalRead(CLEANINGMODE) == LOW ) {   // if the switch for cleaning mode is ON (==LOW)...
  174.       cleaningModeActive=1;                     // set the cleaningModeActive variable to 1
  175.       digitalWrite(arduinoRunsLED, LOW);        // and the running LED off
  176.     }
  177.     if ( digitalRead(PARTYMODE) == LOW ) {      // if the switch for party mode is ON (==LOW)...
  178.       partyModeActive=1;                        // set the cleaningModeActive variable to 1
  179.       digitalWrite(arduinoRunsLED, LOW);        // and the running LED off
  180.     }
  181.    
  182.     // register the current time (in msec, for later use to optimize the execution loop)
  183.     timeLoopStart=millis();
  184.  
  185.     // By default read the PIR inputs (unless LDR sensors are used and it is light enough...)
  186.     readPIRInputs = true;
  187.     if ( useLDR ) {
  188.       // Read the (new) average value of the LDR (we use a sample array to filter out walk-by and sensor spikes)
  189.       LDRValue = readAverageLDR();
  190.  
  191.       // For finetuning, show the LDR value, so the LDRThreshold can be determined ; once it works disable the next statement with '//'
  192.       // Serial.println(LDRValue);
  193.  
  194.       // Check if LDR senses low light conditions ...
  195.       if ( LDRValue >= LDRThreshold ) {  
  196.         // There is enough light, the stairs/ledstips will not be activated (readPIRInputs = false)
  197.         readPIRInputs = false;
  198.  
  199.         unsigned long currentLEDMillis = millis();
  200.  
  201.         // let the running LED blink when the LDR detects light
  202.         if ( currentLEDMillis - previousLEDMillis >= LEDinterval ) {
  203.           // save the last time you blinked the LED
  204.           previousLEDMillis = currentLEDMillis;
  205.  
  206.           // if the LED is off turn it on and vice-versa:
  207.           if ( arduinoRunsLED == LOW ) {
  208.             arduinoRunsLEDState = HIGH;
  209.           } else {
  210.             arduinoRunsLEDState = LOW;
  211.           }
  212.  
  213.           // set the LED with the ledState of the variable:
  214.           digitalWrite(arduinoRunsLED, arduinoRunsLEDState);
  215.         }
  216.  
  217.         // Show that stair will not turn on / on PIR detection, due to LDR logic (daylight mode detected)
  218.         // NOTE: These "Serial" statement can be deleted when everything works fine.
  219.         //       its here for finetuning the LDRThreshold value, which you should configure in the begin of this file.
  220.         Serial.println("LDR detected Daylight according to LDRThreshold configuration.");
  221.         Serial.print("LDR Average value = ");
  222.         Serial.println(LDRValue);
  223.       }
  224.       else {
  225.         // It is dark enough. The stairs/ledstips will be activated. (readPIRInputs = true)
  226.         alarmValueTop = LOW;
  227.         alarmValueBottom = LOW;
  228.         digitalWrite(arduinoRunsLED, HIGH);   // Turns on running LED
  229.       }
  230.     }
  231.    
  232.    
  233.     // Read the PIR inputs ?
  234.     if (readPIRInputs) {
  235.       alarmValueTop = digitalRead(alarmPinTop); // Constantly poll the PIR at the top of the stairs
  236.       alarmValueBottom = digitalRead(alarmPinBottom); // Constantly poll the PIR at the bottom of the stairs
  237.     }
  238.    
  239.     // Check if PIR Top was triggered an leds must be turned on
  240.     if ( (alarmValueTop == HIGH) && (downUp == 0) ) { // the 2nd term indicates that there is currently no activity (up or down)
  241.       timeOut=millis(); // Timestamp when the PIR is triggered. The LED cycle wil then start.
  242.       downUp = 1;
  243.       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
  244.     }
  245.  
  246.     // Check if PIR Bottom was triggered an leds must be turned on
  247.     if ( (alarmValueBottom == HIGH) && (downUp == 0)) { // the 2nd term indicates that there is currently no activity (up or down)
  248.       timeOut=millis(); // Timestamp when the PIR is triggered. The LED cycle wil then start.
  249.       downUp = 2;
  250.       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
  251.     }
  252.  
  253.     // Restart on-timer when a PIR sensor gets HIGH again while the lights are on
  254.     if ( ( downUp != 0 ) && ( ( alarmValueTop == HIGH ) || ( alarmValueBottom == HIGH ) ) ) {
  255.       timeOut=millis();
  256.     }
  257.    
  258.     // Logic to turn the leds off (determines the turn-off direction)
  259.     if ( (downUp!=0) && (timeOut+keepLedsOnTime < millis()) ) { //switch off LED's in the direction of travel.
  260.       if (downUp == 1) {
  261.         downUp = 3;     // mode = turn off leds from top to down
  262.         colourWipeDown(strip.Color(0, 0, 0, 0), turnOffSpeed); // Off
  263.         downUp=5;      // Stairs are just turned off    
  264.       }
  265.       if (downUp == 2) {
  266.         downUp = 4;  // mode = turn off leds from bottom to top      
  267.         colourWipeUp(strip.Color(0, 0, 0, 0), turnOffSpeed); // Off
  268.         downUp=5;      // Stairs are just turned off          
  269.       }
  270.   }
  271.     // Enable firstSteps Effect when needed.
  272.     if (downUp==0) {          // Currently no activity on the stairs ? (in idle mode, not turned (or turning) on or off ?)
  273.  
  274.       // Check if PIRs are read (not when it is dark), or when breathe function must also work during the day
  275.       if ( ( readPIRInputs==true ) && ( (readPIRInputs) || (useFirstStepsAtDaylight) ) ) {    
  276.         firstSteps(); // set fader for firstSteps to 0
  277.       }
  278.       else {
  279.         bFade = 0;
  280.         clearStrip();          // during daylight all leds turned off.
  281.       }
  282.     }
  283.     else if (downUp==5) {     // eventually the stairs led lights will be turned off again (mode=5)
  284.       delay(keepLedsOffTime); // allow small delay/pause and then activate the stairs again with the breathe and motion detection function
  285.       downUp=0;               // set to 0 to allow breathe/motion detection (-1 for debugging one run)
  286.       bFade = 0; // set fader for firstSteps to 0
  287.     }
  288.   }
  289.   // while loops for cleaning and party mode. If the variables are ==1, run the voids.
  290.   while ( cleaningModeActive == 1 ) {
  291.     cleaningMode();
  292.   }
  293.   while ( partyModeActive == 1 ) {
  294.     partyMode();
  295.   }
  296.  
  297. }
  298.  
  299. long readAverageLDR() {
  300.  
  301.   // Subtract the last reading:
  302.   total = total - readings[readIndex];
  303.  
  304.   // Read the current value of the Light Sensor, and store in samples array
  305.   readings[readIndex] = analogRead(LDRSensor);
  306.  
  307.   // Add the reading to the total:
  308.   total = total + readings[readIndex];
  309.  
  310.   // Advance to the next position in the array:
  311.   readIndex = readIndex + 1;
  312.  
  313.   // If we're at the end of the array...
  314.   if (readIndex >= numReadings) {
  315.     // ...wrap around to the beginning:
  316.     readIndex = 0;
  317.   }
  318.  
  319.   // Calculate the average:
  320.   average = total / numReadings;
  321.  
  322.   return (average);
  323. }
  324.  
  325. void cleaningMode() {
  326.   digitalWrite(cleaningModeLED, HIGH);                // turns on the cleaning mode LED
  327.   for (int l=0; l<NUMPIXELS; l++){                    // for every LED
  328.     strip.setBrightness(255);                         // set additional brightness
  329.     strip.setPixelColor(l, strip.Color(0,0,0,255));   // set white as color, note RGB strips need three color values instead of four!
  330.   }
  331.   strip.show();                                       // This sends the updated pixel's to the hardware.  
  332.   if ( digitalRead(CLEANINGMODE) == HIGH ) {          // if the cleaning mode switch is OFF
  333.     digitalWrite(arduinoRunsLED, HIGH);               // turn on the arduino runing LED
  334.     digitalWrite(cleaningModeLED, LOW);               // turn off the cleaning mode LED
  335.     clearStrip();                                     // clear the strip
  336.     downUp=5;                                         // set the stairs variable to 5
  337.     cleaningModeActive=0;                             // set the cleaning mode variable to 0
  338.     strip.setBrightness(BRIGHTNESS);                  // set brightness to the value defined on top
  339.     delay(100);                                       // delay for debouncing the switch
  340.   }
  341. }
  342.  
  343. void partyMode() {
  344.   digitalWrite(partyModeLED, HIGH);   // turn the partyModeLED on
  345.   now = millis();   // start millis()
  346.   ws2812fx.service();   // initiate ws2812fx
  347.   if(now - last_change > TIMER_MS) {    // if the timer reaches TIMER_MS value (default 5000ms)
  348.     uint8_t nextMode = ws2812fx.getMode() + 1;    // add 1 to the mode counter
  349.     // Filter for WS2812FX mode counters. Couldn't get the array from the top working
  350.     // If the nextMode variable equals one of those numbers, set nextMode to the next number which is allowed
  351.     if ( ( nextMode == 1 ) || ( nextMode == 2 ) || ( nextMode == 3 ) ) nextMode = 4;
  352.     if ( ( nextMode == 24 ) || ( nextMode == 25 ) || ( nextMode == 26 ) || ( nextMode == 27 ) || ( nextMode == 28 ) || ( nextMode == 29 ) ) nextMode = 30;
  353.     if ( ( nextMode == 34 ) || ( nextMode == 35 ) ) nextMode = 36;
  354.     if ( ( nextMode == 45 ) ) nextMode = 46;
  355.     if ( ( nextMode == 48 ) ) nextMode = 49;
  356.     if ( ( nextMode == 50 ) ) nextMode = 51;
  357.    
  358.     // 2 tries for filter using the array...doesn't work, so commented out
  359.     /*if ( nextMode == forbiddenModes[nextMode] ) {
  360.       nextMode+1;
  361.     } */
  362.     /*if ( nextMode == forbiddenModes[nextMode] ) {
  363.       nextMode = nextMode +1 ;
  364.     }*/
  365.     ws2812fx.setMode(nextMode % ws2812fx.getModeCount());   // let WS2812FX show the mode
  366.     last_change = now;    // set timer to 0
  367.    
  368.   }
  369.  
  370.   if ( digitalRead(PARTYMODE) == HIGH ) {   // if the partymode switch is HIGH, means it's turned OFF!
  371.     digitalWrite(arduinoRunsLED, HIGH);     // turn on the arduino running LED
  372.     digitalWrite(partyModeLED, LOW);        // turn off the partymode led
  373.     clearStrip();                           // "clear" the strip by using the clearStrip() function
  374.     downUp=5;                               // set the stair mode to 5
  375.     partyModeActive=0;                       // set partyMode to 0
  376.     delay(100);                             // delay for debouncing the switch
  377.   }
  378. }
  379.  
  380. // fades in the first steps, defined by bottomSteps and topSteps. bFade is the brightness of the white color
  381. void firstSteps() {
  382.   for (bFade; bFade < 30; bFade++) {
  383.     for (int i = 0; i < LEDSPERSTAIR; i++) {
  384.       strip.setPixelColor(bottomStep[i], strip.Color(0,0,0,bFade));
  385.       strip.setPixelColor(topStep[i], strip.Color(0,0,0,bFade));
  386.       strip.show();
  387.       delay(0);
  388.     }
  389.     delay(6);
  390.   }
  391. }
  392.  
  393. // Fade light each step strip
  394. void colourWipeDown(uint32_t c, uint16_t wait) {
  395.   for (uint16_t k = 0; k < LEDSTRIPS; k++){
  396.     int start = (NUMPIXELS/LEDSTRIPS) *k;
  397.       for (uint16_t j = start; j < start + LEDSPERSTAIR; j++){
  398.         strip.setPixelColor(j, c);
  399.         delay(0);
  400.     }
  401.     strip.show();
  402.     delay(wait);
  403.   }
  404. }
  405.  
  406.  
  407.  
  408. // Fade light each step strip
  409. void colourWipeUp(uint32_t c, uint16_t wait) {
  410.   for (uint16_t k = LEDSTRIPS; k > 0; k--){
  411.     int start = NUMPIXELS/LEDSTRIPS *k;
  412.     int x = start;
  413.     do
  414.     {
  415.       strip.setPixelColor(x-1, c); // white of RGBW
  416.       x--;
  417.     } while (x > start - LEDSPERSTAIR);
  418.    
  419.     strip.show();
  420.     delay(wait);
  421.   }
  422. }
  423.  
  424. void clearStrip(){
  425.   // All pixels off
  426.   for (int l=0; l<NUMPIXELS; l++){
  427.     strip.setPixelColor(l, strip.Color(0,0,0,0));
  428.   }
  429.   strip.show(); // This sends the updated pixel's to the hardware.  
  430. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement