Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include "FastLED.h"
- #define DATA_PIN 0
- #define MIC_PIN A1
- #define DC_OFFSET 0
- #define NOISE 50
- #define SAMPLES 60
- #define TOP (NUM_LEDS +2) // Allow dot to go slightly off scale
- #define PEAK_FALL 20
- #define BUTTON_LEAD 4
- #define NUMBER_OF_MODES 6
- #define LED_TYPE WS2812B
- #define COLOR_ORDER GRB
- #define NUM_LEDS 175
- CRGB leds[NUM_LEDS];
- #define BRIGHTNESS 255
- #define FRAMES_PER_SECOND 120
- //The following constant is the delay between each pixel flash
- const int interval = 25;
- unsigned long previousMillis = millis();
- int mode = 1; //Default mode is one.
- byte
- peak = 0, // Used for falling dot
- dotCount = 0, // Frame counter for delaying dot-falling speed
- 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;
- bool buttonState = LOW;
- bool lastButtonState = LOW;
- void setup(){
- pinMode(BUTTON_LEAD, INPUT_PULLUP);
- memset(vol,0,sizeof(int)*SAMPLES);//Thanks Neil!
- FastLED.addLeds<LED_TYPE, DATA_PIN, COLOR_ORDER>(leds, NUM_LEDS).setCorrection(TypicalLEDStrip);
- FastLED.setBrightness(BRIGHTNESS);
- }
- uint8_t gHue = 0;
- void loop() {
- switch (mode) {
- case 1:
- sinelon();
- break;
- case 2:
- vuscanner();
- break;
- case 3:
- confetti();
- break;
- case 4:
- juggle();
- break;
- case 5:
- bpm();
- break;
- default:
- mode = 1;
- break;
- }
- FastLED.show();
- EVERY_N_MILLISECONDS( 20 ) { gHue++; }
- }
- /* monitor button press */
- bool buttonListener() {
- bool modeChanged = false;
- buttonState = digitalRead(BUTTON_LEAD);
- if (buttonState != lastButtonState) {
- if (buttonState == LOW) {
- mode++;
- modeChanged = true;
- delay(250); // Debounce delay. I checked the best parameter and 250 was it.
- }
- }
- lastButtonState = buttonState;
- return modeChanged;
- }
- void sinelon() {
- if(buttonListener()) { return; }
- if(millis() - previousMillis >= interval) {
- previousMillis = millis();
- fadeToBlackBy(leds, NUM_LEDS, 20);
- int pos = beatsin16(13,0,NUM_LEDS);
- leds[pos] += CHSV(gHue, 255, 192);
- }
- }
- void confetti() {
- if(buttonListener()) { return; }
- if(millis() - previousMillis >= interval) {
- previousMillis = millis();
- fadeToBlackBy(leds, NUM_LEDS, 10);
- int pos = random16(NUM_LEDS);
- leds[pos] += CHSV( gHue + random8(64), 200, 255);
- }
- }
- void juggle() {
- if(buttonListener()) { return; }
- if(millis() - previousMillis >= interval) {
- previousMillis = millis();
- fadeToBlackBy(leds, NUM_LEDS, 20);
- byte dothue = 0;
- for(int i = 0; i < 8; i++) {
- leds[beatsin16(i+7,0,NUM_LEDS)] |= CHSV(dothue, 200, 255);
- dothue += 32;
- }
- }
- }
- void vuscanner() {
- if(buttonListener()) { return; }
- uint8_t i;
- uint16_t minLvl, maxLvl;
- int n, 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
- lvl = ((lvl * 7) + n) >> 3; // "Dampened" reading (else looks twitchy)
- // Calculate bar height based on dynamic min/max levels (fixed point):
- height = TOP * (lvl - minLvlAvg) / (long)(maxLvlAvg - minLvlAvg);
- if (height < 0L) height = 0; // Clip output
- else if (height > TOP) height = TOP;
- if (height > peak) peak = height; // Keep 'peak' dot at top
- // Color pixels based on rainbow gradient
- for (i=0; i<NUM_LEDS; i++) {
- if (i >= height) leds[i].setRGB( 0, 0,0);
- //uncomment one of the following lines to set strip effect
- //else leds[i] = CHSV(map(i,0,NUM_LEDS-1,0,255), 255, 255); //CHSV values set for rainbow
- else leds[i] = CHSV(gHue, 255, 255); //CHSV values set to fade rgb
- }
- // Draw peak dot
- if (peak > 0 && peak <= NUM_LEDS-1) leds[peak] = CHSV(map(peak,0,NUM_LEDS-1,0,255), 255, 255);
- // Every few frames, make the peak pixel drop by 1:
- if (++dotCount >= PEAK_FALL) { // fall rate
- if(peak > 0) peak--;
- dotCount = 0;
- }
- vol[volCount] = n; // Save sample for dynamic leveling
- if (++volCount >= SAMPLES) volCount = 0; // Advance/rollover sample counter
- // Get volume range of prior frames
- minLvl = maxLvl = vol[0];
- for (i=1; i<SAMPLES; i++) {
- if (vol[i] < minLvl) minLvl = vol[i];
- else if (vol[i] > maxLvl) maxLvl = vol[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((maxLvl - minLvl) < TOP) maxLvl = minLvl + TOP;
- minLvlAvg = (minLvlAvg * 63 + minLvl) >> 6; // Dampen min/max levels
- maxLvlAvg = (maxLvlAvg * 63 + maxLvl) >> 6; // (fake rolling average)
- }
- void bpm() {
- if(buttonListener()) { return; }
- if(millis() - previousMillis >= interval) {
- previousMillis = millis();
- uint8_t BeatsPerMinute = 62;
- CRGBPalette16 palette = PartyColors_p;
- uint8_t beat = beatsin8(BeatsPerMinute, 64, 255);
- for(int i = 0; i < NUM_LEDS; i++) {
- leds[i] = ColorFromPalette(palette, gHue+(i*2), beat-gHue+(i*10));
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement