Guest User

Untitled

a guest
Mar 20th, 2020
158
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Arduino 14.80 KB | None | 0 0
  1. /*
  2.  * Description: Motion activated stair lights.
  3.  * Author: Dean Montgomery
  4.  * Version: 2.2
  5.  *
  6.  * Date: Feb 11, 2016
  7.  *
  8.  * 2 PIR sesors at the top and bottom of the stairs.
  9.  * WS28012B Addressable RGB lights - 2 LEDs on each stair - This spread out the strip of 30 and left 2-pairs for spare bulbs.
  10.  * My Arduino is at the top of the stairs and the RGB strip is connected at the top.
  11.  * This will cycle through several varitions of stair walkers.
  12.  *
  13.  * Version 2 is a rewrite to properly handle multi-tasking the PIR sensors in parallel with LED updates.
  14.  * TODO: Do some code cleanup, variable naming etc.
  15.  *
  16. */
  17.  
  18. #include "FastLED.h"
  19. //#include <avr/eeprom.h>
  20.  
  21. #define NUM_LEDS 26
  22. //#define NUM_LEDS 14
  23. #define LEDS_PER_STAIR 2        // Number of Leds per stair.  Not yet currenlty changable - just noteable
  24. #define BRIGHTNESS  120         // 0...255  ( used in fade7 )
  25. #define PIN_LED 3               // LED Data pin
  26. #define PIN_PIR_DOWN 5          // PIR Downstairs Pin
  27. #define PIN_PIR_UP 7            // PIR Upstairs Pin
  28. #define GO_UP -1                // Direction control - Arduino at top of stairs
  29. #define GO_DOWN 1               // Direction control - Arduino at top of stairs
  30. uint8_t gHue = 0;               // track color shifts.
  31. int8_t gStair = 0;             // track curent stair.
  32. uint8_t gBright = 0;            // track brightness
  33. uint8_t gUpDown[NUM_LEDS];      // directional array to walk/loop up or down stairs.
  34. int8_t gupDownDir = 1;
  35. CRGB    leds[NUM_LEDS];         // setup leds object to access the string
  36. CRGBPalette16 gPalette;         // some favorite and random colors for display.
  37. CRGBPalette16 fade6 =         (CRGB( BRIGHTNESS, 0, 0),      CRGB(BRIGHTNESS,BRIGHTNESS,0), CRGB(0,BRIGHTNESS,0),
  38.                               CRGB(0,BRIGHTNESS,BRIGHTNESS), CRGB(0,0,BRIGHTNESS),         CRGB(BRIGHTNESS, 0, BRIGHTNESS),
  39.                               CRGB( BRIGHTNESS, 0, 0));
  40. CRGBPalette16 z;
  41. int8_t  gLastPalette = 15;      // track last chosen palette.
  42. uint8_t gLastWalk = 1;
  43. unsigned long currentMillis = millis(); // define here so it does not redefine in the loop.
  44. long    previousMillis = 0;
  45. long    previousOffMillis = 0; // countdown power off timer
  46. long    offInterval = 30000; // 1000mills * 30sec
  47. //long offInterval = 7000;
  48. long    interval = 40;
  49. enum Effects { ewalk, eflicker, efade6 };
  50. Effects effect = ewalk;
  51. enum WalkEffects { sparkle, pulsate1, pulsate2, flash };
  52. WalkEffects walk_effect = sparkle;
  53. // Stages of the animation.  Allows for PIR sensor to re-activation the run stage of the animation.
  54. enum Stage { off, stage_init, stage_grow, stage_init_run, stage_run, stage_init_dim, stage_dim };
  55. Stage stage = off;
  56. int i = 0;
  57. int x = 0;
  58. uint8_t var = 0;
  59. uint8_t valTop = 200;
  60. uint8_t rnd = 0;
  61. uint8_t r = 0, g = 0, b = 0, h = 0, s = 0, v = 0;
  62. int8_t stair = 0;
  63. CRGB c1;
  64. CRGB c2;
  65. CRGB trans;
  66. CRGB trans2;
  67.  
  68.  
  69. void setup() {
  70.   delay (3000); // Power Up 3 second safety delay.
  71.   //Serial.begin(57600);
  72.   randomSeed(millis());
  73.   FastLED.addLeds<WS2812B, PIN_LED, GRB>(leds, NUM_LEDS);  // NOTE set LED string type here.
  74.   FastLED.setDither( 0 );  // Stops flikering in animations.
  75.   pinMode(PIN_PIR_DOWN, INPUT);
  76.   pinMode(PIN_PIR_UP, INPUT);
  77.   pinMode(13, OUTPUT);
  78.   digitalWrite(PIN_PIR_DOWN, LOW);
  79.   digitalWrite(PIN_PIR_UP, LOW);
  80.   welcomeRainbow();             // rainbow - give time for PIR sensors to colibrate.
  81.   setUpDown(GO_DOWN);           // populate the array index used for stair direction.
  82.   setPalette();                 // setup some favorite & random colors
  83.   stage = off;
  84. }
  85.  
  86. // Main Loop track PIR sensors.
  87. void loop() {
  88.   currentMillis = millis();
  89.   readSensors();
  90.   if(currentMillis - previousMillis > interval) {
  91.     previousMillis = currentMillis;
  92.     update_effect();
  93.     FastLED.show();
  94.   }
  95.   if((currentMillis - previousOffMillis > offInterval) && stage == stage_run){
  96.     stage = stage_init_dim;
  97.     i = 0; r = 0; g = 0; b = 0;
  98.   }
  99. }
  100.  
  101. void readSensors(){
  102.   if ( digitalRead(PIN_PIR_UP) == HIGH ){  // Walk Down.
  103.     previousOffMillis = currentMillis;
  104.     //if ( stage == stage_run ){
  105.     //  return;  //keep the animation fast.
  106.     //} else
  107.     if ( stage == off ){
  108.       chooseEffects();
  109.       stage = stage_init;
  110.       setUpDown(GO_DOWN);
  111.     } else if ( stage == stage_dim || stage == stage_init_dim ){
  112.       stage = stage_init_run;
  113.     }
  114.   } else if ( digitalRead(PIN_PIR_DOWN) == HIGH  ){ // Walk Up.
  115.     previousOffMillis = currentMillis;
  116.     if ( stage == off ){
  117.       chooseEffects();
  118.       stage = stage_init;
  119.       setUpDown(GO_UP);
  120.     } else if ( stage == stage_dim || stage == stage_init_dim){
  121.       stage = stage_init_run;
  122.     }
  123.   }
  124. }
  125.    
  126. void chooseEffects(){
  127.   randomSeed(millis());
  128.   r = random8(1, 255);
  129.   //effect = efade6;
  130.   //return;
  131.   if ( r >= 0 && r <= 100 ){ effect = ewalk; // My favorite transition with random effect variations } else if ( r > 100 && r <= 175 ){ effect = eflicker; // Candle with embers. } else { effect = efade6; // hueshift rainbow. } } void update_effect(){ if ( effect == ewalk ){ walk(); } else if ( effect == eflicker ){ flicker(); } else if ( effect == efade6 ){ fade(); } } // setup walking gUpDown array in forward: 0,1,2,3... or reverse: ...3,2,1,0 void setUpDown(int8_t upDownDir){ gupDownDir = upDownDir; uint8_t gStairStart = 0; if (upDownDir == GO_UP){ for ( gStair = NUM_LEDS -1; gStair >= 0; gStair-- ){
  132.       gUpDown[gStair] = gStairStart++;
  133.     }
  134.   } else {
  135.     for ( gStair = 0; gStair <= NUM_LEDS; gStair++ ){ gUpDown[gStair] = gStairStart++; } } } // Increment to the next color pair in the palette. void choosePalette(){ if ( gLastPalette >= 15 ) {
  136.     gLastPalette = 0;
  137.   } else {
  138.     gLastPalette+=2;
  139.   }
  140. }
  141.  
  142. // Fill a palette with some colors that my wife picked.
  143. void setPalette(){
  144.   /*
  145.    * Jenn's colors RGB  0 0 81  BLUE
  146.    * 0 100 100 Teal 006464
  147.    * 60 100 100 Cool White 3C6464
  148.    * 60 10 100 Violet 3C0A64
  149.    * 60 0 50 Purple 3C0032
  150.    * start white fades to Teal
  151.    * violet to purple
  152.    * teal to blue
  153.    * red to blue
  154.    */
  155.   uint8_t r = random8(1, 255); // call it once first.
  156.   fill_solid( gPalette, 16, CRGB::Red);
  157.   gPalette[0] = CRGB( 60, 100, 100 ); // Jenn cool white
  158.   gPalette[1] = CRGB( 0, 90, 90 );    // Jenn teal
  159.   gPalette[2] = CRGB( 60, 10, 100 );  // Jenn violet
  160.   gPalette[3] = CRGB( 60, 0, 50 );    // Jenn purple
  161.   gPalette[4] = CRGB( 0, 0, 81);      // Jenn blue
  162.   gPalette[5] = CRGB( 100, 0, 0);     // Red
  163.   gPalette[6] = CRGB( 0, 0, 100);     // Blue
  164.   gPalette[7] = CRGB( 120, 0, 120);
  165.   // Random fill the rest.
  166.   for (uint8_t i = 8; i<16; i++){
  167.     gPalette[i] = CRGB(random8(3,100), random8(3,100), random8(3,100));
  168.   }
  169. }
  170.  
  171. // Walk the stairs adding random effects.
  172. void walk() {
  173.  
  174.   if ( stage == stage_init ){
  175.     valTop = 200;
  176.     // Pick two colors from the palette.
  177.     choosePalette();
  178.     c1 = gPalette[gLastPalette];
  179.     c2 = gPalette[gLastPalette+1];
  180.     // chance of a random palette
  181.     if ( random8( 5 ) == 3 ){
  182.       c1 = CRGB(random8(3,100),random8(3,100),random8(3,100));
  183.       c2 = CRGB(random8(3,100),random8(3,100),random8(3,100));
  184.     }
  185.     // fix random Black palette.
  186.     if ( (int(c1.r) + int(c1.g) + int(c1.b)) < 8 ){
  187.       c1 = gPalette[2];
  188.       c2 = gPalette[4];
  189.     }
  190.     trans = CRGB::Black;
  191.     trans2 = CRGB::Black;
  192.     z[0] = c2;
  193.     z[1] = c1;
  194.     z[2] = CRGB(random8(2,100),random8(2,100),random8(2,100));
  195.     z[3] = c1;
  196.     z[4] = c2;
  197.     //(r2-r1)/ticks * tick)
  198.     gStair=0;
  199.     gBright=0;
  200.     interval=5;
  201.     i = 0;
  202.     x = 0;
  203.     r = 0;
  204.     g = 0;
  205.     b = 0;
  206.     walk_effect = (WalkEffects)random8( 0, 4 );
  207.     stage = stage_grow;
  208.   } else if ( stage == stage_grow ) {
  209.     if (gBright < 255){
  210.       if ( gStair < NUM_LEDS ){ trans = blend(CRGB::Black,c1,gBright); // fade in next two leds[gUpDown[gStair]] = trans; leds[gUpDown[gStair + 1]] = trans; } if ( gStair >= 2 ) { // shift last two stairs to the 2nd color.
  211.         trans2 = blend(c1,c2,gBright);
  212.         leds[gUpDown[gStair - 1]] = trans2;
  213.         leds[gUpDown[gStair - 2]] = trans2;
  214.       }
  215.       gBright = qadd8(gBright, 4);
  216.     } else {
  217.       if ( gStair < NUM_LEDS - 2 ) {
  218.         gStair+=2;  //next stair.
  219.       } else {
  220.         stage = stage_init_run;
  221.         gStair = 0;
  222.       }
  223.       gBright = 0;
  224.     }
  225.   } else if ( stage == stage_init_run ) {
  226.     fill_solid(leds, NUM_LEDS, c2);
  227.     x = 0;
  228.     stage = stage_run;
  229.   } else if ( stage == stage_run ) {
  230.     trans2 = c2;
  231.     randomEffect();  // waits for timer to run out.
  232.   } else if ( stage == stage_init_dim ) {
  233.     interval = 3;
  234.     for(b=0; b<255; b++) {
  235.       trans = blend(trans2,c2,b);
  236.       fill_solid(leds, NUM_LEDS, trans);
  237.       FastLED.show();
  238.       FastLED.delay(8);
  239.     }
  240.     interval = 8;
  241.     gBright = 0;
  242.     gStair = 0;
  243.     stage = stage_dim;
  244.   } else if ( stage == stage_dim ) {
  245.     if ( gBright <= valTop  ) {
  246.       if ( gStair < NUM_LEDS ){
  247.         leds[gUpDown[gStair]].fadeToBlackBy( 6 );
  248.         leds[gUpDown[gStair + 1]].fadeToBlackBy( 6 );
  249.         gBright+=4;
  250.       } else {
  251.         stage = off;
  252.       }
  253.     } else {
  254.       leds[gUpDown[gStair]] = CRGB( 0, 0, 0);
  255.       leds[gUpDown[gStair + 1]] = CRGB( 0, 0, 0);
  256.       gStair += 2;
  257.       gBright = 0;
  258.     }
  259.   } else {
  260.     stage = off;
  261.   }  
  262. }
  263.  
  264. // Random effects for the walk() stair function.
  265. void randomEffect(){
  266.   if ( walk_effect == sparkle ) {
  267.     interval = 8;
  268.     fill_solid(leds, NUM_LEDS, c2);
  269.     addGlitter(80);
  270.   } else if ( walk_effect == pulsate1 ) {
  271.     interval = 10;
  272.     if ( b < 255 ){
  273.       if ( i < 4 ) {
  274.         trans2 = blend(z[i],z[i+1],b);
  275.         fill_solid(leds, NUM_LEDS, trans2);
  276.         b=qadd8(b,1);
  277.       } else {
  278.         i = 0;
  279.       }
  280.     } else {
  281.       i++;
  282.       b=0;
  283.     }
  284.   } else if ( walk_effect == pulsate2 ) {
  285.     interval = 5;
  286.     for(gStair=0; gStair < NUM_LEDS; gStair++) {
  287.       trans2 = blend(c1,c2,quadwave8(r+=( -20 * gupDownDir )));
  288.       leds[gStair] = trans2;
  289.     }
  290.     gStair = 0;
  291.     r = ++g;
  292.   } else if ( walk_effect == flash ) {
  293.     if ( x == 0 ) {
  294.       for(gStair=0; gStair < NUM_LEDS; gStair+=2) {
  295.         leds[gUpDown[gStair]] = CRGB( 100, 100, 100);
  296.         leds[gUpDown[gStair + 1]] = CRGB( 100, 100, 100);
  297.         FastLED.show();
  298.         FastLED.delay(1);
  299.       }
  300.       for(gStair=0; gStair < NUM_LEDS; gStair+=2) {
  301.         leds[gUpDown[gStair]] = c2;
  302.         leds[gUpDown[gStair+1]] = c2;
  303.         FastLED.show();
  304.         FastLED.delay(1);
  305.       }
  306.       x = 1;
  307.       gStair=0;
  308.     }
  309.   }
  310. }
  311.  
  312. // Sparkle rainbow welcome give delay to calibrate pir sensors.  This also indicates if program crashed.
  313. void welcomeRainbow(){
  314.   for ( int i = 0; i < 500; i++ ){
  315.     rainbowWithGlitter();
  316.     FastLED.show();
  317.     FastLED.delay(8.3);
  318.     EVERY_N_MILLISECONDS( 20 ) { gHue++; }
  319.   }
  320.   for (int tick=0; tick < 64; tick++){
  321.     for ( uint8_t i = 0; i < NUM_LEDS; i++ ){
  322.       leds[i].fadeToBlackBy( 64 );
  323.       FastLED.show();
  324.       FastLED.delay(1);
  325.     }
  326.   }
  327. }
  328.  
  329. // built-in FastLED rainbow, plus some random sparkly glitter
  330. void rainbowWithGlitter() {
  331.   rainbow();
  332.   addGlitter(80);
  333. }
  334.  
  335. // paint rainbow
  336. void rainbow() {
  337.   // FastLED's built-in rainbow generator
  338.   fill_rainbow( leds, NUM_LEDS, gHue, 7);
  339. }
  340.  
  341. // Add random glitter
  342. void addGlitter( fract8 chanceOfGlitter) {
  343.   if( random8() < chanceOfGlitter) {
  344.     leds[ random16(NUM_LEDS) ] += CRGB(100,100,100);
  345.   }
  346. }
  347.  
  348. // Candle flicker, blown out, + ember glow
  349. void flicker(){
  350.   if ( stage == stage_init ){
  351.     i = 0;
  352.     rnd = 0;
  353.     r = 0; g = 0; b = 0;
  354.     stair = 0;
  355.     gStair = 0;
  356.     x = 0;
  357.     gBright = 0;
  358.     interval = 27;
  359.     stage = stage_grow;
  360.   } else if ( stage == stage_grow ){
  361.     if ( i <= 10 ){  // number of flicker between steps
  362.       if ( gStair < NUM_LEDS ){  // for each step
  363.         for ( stair = 0; stair <= gStair; stair +=2 ){  // up to currently lit step.
  364.           rnd = random8(1, 4);
  365.           if ( rnd == 2 ){
  366.             gBright = random8(110,140);
  367.             leds[gUpDown[stair]] = CHSV( 60, 200, gBright );
  368.             leds[gUpDown[stair + 1]] = CHSV( 60, 200, gBright );
  369.           }
  370.         }
  371.         i++;
  372.       } else {
  373.         stage = stage_init_run;
  374.       }
  375.     } else {
  376.       i = 0;
  377.       gStair += 2;
  378.     }
  379.   } else if ( stage == stage_init_run ){
  380.     stage = stage_run;
  381.   } else if ( stage == stage_run ){
  382.     for( gStair = 0; gStair < NUM_LEDS; gStair+=2) {  
  383.       rnd = random8(1, 4);
  384.       if ( rnd == 2 ){
  385.         gBright = random8(110,140);
  386.         leds[gStair] = CHSV( 60, 200, gBright );
  387.         leds[gStair+1] = CHSV( 60, 200, gBright );
  388.       }
  389.     }
  390.   } else if ( stage == stage_init_dim ){
  391.     // Blow out candles and leave an ember.
  392.     for(gStair=0; gStair < NUM_LEDS; gStair+=2) {
  393.       rnd = random8(4, 6);
  394.       r = rnd+1;
  395.       g = rnd-2;
  396.       leds[gUpDown[gStair]] = CRGB( r,g,0 );
  397.       leds[gUpDown[gStair + 1]] = CRGB( r,g,0 );
  398.       FastLED.show();
  399.       FastLED.delay(50);
  400.     }
  401.     i = 0;
  402.     gStair=0;
  403.     stage = stage_dim;
  404.   } else if ( stage == stage_dim ){
  405.     if ( i <= 150 ){
  406.       rnd = random8(0, NUM_LEDS);
  407.       leds[gUpDown[rnd]].fadeToBlackBy( 3 );
  408.       i++;
  409.     } else {
  410.       fill_solid(leds, NUM_LEDS, CRGB( 0, 0, 0 ));
  411.       FastLED.show();
  412.       stage = off;
  413.     }
  414.   } else {
  415.     stage = off;
  416.   }  
  417. }
  418.  
  419. // Fade6 effect with each led using a hue shift
  420. void fade(){
  421.   if ( stage == stage_init ){
  422.     gBright = 0;
  423.     gStair = 0;
  424.     interval = 5;
  425.     h = 128;
  426.     s = 140;
  427.     v = BRIGHTNESS;
  428.     r = 0;
  429.     g = ( random8() < 120 );
  430.     stage = stage_grow;
  431.   } else if ( stage == stage_grow ){
  432.     if ( gBright<255 ){
  433.       if ( gStair < NUM_LEDS ){
  434.         trans = blend(CHSV(h,s,0),CHSV(h,s,v),gBright);
  435.         leds[gUpDown[gStair]] = trans;
  436.         leds[gUpDown[gStair + 1]] = trans;
  437.         gBright = qadd8(gBright, 1);
  438.       } else {
  439.         stage = stage_init_run;
  440.         gBright=0;
  441.         gStair=0;
  442.       }
  443.       gBright = qadd8(gBright, 2);
  444.     } else {
  445.       gBright = 0;
  446.       gStair += 2;
  447.     }
  448.   } else if ( stage == stage_init_run ) {
  449.     v = BRIGHTNESS;
  450.     interval = 70;
  451.     stage = stage_run;
  452.   } else if ( stage == stage_run ){
  453.     r = h;
  454.     for(gStair=0; gStair < NUM_LEDS; gStair++) { h+=(3*gupDownDir); // left PIR go down leds[gUpDown[gStair]] = CHSV(h, s, v); } h = r + (3*gupDownDir*-1); } else if ( stage == stage_init_dim ){ interval = 7; h = h - gStair; gStair = 0; stage = stage_dim; } else if ( stage == stage_dim ){ if ( v > 0 ) {
  455.       if ( gStair < NUM_LEDS ){
  456.         leds[gUpDown[gStair]] = CHSV(gStair + h, s, v);
  457.         leds[gUpDown[gStair + 1]]= CHSV(gStair + h, s, v);
  458.         v = qsub8(v, 1);
  459.       } else {
  460.         stage = off;
  461.       }
  462.     } else {
  463.       leds[gUpDown[gStair]] = CRGB( 0, 0, 0);
  464.       leds[gUpDown[gStair + 1]] = CRGB( 0, 0, 0);
  465.       gStair += 2;
  466.       v = BRIGHTNESS;
  467.       h+=2;
  468.     }
  469.   } else {
  470.     stage = off;
  471.   }
  472. }
Add Comment
Please, Sign In to add comment