Advertisement
Guest User

rmt_cntrld_neopix

a guest
Apr 2nd, 2024
119
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 10.04 KB | Source Code | 0 0
  1. //library to manage neopixel LEDS
  2. #include <Adafruit_NeoPixel.h>
  3. #include <IRremote.h>
  4.  
  5.  
  6. //********************************local class to wrap light functionality **************************************************
  7. class LED {
  8.   public:
  9.     //wrapper needs the number of individual leds and the digital pin ID to work with the library
  10.     //initialized in the OFF state
  11.     LED(uint16_t num_leds, uint16_t ctrl_pin)
  12.     : pixels(num_leds,ctrl_pin,NEO_GRBW+NEO_KHZ800), num(num_leds), isOff(true), brightness(40) {
  13.       pixels.begin();
  14.       pixels.setBrightness(brightness);
  15.       show();
  16.     }
  17.  
  18.  
  19.     //show current state
  20.     void show() { pixels.show(); }
  21.     //change the global brightness
  22.     uint8_t getBrightness() { return pixels.getBrightness(); }
  23.     void setBrightness(uint8_t brightness) { pixels.setBrightness(brightness); }
  24.     //change the global brightness by some amount but keep it above 0
  25.     void adjustBrightness(int8_t adjustment) {
  26.       if(!isOff) {
  27.         int16_t saturation=(int16_t)getBrightness()+(int16_t)adjustment;
  28.         if(saturation <= 0) saturation = 1;
  29.         else if (saturation > 255) saturation = 255;
  30.         setBrightness((uint8_t)saturation);
  31.       }
  32.     }
  33.     //flip the power state
  34.     void switchPower() {
  35.       isOff = !isOff;
  36.       if(isOff) {
  37.         brightness = pixels.getBrightness();
  38.         pixels.setBrightness(0);
  39.       } else pixels.setBrightness(brightness);
  40.     }
  41.     //get the power state
  42.     bool getOff() { return isOff; }
  43.  
  44.  
  45.     //apply a uniform color to all pixels
  46.     void fillPixels(uint8_t r, uint8_t g, uint8_t b, uint8_t w) {
  47.       pixels.fill(pixels.Color(r,g,b,w),0,num);
  48.     }
  49.     //randomize the colors of each pixel with no extra white
  50.     void randomizePixels() {
  51.       for(int i=0;i<num;i++) {
  52.         uint32_t color = pixels.Color(random(256),random(256),random(256),0);
  53.         pixels.setPixelColor(i,color);
  54.       }
  55.     }
  56.     //diffuse the current colors
  57.     const int8_t diffuser[4] = {1,-2,3,0};
  58.     void diffusePixels() {
  59.       for(uint16_t i=0;i<num;i++) {
  60.         uint32_t color = pixels.getPixelColor(i);
  61.         uint8_t* rgbw = reinterpret_cast<uint8_t*>(&color);
  62.         for(int j=0;j<4;j++) {
  63.           if(random(50)-49>0)
  64.             rgbw[j]=random(256);
  65.           else
  66.             rgbw[j]=rgbw[j]+diffuser[j];
  67.           pixels.setPixelColor(i,color);
  68.         }
  69.       }
  70.     }
  71.     //overwrite each led index with the corresponding colors in the order array
  72.     void overwritePixels(uint16_t* litLeds, uint16_t numLit ,uint8_t* newColors) {
  73.       for(uint16_t i=0;i<numLit;i++) {
  74.         uint16_t j=i*4;
  75.         pixels.setPixelColor(litLeds[i],
  76.         pixels.Color(newColors[j],newColors[j+1],newColors[j+2],newColors[j+3]));
  77.       }
  78.     }
  79.     //move iteratively through different colors and hues
  80.     void rollPixels() {
  81.       for (uint16_t i=0;i<num;i++) {
  82.         uint32_t color = pixels.getPixelColor(i);
  83.         uint8_t* rgbw = reinterpret_cast<uint8_t*>(&color);
  84.         uint8_t maxValue,maxIndex,nextValue,nextIndex = 0;
  85.         for(int j=0;j<4;j++)
  86.           if(rgbw[j]>maxValue) {
  87.             maxValue =rgbw[j];
  88.             nextValue=rgbw[j];
  89.             maxIndex = j;
  90.             if(maxIndex==3) nextIndex=0; else nextIndex=maxIndex+1;
  91.           }
  92.         rgbw[maxIndex]=rgbw[maxIndex]-1;
  93.         rgbw[nextIndex]=rgbw[nextIndex]+1;
  94.         pixels.setPixelColor(i,color);
  95.       }
  96.     }
  97.  
  98.     uint16_t num; //number of leds for iteration
  99.   private:
  100.     Adafruit_NeoPixel pixels; //LED control object
  101.     bool isOff; //current power state
  102.     uint8_t brightness; //stores current brightness while off, used to turn leds back on
  103. };
  104.  
  105.  
  106.  
  107.  
  108. //************************************local class to wrap an IRremote reciever***********************************
  109. class Remote {
  110.   public:
  111.     //reciever wrapper only requires the irr signal pin
  112.     Remote(uint16_t comm_pin) : reciever(comm_pin) {
  113.       reciever.start();
  114.     }
  115.     //enumeration of capturable signals
  116.     enum Signal {
  117.       POWER,
  118.       MODE,
  119.       PLUS,
  120.       MINUS,
  121.       PAUSE,
  122.       FASTER,
  123.       SLOWER,
  124.       OTHER,
  125.       NIL
  126.     };
  127.     //get most recent signal or NIL for none
  128.     Signal updateSignal() {
  129.       if(reciever.decode()){
  130.         lastMsg = reciever.decodedIRData.command;
  131.         reciever.resume();
  132.         //determine signal from raw command
  133.         switch(lastMsg)
  134.         {
  135.           case 0: return NIL;
  136.           case 69: return POWER;
  137.           case 70: return MODE;
  138.           case 9: return PLUS;
  139.           case 21: return MINUS;
  140.           case 68: return PAUSE;
  141.           case 67: return FASTER;
  142.           case 64: return SLOWER;
  143.           default: return OTHER;
  144.         }
  145.       } else return NIL; //nil for no signal
  146.     }
  147.     //get the last raw signal from updateSignal
  148.     uint16_t getLastSignal() { return lastMsg; }
  149.   private:
  150.     uint16_t lastMsg = 0;
  151.     IRrecv reciever;
  152. };
  153.  
  154.  
  155.  
  156.  
  157. //*****************************local class to wrap i2s microphone************************************
  158. class Microphone {
  159. };
  160.  
  161.  
  162.  
  163.  
  164.  
  165.  
  166.  
  167.  
  168. //****************************************************** MAIN PROCESS ******************************************************
  169. const uint16_t NUM_LED = 21;  //number of neopixel leds
  170. const uint16_t LED_PIN = 7;   //arduino pin to neopixel data in
  171. const uint16_t RMT_PIN = 6;   //arudino pin to reciever signal pin
  172. const long INPUT_DEAD_TIME = 150; //ms wait to prevent overhandling signal
  173. long inputTime = millis()+1000;   //timestamp after which input is allowed
  174. uint16_t waitTime = 50;           //default loop delay time in ms
  175. //hardware instance wrappers
  176. LED* lights;
  177. Remote* remote;
  178. //enumeration of available led update modes
  179. enum Mode {
  180.   RED,
  181.   GREEN,
  182.   BLUE,
  183.   WHITE,
  184.   RANDOMIZING,
  185.   SNAKING,
  186.   LOADING,
  187.   SPARKING,
  188.   ROLLING,
  189.   DIFFUSING,
  190.   count
  191. };
  192. Mode mode = SNAKING;
  193. //open serial communication, create wrappers, and start in default state
  194. void setup() {
  195.   Serial.begin(9600);
  196.   lights = new LED(NUM_LED,LED_PIN);
  197.   remote = new Remote(RMT_PIN);
  198.   delay(100);
  199. }
  200. //main update loop; check signal, handle state, set leds, move to next state
  201. void loop() {
  202.   Remote::Signal signal = remote->updateSignal();  //check remote signal state
  203.   bool wantsNewMode = false;  //used to handle mode switching for complex modes which require an initial state
  204.   bool isPaused = false;      //flag to flip for pause request
  205.   long now = millis();
  206.   // HANDLE REMOTE SIGNAL IF INPUT IS ALLOWED
  207.   if(now > inputTime) {
  208.     inputTime = now+INPUT_DEAD_TIME;  //set time input next allowed
  209.     switch(signal) {
  210.       case Remote::POWER: lights->switchPower(); break;
  211.       case Remote::MODE: wantsNewMode=true; break;
  212.       case Remote::PLUS: lights->adjustBrightness(20); break;
  213.       case Remote::MINUS: lights->adjustBrightness(-20); break;
  214.       case Remote::PAUSE: isPaused = true; break;
  215.       case Remote::SLOWER: waitTime = waitTime+25; break;
  216.       case Remote::FASTER: waitTime = waitTime-25; break;
  217.       case Remote::OTHER:
  218.       Serial.print("Invalid mode from signal: "); Serial.println(remote->getLastSignal()); break;
  219.       case Remote::NIL: inputTime = now; break;
  220.     }
  221.     if(waitTime < 25) waitTime = 25;  //prevent super fast updating
  222.   }
  223.   //go to next mode if requested
  224.   if(wantsNewMode) {
  225.     mode = static_cast<Mode>(mode+1);
  226.     if(mode >= count) mode = static_cast<Mode>(0);
  227.   }
  228.   // HANDLE SELECTED MODE IF ON
  229.   if(!lights->getOff())
  230.     switch(mode) {
  231.       //simple modes
  232.       case RED: lights->fillPixels(255,0,0,0); break;
  233.       case GREEN: lights->fillPixels(0,255,0,0); break;
  234.       case BLUE: lights->fillPixels(0,0,255,0); break;
  235.       case WHITE: lights->fillPixels(0,0,0,255); break;
  236.       //routine modes
  237.       case RANDOMIZING: lights->randomizePixels(); break;
  238.       case SNAKING: handleSnaking(); break;
  239.       case SPARKING: handleSparking(); break;
  240.       //fanciful modes with initial state
  241.       case DIFFUSING:
  242.         if(wantsNewMode) lights->randomizePixels();
  243.         else lights->diffusePixels();
  244.         break;
  245.       case ROLLING:
  246.         if(wantsNewMode) lights->randomizePixels();
  247.         else lights->rollPixels();
  248.         break;
  249.     }
  250.   //update the leds and wait to begin the next loop or begin pause loop
  251.   if(isPaused) {
  252.     inputTime = millis()+INPUT_DEAD_TIME;
  253.     //begin pause loop
  254.     while(isPaused) {
  255.       now = millis();
  256.       if(now >= inputTime) {
  257.         inputTime = now+INPUT_DEAD_TIME;
  258.         signal = remote->updateSignal();
  259.         switch(signal)
  260.         {
  261.           case Remote::PAUSE: isPaused = false; break;
  262.           case Remote::FASTER: isPaused = false; break;
  263.           case Remote::SLOWER: isPaused = false; break;
  264.           case Remote::POWER: lights->switchPower(); isPaused = false; break;
  265.           case Remote::PLUS: lights->adjustBrightness(20); lights->show(); break;
  266.           case Remote::MINUS: lights->adjustBrightness(-20); lights->show(); break;
  267.           case Remote::OTHER:
  268.           Serial.println("Invalid signal while paused: "); Serial.println(remote->getLastSignal()); break;
  269.           case Remote::NIL: inputTime = now; break;
  270.         }
  271.       }
  272.       delay(50);
  273.     }
  274.   }
  275.   else {
  276.     //move to next call of loop()
  277.     lights->show();
  278.     delay(waitTime);
  279.   }
  280. }
  281.  
  282.  
  283. //moves an led snake along the neopixel array
  284. uint16_t snake[] = {0,8,15};
  285. uint8_t snakeSkin[] = {250,0,0,0,0,250,0,0,0,0,250,0};
  286. size_t snakeSize = sizeof(snake) / sizeof(snake[0]);
  287. void handleSnaking() {
  288.   lights->fillPixels(0,0,0,0);
  289.   lights->overwritePixels(snake, snakeSize, snakeSkin);
  290.   for(int i=0;i<snakeSize;i++) {
  291.     int newIndex = snake[i]+1;
  292.     if(newIndex >= lights->num) newIndex = 0;
  293.     snake[i] = newIndex;
  294.   }
  295. }
  296. //handles particle emitters in the neopixel array TODO *****************
  297. uint16_t spark[] = {7};
  298. uint8_t bgcolor[] = {250,250,0,0};
  299. uint8_t spcolor[] = {0,0,250,250};
  300. size_t numSparks = sizeof(spark) / sizeof(spark[0]);
  301. void handleSparking() {
  302.   lights->fillPixels(bgcolor[0],bgcolor[1],bgcolor[2],bgcolor[3]);
  303.   for(int i=0;i<numSparks;i++) {
  304.     int newIndex= spark[i];
  305.   }
  306. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement