Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- //library to manage neopixel LEDS
- #include <Adafruit_NeoPixel.h>
- #include <IRremote.h>
- //********************************local class to wrap light functionality **************************************************
- class LED {
- public:
- //wrapper needs the number of individual leds and the digital pin ID to work with the library
- //initialized in the OFF state
- LED(uint16_t num_leds, uint16_t ctrl_pin)
- : pixels(num_leds,ctrl_pin,NEO_GRBW+NEO_KHZ800), num(num_leds), isOff(true), brightness(40) {
- pixels.begin();
- pixels.setBrightness(brightness);
- show();
- }
- //show current state
- void show() { pixels.show(); }
- //change the global brightness
- uint8_t getBrightness() { return pixels.getBrightness(); }
- void setBrightness(uint8_t brightness) { pixels.setBrightness(brightness); }
- //change the global brightness by some amount but keep it above 0
- void adjustBrightness(int8_t adjustment) {
- if(!isOff) {
- int16_t saturation=(int16_t)getBrightness()+(int16_t)adjustment;
- if(saturation <= 0) saturation = 1;
- else if (saturation > 255) saturation = 255;
- setBrightness((uint8_t)saturation);
- }
- }
- //flip the power state
- void switchPower() {
- isOff = !isOff;
- if(isOff) {
- brightness = pixels.getBrightness();
- pixels.setBrightness(0);
- } else pixels.setBrightness(brightness);
- }
- //get the power state
- bool getOff() { return isOff; }
- //apply a uniform color to all pixels
- void fillPixels(uint8_t r, uint8_t g, uint8_t b, uint8_t w) {
- pixels.fill(pixels.Color(r,g,b,w),0,num);
- }
- //randomize the colors of each pixel with no extra white
- void randomizePixels() {
- for(int i=0;i<num;i++) {
- uint32_t color = pixels.Color(random(256),random(256),random(256),0);
- pixels.setPixelColor(i,color);
- }
- }
- //diffuse the current colors
- const int8_t diffuser[4] = {1,-2,3,0};
- void diffusePixels() {
- for(uint16_t i=0;i<num;i++) {
- uint32_t color = pixels.getPixelColor(i);
- uint8_t* rgbw = reinterpret_cast<uint8_t*>(&color);
- for(int j=0;j<4;j++) {
- if(random(50)-49>0)
- rgbw[j]=random(256);
- else
- rgbw[j]=rgbw[j]+diffuser[j];
- pixels.setPixelColor(i,color);
- }
- }
- }
- //overwrite each led index with the corresponding colors in the order array
- void overwritePixels(uint16_t* litLeds, uint16_t numLit ,uint8_t* newColors) {
- for(uint16_t i=0;i<numLit;i++) {
- uint16_t j=i*4;
- pixels.setPixelColor(litLeds[i],
- pixels.Color(newColors[j],newColors[j+1],newColors[j+2],newColors[j+3]));
- }
- }
- //move iteratively through different colors and hues
- void rollPixels() {
- for (uint16_t i=0;i<num;i++) {
- uint32_t color = pixels.getPixelColor(i);
- uint8_t* rgbw = reinterpret_cast<uint8_t*>(&color);
- uint8_t maxValue,maxIndex,nextValue,nextIndex = 0;
- for(int j=0;j<4;j++)
- if(rgbw[j]>maxValue) {
- maxValue =rgbw[j];
- nextValue=rgbw[j];
- maxIndex = j;
- if(maxIndex==3) nextIndex=0; else nextIndex=maxIndex+1;
- }
- rgbw[maxIndex]=rgbw[maxIndex]-1;
- rgbw[nextIndex]=rgbw[nextIndex]+1;
- pixels.setPixelColor(i,color);
- }
- }
- uint16_t num; //number of leds for iteration
- private:
- Adafruit_NeoPixel pixels; //LED control object
- bool isOff; //current power state
- uint8_t brightness; //stores current brightness while off, used to turn leds back on
- };
- //************************************local class to wrap an IRremote reciever***********************************
- class Remote {
- public:
- //reciever wrapper only requires the irr signal pin
- Remote(uint16_t comm_pin) : reciever(comm_pin) {
- reciever.start();
- }
- //enumeration of capturable signals
- enum Signal {
- POWER,
- MODE,
- PLUS,
- MINUS,
- PAUSE,
- FASTER,
- SLOWER,
- OTHER,
- NIL
- };
- //get most recent signal or NIL for none
- Signal updateSignal() {
- if(reciever.decode()){
- lastMsg = reciever.decodedIRData.command;
- reciever.resume();
- //determine signal from raw command
- switch(lastMsg)
- {
- case 0: return NIL;
- case 69: return POWER;
- case 70: return MODE;
- case 9: return PLUS;
- case 21: return MINUS;
- case 68: return PAUSE;
- case 67: return FASTER;
- case 64: return SLOWER;
- default: return OTHER;
- }
- } else return NIL; //nil for no signal
- }
- //get the last raw signal from updateSignal
- uint16_t getLastSignal() { return lastMsg; }
- private:
- uint16_t lastMsg = 0;
- IRrecv reciever;
- };
- //*****************************local class to wrap i2s microphone************************************
- class Microphone {
- };
- //****************************************************** MAIN PROCESS ******************************************************
- const uint16_t NUM_LED = 21; //number of neopixel leds
- const uint16_t LED_PIN = 7; //arduino pin to neopixel data in
- const uint16_t RMT_PIN = 6; //arudino pin to reciever signal pin
- const long INPUT_DEAD_TIME = 150; //ms wait to prevent overhandling signal
- long inputTime = millis()+1000; //timestamp after which input is allowed
- uint16_t waitTime = 50; //default loop delay time in ms
- //hardware instance wrappers
- LED* lights;
- Remote* remote;
- //enumeration of available led update modes
- enum Mode {
- RED,
- GREEN,
- BLUE,
- WHITE,
- RANDOMIZING,
- SNAKING,
- LOADING,
- SPARKING,
- ROLLING,
- DIFFUSING,
- count
- };
- Mode mode = SNAKING;
- //open serial communication, create wrappers, and start in default state
- void setup() {
- Serial.begin(9600);
- lights = new LED(NUM_LED,LED_PIN);
- remote = new Remote(RMT_PIN);
- delay(100);
- }
- //main update loop; check signal, handle state, set leds, move to next state
- void loop() {
- Remote::Signal signal = remote->updateSignal(); //check remote signal state
- bool wantsNewMode = false; //used to handle mode switching for complex modes which require an initial state
- bool isPaused = false; //flag to flip for pause request
- long now = millis();
- // HANDLE REMOTE SIGNAL IF INPUT IS ALLOWED
- if(now > inputTime) {
- inputTime = now+INPUT_DEAD_TIME; //set time input next allowed
- switch(signal) {
- case Remote::POWER: lights->switchPower(); break;
- case Remote::MODE: wantsNewMode=true; break;
- case Remote::PLUS: lights->adjustBrightness(20); break;
- case Remote::MINUS: lights->adjustBrightness(-20); break;
- case Remote::PAUSE: isPaused = true; break;
- case Remote::SLOWER: waitTime = waitTime+25; break;
- case Remote::FASTER: waitTime = waitTime-25; break;
- case Remote::OTHER:
- Serial.print("Invalid mode from signal: "); Serial.println(remote->getLastSignal()); break;
- case Remote::NIL: inputTime = now; break;
- }
- if(waitTime < 25) waitTime = 25; //prevent super fast updating
- }
- //go to next mode if requested
- if(wantsNewMode) {
- mode = static_cast<Mode>(mode+1);
- if(mode >= count) mode = static_cast<Mode>(0);
- }
- // HANDLE SELECTED MODE IF ON
- if(!lights->getOff())
- switch(mode) {
- //simple modes
- case RED: lights->fillPixels(255,0,0,0); break;
- case GREEN: lights->fillPixels(0,255,0,0); break;
- case BLUE: lights->fillPixels(0,0,255,0); break;
- case WHITE: lights->fillPixels(0,0,0,255); break;
- //routine modes
- case RANDOMIZING: lights->randomizePixels(); break;
- case SNAKING: handleSnaking(); break;
- case SPARKING: handleSparking(); break;
- //fanciful modes with initial state
- case DIFFUSING:
- if(wantsNewMode) lights->randomizePixels();
- else lights->diffusePixels();
- break;
- case ROLLING:
- if(wantsNewMode) lights->randomizePixels();
- else lights->rollPixels();
- break;
- }
- //update the leds and wait to begin the next loop or begin pause loop
- if(isPaused) {
- inputTime = millis()+INPUT_DEAD_TIME;
- //begin pause loop
- while(isPaused) {
- now = millis();
- if(now >= inputTime) {
- inputTime = now+INPUT_DEAD_TIME;
- signal = remote->updateSignal();
- switch(signal)
- {
- case Remote::PAUSE: isPaused = false; break;
- case Remote::FASTER: isPaused = false; break;
- case Remote::SLOWER: isPaused = false; break;
- case Remote::POWER: lights->switchPower(); isPaused = false; break;
- case Remote::PLUS: lights->adjustBrightness(20); lights->show(); break;
- case Remote::MINUS: lights->adjustBrightness(-20); lights->show(); break;
- case Remote::OTHER:
- Serial.println("Invalid signal while paused: "); Serial.println(remote->getLastSignal()); break;
- case Remote::NIL: inputTime = now; break;
- }
- }
- delay(50);
- }
- }
- else {
- //move to next call of loop()
- lights->show();
- delay(waitTime);
- }
- }
- //moves an led snake along the neopixel array
- uint16_t snake[] = {0,8,15};
- uint8_t snakeSkin[] = {250,0,0,0,0,250,0,0,0,0,250,0};
- size_t snakeSize = sizeof(snake) / sizeof(snake[0]);
- void handleSnaking() {
- lights->fillPixels(0,0,0,0);
- lights->overwritePixels(snake, snakeSize, snakeSkin);
- for(int i=0;i<snakeSize;i++) {
- int newIndex = snake[i]+1;
- if(newIndex >= lights->num) newIndex = 0;
- snake[i] = newIndex;
- }
- }
- //handles particle emitters in the neopixel array TODO *****************
- uint16_t spark[] = {7};
- uint8_t bgcolor[] = {250,250,0,0};
- uint8_t spcolor[] = {0,0,250,250};
- size_t numSparks = sizeof(spark) / sizeof(spark[0]);
- void handleSparking() {
- lights->fillPixels(bgcolor[0],bgcolor[1],bgcolor[2],bgcolor[3]);
- for(int i=0;i<numSparks;i++) {
- int newIndex= spark[i];
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement