// This #include statement was automatically added by the Spark IDE. #include "neopixel/neopixel.h" /*L3D demo code - EZU added Valentine's'*/ #include //set up the pin that controls the LEDs, the type of LEDs (WS2812B) and the number of LEDs in the cube (8*8*8=512) #define PIXEL_PIN D0 #define PIXEL_COUNT 512 #define PIXEL_TYPE WS2812B #define SIDE 8 SYSTEM_MODE(SEMI_AUTOMATIC); //don't connect to the internet on boot #define BUTTON D2 //press this button to connect to the internet #define MODE D3 #define MICROPHONE 12 #define GAIN_CONTROL 11 #define MAX_POINTS 20 #define SPEED 0.22 #define MIN_SALVO_SPACING 100 bool onlinePressed=false; bool lastOnline=true; #define FIREWORKS 0 #define PLASMA 1 #define SQUARRAL 2 #define PURPLE_RAIN 3 #define VALENTINE 4 #define DEMO_ROUTINES 5 /* datatype definitions */ typedef struct{ unsigned char red, green, blue; } color; typedef struct{ float x; float y; float z; } point; typedef struct{ point raindrops[MAX_POINTS]; bool dead; } salvo; /****************************** * function definitions * ***************************/ void background(color col); color getPixel(int x, int y, int z); void setPixel(int x, int y, int z, color col); color colorMap(float val, float min, float max); color lerpColor(color a, color b, int val, int min, int max); void add(point& a, point& b); /****************************** * Valentine's definitions *******************************/ /* For now just draw a simple red heart in the center */ float vRotAngle = 0.0; /****************************** * fireworks variables * * ****************************/ color black; int centerX, centerY, centerZ; int launchX, launchZ; int red, green, blue; int brightness=35; float radius=0; float speed; bool showRocket; bool exploded; float xInc, yInc, zInc; float rocketX, rocketY, rocketZ; float launchTime; int maxSize; color rocketColor, fireworkColor; /********************************* * squarral variables * * ******************************/ #define TRAIL_LENGTH 50 int frame=0; color pixelColor; point position, increment, pixel; point trailPoints[TRAIL_LENGTH]; int posX, posY, posZ; int incX, incY, incZ; int squarral_zInc=1; int bound=0; int boundInc=1; unsigned char axis=0; bool rainbow=true; //maxBrightness is the brightness limit for each pixel. All color data will be scaled down //so that the largest value is maxBrightness int maxBrightness=50; /******************************** * zplasma variables * * *****************************/ float phase = 0.0; float phaseIncrement = 0.035; // Controls the speed of the moving points. Higher == faster float colorStretch = 0.23; // Higher numbers will produce tighter color bands float plasmaBrightness = 0.2; color plasmaColor; /********************************* * purple rain variables * * *******************************/ int threshhold; int max=-1; int min=10000; float sensitivity=0.5; int maxAmplitude=0; bool aboveThreshhold=false; int timeAboveThreshhold; color rainColor; salvo salvos[SIDE]; /********************************** * flip variables * * ********************************/ //accelerometer pinout #define X 13 #define Y 14 #define Z 15 #define AUTOCYCLE_TIME 30000 #define FACEPLANT 2300 #define UPSIDE_DOWN 1850 #define RIGHTSIDE_UP 2400 #define LEFT_SIDE 1800 #define RIGHT_SIDE 2400 #define FLIP_TIMEOUT 3000 #define FLIP_DEBOUNCE 250 long lastFaceplant=-1*FLIP_TIMEOUT; bool upsideDown=false; bool sideways=false; bool autoCycle=true; //start on autocycle by default int upsideDownTime=-1*FLIP_TIMEOUT; long lastAutoCycle=0; int lastLeft=-1*FLIP_TIMEOUT; int lastRight=-1*FLIP_TIMEOUT; int accelerometer[3]; long lastChange=0; int demo=FIREWORKS; Adafruit_NeoPixel strip=Adafruit_NeoPixel(PIXEL_COUNT, PIXEL_PIN, PIXEL_TYPE); int frameCount=0; /******************************* * fade variables * * ****************************/ bool fading=false; int fadeValue=255; int fadeSpeed=2; void setup() { pinMode(7,OUTPUT); digitalWrite(7, HIGH); // seed the random number generator. THINGS WILL NEVER BE THE SAME AGAIN uint32_t seed = millis(); srand(seed); // Serial.begin(115200); initCube(); initCloudButton(); initSquarral(); initFireworks(); initMicrophone(); initSalvos(); initValentine(); } void initValentine() { } float heartColor(int x, int z, int y) { // translate the coordinates from 0..7 to -2..+2 range float vX=abs((float)x-3.5)/1.8; float vY=((float)y-3.5)*1.8; // y is squished by a factor 3 float vZ=(3.5-(float)z)/1.8; // Rotate 45degrees around Y axis to create a heart float hX= vX * 0.7071 - vZ * 0.7071; //vX*cos(theta) - vZ*sin(theta); float hY= vY; float hZ= vX * 0.7071 + vZ * 0.7071; //vX * sin(theta) + vZ*cos(theta); // Let's give it some heartbeat :-) float rX= hX; float rY= hY * cos(vRotAngle) - hZ * sin(vRotAngle); float rZ= hZ * sin(vRotAngle) + hY * cos(vRotAngle); if(rX>1.0) { //inside a Sphere centered in 1,0,0 if(distance(rX,rY,rZ,1.0,0.0,0.0) <1.0) return(0.5); } else // inside a cylinder diameter 1, around X axis if(distance(rX,rY,rZ,rX,0.0,0.0) < 1.0) return(0.5); //outside! return (0.0); } void doValentine() { int x, y, z; color pixelColor; pixelColor.green=0; pixelColor.blue=0; for(int x=0;x0) pixelColor.red--; if(pixelColor.green>0) pixelColor.green--; if(pixelColor.blue>0) pixelColor.blue--; setPixel(x,y,z, pixelColor); } } //sets a pixel at position (x,y,z) to the col parameter's color void setPixel(int x, int y, int z, color col) { int index = (z*SIDE*SIDE) + (x*SIDE) + y; strip.setPixelColor(index,strip.Color(col.red, col.green, col.blue)); } //returns the color value currently displayed at the x,y,z location color getPixel(int x, int y, int z) { int index = (z*SIDE*SIDE) + (x*SIDE) + y; uint32_t col=strip.getPixelColor(index); color pixelColor; pixelColor.red=(col>>16)&255; pixelColor.green=(col>>8)&255; pixelColor.blue=col&255; return pixelColor; } void initCube() { black.red=0; black.green=0; black.blue=0; } void background(color col) { for(int x=0;xmaxSize) prepRocket(); if(abs(distance(centerX,centerY,centerZ,rocketX, rocketY, rocketZ)-radius)<2) { showRocket=false; exploded=true; } } float distance(float x, float y, float z, float x1, float y1, float z1) { return(sqrt(pow(x-x1,2)+pow(y-y1,2)+pow(z-z1,2))); } void prepRocket() { radius=0; centerX=rand()%8; centerY=rand()%8; centerZ=rand()%8; fireworkColor.red=rand()%brightness; fireworkColor.green=rand()%brightness; fireworkColor.blue=rand()%brightness; launchX=rand()%8; launchZ=rand()%8; rocketX=launchX; rocketY=0; rocketZ=launchZ; launchTime=15+rand()%25; xInc=(centerX-rocketX)/launchTime; yInc=(centerY-rocketY)/launchTime; zInc=(centerZ-rocketZ)/launchTime; showRocket=true; exploded=false; speed=0.15; maxSize=2+rand()%6; //speed=rand()%5; //speed*=0.1; } void initFireworks() { rocketColor.red=255; rocketColor.green=150; rocketColor.blue=100; prepRocket(); } void initSquarral() { position={0,0,0}; increment={1,0,0}; } void squarral() { add(position, increment); if((increment.x==1)&&(position.x==SIDE-1-bound)) increment={0,1,0}; if((increment.x==-1)&&(position.x==bound)) increment={0,-1,0}; if((increment.y==1)&&(position.y==SIDE-1-bound)) increment={-1,0,0}; if((increment.y==-1)&&(position.y==bound)) { increment={1,0,0}; position.z+=squarral_zInc; bound+=boundInc; if((position.z==3)&&(squarral_zInc>0)) boundInc=0; if((position.z==4)&&(squarral_zInc>0)) boundInc=-1; if((position.z==3)&&(squarral_zInc<0)) boundInc=-1; if((position.z==4)&&(squarral_zInc<0)) boundInc=0; if((position.z==0)||(position.z==SIDE-1)) boundInc*=-1; if((position.z==SIDE-1)||(position.z==0)) { squarral_zInc*=-1; if(squarral_zInc==1) { axis=rand()%6; if(rand()%5==0) rainbow=true; else rainbow=false; } } } posX=position.x; posY=position.y; posZ=position.z; incX=increment.x; incY=increment.y; incZ=increment.z; for(int i=TRAIL_LENGTH-1;i>0;i--) { trailPoints[i].x=trailPoints[i-1].x; trailPoints[i].y=trailPoints[i-1].y; trailPoints[i].z=trailPoints[i-1].z; } trailPoints[0].x=pixel.x; trailPoints[0].y=pixel.y; trailPoints[0].z=pixel.z; switch(axis) { case(0): pixel.x=position.x; pixel.y=position.y; pixel.z=position.z; break; case(1): pixel.x=position.z; pixel.y=position.x; pixel.z=position.y; break; case(2): pixel.x=position.y; pixel.y=position.z; pixel.z=position.x; break; case(3): pixel.x=position.z; pixel.y=SIDE-1-position.x; pixel.z=position.y; break; case(4): pixel.x=position.y; pixel.y=position.z; pixel.z=SIDE-1-position.x; break; case(5): pixel.x=position.x; pixel.y=SIDE-1-position.y; pixel.z=position.z; break; } pixelColor=colorMap(frame%1000,0,1000); setPixel((int)pixel.x, (int)pixel.y, (int)pixel.z, pixelColor); for(int i=0;imax) max=mic; float range=max-min; int mean=(max-min)/2; /* if(minmean) max--; */ threshhold=mean+sensitivity*(range/2); if(mic>threshhold) { if((!aboveThreshhold)&&((timeAboveThreshhold-millis())>MIN_SALVO_SPACING)) { launchRain(mic-threshhold); aboveThreshhold=true; timeAboveThreshhold=millis(); } } else aboveThreshhold=false; /* Serial.print(mic); Serial.print(": "); Serial.print(threshhold); Serial.print(" - above threshhold: "); Serial.println(aboveThreshhold); */ } void launchRain(int amplitude) { int i; for(i=0;((imaxAmplitude) maxAmplitude=amplitude; int numDrops=map(amplitude,0, maxAmplitude,0, MAX_POINTS); for(int j=0;jFACEPLANT) //if the cube is upside-down, set the upside-down flag and mark the time when it was flipped { lastFaceplant=millis(); // Serial.println("I'm upside-down!"); } if(accelerometer[1]RIGHT_SIDE) { lastRight=millis(); // Serial.println("I'm on my right side"); } if(accelerometer[2]>RIGHTSIDE_UP) { // Serial.println("whew! I'm rightside-up"); /* if(((millis()-upsideDownTime)FLIP_DEBOUNCE)) { // Serial.println("turned upside down and back"); lastChange=millis(); autoCycle=!autoCycle; upsideDownTime=millis()-FLIP_TIMEOUT; lastLeft=millis()-FLIP_TIMEOUT; //clears the left and right turns, in case the user turned it sideways lastRight=millis()-FLIP_TIMEOUT; //clears the left and right turns, in case the user turned it sideways } if(((millis()-lastLeft)FLIP_DEBOUNCE)) { // Serial.println("turned to the left and back"); lastChange=millis(); decrementDemo(); lastLeft=millis()-FLIP_TIMEOUT; } if(((millis()-lastRight)FLIP_DEBOUNCE)) { // Serial.println("turned to the right and back"); lastChange=millis(); incrementDemo(); lastRight=millis()-FLIP_TIMEOUT; } } */ if(((millis()-lastFaceplant)FLIP_DEBOUNCE)) { autoCycle=false; lastFaceplant=millis()-FLIP_TIMEOUT; color flash; flash.red=maxBrightness; flash.green=maxBrightness; flash.blue=maxBrightness; background(flash); } if(((millis()-lastLeft)FLIP_DEBOUNCE)) { // Serial.println("turned to the left and back"); autoCycle=false; lastChange=millis(); decrementDemo(); lastLeft=millis()-FLIP_TIMEOUT; } if(((millis()-lastRight)FLIP_DEBOUNCE)) { // Serial.println("turned to the right and back"); autoCycle=false; lastChange=millis(); incrementDemo(); lastRight=millis()-FLIP_TIMEOUT; } } if(autoCycle) if(millis()-lastAutoCycle>AUTOCYCLE_TIME) //in autocycle, change demos every 15 seconds { incrementDemo(); // Serial.print("autocycling...Demo is "); // Serial.println(demo); lastAutoCycle=millis(); } } void updateAccelerometer() { for(int i=0;i<3;i++) accelerometer[i]=analogRead(X+i); } void setFadeSpeed() { if(autoCycle) fadeSpeed=2; else fadeSpeed=20; } void incrementDemo() { demo++; setFadeSpeed(); fading=true; if(demo>=DEMO_ROUTINES) demo=0; } void decrementDemo() { demo--; setFadeSpeed(); fading=true; if(demo<0) demo=DEMO_ROUTINES-1; }