임베디드 보드/ESP32

ESP32 + LED STRIP + SOUND SENSOR

ZEROWIN.TECH 2022. 1. 8. 20:38
728x90

ESP32

  • 와이파이 / 블루투스 내장
  • A feature-rich MCU with integrated Wi-Fi and
    Bluetooth connectivity for a wide-range
    of applications
  • ESP32-WROOM-32는 저전력 센서 네트워크에서 음성 인코딩, 음악 스트리밍 및 MP3 디코딩과 같은 가장 까다로운 작업에 이르기까지 다양한 애플리케이션을 대상으로 하는 강력한 일반 Wi-Fi BT BLE MCU 모듈입니다.
https://www.espressif.com/en/products/socs/esp32
참조 https://makernambo.com/54

데이터 시트 https://www.espressif.com/sites/default/files/documentation/esp32-wroom-32_datasheet_en.pdf


 

 

 

아두이노 마이크로폰 소리 증폭 감지 센서 MAX9814 / 사운드

이 멋진 마이크 앰프 모듈은 자동 게인 제어 기능이 내장되어 있어 다른 제품보다 한 단계 더 높습니다. 앰프의 AGC는 가까운 '큰' 소리가 조용해져서 앰프를 압도하지 않고 '잘라내지' 않고 조용하고 멀리 있는 소리도 증폭된다는 것을 의미합니다. 이 앰프는 레벨이 변하는 설정에서 오디오를 녹음하거나 감지하고 항상 앰프 게인을 조정할 필요가 없는 경우에 적합합니다.
https://learn.adafruit.com/adafruit-agc-electret-microphone-amplifier-max9814

 

FASTLED Library

라이브러리 참조

이것은 adafruit(Neopixel, DotStar, LPD8806), Sparkfun(WS2801) 및 aliexpress에서 판매하는 것과 같은 다양한 LED 칩셋을 쉽고 효율적으로 제어하기 위한 라이브러리입니다. LED에 쓰는 것 외에도 이 라이브러리에는 RGB 값을 조작하기 위한 고성능 8비트 수학을 위한 여러 기능과 핀 및 SPI 하드웨어에 대한 액세스를 추상화하기 위한 저수준 클래스가 포함되어 있습니다. 가능한 한. arduino.cc에서 최대 1.6.5까지 Arduino로 테스트했습니다.
  • 새로운 개발자를 위한 빠른 시작 - LED를 연결하고 사용 중인 LED 칩셋의 세부 사항에 대해 생각할 필요가 없습니다.
  • 제로 페인 스위칭 LED 칩셋 - 라이브러리가 지원하는 몇 가지 새로운 LED를 얻을 수 있습니다. 사용 중인 LED의 정의만 변경하면 됩니다. 짜잔! 코드가 새 LED로 실행 중입니다.
  • 고성능 - 비용이 들지 않는 전역 밝기 조정, RGB 조작을 위한 고성능 8비트 수학, 가장 빠른 비트 뱅 SPI 지원과 같은 기능을 통해 FastLED는 LED 패턴에 사용할 수 있는 CPU 주기를 최대한 유지하려고 합니다. 가능한
https://github.com/FastLED/FastLED

라이브러리 샘플 예제

DemoReal100.ino

 
 

 

ColorPalette.ino

다양한 색상 팔레트가 있습니다.

FastLED는 여러 '사전 설정' 팔레트를 제공합니다. RainbowColors_p, RainbowStripeColors_p,
OceanColors_p, CloudColors_p, LavaColors_p, ForestColors_p 및 PartyColors_p.

추가적으로 자신만의 색상 팔레트를 수동으로 정의하거나 다음과 같이 작성할 수 있습니다.
즉석에서 색상 팔레트를 생성하는 코드. 모두 여기에 표시됩니다.
 

ColorPaletteSerialInput.ino

 

  • 시리얼모니터를 이용하여 LED 패턴을 변경합니다.
#include <FastLED.h>
#include <EEPROM.h>

#define LED_PIN     17

// #define NUM_LEDS    128
int NUM_LEDS = 64;
#define BRIGHTNESS  64
#define LED_TYPE    WS2811
#define COLOR_ORDER GRB

// CRGB leds[NUM_LEDS];
CRGB * leds; // [NUM_LEDS];

#define UPDATES_PER_SECOND 100

int user_delay = 100;


CRGBPalette16 currentPalette;
TBlendType    currentBlending;

extern CRGBPalette16 myRedWhiteBluePalette;
extern const TProgmemPalette16 myRedWhiteBluePalette_p PROGMEM;

void writeIntIntoEEPROM(int address, int number)
{ 
  EEPROM.write(address, number >> 8);
  EEPROM.write(address + 1, number & 0xFF);
  EEPROM.commit();
}
int readIntFromEEPROM(int address)
{
  return (EEPROM.read(address) << 8) + EEPROM.read(address + 1);
}


void setup() {
    delay( 3000 ); // power-up safety delay
    EEPROM.begin(100);

    Serial.begin(57600);

    NUM_LEDS = readIntFromEEPROM(0);
    if(1025 < NUM_LEDS) NUM_LEDS = 1024;
    Serial.print("NUM_LEDS=");
    Serial.print(NUM_LEDS);

    leds = (CRGB*)malloc(sizeof(CRGB)* NUM_LEDS);
    FastLED.addLeds<LED_TYPE, LED_PIN, COLOR_ORDER>(leds, NUM_LEDS).setCorrection( TypicalLEDStrip );
    FastLED.setBrightness(  BRIGHTNESS );
    
    // currentPalette = RainbowColors_p;
    // currentBlending = LINEARBLEND;
    int hand = readIntFromEEPROM(4);    
    if(10 < hand) hand = 1;
    Serial.print(",hand=");
    Serial.print(hand);
    ChangePalettePeriodically(hand);

    user_delay = readIntFromEEPROM(2);    
    if(1000 < user_delay) user_delay = 50;
    Serial.print(",user_delay=");
    Serial.println(user_delay);
}


void loop()
{
    if(0 < Serial.available()) {

        String str = Serial.readString();
        char buffer[20];
        str.toCharArray(buffer, 20);
        if(buffer[0] == 'D') {
            user_delay = atoi(buffer+1);
            Serial.print("DELAY=");        
            Serial.println(user_delay);
            writeIntIntoEEPROM(2, user_delay);
        }
        else
        if(buffer[0] == 'N') {
            NUM_LEDS = atoi(buffer+1);
            Serial.print("NUM_LEDS=");        
            Serial.println(NUM_LEDS);

            writeIntIntoEEPROM(0, NUM_LEDS);
            ESP.restart();

        }        
        else {
            int hand= atoi(buffer);
            Serial.println(hand);        
            ChangePalettePeriodically(hand);
            writeIntIntoEEPROM(4, hand);
        }
    }
    // ChangePalettePeriodically();
    
    static uint8_t startIndex = 0;
    startIndex = startIndex + 1; /* motion speed */
    
    FillLEDsFromPaletteColors( startIndex);
    
    FastLED.show();
    if(0 < user_delay) {
        FastLED.delay(user_delay);
    }
}

void FillLEDsFromPaletteColors( uint8_t colorIndex)
{
    uint8_t brightness = 255;
    
    for( int i = 0; i < NUM_LEDS; ++i) {
        leds[i] = ColorFromPalette( currentPalette, colorIndex, brightness, currentBlending);
        colorIndex += 3;
    }
}


// There are several different palettes of colors demonstrated here.
//
// FastLED provides several 'preset' palettes: RainbowColors_p, RainbowStripeColors_p,
// OceanColors_p, CloudColors_p, LavaColors_p, ForestColors_p, and PartyColors_p.
//
// Additionally, you can manually define your own color palettes, or you can write
// code that creates color palettes on the fly.  All are shown here.

// void ChangePalettePeriodically()
// {
//     uint8_t secondHand = (millis() / 1000) % 60;
//     static uint8_t lastSecond = 99;
    
//     if( lastSecond != secondHand) {
//         lastSecond = secondHand;
//         if( secondHand ==  0)  { currentPalette = RainbowColors_p;         currentBlending = LINEARBLEND; }
//         if( secondHand == 10)  { currentPalette = RainbowStripeColors_p;   currentBlending = NOBLEND;  }
//         if( secondHand == 15)  { currentPalette = RainbowStripeColors_p;   currentBlending = LINEARBLEND; }
//         if( secondHand == 20)  { SetupPurpleAndGreenPalette();             currentBlending = LINEARBLEND; }
//         if( secondHand == 25)  { SetupTotallyRandomPalette();              currentBlending = LINEARBLEND; }
//         if( secondHand == 30)  { SetupBlackAndWhiteStripedPalette();       currentBlending = NOBLEND; }
//         if( secondHand == 35)  { SetupBlackAndWhiteStripedPalette();       currentBlending = LINEARBLEND; }
//         if( secondHand == 40)  { currentPalette = CloudColors_p;           currentBlending = LINEARBLEND; }
//         if( secondHand == 45)  { currentPalette = PartyColors_p;           currentBlending = LINEARBLEND; }
//         if( secondHand == 50)  { currentPalette = myRedWhiteBluePalette_p; currentBlending = NOBLEND;  }
//         if( secondHand == 55)  { currentPalette = myRedWhiteBluePalette_p; currentBlending = LINEARBLEND; }
//     }
// }

void ChangePalettePeriodically(int secondHand)
{
        if( secondHand == 0)  { currentPalette = RainbowColors_p;         currentBlending = LINEARBLEND; }
        if( secondHand == 1)  { currentPalette = RainbowStripeColors_p;   currentBlending = NOBLEND;  }
        if( secondHand == 2)  { currentPalette = RainbowStripeColors_p;   currentBlending = LINEARBLEND; }
        if( secondHand == 3)  { SetupPurpleAndGreenPalette();             currentBlending = LINEARBLEND; }
        if( secondHand == 4)  { SetupTotallyRandomPalette();              currentBlending = LINEARBLEND; }
        if( secondHand == 5)  { SetupBlackAndWhiteStripedPalette();       currentBlending = NOBLEND; }
        if( secondHand == 6)  { SetupBlackAndWhiteStripedPalette();       currentBlending = LINEARBLEND; }
        if( secondHand == 7)  { currentPalette = CloudColors_p;           currentBlending = LINEARBLEND; }
        if( secondHand == 8)  { currentPalette = PartyColors_p;           currentBlending = LINEARBLEND; }
        if( secondHand == 9)  { currentPalette = myRedWhiteBluePalette_p; currentBlending = NOBLEND;  }
        if( secondHand == 10)  { currentPalette = myRedWhiteBluePalette_p; currentBlending = LINEARBLEND; }
}

// This function fills the palette with totally random colors.
void SetupTotallyRandomPalette()
{
    for( int i = 0; i < 16; ++i) {
        currentPalette[i] = CHSV( random8(), 255, random8());
    }
}

// This function sets up a palette of black and white stripes,
// using code.  Since the palette is effectively an array of
// sixteen CRGB colors, the various fill_* functions can be used
// to set them up.
void SetupBlackAndWhiteStripedPalette()
{
    // 'black out' all 16 palette entries...
    fill_solid( currentPalette, 16, CRGB::Black);
    // and set every fourth one to white.
    currentPalette[0] = CRGB::White;
    currentPalette[4] = CRGB::White;
    currentPalette[8] = CRGB::White;
    currentPalette[12] = CRGB::White;
    
}

// This function sets up a palette of purple and green stripes.
void SetupPurpleAndGreenPalette()
{
    CRGB purple = CHSV( HUE_PURPLE, 255, 255);
    CRGB green  = CHSV( HUE_GREEN, 255, 255);
    CRGB black  = CRGB::Black;
    
    currentPalette = CRGBPalette16(
                                   green,  green,  black,  black,
                                   purple, purple, black,  black,
                                   green,  green,  black,  black,
                                   purple, purple, black,  black );
}


// This example shows how to set up a static color palette
// which is stored in PROGMEM (flash), which is almost always more
// plentiful than RAM.  A static PROGMEM palette like this
// takes up 64 bytes of flash.
const TProgmemPalette16 myRedWhiteBluePalette_p PROGMEM =
{
    CRGB::Red,
    CRGB::Gray, // 'white' is too bright compared to red and blue
    CRGB::Blue,
    CRGB::Black,
    
    CRGB::Red,
    CRGB::Gray,
    CRGB::Blue,
    CRGB::Black,
    
    CRGB::Red,
    CRGB::Red,
    CRGB::Gray,
    CRGB::Gray,
    CRGB::Blue,
    CRGB::Blue,
    CRGB::Black,
    CRGB::Black
};

테스트

 

소리크기에 따라 LED 로 표현합니다.

 

 

//first include library/ download library: Adafruit Neopixel and FirstLED
    #include <Adafruit_NeoPixel.h>
    #ifdef __AVR__
      #include <avr/power.h>
    #endif

    #include <FastLED.h>
//    #include <EEPROM.h>
    
    #define N_PIXELS    128  // Number of pixels in strand
    #define N_PIXELS_HALF (N_PIXELS/2)
    #define MIC_PIN     2  // Microphone is attached to this analog pin
    
    #define LED_PIN    17  // NeoPixel LED strand is connected to this pin
    #define LED_PIN2    16  // NeoPixel LED strand is connected to this pin
    #define LED_PIN3    18  // NeoPixel LED strand is connected to this pin
    
    #define SAMPLE_WINDOW   10  // Sample window for average level
    #define PEAK_HANG 24 //Time of pause before peak dot falls
    #define PEAK_FALL 20 //Rate of falling peak dot
    #define PEAK_FALL2 8 //Rate of falling peak dot
    #define INPUT_FLOOR 0 // 10 // Lower range of analogRead input
    #define INPUT_CEILING 800 // 1000 //Max range of analogRead input, the lower the value the more sensitive (1023 = max)300 (150)
    #define DC_OFFSET  0  // DC offset in mic signal - if unusure, leave 0
    #define NOISE     10  // Noise/hum/interference in mic signal
    #define SAMPLES   60  // Length of buffer for dynamic level adjustment
    #define TOP       (N_PIXELS + 2) // Allow dot to go slightly off scale
    #define SPEED .20       // Amount to increment RGB color by each cycle
    #define TOP2      (N_PIXELS + 1) // Allow dot to go slightly off scale
    #define LAST_PIXEL_OFFSET N_PIXELS-1
    #define PEAK_FALL_MILLIS 10  // Rate of peak falling dot
    #define POT_PIN 4
    #define BG 0
    #define LAST_PIXEL_OFFSET N_PIXELS-1
    #if FASTLED_VERSION < 3001000
    #error "Requires FastLED 3.1 or later; check github for latest code."
    #endif
    #define BRIGHTNESS  255
    #define LED_TYPE    WS2812B // Only use the LED_PIN for WS2812's
    #define COLOR_ORDER GRB
    #define COLOR_MIN           0
    #define COLOR_MAX         255
    #define DRAW_MAX          100
    #define SEGMENTS            4  // Number of segments to carve amplitude bar into
    #define COLOR_WAIT_CYCLES  10  // Loop cycles to wait between advancing pixel origin
    #define qsubd(x, b)  ((x>b)?b:0)     
    #define qsuba(x, b)  ((x>b)?x-b:0)                                              // Analog Unsigned subtraction macro. if result <0, then => 0. By Andrew Tuline.
    #define ARRAY_SIZE(A) (sizeof(A) / sizeof((A)[0]))

//	#define CENTERED
    
     //Variables will change:
     // 1 x
     // 9 x
     // 2, 3, 4, 5, 6, 7, 8, 10
int buttonPushCounter = 7; // 2; // 1 ; // 0;   // counter for the number of button presses
int buttonState = 0;         // current state of the button
int lastButtonState = 0;

    struct CRGB leds[N_PIXELS];

    Adafruit_NeoPixel strip = Adafruit_NeoPixel(N_PIXELS, LED_PIN, NEO_GRB + NEO_KHZ800);
	Adafruit_NeoPixel strip2 = Adafruit_NeoPixel(N_PIXELS, LED_PIN2, NEO_GRB + NEO_KHZ800);
	Adafruit_NeoPixel strip3 = Adafruit_NeoPixel(N_PIXELS, LED_PIN3, NEO_GRB + NEO_KHZ800);
    
    static uint16_t dist;         // A random number for noise generator.
    uint16_t scale = 30;          // Wouldn't recommend changing this on the fly, or the animation will be really blocky.
    uint8_t maxChanges = 48;      // Value for blending between palettes.
 
    CRGBPalette16 currentPalette(OceanColors_p);
    CRGBPalette16 targetPalette(CloudColors_p);


//new ripple vu
uint8_t timeval = 20;                             // Currently 'delay' value. No, I don't use delays, I use EVERY_N_MILLIS_I instead.
uint16_t loops = 0;                              // Our loops per second counter.
bool     samplepeak = 0;                        // This sample is well above the average, and is a 'peak'.
uint16_t oldsample = 0;                         // Previous sample is used for peak detection and for 'on the fly' values.
bool thisdir = 0;         
//new ripple vu

// Modes
enum 
{
} MODE;
// bool reverse = true;
int BRIGHTNESS_MAX = 80;
int brightness = 20;


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
  reading,
  vol[SAMPLES],       // Collection of prior volume samples
  lvl       = 10,      // Current "dampened" audio level
  minLvlAvg = 0,      // For dynamic adjustment of graph low & high
  maxLvlAvg = 512;    
float
  greenOffset = 30,
  blueOffset = 150;
// cycle variables

int CYCLE_MIN_MILLIS = 2;
int CYCLE_MAX_MILLIS = 1000;
int cycleMillis = 20;
bool paused = false;
long lastTime = 0;
bool boring = true;
bool gReverseDirection = false;
int          myhue =   0;
//vu ripple
uint8_t colour; 
uint8_t myfade = 255;                 // Starting brightness.
#define maxsteps 16                  // Case statement wouldn't allow a variable.
int peakspersec = 0;
int peakcount = 0;
uint8_t bgcol = 0;   
int thisdelay = 20; 
uint8_t max_bright = 255;


  unsigned int sample;

//Samples
#define NSAMPLES 64
unsigned int samplearray[NSAMPLES];
unsigned long samplesum = 0;
unsigned int sampleavg = 0;
int samplecount = 0;
//unsigned int sample = 0;
unsigned long oldtime = 0;
unsigned long newtime = 0;

//Ripple variables
int color;
int center = 0;
int step = -1;
int maxSteps = 16;
float fadeRate = 0.80;
int diff;

//vu 8 variables
int
  origin = 0,
  color_wait_count = 0,
  scroll_color = COLOR_MIN,
  last_intensity = 0,
  intensity_max = 0,
  origin_at_flip = 0;
uint32_t
    draw[DRAW_MAX];
boolean
  growing = false,
  fall_from_left = true;

//background color
uint32_t currentBg = random(256);
uint32_t nextBg = currentBg;
TBlendType    currentBlending;  
     
const int buttonPin = 0;     // the number of the pushbutton pin


    
    byte peak = 16;      // Peak level of column; used for falling dots
//    unsigned int sample;
     
    byte dotCount = 0;  //Frame counter for peak dot
    byte dotHangCount = 0; //Frame counter for holding peak dot
     
void setup() {
      
     // analogReference(EXTERNAL);
        
    pinMode(buttonPin, INPUT);  
  //initialize the buttonPin as output
   digitalWrite(buttonPin, HIGH); 
     
      // Serial.begin(9600);
      strip.begin();
      strip.show(); // all pixels to 'off'
      strip2.begin();
      strip2.show(); // all pixels to 'off'
      strip3.begin();
      strip3.show(); // all pixels to 'off'

      Serial.begin(57600);
      delay(100);
 
  LEDS.addLeds<LED_TYPE, LED_PIN, COLOR_ORDER>(leds,N_PIXELS).setCorrection(TypicalLEDStrip); 
  LEDS.addLeds<LED_TYPE, LED_PIN2, COLOR_ORDER>(leds,N_PIXELS).setCorrection(TypicalLEDStrip); 
  LEDS.addLeds<LED_TYPE, LED_PIN3, COLOR_ORDER>(leds,N_PIXELS).setCorrection(TypicalLEDStrip); 
  
  LEDS.setBrightness(BRIGHTNESS);
  dist = random16(12345);          // A semi-random number for our noise generator

 }


float fscale( float originalMin, float originalMax, float newBegin, float newEnd, float inputValue, float curve){

  float OriginalRange = 0;
  float NewRange = 0;
  float zeroRefCurVal = 0;
  float normalizedCurVal = 0;
  float rangedValue = 0;
  boolean invFlag = 0;


  // condition curve parameter
  // limit range

  if (curve > 10) curve = 10;
  if (curve < -10) curve = -10;

  curve = (curve * -.1) ; // - invert and scale - this seems more intuitive - postive numbers give more weight to high end on output
  curve = pow(10, curve); // convert linear scale into lograthimic exponent for other pow function

  
  // Check for out of range inputValues
  if (inputValue < originalMin) {
    inputValue = originalMin;
  }
  if (inputValue > originalMax) {
    inputValue = originalMax;
  }

  // Zero Refference the values
  OriginalRange = originalMax - originalMin;

  if (newEnd > newBegin){
    NewRange = newEnd - newBegin;
  }
  else
  {
    NewRange = newBegin - newEnd;
    invFlag = 1;
  }

  zeroRefCurVal = inputValue - originalMin;
  normalizedCurVal  =  zeroRefCurVal / OriginalRange;   // normalize to 0 - 1 float

 
  // Check for originalMin > originalMax  - the math for all other cases i.e. negative numbers seems to work out fine
  if (originalMin > originalMax ) {
    return 0;
  }

  if (invFlag == 0){
    rangedValue =  (pow(normalizedCurVal, curve) * NewRange) + newBegin;

  }
  else     // invert the ranges
  { 
    rangedValue =  newBegin - (pow(normalizedCurVal, curve) * NewRange);
  }

  return rangedValue;
  
  }
    
  void loop() {

    if(0 < Serial.available()) {

      String str = Serial.readString();
      char buffer[20];
      str.toCharArray(buffer, 20);
      int nRead= atoi(buffer);
      Serial.println(nRead);
      buttonPushCounter = nRead;
    }
  
    //for mic
    uint8_t  i;
    uint16_t minLvl, maxLvl;
    int      n, height;
    // end mic

  // Serial.println("loop");

 // read the pushbutton input pin:
  // buttonState = digitalRead(buttonPin);
  //   // compare the buttonState to its previous state
  // if (buttonState != lastButtonState) {
  //   // if the state has changed, increment the counter
  //   if (buttonState == HIGH) {
  //     // if the current state is HIGH then the button
  //     // wend from off to on:
  //     buttonPushCounter++;
  //     Serial.println("on");
  //     Serial.print("number of button pushes:  ");
  //     Serial.println(buttonPushCounter);
  //     if(buttonPushCounter==16) {
  //     buttonPushCounter=1;
  //     }
  //   } 
  //   else {
  //     // if the current state is LOW then the button
  //     // wend from on to off:
  //     Serial.println("off"); 
  //   }
  // }
  // // save the current state as the last state, 
  // //for next time through the loop
  // lastButtonState = buttonState;


switch (buttonPushCounter){

    case 1:
     buttonPushCounter==1; {     
     All2(); // NORMAL
      break;}     
 
      case 2:
     buttonPushCounter==2; {     
     vu(); // NORMAL
      break;}     
       
     case 3:
     buttonPushCounter==3; {
       vu1(); // Centre out
      break;}
      
   case 4:
     buttonPushCounter==4; {
    vu2(); // Centre Inwards
      break;}
         
    case 5:
     buttonPushCounter==5; {
    Vu3(); // Normal Rainbow
      break;}  

      case 6:
     buttonPushCounter==6; {
    Vu4(); // Centre rainbow
      break;} 

       case 7:
     buttonPushCounter==7; {
    Vu5(0); // Shooting Star
      break;} 
       case 71:
     {
    Vu5(1); // Shooting Star
      break;} 
       case 72:
     {
    Vu5(2); // Shooting Star
      break;} 

         case 8:
     buttonPushCounter==8; {
      Vu6(0); // Falling star
      break;} 
         case 81:
     buttonPushCounter==8; {
      Vu6(1); // Falling star
      break;} 
         case 82:
     buttonPushCounter==8; {
      Vu6(2); // Falling star
      break;} 

          // case 9:
    //  buttonPushCounter==9; {
    //   vu7(); // Ripple with background
      // break;} 

            case 10:
     buttonPushCounter==10; {
    vu8(); // Shatter
      break;} 

            case 11:
     buttonPushCounter==11; {
    vu9(); // Pulse
      break;} 

            case 12:
     buttonPushCounter==12; {
     vu10(); // stream
      break;} 
           case 13:
     buttonPushCounter==13; {
     vu11(); // Ripple without Background
      break;} 

            case 14:
     buttonPushCounter==14; {
     vu12(); // Ripple without Background
      break;} 

    case 15:
     buttonPushCounter==15; {
     vu13(); // Ripple without Background
      break;} 

   
    case 16:
      buttonPushCounter==16; {
      colorWipe(strip.Color(0, 0, 0), 10); // Black
      break;}      
  } 

//	delay(1);

}

void colorWipe(uint32_t c, uint8_t wait) {
	
  for(uint16_t i=0; i<strip.numPixels(); i++) {
      strip.setPixelColor(i, c);
      strip2.setPixelColor(i, c);
      strip3.setPixelColor(i, c);
      strip.show();
      strip2.show();
      strip3.show();

//      if (digitalRead(buttonPin) != lastButtonState)  // <------------- add this
//       return;         // <------------ and this

      delay(wait);
}}

#define MAX_LEN 100
int array[MAX_LEN]; // 1sec
int valueOld = 0;
int mic_in() {
  // put your main code here, to run repeatedly:
  int value = analogRead(2) + 100;
  memcpy(array, &array[1], sizeof(array) - sizeof(int));
  array[MAX_LEN-1] =  abs(value-valueOld);
  valueOld = value;
    double total = 0;
    for(int i = 0; i < MAX_LEN; i++) {
      total += array[i];
    }
    total /= MAX_LEN;
//    Serial.println(total); 
//    Serial.print(',');
//    Serial.println(value/4);

  return total;
  // return value/2;
}

void vu() {
 
  uint8_t  i;
  uint16_t minLvl, maxLvl;
  int      n, height;
  
  n   = mic_in(); // 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<N_PIXELS; i++) {
    if(i >= height)               {
		strip.setPixelColor(i,   0,   0, 0);
		strip2.setPixelColor(i,   0,   0, 0);
		strip3.setPixelColor(i,   0,   0, 0);
    }
    else {
		strip.setPixelColor(i,Wheel(map(i,0,strip.numPixels()-1,30,150)));
		strip2.setPixelColor(i,Wheel(map(i,0,strip.numPixels()-1,30,150)));
		strip3.setPixelColor(i,Wheel(map(i,0,strip.numPixels()-1,30,150)));
    }
    
  }
 
 
  // Draw peak dot  
  if(peak > 0 && peak <= N_PIXELS-1) {
  	strip.setPixelColor(peak,Wheel(map(peak,0,strip.numPixels()-1,30,150)));
	strip2.setPixelColor(peak,Wheel(map(peak,0,strip.numPixels()-1,30,150)));
	strip3.setPixelColor(peak,Wheel(map(peak,0,strip.numPixels()-1,30,150)));
  }
  
   strip.show(); // Update strip
   strip2.show(); // Update strip
   strip3.show(); // Update strip
 
// 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)
 
}
 
// 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 vu1() {
  
  uint8_t  i;
  uint16_t minLvl, maxLvl;
  int      n, height;
 
 
 
  n   = mic_in(); // 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<N_PIXELS_HALF; i++) {
    if(i >= height) {              
      strip.setPixelColor(N_PIXELS_HALF-i-1,   0,   0, 0);
	  strip2.setPixelColor(N_PIXELS_HALF-i-1,   0,   0, 0);
	  strip3.setPixelColor(N_PIXELS_HALF-i-1,   0,   0, 0);
      strip.setPixelColor(N_PIXELS_HALF+i,   0,   0, 0);
      strip2.setPixelColor(N_PIXELS_HALF+i,   0,   0, 0);
	  strip3.setPixelColor(N_PIXELS_HALF+i,   0,   0, 0);
    }
    else {
      uint32_t color = Wheel(map(i,0,N_PIXELS_HALF-1,30,150));
      strip.setPixelColor(N_PIXELS_HALF-i-1,color);
	  strip2.setPixelColor(N_PIXELS_HALF-i-1,color);
	  strip3.setPixelColor(N_PIXELS_HALF-i-1,color);
      strip.setPixelColor(N_PIXELS_HALF+i,color);
	  strip2.setPixelColor(N_PIXELS_HALF+i,color);
	  strip3.setPixelColor(N_PIXELS_HALF+i,color);
    }
    
  } 
 
  // Draw peak dot  
  if(peak > 0 && peak <= N_PIXELS_HALF-1) {
    uint32_t color = Wheel(map(peak,0,N_PIXELS_HALF-1,30,150));
    strip.setPixelColor(N_PIXELS_HALF-peak-1,color);
	strip2.setPixelColor(N_PIXELS_HALF-peak-1,color);
	strip3.setPixelColor(N_PIXELS_HALF-peak-1,color);
    strip.setPixelColor(N_PIXELS_HALF+peak,color);
	strip2.setPixelColor(N_PIXELS_HALF+peak,color);
	strip3.setPixelColor(N_PIXELS_HALF+peak,color);
  }
  
   strip.show(); // Update strip
   strip2.show(); // Update strip
   strip3.show(); // Update strip
 
// 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 vu2() 
    {
      unsigned long startMillis= millis();  // Start of sample window
      float peakToPeak = 0;   // peak-to-peak level
     
      unsigned int signalMax = 0;
      unsigned int signalMin = 1023;
      unsigned int c, y;
      
      while (millis() - startMillis < SAMPLE_WINDOW)
      {
        sample = mic_in(); // analogRead(MIC_PIN);
        if (sample < 1024)  
        {
          if (sample > signalMax)
          {
            signalMax = sample;  
          }
          else if (sample < signalMin)
          {
            signalMin = sample;  
          }
        }
      }
      peakToPeak = signalMax - signalMin;  
     
      // Serial.println(peakToPeak);
      
      for (int i=0;i<=N_PIXELS_HALF-1;i++){
        uint32_t color = Wheel(map(i,0,N_PIXELS_HALF-1,30,150));
        strip.setPixelColor(N_PIXELS-i,color);
		strip2.setPixelColor(N_PIXELS-i,color);
		strip3.setPixelColor(N_PIXELS-i,color);
        strip.setPixelColor(0+i,color);
		strip2.setPixelColor(0+i,color);
		strip3.setPixelColor(0+i,color);
      }

      c = fscale(INPUT_FLOOR, INPUT_CEILING, N_PIXELS_HALF, 0, peakToPeak, 2);
     
      if(c < peak) {
        peak = c;        // Keep dot on top
        dotHangCount = 0;    // make the dot hang before falling
      }
      if (c <= strip.numPixels()) { // Fill partial column with off pixels
        drawLine(N_PIXELS_HALF, N_PIXELS_HALF-c, strip.Color(0, 0, 0));
        drawLine(N_PIXELS_HALF, N_PIXELS_HALF+c, strip.Color(0, 0, 0));
      }
 
      y = N_PIXELS_HALF - peak;
      uint32_t color1 = Wheel(map(y,0,N_PIXELS_HALF-1,30,150));
      strip.setPixelColor(y-1,color1);
	  strip2.setPixelColor(y-1,color1);
	  strip3.setPixelColor(y-1,color1);
      //strip.setPixelColor(y-1,Wheel(map(y,0,N_PIXELS_HALF-1,30,150)));

      y = N_PIXELS_HALF + peak;
      strip.setPixelColor(y,color1);
	  strip2.setPixelColor(y,color1);
	  strip3.setPixelColor(y,color1);
      //strip.setPixelColor(y+1,Wheel(map(y,0,N_PIXELS_HALF+1,30,150)));
     
      strip.show();
	  strip2.show();
	  strip3.show();
     
      // Frame based peak dot animation
      if(dotHangCount > PEAK_HANG) { //Peak pause length
        if(++dotCount >= PEAK_FALL2) { //Fall rate 
          peak++;
          dotCount = 0;
        }
      } 
      else {
        dotHangCount++; 
      }
    }


void Vu3() {
  uint8_t i;
  uint16_t minLvl, maxLvl;
  int n, height;

  n = mic_in(); // 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

  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; i++) {
    if (i >= height) {
      strip.setPixelColor(i, 0, 0, 0);
	  strip2.setPixelColor(i, 0, 0, 0);
	  strip3.setPixelColor(i, 0, 0, 0);
    } else {
      strip.setPixelColor(i, Wheel(
        map(i, 0, strip.numPixels() - 1, (int)greenOffset, (int)blueOffset)
      ));
      strip2.setPixelColor(i, Wheel(
        map(i, 0, strip.numPixels() - 1, (int)greenOffset, (int)blueOffset)
      ));
      strip3.setPixelColor(i, Wheel(
        map(i, 0, strip.numPixels() - 1, (int)greenOffset, (int)blueOffset)
      ));
	  
    }
  }
  // Draw peak dot  
  if(peak > 0 && peak <= N_PIXELS-1) {
  	strip.setPixelColor(peak,Wheel(map(peak,0,strip.numPixels()-1,30,150)));
	strip2.setPixelColor(peak,Wheel(map(peak,0,strip.numPixels()-1,30,150)));
	strip3.setPixelColor(peak,Wheel(map(peak,0,strip.numPixels()-1,30,150)));
  }
  
   strip.show(); // Update strip
   strip2.show(); // Update strip
   strip3.show(); // Update strip
 
// Every few frames, make the peak pixel drop by 1:
 
    if(++dotCount >= PEAK_FALL) { //fall rate 
      
      if(peak > 0) peak--;
      dotCount = 0;
    }
  strip.show();  // Update strip
  strip2.show();  // Update strip
  strip3.show();  // Update strip

  vol[volCount] = n;
  if (++volCount >= SAMPLES) {
    volCount = 0;
  }

  // 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 Vu4() {
    uint8_t  i;
  uint16_t minLvl, maxLvl;
  int      n, height;
  
  n   = mic_in(); // 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
  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);
	  strip2.setPixelColor(N_PIXELS_HALF-i-1, 0, 0, 0);
	  strip3.setPixelColor(N_PIXELS_HALF-i-1, 0, 0, 0);
      strip.setPixelColor(N_PIXELS_HALF+i, 0, 0, 0);
	  strip2.setPixelColor(N_PIXELS_HALF+i, 0, 0, 0);
	  strip3.setPixelColor(N_PIXELS_HALF+i, 0, 0, 0);
    }
    else {
      uint32_t color = Wheel(map(i,0,N_PIXELS_HALF-1,(int)greenOffset, (int)blueOffset));
      strip.setPixelColor(N_PIXELS_HALF-i-1,color);
	  strip2.setPixelColor(N_PIXELS_HALF-i-1,color);
	  strip3.setPixelColor(N_PIXELS_HALF-i-1,color);
      strip.setPixelColor(N_PIXELS_HALF+i,color);
	  strip2.setPixelColor(N_PIXELS_HALF+i,color);
	  strip3.setPixelColor(N_PIXELS_HALF+i,color);
    }
  }
 
  // Draw peak dot  
  if(peak > 0 && peak <= N_PIXELS_HALF-1) {

    uint32_t color = Wheel(map(peak, 0, N_PIXELS_HALF-1, 30, 150));

    strip.setPixelColor(N_PIXELS_HALF-peak-1,color);
	strip2.setPixelColor(N_PIXELS_HALF-peak-1,color);
	strip3.setPixelColor(N_PIXELS_HALF-peak-1,color);
    strip.setPixelColor(N_PIXELS_HALF+peak,color);
	strip2.setPixelColor(N_PIXELS_HALF+peak,color);
	strip3.setPixelColor(N_PIXELS_HALF+peak,color);
  }
  
  strip.show(); // Update strip
  strip2.show(); // Update strip
  strip3.show(); // Update strip
 
// 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)
 
}

int vu5_timeout = 0;
void Vu5(int mode)
{
  int  i;
  uint16_t minLvl, maxLvl;
  int      n, height;

  n   = mic_in(); // 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 = TOP2 * (lvl - minLvlAvg) / (long)(maxLvlAvg - minLvlAvg);

  if(height < 0L)       height = 0;      // Clip output
  else if(height > TOP2) height = TOP2;
  if(height > peak)     peak   = height; // Keep 'peak' dot at top


#ifdef CENTERED
 // Color pixels based on rainbow gradient
  for(i=0; i<(N_PIXELS/2); i++) {
    if(((N_PIXELS/2)+i) >= height)
    {
      strip.setPixelColor(((N_PIXELS/2) + i),   0,   0, 0);
	  strip2.setPixelColor(((N_PIXELS/2) + i),   0,   0, 0);
	  strip3.setPixelColor(((N_PIXELS/2) + i),   0,   0, 0);
      strip.setPixelColor(((N_PIXELS/2) - i),   0,   0, 0);
	  strip2.setPixelColor(((N_PIXELS/2) - i),   0,   0, 0);
	  strip3.setPixelColor(((N_PIXELS/2) - i),   0,   0, 0);
    }
    else
    {
      strip.setPixelColor(((N_PIXELS/2) + i),Wheel(map(((N_PIXELS/2) + i),0,strip.numPixels()-1,30,150)));
	  strip2.setPixelColor(((N_PIXELS/2) + i),Wheel(map(((N_PIXELS/2) + i),0,strip.numPixels()-1,30,150)));
	  strip3.setPixelColor(((N_PIXELS/2) + i),Wheel(map(((N_PIXELS/2) + i),0,strip.numPixels()-1,30,150)));
      strip.setPixelColor(((N_PIXELS/2) - i),Wheel(map(((N_PIXELS/2) - i),0,strip.numPixels()-1,30,150)));
	  strip2.setPixelColor(((N_PIXELS/2) - i),Wheel(map(((N_PIXELS/2) - i),0,strip.numPixels()-1,30,150)));
	  strip3.setPixelColor(((N_PIXELS/2) - i),Wheel(map(((N_PIXELS/2) - i),0,strip.numPixels()-1,30,150)));
    }
  }
  
  // Draw peak dot  
  if(peak > 0 && peak <= LAST_PIXEL_OFFSET)
  {
    strip.setPixelColor(((N_PIXELS/2) + peak),255,255,255); // (peak,Wheel(map(peak,0,strip.numPixels()-1,30,150)));
    strip2.setPixelColor(((N_PIXELS/2) + peak),255,255,255); // (peak,Wheel(map(peak,0,strip.numPixels()-1,30,150)));
    strip3.setPixelColor(((N_PIXELS/2) + peak),255,255,255); // (peak,Wheel(map(peak,0,strip.numPixels()-1,30,150)));
    strip.setPixelColor(((N_PIXELS/2) - peak),255,255,255); // (peak,Wheel(map(peak,0,strip.numPixels()-1,30,150)));
    strip2.setPixelColor(((N_PIXELS/2) - peak),255,255,255); // (peak,Wheel(map(peak,0,strip.numPixels()-1,30,150)));
    strip3.setPixelColor(((N_PIXELS/2) - peak),255,255,255); // (peak,Wheel(map(peak,0,strip.numPixels()-1,30,150)));
  }
#else
  // Color pixels based on rainbow gradient

  for(i=0; i<N_PIXELS; i++)
  {
    if(i >= height)
    {
      strip.setPixelColor(i, 0, 0, 0);
//	  strip2.setPixelColor(i, 0, 0, 0);
//	  strip3.setPixelColor(i, 0, 0, 0);
    }
    else
    {
      strip.setPixelColor(i,
        Wheel(map(i,0,
          (mode == 0) ? strip.numPixels()-1 : 30,
          (mode == 1) ? strip.numPixels()-1 : 30,
          (mode == 2) ? strip.numPixels()-1 : 150
        )));
	  /*
      strip2.setPixelColor(i,
        Wheel(map(i,0,
          (mode == 0) ? strip.numPixels()-1 : 30,
          (mode == 1) ? strip.numPixels()-1 : 30,
          (mode == 2) ? strip.numPixels()-1 : 150
        )));
      strip3.setPixelColor(i,
        Wheel(map(i,0,
          (mode == 0) ? strip.numPixels()-1 : 30,
          (mode == 1) ? strip.numPixels()-1 : 30,
          (mode == 2) ? strip.numPixels()-1 : 150
        ))); */
    }
  }

  // Draw peak dot  
  if(peak > 0 && peak <= LAST_PIXEL_OFFSET)
  {
    strip.setPixelColor(peak,255,255,255); // (peak,Wheel(map(peak,0,strip.numPixels()-1,30,150)));
//    strip2.setPixelColor(peak,255,255,255); // (peak,Wheel(map(peak,0,strip.numPixels()-1,30,150)));
//    strip3.setPixelColor(peak,255,255,255); // (peak,Wheel(map(peak,0,strip.numPixels()-1,30,150)));
  }
  
#endif  

  // Every few frames, make the peak pixel drop by 1:

  if (millis() - lastTime >= PEAK_FALL_MILLIS)
  {
    lastTime = millis();

    strip.show(); // Update strip
//    strip2.show(); // Update strip
//    strip3.show(); // Update strip

	vu5_timeout = 2;

    //fall rate 
    if(peak > 0) peak--;
  }
  else {
  	
	if(0 < vu5_timeout) {
		// Serial.println("#");
//		if(vu5_timeout == 2) strip2.show(); // Update strip
//		if(vu5_timeout == 1) strip3.show(); // Update strip
		vu5_timeout -= 1;
		
	}
  }
  

  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) < TOP2) maxLvl = minLvl + TOP2;
  minLvlAvg = (minLvlAvg * 63 + minLvl) >> 6; // Dampen min/max levels
  maxLvlAvg = (maxLvlAvg * 63 + maxLvl) >> 6; // (fake rolling average)
}

void Vu6(int mode)
{
  int  i;
  uint16_t minLvl, maxLvl;
  int      n, height;

  n   = mic_in(); // 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 = TOP2 * (lvl - minLvlAvg) / (long)(maxLvlAvg - minLvlAvg);

  if(height < 0L)       height = 0;      // Clip output
  else if(height > TOP2) height = TOP2;
  if(height > peak)     peak   = height; // Keep 'peak' dot at top


#ifdef CENTERED
  // Draw peak dot  
  if(peak > 0 && peak <= LAST_PIXEL_OFFSET)
  {
    strip.setPixelColor(((N_PIXELS/2) + peak),255,255,255); // (peak,Wheel(map(peak,0,strip.numPixels()-1,30,150)));
    strip.setPixelColor(((N_PIXELS/2) - peak),255,255,255); // (peak,Wheel(map(peak,0,strip.numPixels()-1,30,150)));
  }
#else
  // Color pixels based on rainbow gradient
  for(i=0; i<N_PIXELS; i++)
  {
    if(i >= height)
    {
      strip.setPixelColor(i, 0, 0, 0);
	  strip2.setPixelColor(i, 0, 0, 0);
	  strip3.setPixelColor(i, 0, 0, 0);
    }
    else
    {
     }
  }

  // Draw peak dot  
  if(peak > 0 && peak <= LAST_PIXEL_OFFSET)
  {
    strip.setPixelColor(peak,
      (mode == 0) ? 255 : 0,
      (mode == 1) ? 255 : 0,
      (mode == 2) ? 255 : 0); // (peak,Wheel(map(peak,0,strip.numPixels()-1,30,150)));
    strip2.setPixelColor(peak,
      (mode == 0) ? 255 : 0,
      (mode == 1) ? 255 : 0,
      (mode == 2) ? 255 : 0); // (peak,Wheel(map(peak,0,strip.numPixels()-1,30,150)));
    strip3.setPixelColor(peak,
      (mode == 0) ? 255 : 0,
      (mode == 1) ? 255 : 0,
      (mode == 2) ? 255 : 0); // (peak,Wheel(map(peak,0,strip.numPixels()-1,30,150)));
      
      
  }
  
#endif  

  // Every few frames, make the peak pixel drop by 1:

  if (millis() - lastTime >= PEAK_FALL_MILLIS)
  {
    lastTime = millis();

    strip.show(); // Update strip
    strip2.show(); // Update strip
    strip3.show(); // Update strip

    //fall rate 
    if(peak > 0) peak--;
    }

  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) < TOP2) maxLvl = minLvl + TOP2;
  minLvlAvg = (minLvlAvg * 63 + minLvl) >> 6; // Dampen min/max levels
  maxLvlAvg = (maxLvlAvg * 63 + maxLvl) >> 6; // (fake rolling average)
}

void vu7() {

  EVERY_N_MILLISECONDS(1000) {
    peakspersec = peakcount;                                       // Count the peaks per second. This value will become the foreground hue.
    peakcount = 0;                                                 // Reset the counter every second.
  }

  soundmems();

  EVERY_N_MILLISECONDS(20) {
   ripple3();
  }

   show_at_max_brightness_for_power();

} // loop()


void soundmems() {                                                  // Rolling average counter - means we don't have to go through an array each time.
  newtime = millis();
  int tmp = mic_in() - 512; // analogRead(MIC_PIN) - 512;
  sample = abs(tmp);

  int potin = map(mic_in(), 0, 1023, 0, 60);

  samplesum = samplesum + sample - samplearray[samplecount];        // Add the new sample and remove the oldest sample in the array 
  sampleavg = samplesum / NSAMPLES;                                 // Get an average
  samplearray[samplecount] = sample;                                // Update oldest sample in the array with new sample
  samplecount = (samplecount + 1) % NSAMPLES;                       // Update the counter for the array

  if (newtime > (oldtime + 200)) digitalWrite(13, LOW);             // Turn the LED off 200ms after the last peak.

  if ((sample > (sampleavg + potin)) && (newtime > (oldtime + 60)) ) { // Check for a peak, which is 30 > the average, but wait at least 60ms for another.
    step = -1;
    peakcount++;
    digitalWrite(13, HIGH);
    oldtime = newtime;
  }
}  // soundmems()

void ripple3() {

  for (int i = 0; i < N_PIXELS; i++) leds[i] = CHSV(bgcol, 255, sampleavg*2);  // Set the background colour.

  switch (step) {

    case -1:                                                          // Initialize ripple variables.
      center = random(N_PIXELS);
      colour = (peakspersec*10) % 255;                                             // More peaks/s = higher the hue colour.
      step = 0;
      bgcol = bgcol+8;
      break;

    case 0:
      leds[center] = CHSV(colour, 255, 255);                          // Display the first pixel of the ripple.
      step ++;
      break;

    case maxsteps:                                                    // At the end of the ripples.
      // step = -1;
      break;

    default:                                                             // Middle of the ripples.
      leds[(center + step + N_PIXELS) % N_PIXELS] += CHSV(colour, 255, myfade/step*2);       // Simple wrap from Marc Miller.
      leds[(center - step + N_PIXELS) % N_PIXELS] += CHSV(colour, 255, myfade/step*2);
      step ++;                                                         // Next step.
      break;  
  } // switch step

} // ripple()


void vu8() {
  int intensity = calculateIntensity();
  updateOrigin(intensity);
  assignDrawValues(intensity);
  writeSegmented();
  updateGlobals();
}

int calculateIntensity() {
  int      intensity;
  
  reading   = mic_in(); // analogRead(MIC_PIN);                        // Raw reading from mic 
  reading   = abs(reading - 512 - DC_OFFSET); // Center on zero
  reading   = (reading <= NOISE) ? 0 : (reading - NOISE);             // Remove noise/hum
  lvl = ((lvl * 7) + reading) >> 3;    // "Dampened" reading (else looks twitchy)

  // Calculate bar height based on dynamic min/max levels (fixed point):
  intensity = DRAW_MAX * (lvl - minLvlAvg) / (long)(maxLvlAvg - minLvlAvg);

  return constrain(intensity, 0, DRAW_MAX-1);
}

void updateOrigin(int intensity) {
  // detect peak change and save origin at curve vertex
  if (growing && intensity < last_intensity) {
    growing = false;
    intensity_max = last_intensity;
    fall_from_left = !fall_from_left;
    origin_at_flip = origin;
  } else if (intensity > last_intensity) {
    growing = true;
    origin_at_flip = origin;
  }
  last_intensity = intensity;
  
  // adjust origin if falling
  if (!growing) {
    if (fall_from_left) {
      origin = origin_at_flip + ((intensity_max - intensity) / 2);
    } else {
      origin = origin_at_flip - ((intensity_max - intensity) / 2);
    }
    // correct for origin out of bounds
    if (origin < 0) {
      origin = DRAW_MAX - abs(origin);
    } else if (origin > DRAW_MAX - 1) {
      origin = origin - DRAW_MAX - 1;
    }
  }
}

void assignDrawValues(int intensity) {
  // draw amplitue as 1/2 intensity both directions from origin
  int min_lit = origin - (intensity / 2);
  int max_lit = origin + (intensity / 2);
  if (min_lit < 0) {
    min_lit = min_lit + DRAW_MAX;
  }
  if (max_lit >= DRAW_MAX) {
    max_lit = max_lit - DRAW_MAX;
  }
  for (int i=0; i < DRAW_MAX; i++) {
    // if i is within origin +/- 1/2 intensity
    if (
      (min_lit < max_lit && min_lit < i && i < max_lit) // range is within bounds and i is within range
      || (min_lit > max_lit && (i > min_lit || i < max_lit)) // range wraps out of bounds and i is within that wrap
    ) {
      draw[i] = Wheel(scroll_color);
    } else {
      draw[i] = 0;
    }
  }
}

void writeSegmented() {
  int seg_len = N_PIXELS / SEGMENTS;

  for (int s = 0; s < SEGMENTS; s++) {
    for (int i = 0; i < seg_len; i++) {
      strip.setPixelColor(i + (s*seg_len), draw[map(i, 0, seg_len, 0, DRAW_MAX)]);
	  strip2.setPixelColor(i + (s*seg_len), draw[map(i, 0, seg_len, 0, DRAW_MAX)]);
	  strip3.setPixelColor(i + (s*seg_len), draw[map(i, 0, seg_len, 0, DRAW_MAX)]);
    }
  }
  strip.show();
    strip2.show();
	  strip3.show();


}

uint32_t * segmentAndResize(uint32_t* draw) {
  int seg_len = N_PIXELS / SEGMENTS;
  
  uint32_t segmented[N_PIXELS];
  for (int s = 0; s < SEGMENTS; s++) {
    for (int i = 0; i < seg_len; i++) {
      segmented[i + (s * seg_len) ] = draw[map(i, 0, seg_len, 0, DRAW_MAX)];
    }
  }
  
  return segmented;
}

void writeToStrip(uint32_t* draw) {
  for (int i = 0; i < N_PIXELS; i++) {
    strip.setPixelColor(i, draw[i]);
	strip2.setPixelColor(i, draw[i]);
	strip3.setPixelColor(i, draw[i]);
  }
  strip.show();
  strip2.show();
  strip3.show();
}

void updateGlobals() {
  uint16_t minLvl, maxLvl;
    
  //advance color wheel
  color_wait_count++;
  if (color_wait_count > COLOR_WAIT_CYCLES) {
    color_wait_count = 0;
    scroll_color++;
    if (scroll_color > COLOR_MAX) {
      scroll_color = COLOR_MIN;
    }
  }
  
  vol[volCount] = reading;                      // 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(uint8_t 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) < N_PIXELS) maxLvl = minLvl + N_PIXELS;
  minLvlAvg = (minLvlAvg * 63 + minLvl) >> 6; // Dampen min/max levels
  maxLvlAvg = (maxLvlAvg * 63 + maxLvl) >> 6; // (fake rolling average)
}

void vu9() {
  //currentBlending = LINEARBLEND;
  currentPalette = OceanColors_p;                             // Initial palette.
  currentBlending = LINEARBLEND; 
  EVERY_N_SECONDS(5) {                                        // Change the palette every 5 seconds.
    for (int i = 0; i < 16; i++) {
      targetPalette[i] = CHSV(random8(), 255, 255);
    }
  }
  
  EVERY_N_MILLISECONDS(100) {                                 // AWESOME palette blending capability once they do change.
    uint8_t maxChanges = 24; 
    nblendPaletteTowardPalette(currentPalette, targetPalette, maxChanges);
  }


  EVERY_N_MILLIS_I(thistimer,20) {                            // For fun, let's make the animation have a variable rate.
    uint8_t timeval = beatsin8(10,20,50);                     // Use a sinewave for the line below. Could also use peak/beat detection.
    thistimer.setPeriod(timeval);                             // Allows you to change how often this routine runs.
    fadeToBlackBy(leds, N_PIXELS, 16);                        // 1 = slow, 255 = fast fade. Depending on the faderate, the LED's further away will fade out.
    sndwave();
    soundble();
  }
  FastLED.setBrightness(max_bright);
  FastLED.show();

} // loop()



void soundble() {                                            // Quick and dirty sampling of the microphone.
  
  int tmp = mic_in() - 512 - DC_OFFSET;
  sample = abs(tmp);
  
}  // soundmems()



void sndwave() {
  
  leds[N_PIXELS/2] = ColorFromPalette(currentPalette, sample, sample*2, currentBlending); // Put the sample into the center
  
  for (int i = N_PIXELS - 1; i > N_PIXELS/2; i--) {       //move to the left      // Copy to the left, and let the fade do the rest.
    leds[i] = leds[i - 1];
  }

  for (int i = 0; i < N_PIXELS/2; i++) {                  // move to the right    // Copy to the right, and let the fade to the rest.
    leds[i] = leds[i + 1];
  }
  addGlitter(sampleavg);
}

void vu10() {
  
EVERY_N_SECONDS(5) {                                        // Change the target palette to a random one every 5 seconds.
    static uint8_t baseC = random8();                         // You can use this as a baseline colour if you want similar hues in the next line.
    
    for (int i = 0; i < 16; i++) {
      targetPalette[i] = CHSV(random8(), 255, 255);
    }
  }
  
  EVERY_N_MILLISECONDS(100) {
    uint8_t maxChanges = 24; 
    nblendPaletteTowardPalette(currentPalette, targetPalette, maxChanges);   // AWESOME palette blending capability.
  }
  
  EVERY_N_MILLISECONDS(thisdelay) {                           // FastLED based non-blocking delay to update/display the sequence.
    soundtun();
    FastLED.setBrightness(max_bright);
    FastLED.show();
  }
} // loop()



void soundtun() {

  int n;
  n = mic_in(); // analogRead(MIC_PIN);                                    // Raw reading from mic
  n = qsuba(abs(n-512), 10);                                  // Center on zero and get rid of low level noise
  CRGB newcolour = ColorFromPalette(currentPalette, constrain(n,0,255), constrain(n,0,255), currentBlending);
  nblend(leds[0], newcolour, 128);
  
  for (int i = N_PIXELS-1; i>0; i--) {
    leds[i] = leds[i-1];
  }
  
} // soundmems()


void vu11() {

  EVERY_N_MILLISECONDS(1000) {
    peakspersec = peakcount;                                  // Count the peaks per second. This value will become the foreground hue.
    peakcount = 0;                                            // Reset the counter every second.
  }

  soundrip();

  EVERY_N_MILLISECONDS(20) {
   rippled();
  }

   FastLED.show();

} // loop()


void soundrip() {                                            // Rolling average counter - means we don't have to go through an array each time.

  newtime = millis();
  int tmp = mic_in() - 512;
  sample = abs(tmp);

  int potin = map(mic_in(), 0, 1023, 0, 60);

  samplesum = samplesum + sample - samplearray[samplecount];  // Add the new sample and remove the oldest sample in the array 
  sampleavg = samplesum / NSAMPLES;                           // Get an average

  Serial.println(sampleavg);

  
  samplearray[samplecount] = sample;                          // Update oldest sample in the array with new sample
  samplecount = (samplecount + 1) % NSAMPLES;                 // Update the counter for the array

  if (newtime > (oldtime + 200)) digitalWrite(13, LOW);       // Turn the LED off 200ms after the last peak.

  if ((sample > (sampleavg + potin)) && (newtime > (oldtime + 60)) ) { // Check for a peak, which is 30 > the average, but wait at least 60ms for another.
    step = -1;
    peakcount++;
    oldtime = newtime;
  }
  
}  // soundmems()



void rippled() {

  fadeToBlackBy(leds, N_PIXELS, 64);                          // 8 bit, 1 = slow, 255 = fast
  
  switch (step) {

    case -1:                                                  // Initialize ripple variables.
      center = random(N_PIXELS);
      colour = (peakspersec*10) % 255;                        // More peaks/s = higher the hue colour.
      step = 0;
      break;

    case 0:
      leds[center] = CHSV(colour, 255, 255);                  // Display the first pixel of the ripple.
      step ++;
      break;

    case maxsteps:                                            // At the end of the ripples.
      // step = -1;
      break;

    default:                                                  // Middle of the ripples.
      leds[(center + step + N_PIXELS) % N_PIXELS] += CHSV(colour, 255, myfade/step*2);       // Simple wrap from Marc Miller.
      leds[(center - step + N_PIXELS) % N_PIXELS] += CHSV(colour, 255, myfade/step*2);
      step ++;                                                // Next step.
      break;  
  } // switch step
  
} // ripple()


 //Used to draw a line between two points of a given color
    void drawLine(uint8_t from, uint8_t to, uint32_t c) {
      uint8_t fromTemp;
      if (from > to) {
        fromTemp = from;
        from = to;
        to = fromTemp;
      }
      for(int i=from; i<=to; i++){
        strip.setPixelColor(i, c);
		strip2.setPixelColor(i, c);
		strip3.setPixelColor(i, c);
      }
    }

void setPixel(int Pixel, byte red, byte green, byte blue) {
    strip.setPixelColor(Pixel, strip.Color(red, green, blue));
	strip2.setPixelColor(Pixel, strip.Color(red, green, blue));
	strip3.setPixelColor(Pixel, strip.Color(red, green, blue));

}


void setAll(byte red, byte green, byte blue) {

  for(int i = 0; i < N_PIXELS; i++ ) {

    setPixel(i, red, green, blue); 

  }

  strip.show();
  strip2.show();
  strip3.show();

}
void vu12() {

  EVERY_N_MILLISECONDS(1000) {
    peakspersec = peakcount;                                  // Count the peaks per second. This value will become the foreground hue.
    peakcount = 0;                                            // Reset the counter every second.
  }

  soundripped();

  EVERY_N_MILLISECONDS(20) {
  rippvu();
  }

   FastLED.show();

} // loop()


void soundripped() {                                            // Rolling average counter - means we don't have to go through an array each time.

  newtime = millis();
  int tmp = mic_in() - 512;
  sample = abs(tmp);

  int potin = map(mic_in(), 0, 1023, 0, 60);

  samplesum = samplesum + sample - samplearray[samplecount];  // Add the new sample and remove the oldest sample in the array 
  sampleavg = samplesum / NSAMPLES;                           // Get an average

  Serial.println(sampleavg);

  
  samplearray[samplecount] = sample;                          // Update oldest sample in the array with new sample
  samplecount = (samplecount + 1) % NSAMPLES;                 // Update the counter for the array

  if (newtime > (oldtime + 200)) digitalWrite(13, LOW);       // Turn the LED off 200ms after the last peak.

  if ((sample > (sampleavg + potin)) && (newtime > (oldtime + 60)) ) { // Check for a peak, which is 30 > the average, but wait at least 60ms for another.
    step = -1;
    peakcount++;
    oldtime = newtime;
  }
  
}  // soundmems()
void rippvu() {                                                                 // Display ripples triggered by peaks.

fadeToBlackBy(leds, N_PIXELS, 64);                          // 8 bit, 1 = slow, 255 = fast
  
  switch (step) {

    case -1:                                                  // Initialize ripple variables.
      center = random(N_PIXELS);
      colour = (peakspersec*10) % 255;                        // More peaks/s = higher the hue colour.
      step = 0;
      break;

    case 0:
      leds[center] = CHSV(colour, 255, 255);                  // Display the first pixel of the ripple.
      step ++;
      break;

    case maxsteps:                                            // At the end of the ripples.
      // step = -1;
      break;

    default:                                                  // Middle of the ripples.
      leds[(center + step + N_PIXELS) % N_PIXELS] += CHSV(colour, 255, myfade/step*2);       // Simple wrap from Marc Miller.
      leds[(center - step + N_PIXELS) % N_PIXELS] += CHSV(colour, 255, myfade/step*2);
      step ++;                                                // Next step.
      break;  
  } // switch step
   addGlitter(sampleavg);
} // ripple()



void vu13() {                                                                   // The >>>>>>>>>> L-O-O-P <<<<<<<<<<<<<<<<<<<<<<<<<<<<  is buried here!!!11!1!

 
  EVERY_N_MILLISECONDS(1000) {
    peakspersec = peakcount;                                  // Count the peaks per second. This value will become the foreground hue.
    peakcount = 0;                                            // Reset the counter every second.
  }

  soundripper();

  EVERY_N_MILLISECONDS(20) {
  jugglep();
  }

   FastLED.show();

} // loop()


void soundripper() {                                            // Rolling average counter - means we don't have to go through an array each time.

  newtime = millis();
  int tmp = mic_in() - 512;
  sample = abs(tmp);

  int potin = map(mic_in(), 0, 1023, 0, 60);

  samplesum = samplesum + sample - samplearray[samplecount];  // Add the new sample and remove the oldest sample in the array 
  sampleavg = samplesum / NSAMPLES;                           // Get an average

  Serial.println(sampleavg);

  
  samplearray[samplecount] = sample;                          // Update oldest sample in the array with new sample
  samplecount = (samplecount + 1) % NSAMPLES;                 // Update the counter for the array

  if (newtime > (oldtime + 200)) digitalWrite(13, LOW);       // Turn the LED off 200ms after the last peak.

  if ((sample > (sampleavg + potin)) && (newtime > (oldtime + 60)) ) { // Check for a peak, which is 30 > the average, but wait at least 60ms for another.
    step = -1;
    peakcount++;
    oldtime = newtime;
                                                    // Change the current pattern function periodically.
    jugglep();
  }

} // loop()


void jugglep() {                                                                // Use the juggle routine, but adjust the timebase based on sampleavg for some randomness.

// Persistent local variables
  static uint8_t thishue=0;

  timeval = 40;                                                                 // Our EVERY_N_MILLIS_I timer value.

  leds[0] = ColorFromPalette(currentPalette, thishue++, sampleavg, LINEARBLEND);
  
  for (int i = N_PIXELS-1; i >0 ; i-- ) leds[i] = leds[i-1];

  addGlitter(sampleavg/2);                                                      // Add glitter based on sampleavg. By Andrew Tuline.
  
} // matrix()



 
// 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 addGlitter( fract8 chanceOfGlitter) {                                      // Let's add some glitter, thanks to Mark
  
  if( random8() < chanceOfGlitter) {
    leds[random16(N_PIXELS)] += CRGB::White;
  }

} // addGlitter()
// List of patterns to cycle through.  Each is defined as a separate function below.
// typedef void (*SimplePatternList[])();
// SimplePatternList qPatterns = {vu, vu1, vu2, Vu3, Vu4, Vu5, Vu6, vu7, vu8, vu9, vu10, vu11, vu12, vu13};
// uint8_t qCurrentPatternNumber = 0; // Index number of which pattern is current

// void nextPattern2()
// {
//   // add one to the current pattern number, and wrap around at the end
//   qCurrentPatternNumber = (qCurrentPatternNumber + 1) % ARRAY_SIZE( qPatterns);
// }
void All2()
{
  // Call the current pattern function once, updating the 'leds' array
  // qPatterns[qCurrentPatternNumber]();
  // EVERY_N_SECONDS( 30 ) { nextPattern2(); } // change patterns periodically
}

음량에 따라 다른 LED 패턴 변경

 

사운드 음량 표시 - 시리얼 플로터 

 

 

'임베디드 보드 > ESP32' 카테고리의 다른 글

Raspberry Pico + Ethernet W5500  (0) 2022.03.07
ESP32 + Ethernet W5500  (0) 2022.02.25
ESP32 + LED STRIP + 블루투스 제어  (0) 2021.12.30
ESP32 DOWNLOAD  (0) 2021.12.29
ESP8266 on thingsboard server  (0) 2021.05.01