#define FASTLED_INTERNAL #include #include //#include #define PIN 5 #define N_PIXELS 32 #define BG 0 #define COLOR_ORDER GRB // Try mixing up the letters (RGB, GBR, BRG, etc) for a whole new world of color combinations #define BRIGHTNESS 64 // 0-255, higher number is brighter. #define LED_TYPE WS2812B #define MIC_PIN A0 // Microphone is attached to this analog pin #define MIC_PIN_2 A1 #define DC_OFFSET 0 // DC offset in mic signal - if unusure, leave 0 #define NOISE 10 // Noise/hum/interference in mic signal #define SAMPLES 64 // Length of buffer for dynamic level adjustment #define SAMPLES2 64 #define TOP (N_PIXELS + 2) // Allow dot to go slightly off scale #define PEAK_FALL 20 // Rate of peak falling dot #define N_PIXELS_HALF (N_PIXELS/2) #define GRAVITY -9.81 // Downward (negative) acceleration of gravity in m/s^2 #define h0 1 // Starting height, in meters, of the ball (strip length) #define NUM_BALLS 3 // Number of bouncing balls you want (recommend < 7, but 20 is fun in its own way) #define SPEED .20 // Amount to increment RGB color by each cycle #define ARRAY_SIZE(A) (sizeof(A) / sizeof((A)[0])) //config for balls float h[NUM_BALLS] ; // An array of heights float vImpact0 = sqrt( -2 * GRAVITY * h0 ); // Impact velocity of the ball when it hits the ground if "dropped" from the top of the strip float vImpact[NUM_BALLS] ; // As time goes on the impact velocity will change, so make an array to store those values float tCycle[NUM_BALLS] ; // The time since the last time the ball struck the ground int pos[NUM_BALLS] ; // The integer position of the dot on the strip (LED index) long tLast[NUM_BALLS] ; // The clock time of the last ground strike float COR[NUM_BALLS] ; // Coefficient of Restitution (bounce damping) float greenOffset = 30, blueOffset = 150; byte peakLeft = 0, // Used for falling dot peakRight = 0, dotCountLeft = 0, // Frame counter for delaying dot-falling speed dotCountRight = 0, volCount = 0; // Frame counter for storing past volume data int vol[SAMPLES], // Collection of prior volume samples lvl = 10, // Current "dampened" audio level minLvlAvg = 0, // For dynamic adjustment of graph low & high maxLvlAvg = 512; uint8_t volCountLeft = 0; int volLeft[SAMPLES]; int lvlLeft = 10; int minLvlAvgLeft = 0; int maxLvlAvgLeft = 512; uint8_t volCountRight = 0; int volRight[SAMPLES2]; int lvlRight = 10; int minLvlAvgRight = 0; int maxLvlAvgRight = 512; int brightnessValue, prevBrightnessValue; int sensorDeviationBrightness = 1; int sensitivityValue = 128; // 0 - 255, initial value (value read from the potentiometer if useSensorValues = true) int maxSensitivity = 2 * 255; // let the 'volume' go up to 200%! int ledBrightness = 64; // 0 - 255, initial value (value read from the potentiometer if useSensorValues = true) int nPatterns = 1; int Pattern = 1; Adafruit_NeoPixel strip = Adafruit_NeoPixel(N_PIXELS, PIN, NEO_GRB + NEO_KHZ800); // FOR SYLON ETC uint8_t thisbeat = 23; uint8_t thatbeat = 28; uint8_t thisfade = 2; // How quickly does it fade? Lower = slower fade rate. uint8_t thissat = 255; // The saturation, where 255 = brilliant colours. uint8_t thisbri = 64; //FOR JUGGLE uint8_t numdots = 4; // Number of dots in use. uint8_t faderate = 2; // How long should the trails be. Very low value = longer trails. uint8_t hueinc = 16; // Incremental change in hue between each dot. uint8_t thishue = 0; // Starting hue. uint8_t curhue = 0; uint8_t thisbright = 64; // How bright should the LED/display be. uint8_t basebeat = 5; uint8_t max_bright = 64; // Twinkle float redStates[N_PIXELS]; float blueStates[N_PIXELS]; float greenStates[N_PIXELS]; float Fade = 0.96; // Vu meter 4 const uint32_t Red = strip.Color(128, 0, 0); const uint32_t Yellow = strip.Color(128, 128, 0); const uint32_t Green = strip.Color(0, 128, 0); const uint32_t Blue = strip.Color(0, 0, 128); const uint32_t White = strip.Color(255, 255, 255); const uint32_t Dark = strip.Color(0, 0, 0); unsigned int sample; CRGB leds[N_PIXELS]; int myhue = 0; // Modes enum { } MODE; bool reverse = true; //Ripple variables int color; int center = 0; int step = -1; int maxSteps = 8; float fadeRate = 0.80; int diff; //background color uint32_t currentBg = random(256); uint32_t nextBg = currentBg; byte peak = 16; byte dotCount = 0; byte dotHangCount = 0; //************************************************************************ void setup() { delay( 2000 ); // power-up safety delay FastLED.addLeds(leds, N_PIXELS).setCorrection( TypicalLEDStrip ); FastLED.setBrightness( BRIGHTNESS ); // analogReference(EXTERNAL); memset(vol, 0, sizeof(vol)); LEDS.addLeds(leds, N_PIXELS); strip.setBrightness(ledBrightness); strip.begin(); strip.show(); // Initialize all pixels to 'off' for (int i = 0 ; i < NUM_BALLS ; i++) { // Initialize variables tLast[i] = millis(); h[i] = h0; pos[i] = 0; // Balls start on the ground vImpact[i] = vImpact0; // And "pop" up at vImpact0 tCycle[i] = 0; COR[i] = 0.90 - float(i) / pow(NUM_BALLS, 2); } } void loop() { //for mic uint8_t i; uint16_t minLvlLeft, maxLvlLeft; uint16_t minLvlRight, maxLvlRight; int n, n1, height; // end mic Pattern = Pattern + 1; if ( Pattern > nPatterns ) Pattern = 1; switch (Pattern) { case 1: All(); break; } } void colorWipe(uint32_t c, uint8_t wait) { for (uint16_t i = 0; i < strip.numPixels(); i++) { strip.setPixelColor(i, c); strip.show(); if (Pattern != nPatterns) // <------------- add this return; // <------------ and this delay(wait); } } void Vu4() { uint8_t i; uint16_t minLvlLeft, maxLvlLeft; uint16_t minLvlRight, maxLvlRight; int n, n1, height; n = analogRead(MIC_PIN); // Raw reading from mic n = abs(n - 512 - DC_OFFSET); // Center on zero n = (n <= NOISE) ? 0 : (n - NOISE); // Remove noise/hum lvlLeft = ((lvlLeft * 7) + n) >> 3; // "Dampened" reading (else looks twitchy) // Calculate bar height based on dynamic min/max levels (fixed point): height = TOP * (lvlLeft - minLvlAvgLeft) / (long)(maxLvlAvgLeft - minLvlAvgLeft); if (height < 0L) height = 0; // Clip output else if (height > TOP) height = TOP; if (height > peakLeft) peakLeft = height; // Keep 'peak' dot at top greenOffset += SPEED; blueOffset += SPEED; if (greenOffset >= 255) greenOffset = 0; if (blueOffset >= 255) blueOffset = 0; // Color pixels based on rainbow gradient for (i = 0; i < N_PIXELS_HALF; i++) { if (i >= height) { strip.setPixelColor(N_PIXELS_HALF + i, 0, 0, 0); } else { uint32_t color = Wheel(map(N_PIXELS_HALF + i, 0, strip.numPixels() - 1, (int)greenOffset, (int)blueOffset)); strip.setPixelColor(N_PIXELS_HALF + i, color); } } // Draw peak dot if (peakLeft > 0 && peakLeft <= N_PIXELS_HALF - 1) { uint32_t color = Wheel(map(N_PIXELS_HALF + peakLeft, 0, strip.numPixels() - 1, 30, 150)); strip.setPixelColor(N_PIXELS_HALF + peakLeft, color); } strip.show(); // Update strip // Every few frames, make the peak pixel drop by 1: if (++dotCountLeft >= PEAK_FALL) { //fall rate if (peakLeft > 0) peakLeft--; dotCountLeft = 0; } volLeft[volCountLeft] = n; // Save sample for dynamic leveling if (++volCountLeft >= SAMPLES) volCountLeft = 0; // Advance/rollover sample counter // Get volume range of prior frames minLvlLeft = maxLvlLeft = vol[0]; for (i = 1; i < SAMPLES; i++) { if (volLeft[i] < minLvlLeft) minLvlLeft = volLeft[i]; else if (volLeft[i] > maxLvlLeft) maxLvlLeft = volLeft[i]; } // minLvl and maxLvl indicate the volume range over prior frames, used // for vertically scaling the output graph (so it looks interesting // regardless of volume level). If they're too close together though // (e.g. at very low volume levels) the graph becomes super coarse // and 'jumpy'...so keep some minimum distance between them (this // also lets the graph go to zero when no sound is playing): if ((maxLvlLeft - minLvlLeft) < TOP) maxLvlLeft = minLvlLeft + TOP; minLvlAvgLeft = (minLvlAvgLeft * 63 + minLvlLeft) >> 6; // Dampen min/max levels maxLvlAvgLeft = (maxLvlAvgLeft * 63 + maxLvlLeft) >> 6; // (fake rolling average) n1 = analogRead(MIC_PIN_2); // Raw reading from mic n1 = abs(n1 - 512 - DC_OFFSET); // Center on zero n1 = (n1 <= NOISE) ? 0 : (n1 - NOISE); // Remove noise/hum lvlRight = ((lvlRight * 7) + n1) >> 3; // "Dampened" reading (else looks twitchy) // Calculate bar height based on dynamic min/max levels (fixed point): height = TOP * (lvlRight - minLvlAvgRight) / (long)(maxLvlAvgRight - minLvlAvgRight); if (height < 0L) height = 0; // Clip output else if (height > TOP) height = TOP; if (height > peakRight) peakRight = height; // Keep 'peak' dot at top greenOffset += SPEED; blueOffset += SPEED; if (greenOffset >= 255) greenOffset = 0; if (blueOffset >= 255) blueOffset = 0; // Color pixels based on rainbow gradient for (i = 0; i < N_PIXELS_HALF; i++) { if (i >= height) { strip.setPixelColor(N_PIXELS_HALF - i - 1, 0, 0, 0); } else { uint32_t color = Wheel(map(i, 0, strip.numPixels() - 1, (int)greenOffset, (int)blueOffset)); strip.setPixelColor(N_PIXELS_HALF - i - 1, color); } } // Draw peak dot if (peakRight > 0 && peakRight <= N_PIXELS_HALF - 1) { uint32_t color = Wheel(map(N_PIXELS_HALF - peakRight - 1, 0, strip.numPixels() - 1, 30, 150)); strip.setPixelColor(N_PIXELS_HALF - peakRight - 1, color); } strip.show(); // Update strip // Every few frames, make the peak pixel drop by 1: if (++dotCountRight >= PEAK_FALL) { //fall rate if (peakRight > 0) peakRight--; dotCountRight = 0; } volRight[volCountRight] = n; // Save sample for dynamic leveling if (++volCountRight >= SAMPLES2) volCountRight = 0; // Advance/rollover sample counter // Get volume range of prior frames minLvlRight = maxLvlRight = vol[0]; for (i = 1; i < SAMPLES2; i++) { if (volRight[i] < minLvlRight) minLvlRight = volRight[i]; else if (volRight[i] > maxLvlRight) maxLvlRight = volRight[i]; } // minLvl and maxLvl indicate the volume range over prior frames, used // for vertically scaling the output graph (so it looks interesting // regardless of volume level). If they're too close together though // (e.g. at very low volume levels) the graph becomes super coarse // and 'jumpy'...so keep some minimum distance between them (this // also lets the graph go to zero when no sound is playing): if ((maxLvlRight - minLvlRight) < TOP) maxLvlRight = minLvlRight + TOP; minLvlAvgRight = (minLvlAvgRight * 63 + minLvlRight) >> 6; // Dampen min/max levels maxLvlAvgRight = (maxLvlAvgRight * 63 + maxLvlRight) >> 6; // (fake rolling average) } void Vu3() { uint8_t i; uint16_t minLvlLeft, maxLvlLeft; uint16_t minLvlRight, maxLvlRight; int n, n1, height; n = analogRead(MIC_PIN); // Raw reading from mic n = abs(n - 512 - DC_OFFSET); // Center on zero n = (n <= NOISE) ? 0 : (n - NOISE); // Remove noise/hum lvlLeft = ((lvlLeft * 7) + n) >> 3; // "Dampened" reading (else looks twitchy) // Calculate bar height based on dynamic min/max levels (fixed point): height = TOP * (lvlLeft - minLvlAvgLeft) / (long)(maxLvlAvgLeft - minLvlAvgLeft); if (height < 0L) height = 0; // Clip output else if (height > TOP) height = TOP; if (height > peakLeft) peakLeft = height; // Keep 'peak' dot at top greenOffset += SPEED; blueOffset += SPEED; if (greenOffset >= 255) greenOffset = 0; if (blueOffset >= 255) blueOffset = 0; // Color pixels based on rainbow gradient for (i = 0; i < N_PIXELS_HALF / 2; i++) { if (i >= height) { strip.setPixelColor(N_PIXELS_HALF / 2 - i - 1, 0, 0, 0); } else { uint32_t color = Wheel(map(N_PIXELS_HALF / 2 - i - 1, 1, strip.numPixels() - 1, (int)greenOffset, (int)blueOffset)); strip.setPixelColor(N_PIXELS_HALF / 2 - i - 1, color); } } // Draw peak dot if (peakLeft > 0 && peakLeft <= N_PIXELS_HALF / 2 - 1) { uint32_t color = Wheel(map(N_PIXELS_HALF / 2 - peakLeft - 1, 0, strip.numPixels() - 1, 30, 150)); strip.setPixelColor(N_PIXELS_HALF / 2 - peakLeft - 1, color); } strip.show(); // Update strip // Every few frames, make the peak pixel drop by 1: if (++dotCountLeft >= PEAK_FALL) { //fall rate if (peakLeft > 0) peakLeft--; dotCountLeft = 0; } strip.show(); // Update strip volLeft[volCountLeft] = n; if (++volCountLeft >= SAMPLES) { volCountLeft = 0; } // Get volume range of prior frames minLvlLeft = maxLvlLeft = vol[0]; for (i = 1; i < SAMPLES; i++) { if (volLeft[i] < minLvlLeft) { minLvlLeft = volLeft[i]; } else if (volLeft[i] > maxLvlLeft) { maxLvlLeft = volLeft[i]; } } // minLvl and maxLvl indicate the volume range over prior frames, used // for vertically scaling the output graph (so it looks interesting // regardless of volume level). If they're too close together though // (e.g. at very low volume levels) the graph becomes super coarse // and 'jumpy'...so keep some minimum distance between them (this // also lets the graph go to zero when no sound is playing): if ((maxLvlLeft - minLvlLeft) < TOP) { maxLvlLeft = minLvlLeft + TOP; } minLvlAvgLeft = (minLvlAvgLeft * 63 + minLvlLeft) >> 6; // Dampen min/max levels maxLvlAvgLeft = (maxLvlAvgLeft * 63 + maxLvlLeft) >> 6; // (fake rolling average) n1 = analogRead(MIC_PIN_2); // Raw reading from mic n1 = abs(n1 - 512 - DC_OFFSET); // Center on zero n1 = (n1 <= NOISE) ? 0 : (n1 - NOISE); // Remove noise/hum lvlRight = ((lvlRight * 7) + n1) >> 3; // "Dampened" reading (else looks twitchy) // Calculate bar height based on dynamic min/max levels (fixed point): height = TOP * (lvlRight - minLvlAvgRight) / (long)(maxLvlAvgRight - minLvlAvgRight); if (height < 0L) height = 0; // Clip output else if (height > TOP) height = TOP; if (height > peakRight) peakRight = height; // Keep 'peak' dot at top greenOffset += SPEED; blueOffset += SPEED; if (greenOffset >= 255) greenOffset = 0; if (blueOffset >= 255) blueOffset = 0; // Color pixels based on rainbow gradient for (i = 0; i < N_PIXELS_HALF / 2; i++) { if (i >= height) { strip.setPixelColor(N_PIXELS_HALF / 2 + i, 0, 0, 0); } else { uint32_t color = Wheel(map(N_PIXELS_HALF + i, 1, strip.numPixels(), (int)greenOffset, (int)blueOffset)); strip.setPixelColor(N_PIXELS_HALF / 2 + i, color); } } // Draw peak dot if (peakRight > 0 && peakRight <= N_PIXELS_HALF / 2) { uint32_t color = Wheel(map(N_PIXELS_HALF + peakLeft, 1, strip.numPixels(), 30, 150)); strip.setPixelColor(N_PIXELS_HALF + peakLeft, color); } strip.show(); // Update strip // Every few frames, make the peak pixel drop by 1: if (++dotCountRight >= PEAK_FALL) { //fall rate if (peakRight > 0) peakRight--; dotCountRight = 0; } strip.show(); // Update strip volRight[volCountRight] = n1; if (++volCountRight >= SAMPLES2) { volCountRight = 0; } // Get volume range of prior frames minLvlRight = maxLvlRight = vol[0]; for (i = 1; i < SAMPLES2; i++) { if (volRight[i] < minLvlRight) { minLvlRight = volRight[i]; } else if (volRight[i] > maxLvlRight) { maxLvlRight = volRight[i]; } } // minLvl and maxLvl indicate the volume range over prior frames, used // for vertically scaling the output graph (so it looks interesting // regardless of volume level). If they're too close together though // (e.g. at very low volume levels) the graph becomes super coarse // and 'jumpy'...so keep some minimum distance between them (this // also lets the graph go to zero when no sound is playing): if ((maxLvlRight - minLvlRight) < TOP) { maxLvlRight = minLvlRight + TOP; } minLvlAvgRight = (minLvlAvgRight * 63 + minLvlRight) >> 6; // Dampen min/max levels maxLvlAvgRight = (maxLvlAvgRight * 63 + maxLvlRight) >> 6; // (fake rolling average) } void Balls() { for (int i = 0 ; i < NUM_BALLS ; i++) { tCycle[i] = millis() - tLast[i] ; // Calculate the time since the last time the ball was on the ground // A little kinematics equation calculates positon as a function of time, acceleration (gravity) and intial velocity h[i] = 0.5 * GRAVITY * pow( tCycle[i] / 1000 , 2.0 ) + vImpact[i] * tCycle[i] / 1000; if ( h[i] < 0 ) { h[i] = 0; // If the ball crossed the threshold of the "ground," put it back on the ground vImpact[i] = COR[i] * vImpact[i] ; // and recalculate its new upward velocity as it's old velocity * COR tLast[i] = millis(); if ( vImpact[i] < 0.01 ) vImpact[i] = vImpact0; // If the ball is barely moving, "pop" it back up at vImpact0 } pos[i] = round( h[i] * (N_PIXELS - 1) / h0); // Map "h" to a "pos" integer index position on the LED strip } //Choose color of LEDs, then the "pos" LED on for (int i = 0 ; i < NUM_BALLS ; i++) leds[pos[i]] = CHSV( uint8_t (i * 40) , 255, 255); FastLED.show(); //Then off for the next loop around for (int i = 0 ; i < NUM_BALLS ; i++) { leds[pos[i]] = CRGB::Black; } } // Slightly different, this makes the rainbow equally distributed throughout void rainbowCycle(uint8_t wait) { uint16_t i, j; for (j = 0; j < 256 * 5; j++) { // 5 cycles of all colors on wheel for (i = 0; i < strip.numPixels(); i++) { strip.setPixelColor(i, Wheel(((i * 256 / strip.numPixels()) + j) & 255)); } strip.show(); if (Pattern != nPatterns) // <------------- add this return; // <------------ and this delay(wait); } } // HERE void vu() { uint8_t i; uint16_t minLvlLeft, maxLvlLeft; uint16_t minLvlRight, maxLvlRight; int n, n1, height; n = analogRead(MIC_PIN); // Raw reading from mic n = abs(n - 512 - DC_OFFSET); // Center on zero n = (n <= NOISE) ? 0 : (n - NOISE); // Remove noise/hum lvlLeft = ((lvlLeft * 7) + n) >> 3; // "Dampened" reading (else looks twitchy) // Calculate bar height based on dynamic min/max levels (fixed point): height = TOP * (lvlLeft - minLvlAvgLeft) / (long)(maxLvlAvgLeft - minLvlAvgLeft); if (height < 0L) height = 0; // Clip output else if (height > TOP) height = TOP; if (height > peakLeft) peakLeft = height; // Keep 'peak' dot at top // Color pixels based on rainbow gradient for (i = 0; i < N_PIXELS_HALF; i++) { if (i >= height) { strip.setPixelColor(N_PIXELS_HALF - i - 1, 0, 0, 0); } else { uint32_t color = Wheel(map(i, 0, strip.numPixels() - 1, 30, 150)); strip.setPixelColor(N_PIXELS_HALF - i - 1, color); } } // Draw peak dot if (peakLeft > 0 && peakLeft <= N_PIXELS_HALF - 1) { uint32_t color = Wheel(map(N_PIXELS_HALF - peakLeft - 1, 0, strip.numPixels() - 1, 30, 150)); strip.setPixelColor(N_PIXELS_HALF - peakLeft - 1, color); } strip.show(); // Update strip // Every few frames, make the peak pixel drop by 1: if (++dotCountLeft >= PEAK_FALL) { //fall rate if (peakLeft > 0) peakLeft--; dotCountLeft = 0; } volLeft[volCountLeft] = n; // Save sample for dynamic leveling if (++volCountLeft >= SAMPLES) volCountLeft = 0; // Advance/rollover sample counter // Get volume range of prior frames minLvlLeft = maxLvlLeft = vol[0]; for (i = 1; i < SAMPLES; i++) { if (volLeft[i] < minLvlLeft) minLvlLeft = volLeft[i]; else if (volLeft[i] > maxLvlLeft) maxLvlLeft = volLeft[i]; } // minLvl and maxLvl indicate the volume range over prior frames, used // for vertically scaling the output graph (so it looks interesting // regardless of volume level). If they're too close together though // (e.g. at very low volume levels) the graph becomes super coarse // and 'jumpy'...so keep some minimum distance between them (this // also lets the graph go to zero when no sound is playing): if ((maxLvlLeft - minLvlLeft) < TOP) maxLvlLeft = minLvlLeft + TOP; minLvlAvgLeft = (minLvlAvgLeft * 63 + minLvlLeft) >> 6; // Dampen min/max levels maxLvlAvgLeft = (maxLvlAvgLeft * 63 + maxLvlLeft) >> 6; // (fake rolling average) n1 = analogRead(MIC_PIN_2); // Raw reading from mic n1 = abs(n1 - 512 - DC_OFFSET); // Center on zero n1 = (n1 <= NOISE) ? 0 : (n1 - NOISE); // Remove noise/hum lvlRight = ((lvlRight * 7) + n1) >> 3; // "Dampened" reading (else looks twitchy) // Calculate bar height based on dynamic min/max levels (fixed point): height = TOP * (lvlRight - minLvlAvgRight) / (long)(maxLvlAvgRight - minLvlAvgRight); if (height < 0L) height = 0; // Clip output else if (height > TOP) height = TOP; if (height > peakRight) peakRight = height; // Keep 'peak' dot at top // Color pixels based on rainbow gradient for (i = 0; i < N_PIXELS_HALF; i++) { if (i >= height) { strip.setPixelColor(N_PIXELS_HALF + i, 0, 0, 0); } else { uint32_t color = Wheel(map(N_PIXELS_HALF + i, 0, strip.numPixels(), 30, 150)); strip.setPixelColor(N_PIXELS_HALF + i, color); } } // Draw peak dot if (peakRight > 0 && peakRight <= N_PIXELS_HALF) strip.setPixelColor(N_PIXELS_HALF + peakRight, Wheel(map(N_PIXELS_HALF + peakRight, 0, strip.numPixels(), 30, 150))); strip.show(); // Update strip // Every few frames, make the peak pixel drop by 1: if (++dotCountRight >= PEAK_FALL) { //fall rate if (peakRight > 0) peakRight--; dotCountRight = 0; } volRight[volCountRight] = n1; // Save sample for dynamic leveling if (++volCountRight >= SAMPLES2) volCountRight = 0; // Advance/rollover sample counter // Get volume range of prior frames minLvlRight = maxLvlRight = vol[0]; for (i = 1; i < SAMPLES2; i++) { if (volRight[i] < minLvlRight) minLvlRight = volRight[i]; else if (volRight[i] > maxLvlRight) maxLvlRight = volRight[i]; } // minLvl and maxLvl indicate the volume range over prior frames, used // for vertically scaling the output graph (so it looks interesting // regardless of volume level). If they're too close together though // (e.g. at very low volume levels) the graph becomes super coarse // and 'jumpy'...so keep some minimum distance between them (this // also lets the graph go to zero when no sound is playing): if ((maxLvlRight - minLvlRight) < TOP) maxLvlRight = minLvlRight + TOP; minLvlAvgRight = (minLvlAvgRight * 63 + minLvlRight) >> 6; // Dampen min/max levels maxLvlAvgRight = (maxLvlAvgRight * 63 + maxLvlRight) >> 6; // (fake rolling average) } // Input a value 0 to 255 to get a color value. // The colors are a transition r - g - b - back to r. uint32_t Wheel(byte WheelPos) { if (WheelPos < 85) { return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0); } else if (WheelPos < 170) { WheelPos -= 85; return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3); } else { WheelPos -= 170; return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3); } } void vu2() { uint8_t i; uint16_t minLvlLeft, maxLvlLeft; uint16_t minLvlRight, maxLvlRight; int n, n1, height; n = analogRead(MIC_PIN); // Raw reading from mic n = abs(n - 512 - DC_OFFSET); // Center on zero n = (n <= NOISE) ? 0 : (n - NOISE); // Remove noise/hum lvlLeft = ((lvlLeft * 7) + n) >> 3; // "Dampened" reading (else looks twitchy) // Calculate bar height based on dynamic min/max levels (fixed point): height = TOP * (lvlLeft - minLvlAvgLeft) / (long)(maxLvlAvgLeft - minLvlAvgLeft); if (height < 0L) height = 0; // Clip output else if (height > TOP) height = TOP; if (height > peakLeft) peakLeft = height; // Keep 'peak' dot at top // Color pixels based on rainbow gradient for (i = 0; i < N_PIXELS_HALF; i++) { if (i >= height) { strip.setPixelColor(N_PIXELS_HALF - i - 1, 0, 0, 0); } else { uint32_t color = Wheel(map(i, 2, strip.numPixels() - 1, 30, 150)); strip.setPixelColor(N_PIXELS_HALF - i - 1, color); } } // Draw peak dot if (peakLeft > 0 && peakLeft <= N_PIXELS_HALF - 1) { uint32_t color = Wheel(map(N_PIXELS_HALF - peakLeft - 1, 2, strip.numPixels() - 1, 30, 150)); strip.setPixelColor(N_PIXELS_HALF - peak - 1, color); } strip.show(); // Update strip // Every few frames, make the peak pixel drop by 1: if (++dotCountLeft >= PEAK_FALL) { //fall rate if (peakLeft > 0) peakLeft--; dotCountLeft = 0; } volLeft[volCountLeft] = n; // Save sample for dynamic leveling if (++volCountLeft >= SAMPLES) volCountLeft = 0; // Advance/rollover sample counter // Get volume range of prior frames minLvlLeft = maxLvlLeft = vol[0]; for (i = 1; i < SAMPLES; i++) { if (volLeft[i] < minLvlLeft) minLvlLeft = volLeft[i]; else if (volLeft[i] > maxLvlLeft) maxLvlLeft = volLeft[i]; } // minLvl and maxLvl indicate the volume range over prior frames, used // for vertically scaling the output graph (so it looks interesting // regardless of volume level). If they're too close together though // (e.g. at very low volume levels) the graph becomes super coarse // and 'jumpy'...so keep some minimum distance between them (this // also lets the graph go to zero when no sound is playing): if ((maxLvlLeft - minLvlLeft) < TOP) maxLvlLeft = minLvlLeft + TOP; minLvlAvgLeft = (minLvlAvgLeft * 63 + minLvlLeft) >> 6; // Dampen min/max levels maxLvlAvgLeft = (maxLvlAvgLeft * 63 + maxLvlLeft) >> 6; // (fake rolling average) n1 = analogRead(MIC_PIN_2); // Raw reading from mic n1 = abs(n - 512 - DC_OFFSET); // Center on zero n1 = (n1 <= NOISE) ? 0 : (n1 - NOISE); // Remove noise/hum lvlRight = ((lvlRight * 7) + n1) >> 3; // "Dampened" reading (else looks twitchy) // Calculate bar height based on dynamic min/max levels (fixed point): height = TOP * (lvlRight - minLvlAvgRight) / (long)(maxLvlAvgRight - minLvlAvgRight); if (height < 0L) height = 0; // Clip output else if (height > TOP) height = TOP; if (height > peakRight) peakRight = height; // Keep 'peak' dot at top // Color pixels based on rainbow gradient for (i = 0; i < N_PIXELS_HALF; i++) { if (i >= height) { strip.setPixelColor(N_PIXELS_HALF + i, 0, 0, 0); } else { uint32_t color = Wheel(map(N_PIXELS_HALF + i, 2, strip.numPixels() , 30, 150)); strip.setPixelColor(N_PIXELS_HALF + i, color); } } // Draw peak dot if (peakRight > 0 && peakRight <= N_PIXELS_HALF) { uint32_t color = Wheel(map(N_PIXELS_HALF + peakRight, 2, strip.numPixels() , 30, 150)); strip.setPixelColor(N_PIXELS_HALF + peakRight, color); } strip.show(); // Update strip // Every few frames, make the peak pixel drop by 1: if (++dotCountRight >= PEAK_FALL) { //fall rate if (peakRight > 0) peakRight--; dotCountRight = 0; } volRight[volCountRight] = n1; // Save sample for dynamic leveling if (++volCountRight >= SAMPLES2) volCountRight = 0; // Advance/rollover sample counter // Get volume range of prior frames minLvlRight = maxLvlRight = vol[0]; for (i = 1; i < SAMPLES2; i++) { if (volRight[i] < minLvlRight) minLvlRight = volRight[i]; else if (volRight[i] > maxLvlRight) maxLvlRight = volRight[i]; } // minLvl and maxLvl indicate the volume range over prior frames, used // for vertically scaling the output graph (so it looks interesting // regardless of volume level). If they're too close together though // (e.g. at very low volume levels) the graph becomes super coarse // and 'jumpy'...so keep some minimum distance between them (this // also lets the graph go to zero when no sound is playing): if ((maxLvlRight - minLvlRight) < TOP) maxLvlRight = minLvlRight + TOP; minLvlAvgRight = (minLvlAvgRight * 63 + minLvlRight) >> 6; // Dampen min/max levels maxLvlAvgRight = (maxLvlAvgRight * 63 + maxLvlRight) >> 6; // (fake rolling average) } //here................ void ripple() { if (currentBg == nextBg) { nextBg = random(256); } else if (nextBg > currentBg) { currentBg++; } else { currentBg--; } for (uint16_t l = 0; l < N_PIXELS; l++) { leds[l] = CHSV(currentBg, 255, 50); // strip.setPixelColor(l, Wheel(currentBg, 0.1)); } if (step == -1) { center = random(N_PIXELS); color = random(256); step = 0; } if (step == 0) { leds[center] = CHSV(color, 255, 255); // strip.setPixelColor(center, Wheel(color, 1)); step ++; } else { if (step < maxSteps) { leds[wrap(center + step)] = CHSV(color, 255, pow(fadeRate, step) * 255); // strip.setPixelColor(wrap(center + step), Wheel(color, pow(fadeRate, step))); leds[wrap(center - step)] = CHSV(color, 255, pow(fadeRate, step) * 255); // strip.setPixelColor(wrap(center - step), Wheel(color, pow(fadeRate, step))); if (step > 3) { leds[wrap(center + step - 3)] = CHSV(color, 255, pow(fadeRate, step - 2) * 255); // strip.setPixelColor(wrap(center + step - 3), Wheel(color, pow(fadeRate, step - 2))); leds[wrap(center - step + 3)] = CHSV(color, 255, pow(fadeRate, step - 2) * 255); // strip.setPixelColor(wrap(center - step + 3), Wheel(color, pow(fadeRate, step - 2))); } step ++; } else { step = -1; } } LEDS.show(); delay(50); } int wrap(int step) { if (step < 0) return N_PIXELS + step; if (step > N_PIXELS - 1) return step - N_PIXELS; return step; } void one_color_allHSV(int ahue, int abright) { // SET ALL LEDS TO ONE COLOR (HSV) for (int i = 0 ; i < N_PIXELS; i++ ) { leds[i] = CHSV(ahue, 255, abright); } } void ripple2() { if (BG) { if (currentBg == nextBg) { nextBg = random(256); } else if (nextBg > currentBg) { currentBg++; } else { currentBg--; } for (uint16_t l = 0; l < N_PIXELS; l++) { strip.setPixelColor(l, Wheel(currentBg, 0.1)); } } else { for (uint16_t l = 0; l < N_PIXELS; l++) { strip.setPixelColor(l, 0, 0, 0); } } if (step == -1) { center = random(N_PIXELS); color = random(256); step = 0; } if (step == 0) { strip.setPixelColor(center, Wheel(color, 1)); step ++; } else { if (step < maxSteps) { strip.setPixelColor(wrap(center + step), Wheel(color, pow(fadeRate, step))); strip.setPixelColor(wrap(center - step), Wheel(color, pow(fadeRate, step))); if (step > 3) { strip.setPixelColor(wrap(center + step - 3), Wheel(color, pow(fadeRate, step - 2))); strip.setPixelColor(wrap(center - step + 3), Wheel(color, pow(fadeRate, step - 2))); } step ++; } else { step = -1; } } strip.show(); delay(50); } // Input a value 0 to 255 to get a color value. // The colours are a transition r - g - b - back to r. uint32_t Wheel(byte WheelPos, float opacity) { if (WheelPos < 85) { return strip.Color((WheelPos * 3) * opacity, (255 - WheelPos * 3) * opacity, 0); } else if (WheelPos < 170) { WheelPos -= 85; return strip.Color((255 - WheelPos * 3) * opacity, 0, (WheelPos * 3) * opacity); } else { WheelPos -= 170; return strip.Color(0, (WheelPos * 3) * opacity, (255 - WheelPos * 3) * opacity); } } void pattern2() { sinelon(); // Call our sequence. show_at_max_brightness_for_power(); // Power managed display of LED's. } // loop() void sinelon() { // a colored dot sweeping back and forth, with fading trails fadeToBlackBy( leds, N_PIXELS, thisfade); int pos1 = beatsin16(thisbeat, 0, N_PIXELS); int pos2 = beatsin16(thatbeat, 0, N_PIXELS); leds[(pos1 + pos2) / 2] += CHSV( myhue++ / 64, thissat, thisbri); } // Pattern 3 - JUGGLE void pattern3() { ChangeMe(); juggle(); show_at_max_brightness_for_power(); // Power managed display of LED's. } // loop() void juggle() { // Several colored dots, weaving in and out of sync with each other curhue = thishue; // Reset the hue values. fadeToBlackBy(leds, N_PIXELS, faderate); for ( int i = 0; i < numdots; i++) { leds[beatsin16(basebeat + i + numdots, 0, N_PIXELS)] += CHSV(curhue, thissat, thisbright); //beat16 is a FastLED 3.1 function curhue += hueinc; } } // juggle() void ChangeMe() { // A time (rather than loop) based demo sequencer. This gives us full control over the length of each sequence. uint8_t secondHand = (millis() / 1000) % 30; // IMPORTANT!!! Change '30' to a different value to change duration of the loop. static uint8_t lastSecond = 99; // Static variable, means it's only defined once. This is our 'debounce' variable. if (lastSecond != secondHand) { // Debounce to make sure we're not repeating an assignment. lastSecond = secondHand; if (secondHand == 0) { numdots = 1; // You can change values here, one at a time , or altogether. faderate = 2; } if (secondHand == 10) { numdots = 4; thishue = 128; faderate = 8; } if (secondHand == 20) { hueinc = 48; // Only gets called once, and not continuously for the next several seconds. Therefore, no rainbows. thishue = random8(); } } } // ChangeMe() void Twinkle () { if (random(25) == 1) { uint16_t i = random(N_PIXELS); if (redStates[i] < 1 && greenStates[i] < 1 && blueStates[i] < 1) { redStates[i] = random(256); greenStates[i] = random(256); blueStates[i] = random(256); } } for (uint16_t l = 0; l < N_PIXELS; l++) { if (redStates[l] > 1 || greenStates[l] > 1 || blueStates[l] > 1) { strip.setPixelColor(l, redStates[l], greenStates[l], blueStates[l]); if (redStates[l] > 1) { redStates[l] = redStates[l] * Fade; } else { redStates[l] = 0; } if (greenStates[l] > 1) { greenStates[l] = greenStates[l] * Fade; } else { greenStates[l] = 0; } if (blueStates[l] > 1) { blueStates[l] = blueStates[l] * Fade; } else { blueStates[l] = 0; } } else { strip.setPixelColor(l, 0, 0, 0); } } strip.show(); delay(10); } // TOO HERE void rainbow(uint8_t wait) { uint16_t i, j; for (j = 0; j < 256; j++) { for (i = 0; i < strip.numPixels(); i++) { strip.setPixelColor(i, Wheel((i + j) & 255)); } strip.show(); // check if a button pressed if (Pattern != nPatterns) // <------------- add this return; // <------------ and this delay(wait); } } // List of patterns to cycle through. Each is defined as a separate function below. typedef void (*SimplePatternList[])(); SimplePatternList qPatterns = {vu, vu2, Vu3, Vu4, Twinkle, pattern3, pattern2, ripple2, ripple, Balls}; uint8_t qCurrentPatternNumber = 0; // Index number of which pattern is current void nextPattern() { // add one to the current pattern number, and wrap around at the end qCurrentPatternNumber = (qCurrentPatternNumber + 1) % ARRAY_SIZE( qPatterns); } void All() { // Call the current pattern function once, updating the 'leds' array qPatterns[qCurrentPatternNumber](); EVERY_N_MINUTES( 1 ) { nextPattern(); // change patterns periodically } }