Project showcase

Stereo NeoPixel Ring VU Meter © GPL3+

A stereo VU meter built with an Arduino Nano and two NeoPixel LED rings.

  • 19,423 views
  • 196 comments
  • 39 respects

Components and supplies

Apps and online services

About this project

The idea

Having seen some VU meters, I thought it would be cool to have one as well. I bought an Arduino starter kit a while ago and had not used it yet. Then I saw a video about a simple VU meter powered by an Arduino and thought it would be even cooler to build my own VU meter as my first Arduino project. So I ordered some more parts and started building.

Setup for testing

Setup testing video

As shown in the video, I first tested with an LCD display, 2 LED matrices and a LED strip before I settled on using 2 LED rings which I thought looked great and more unique than other VU meters.

I started with a very simple Arduino script which only used one channel and lit up a couple of LEDs. I then added several features to the script:

  • stereo support
  • switchable peak hold function with 'falling down' option
  • adjustable sensitivity setting
  • adjustable LED brightness setting
  • support for one LED strip displaying the left and right channel or 2 LED rings (or strips) displaying one channel each
  • slow 'falling down' of the LEDs
  • variables which can be set to support any number of LEDs and further customize the VU meter

You need the Adafruit_NeoPixel library for the script to work.

Update January 2018: check the new Facebook group over here: https://www.facebook.com/groups/StereoNeoPixelVU/

The finished VU meter

VU meter in action

Update October 30, 2017 - 60 LED ring version

2017, October 30th latest update, testing with a 60 LED ring

Update November 11, 2017 - 19" rack version

19" rack version with additional push select button to cycle though color schemes:

19" rack version Arduino VU meter

Update December 2, 2017 - code update 2 pins and color schemes

The latest version supports connecting 2 rings or strips (left and right) to 2 pins on the Arduino and multiple color schemes.

Search for the variables marked with @EB to set the Sketch correctly for your setup.

Update December 3, 2017 - code update spinning and pulsing

Some experimenting (a.k.a. fooling around) with a spinning and pulsing version (excuse the poor cellphone quality):

spinning and pulsing 60 LED ring VU meter

Update December 10, 2017 - controller box

Although a breadboard for testing is fine, I decided to build an Arduino Nano into a box as a controller for easy connecting and testing multiple LED rings and strips:

Pressing select button 1 will cycle through the 12 color schemes (the last 2 ones with a spinning colorwheel). Button 2 will cycle through spinning and/or pulsing modes. Keeping button 1 pressed for 1 second will toggle the pulsing on or off.

Update January 11, 2018 - correct the overflow problem when no line input is connected

To prevent the leds from overloading when no input signal is connected, connect a 10K resistor between the left audio input pin and ground and another one between the right audio input pin and ground. This pulls the floating input pins to ground.

Update January 21, 2018 - 160 LED rhombus version

160 LED rhombus edition

Update February 2, 2018 - code update logarithmic and non linear audio response

Added logarithmic and non linear audio response.

Update February 12, 2018 - update controller box

Added a USB connection on a DIN connector to the Arduino LED VU meter controller for easy uploading of new code versions.

Update April 2, 2018 - test with microphone module instead of line input

Test with a microphone module instead of the line input. Connecting is similar to using an audio input: connect the output of the microphone to analog input 0 of the Arduino (and also connect to VCC and ground to power the module).

The Sketch does not need any changes for the microphone module although it may require some changes to the sensitivity settings.

License

Feel free to use the code for your personal use, not for commercial purposes.

You can contact me at ericBcreator@gmail.com.

Code

20171105 VU meterArduino
Updated code with optional dropping and bouncing peaks and several other settings.
/*
**********************************************************************
* Stereo VU Meter for 1 or 2 LED rings or strips build by ericBcreator
* Designed to be used with an Arduino UNO, Nano or compatible device.
**********************************************************************
* Last updated 20171105 by ericBcreator
*
* This code is free for personal use, not for commercial purposes.
* Please leave this header intact.
*
* contact: ericBcreator@gmail.com
**********************************************************************
*/

//#define DEBUG                                             // for debugging

//
// include the NeoPixel library:
//

#include <Adafruit_NeoPixel.h>

//
// uncomment the definition for the connected strip or ring(s)
//

//#define led_ring_60
//#define led_strip_60
//#define led_strip_30
#define led_2_rings_24
//#define led_2_rings_30
//#define led_strip_200
//#define led_strip_144

//
// important setting: using potentiometer sensor values or not
// This setting has to be set right or the script will not work correctly:
// - set this to true if using potentiometers
// - set this to false if not using potentiometers
//

const int useSensorValues = true;                         

//
// setup pins
//

int leftPin = A0, rightPin = A1;                          // left audio in on analog 0, right on analog 1
int brightnessPin = A4, sensitivityPin = A5;              // potentiometers for brightness and sensitivity on analog 4 and 5
int stripPin = 6;                                         // DIN of leds on digital pin 6
int showPeaksPin = 7;                                     // switch to toggle peaks on or off on digital pin 7
int momentarySwitch = false;                              // set false for an on/off toggle switch

//
// setup variables for the number of leds and led strip or 2 rings
//

#if defined (led_ring_60)
  //settings for a 60 led ring

  int stripNumOfLeds = 60;                                  // the total number of leds
  uint32_t stripColor[31];                                  // half of the number of leds + 1
  int displayMiddleLed = false;                             // display the middle led (blue). set to true for one strip, false for two strips or rings
  int splitStrip = true;                                    // set to true when using 2 strips or rings, false for one strip
  int middleOffset = 0;                                     // offset for the middle led when using one strip
  int startupAnimationDelay = 6;                            // delay for the startup animation
  int orangeLimitAmount = 0;                                // limit the amount of green of the middle LEDs to make them more orange
  int swapLeftRight = false;                                // swap the left and right input values or not
  
  int dropDelay = 4;                                        // hold time before dropping the leds
  float dropFactor = .92;                                   // value for dropping the leds
  
  int peakTimeNoDropDelay = 250;                            // peak hold time when not dropping the peaks (set droppingPeak true or false)
  int peakTimeFirstDropDelay = 130;                         // peak hold time when dropping the first peak
  int peakTimeDropDelay = 7;                                // peak hold time when dropping the rest of the peaks
  float peakDropFactor = .93;                               // value for dropping the peaks
  int droppingPeakFade = false;                             // display the dropping peak fading to black or not
  
  int bouncingPeaksNumOfLeds = 6;                           // how many leds to bounce up (max)
  int bouncingPeakDelay = 4;                                // delay between peak bounce updates
  int bouncingPeakCounterInc = 10;                          // increase counter for each bounce update. note: it uses a 0-180 sin function for the bouncing

#elif defined (led_strip_60)
  //settings for a 60 led ring

  int stripNumOfLeds = 60;                                  // the total number of leds
  uint32_t stripColor[31];                                  // half of the number of leds + 1
  int displayMiddleLed = true;                              // display the middle led (blue). set to true for one strip, false for two strips or rings
  int splitStrip = false;                                   // set to true when using 2 strips or rings, false for one strip
  int middleOffset = 1;                                     // offset for the middle led when using one strip
  int startupAnimationDelay = 6;                            // delay for the startup animation
  int orangeLimitAmount = 0;                                // limit the amount of green of the middle LEDs to make them more orange
  int swapLeftRight = false;                                // swap the left and right input values or not
  
  int dropDelay = 4;                                        // hold time before dropping the leds
  float dropFactor = .92;                                   // value for dropping the leds
  
  int peakTimeNoDropDelay = 250;                            // peak hold time when not dropping the peaks (set droppingPeak true or false)
  int peakTimeFirstDropDelay = 130;                         // peak hold time when dropping the first peak
  int peakTimeDropDelay = 7;                                // peak hold time when dropping the rest of the peaks
  float peakDropFactor = .93;                               // value for dropping the peaks
  int droppingPeakFade = false;                             // display the dropping peak fading to black or not
  
  int bouncingPeaksNumOfLeds = 6;                           // how many leds to bounce up (max)
  int bouncingPeakDelay = 4;                                // delay between peak bounce updates
  int bouncingPeakCounterInc = 10;                          // increase counter for each bounce update. note: it uses a 0-180 sin function for the bouncing

#elif defined (led_strip_30)
  //settings for a 30 led strip

  int stripNumOfLeds = 30;                                  // the total number of leds
  uint32_t stripColor[16];                                  // half of the number of leds + 1
  int displayMiddleLed = true;                              // display the middle led (blue). set to true for one strip, false for two strips or rings
  int splitStrip = false;                                   // set to true when using 2 strips or rings, false for one strip
  int middleOffset = 1;                                     // offset for the middle led when using one strip
  int startupAnimationDelay = 10;                           // delay for the startup animation
  int orangeLimitAmount = 0;                                // limit the amount of green of the middle LEDs to make them more orange
  int swapLeftRight = false;                                // swap the left and right input values or not
  
  int dropDelay = 10;                                       // hold time before dropping the leds
  float dropFactor = .9;                                    // value for dropping the leds
  
  int peakTimeNoDropDelay = 250;                            // peak hold time when not dropping the peaks (set droppingPeak true or false)
  int peakTimeFirstDropDelay = 150;                         // peak hold time when dropping the first peak
  int peakTimeDropDelay = 15;                               // peak hold time when dropping the rest of the peaks
  float peakDropFactor = .94;                               // value for dropping the peaks
  int droppingPeakFade = false;                             // display the dropping peak fading to black or not
  
  int bouncingPeaksNumOfLeds = 3;                           // how many leds to bounce up (max)
  int bouncingPeakDelay = 4;                                // delay between peak bounce updates
  int bouncingPeakCounterInc = 9;                           // increase counter for each bounce update. note: it uses a 0-180 sin function for the bouncing

#elif defined (led_2_rings_24)
  //settings for 2 24 led rings

  int stripNumOfLeds = 48;
  uint32_t stripColor[25];
  int displayMiddleLed = false;
  int splitStrip = true;
  int middleOffset = 0;
  int startupAnimationDelay = 5;
  int orangeLimitAmount = 0;
  int swapLeftRight = false;
  
  int dropDelay = 2;
  float dropFactor = .96;
  
  int peakTimeNoDropDelay = 250;
  int peakTimeFirstDropDelay = 100;
  int peakTimeDropDelay = 10;
  float peakDropFactor = .94;
  int droppingPeakFade = false;
  
  int bouncingPeaksNumOfLeds = 3;
  int bouncingPeakDelay = 4;
  int bouncingPeakCounterInc = 9;

#elif defined(led_2_rings_30)
  //settings for 2 30 led rings

  int stripNumOfLeds = 60;
  uint32_t stripColor[31];
  int displayMiddleLed = false;
  int splitStrip = true;
  int middleOffset = 0;
  int startupAnimationDelay = 5;
  int orangeLimitAmount = 0;
  int swapLeftRight = false;
  
  int dropDelay = 2;
  float dropFactor = .96;
  
  int peakTimeNoDropDelay = 250;
  int peakTimeFirstDropDelay = 100;
  int peakTimeDropDelay = 10;
  float peakDropFactor = .94;
  int droppingPeakFade = false;
  
  int bouncingPeaksNumOfLeds = 3;
  int bouncingPeakDelay = 4;
  int bouncingPeakCounterInc = 9;

#elif defined (led_strip_200)
  //settings for a 200 led strip

  int stripNumOfLeds = 200;
  uint32_t stripColor[101];
  int displayMiddleLed = false;
  int splitStrip = true;
  int middleOffset = 0;
  int startupAnimationDelay = 1;
  int orangeLimitAmount = 0;
  int swapLeftRight = false;
  
  int dropDelay = 10;
  float dropFactor = .96;
  
  int peakTimeNoDropDelay = 250;
  int peakTimeFirstDropDelay = 100;
  int peakTimeDropDelay = 30;
  float peakDropFactor = .99;
  int droppingPeakFade = false;
  
  int bouncingPeaksNumOfLeds = 8;
  int bouncingPeakDelay = 4;
  int bouncingPeakCounterInc = 9;

#elif defined (led_strip_144)
  //settings for a 200 led strip

  int stripNumOfLeds = 145;
  uint32_t stripColor[73];
  int displayMiddleLed = true;
  int splitStrip = false;
  int middleOffset = 1;
  int startupAnimationDelay = 1;
  int orangeLimitAmount = 0;
  int swapLeftRight = false;
  
  int dropDelay = 10;
  float dropFactor = .85;
  
  int peakTimeNoDropDelay = 250;
  int peakTimeFirstDropDelay = 100;
  int peakTimeDropDelay = 5;
  float peakDropFactor = .94;
  int droppingPeakFade = false;
  
  int bouncingPeaksNumOfLeds = 10;
  int bouncingPeakDelay = 2;
  int bouncingPeakCounterInc = 10;
#endif

//
// setup other variables, user editable
//

// basic settings
int minValue = 10;                                        // min analog input value
int maxValue = 350;                                       // max analog input value (0-1023 equals 0-5V)
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 = 30;                                   // 0 - 255, initial value (value read from the potentiometer if useSensorValues = true)
int sensorDeviationBrightness = 1;                        // eliminate fluctuating values
int overflowDelay = 20;                                   // overflow hold time

// peak settings
int displayPeaks = true;                                  // value will be set by the switch if useSensorValues = true
int droppingPeak = true;                                  // display dropping peaks or not. note: displayPeaks has to be true 
int bouncingPeaks = true;                                 // display bouncing peaks or not. note: displayPeaks has to be true 

//
// initialize other variables needed for the sketch
//

int numOfSegments = stripNumOfLeds / 2;
int halfNumOfSegments = numOfSegments / 2; 
int stripMiddle = stripNumOfLeds / 2;
int maxDisplaySegments = stripMiddle - 1;
float sensitivityFactor;

int brightnessValue, prevBrightnessValue;
float ledFactor, ledFactor_div_numOfSegments;

int leftValue = 0, rightValue = 0, maxReadValue = 0;
int leftAnalogValue = 0, rightAnalogValue = 0;

int prevLeftValue = 0, prevRightValue = 0;
int prevLeftAnalogValue = 0, prevRightAnalogValue = 0;

int i, j;
int dropLeft, dropRight;
int leftDropTime, rightDropTime;

int leftPeak = 0, rightPeak = 0;
int leftPeakTime = 0, rightPeakTime = 0;
int leftFirstPeak = true, rightFirstPeak = true;
int readShowPeaksPin, prevReadShowPeaksPin;

uint32_t stripMiddleColor, stripOverflowColor, stripHoldColor;

int leftPeakBouncing = false, rightPeakBouncing = false;
int leftPeakBounce = 0, rightPeakBounce = 0;
int prevLeftPeakBounce = 0, prevRightPeakBounce = 0;
int leftPeakBounceCounter = 0, rightPeakBounceCounter = 0;
int leftPeakBounceDelayCounter = 0, rightPeakBounceDelayCounter = 0;

//
// initialize the strip or rings
//

Adafruit_NeoPixel strip = Adafruit_NeoPixel(stripNumOfLeds, stripPin, NEO_GRB + NEO_KHZ800);

//
// setup
//

void setup() {
  #ifdef DEBUG
    Serial.begin(9600);
  #endif
  
  pinMode(showPeaksPin, INPUT);  

  strip.begin();
  
  setStripColors();
  startupAnimation();
  
  if (useSensorValues) 
    setInitialDisplayPeaks();
  else
    setSensitivityFactor();
}

//
// main loop
//

void loop() {
  if (useSensorValues) 
    readSensorValues();
  
  readValues();
  drawValues();

  if (displayPeaks) {
    getPeaks();
    drawPeaks();
  }

  storePrevValues();
}

// 
// functions
//

void setInitialDisplayPeaks() {
  readShowPeaksPin = digitalRead(showPeaksPin);
  if (readShowPeaksPin == HIGH)
    displayPeaks = false;
  else
    displayPeaks = true;
  prevReadShowPeaksPin = readShowPeaksPin;
}

void readSensorValues() {
  readShowPeaksPin = digitalRead(showPeaksPin);

  if (momentarySwitch) {
    if (readShowPeaksPin == LOW && prevReadShowPeaksPin == HIGH) {
      if (displayPeaks == true) {
        displayPeaks = false;
        clearLeftPeak();
        clearRightPeak();        
        if (momentarySwitch)
          while (digitalRead(showPeaksPin) == LOW) {}
      }
      else {
        displayPeaks = true;
      }
    }
  } 
  else {
    if (readShowPeaksPin == LOW && prevReadShowPeaksPin == HIGH) 
      displayPeaks = true;
    else if (readShowPeaksPin == HIGH && prevReadShowPeaksPin == LOW) {
      displayPeaks = false;
      clearLeftPeak();
      clearRightPeak();        
    }
  }
  prevReadShowPeaksPin = readShowPeaksPin;
  
  brightnessValue = analogRead(brightnessPin);
  brightnessValue = map(brightnessValue, 0, 1023, 0, 255);
  
  if (abs(brightnessValue - prevBrightnessValue) > sensorDeviationBrightness) {
    ledBrightness = brightnessValue;
    setStripColors();
    prevBrightnessValue = brightnessValue;
  }

  sensitivityValue = analogRead(sensitivityPin);
  sensitivityValue = map(sensitivityValue, 0, 1023, 0, 255);
  setSensitivityFactor();
}

void setSensitivityFactor() {
  //sensitivityValue_div_numOfSegments = sensitivityValue / numOfSegments;
  sensitivityFactor = ((float) sensitivityValue / 255 * (float) maxSensitivity / 255);
}

void readValues() {
  leftAnalogValue = analogRead(leftPin);
  rightAnalogValue = analogRead(rightPin);

  if (swapLeftRight) {
    int tempValue = leftAnalogValue;
    leftAnalogValue = rightAnalogValue;
    rightAnalogValue = tempValue;
  }

  if (leftAnalogValue < prevLeftAnalogValue) {
    leftDropTime++;
    if (leftDropTime > dropDelay) {
      leftAnalogValue = prevLeftAnalogValue * dropFactor;
      leftDropTime = 0;
    }
    else
      leftAnalogValue = prevLeftAnalogValue;
  }
   
  if (rightAnalogValue < prevRightAnalogValue) {
    rightDropTime++;
    if (rightDropTime > dropDelay) {
      rightAnalogValue = prevRightAnalogValue * dropFactor;
      rightDropTime = 0;
    }
    else
      rightAnalogValue = prevRightAnalogValue;
  }

  #ifdef DEBUG
    Serial.print(leftAnalogValue);
    Serial.print(" ");
    Serial.println(rightAnalogValue);
  #endif  

  // map values  
  leftValue = map(leftAnalogValue * sensitivityFactor, minValue, maxValue, 0, maxDisplaySegments);
  rightValue = map(rightAnalogValue * sensitivityFactor, minValue, maxValue, 0, maxDisplaySegments);

  if (leftValue > maxDisplaySegments) {
      leftValue = maxDisplaySegments;
      drawOverflow();
  }
  
  if (rightValue > maxDisplaySegments) {
      rightValue = maxDisplaySegments;
      drawOverflow();
  }
}

void storePrevValues() {
  prevLeftAnalogValue = leftAnalogValue;
  prevRightAnalogValue = rightAnalogValue;

  prevLeftValue = leftValue;
  prevRightValue = rightValue;
}

void getPeaks() {
  if (leftValue > leftPeak) {
    leftPeak = leftValue;
    leftPeakTime = 0;
    leftFirstPeak = true;

    if (bouncingPeaks) {
      leftPeakBouncing = true;
      leftPeakBounceCounter = 0;
      leftPeakBounceDelayCounter = 0;
    }
  }
  else {
    leftPeakTime++;
    if (droppingPeak) {
      if (leftFirstPeak) {
        if (leftPeakTime > peakTimeFirstDropDelay) {
          clearLeftPeak();
          leftFirstPeak = false;
        }
      }
      else {
        if (leftPeakTime > peakTimeDropDelay) {
          clearLeftPeak();
        }
      }
    }
    else {
      if (leftPeakTime > peakTimeNoDropDelay) {
        clearLeftPeak();
      }
    }
  }

  if (leftPeakBouncing) {
    if (leftFirstPeak) {
      leftPeakBounceDelayCounter++;
      if (leftPeakBounceDelayCounter >= bouncingPeakDelay) {
        leftPeakBounceDelayCounter = 0;
        leftPeakBounceCounter += bouncingPeakCounterInc;
  
        if (leftPeakBounceCounter >= 180) {
          clearLeftBouncePeak();
          clearLeftBounce();
        }
        else {        
          leftPeakBounce = min((sin(leftPeakBounceCounter * 0.0174532925) * bouncingPeaksNumOfLeds), (maxDisplaySegments - leftPeak));
          if (leftPeakBounce != prevLeftPeakBounce) {
            clearLeftBouncePeak();
          }
          prevLeftPeakBounce = leftPeakBounce;
        }
      }
    }
  }

  if (rightValue > rightPeak) {
    rightPeak = rightValue;
    rightPeakTime = 0;
    rightFirstPeak = true;

    if (bouncingPeaks) {
      rightPeakBouncing = true;
      rightPeakBounceCounter = 0;
      rightPeakBounceDelayCounter = 0;
    }
  }
  else {
    rightPeakTime++;
    if (droppingPeak) {
      if (rightFirstPeak) {
        if (rightPeakTime > peakTimeFirstDropDelay) {
          clearRightPeak();
          rightFirstPeak = false;
        }
      }
      else {
        if (rightPeakTime > peakTimeDropDelay)
          clearRightPeak();
      }
    }
    else {
      if (rightPeakTime > peakTimeNoDropDelay)
        clearRightPeak();
    }
  }

  if (rightPeakBouncing) {
    if (rightFirstPeak) {
      rightPeakBounceDelayCounter++;
      if (rightPeakBounceDelayCounter >= bouncingPeakDelay) {
        rightPeakBounceDelayCounter = 0;
        rightPeakBounceCounter += bouncingPeakCounterInc;
  
        if (rightPeakBounceCounter >= 180) {
          clearRightBouncePeak();
          clearRightBounce();
        }
        else {        
          rightPeakBounce = min((sin(rightPeakBounceCounter * 0.0174532925) * bouncingPeaksNumOfLeds), (maxDisplaySegments - rightPeak));
          if (rightPeakBounce != prevRightPeakBounce) {
            clearRightBouncePeak();
          }
          prevRightPeakBounce = rightPeakBounce;
        }
      }
    }
  }
}

void drawValues() {
  if (splitStrip) {
    for (i = middleOffset; i < leftValue; i++)
      strip.setPixelColor(i, stripColor[i]);
  
    for (i = prevLeftValue; i > leftValue; i--)
      strip.setPixelColor(i, 0);
  
    for (i = middleOffset; i < rightValue; i++)
      strip.setPixelColor(stripMiddle + i, stripColor[i]);
  
    for (i = prevRightValue; i > rightValue; i--)
      strip.setPixelColor(stripMiddle + i, 0);
  }
  else {
    for (i = middleOffset; i < leftValue; i++)
      strip.setPixelColor(stripMiddle + i, stripColor[i]);
  
    for (i = prevLeftValue; i > leftValue; i--)
      strip.setPixelColor(stripMiddle + i, 0);
  
    for (i = middleOffset; i < rightValue; i++)
      strip.setPixelColor(stripMiddle - i, stripColor[i]);
  
    for (i = prevRightValue; i > rightValue; i--)
      strip.setPixelColor(stripMiddle - i, 0);
  }

  if (displayMiddleLed) strip.setPixelColor(stripMiddle, stripMiddleColor);
  strip.show();
}

void drawPeaks() {
  if (leftPeak > 0) {
    if (droppingPeakFade && leftPeakBouncing == false)
      stripHoldColor = strip.Color(max(1, (255 * leftPeak * ledFactor_div_numOfSegments)), 0, 0);
    else
      stripHoldColor = stripColor[numOfSegments];

    if (splitStrip)
      strip.setPixelColor((leftPeak + leftPeakBounce), stripHoldColor);
    else
      strip.setPixelColor(stripMiddle + (leftPeak + leftPeakBounce), stripHoldColor);
  } 
  
  if (rightPeak > 0) {
    if (droppingPeakFade && rightPeakBouncing == false)
      stripHoldColor = strip.Color(max(1, (255 * rightPeak * ledFactor_div_numOfSegments)), 0, 0);    
    else
      stripHoldColor = stripColor[numOfSegments];

    if (splitStrip)
      strip.setPixelColor(stripMiddle + rightPeak + prevRightPeakBounce, stripHoldColor);
    else 
      strip.setPixelColor(stripMiddle - (rightPeak + prevRightPeakBounce), stripHoldColor);
  }

  if (leftPeak > 0 || rightPeak > 0)
    strip.show();    
}

void clearLeftPeak() {
  if (splitStrip)
    strip.setPixelColor((leftPeak + prevLeftPeakBounce), 0);
  else
    strip.setPixelColor(stripMiddle + (leftPeak + prevLeftPeakBounce), 0);

  if (droppingPeak)
    leftPeak = leftPeak * peakDropFactor;
  else
    leftPeak = 0;
  leftPeakTime = 0;
}

void clearLeftBounce() {
  leftPeakBouncing = false;
  leftPeakBounceCounter = 0;
  leftPeakBounce = 0;
  prevLeftPeakBounce = 0;
}

void clearLeftBouncePeak() {
  if (splitStrip)
    strip.setPixelColor((leftPeak + prevLeftPeakBounce), 0);
  else
    strip.setPixelColor(stripMiddle + (leftPeak + prevLeftPeakBounce), 0);
}

void clearRightPeak() {
  if (splitStrip)
    strip.setPixelColor(stripMiddle + rightPeak + prevRightPeakBounce, 0);
  else 
    strip.setPixelColor(stripMiddle - (rightPeak + prevRightPeakBounce), 0);
  
  if (droppingPeak)
    rightPeak = rightPeak * peakDropFactor;
  else
    rightPeak = 0;
  rightPeakTime = 0;
}

void clearRightBounce() {
  rightPeakBouncing = false;
  rightPeakBounceCounter = 0;
  rightPeakBounce = 0;
  prevRightPeakBounce = 0;
}

void clearRightBouncePeak() {
  if (splitStrip)
    strip.setPixelColor((stripMiddle + rightPeak + prevRightPeakBounce), 0);
  else
    strip.setPixelColor(stripMiddle - (rightPeak + prevRightPeakBounce), 0);
}

void drawOverflow() {
  for (i = 0; i <= numOfSegments; i++) {
    strip.setPixelColor(stripMiddle + i, stripOverflowColor);
    strip.setPixelColor(stripMiddle - i, stripOverflowColor);
  }
  strip.show();
  delay(overflowDelay);

  for (i = 0; i <= numOfSegments; i++) {
    strip.setPixelColor(stripMiddle + i, 0);
    strip.setPixelColor(stripMiddle - i, 0);
  }
  strip.show();
}

void setStripColors() {
  int orangeLimit;
  ledFactor = (float)ledBrightness / 255;

  float orangeFactor = orangeLimitAmount / halfNumOfSegments;
  ledFactor_div_numOfSegments = ledFactor / numOfSegments;
  
  stripOverflowColor = strip.Color(min(255, 255 * ledFactor * 1.5), 0, 0);
  stripMiddleColor = strip.Color(0, 0, 255 * ledFactor);

  stripColor[0] = strip.Color(0, 255 * ledFactor, 0);
  for (i = 1; i <= numOfSegments; i++) {
    if (i <= halfNumOfSegments)
      orangeLimit = (i * orangeFactor);
    else
      orangeLimit = ((numOfSegments - i) * orangeFactor);

    stripColor[i] = strip.Color((255 * i * ledFactor_div_numOfSegments), ((255 - orangeLimit) * (numOfSegments - i) * ledFactor_div_numOfSegments), 0); 
  }

  stripHoldColor = stripColor[numOfSegments];
}

void startupAnimation() {  
  for (j = 0; j < 2; j++) {
    for (i = 0; i <= numOfSegments; i++) {
      strip.setPixelColor(stripMiddle - i, stripColor[i]);
      strip.setPixelColor(stripMiddle + i, stripColor[i]);
      strip.show();
      delay(startupAnimationDelay);
    }
    
    for (i = 0; i <= numOfSegments; i++) {
      strip.setPixelColor(stripMiddle + i, 0);
      strip.setPixelColor(stripMiddle - i, 0);
      strip.show();
      delay(startupAnimationDelay);
    }
  }
}
20180202 VU meter updateArduino
Updated code with a lot of changes.

Note: use the updated diagram, there are some changes in pin connections

- multiple color schemes
- option to connect 2 strip or rings on 2 output pins of the Arduino (the previous code used 1)
- option for pulsing and spinning
- option for logarithmic audio response
/*
**********************************************************************
* Stereo VU Meter for 1 or 2 LED rings or strips build by ericBcreator
* Designed to be used with an Arduino UNO, Nano or compatible device.
**********************************************************************
* Notice: search for @EB in the Sketch for important variables to set
* for the Sketch to work with your setup.
**********************************************************************
* Last updated 20180202 by ericBcreator
*
* This code is free for personal use, not for commercial purposes.
* Please leave this header intact.
*
* contact: ericBcreator@gmail.com
**********************************************************************
*/

//
// include the NeoPixel library:
//

#include <Adafruit_NeoPixel.h>

//
// debugging settings
//
//#define DEBUG                                             // debug: enable serial.print 
//#define DEBUG_NO_PEAK_SWITCH                              // debug: no peak switch connected @EB
//#define DEBUG_TEST_LEDS                                   // debug: display each led (color) slowly at startup
//#define DEBUG_PRINT_LOOP_TIME                             // debug: serial.print the looptime in ms
//#define DEBUG_PRINT_ANALOGVALUES                          // debug: serial.print analog input values
//#define DEBUG_NO_PEAKS                                    // debug: display no peaks, ignoring other settings
//#define DEBUG_PEAKS                                       // debug: display peaks, ignoring other settings

//
// uncomment to average the input levels to the number defined by averageNumOfReadings. increasing the value will make the script less responsive
//
//#define averageReadings                                     // average input levels or not
//#define averageNumOfReadings 3                              // num of readings for averaging

//
// uncomment to map the linear audio input to non-linear response
//
//#define nonLinearSinAudio                                  // uncomment to map the linear audio input signal to a non-linear, reverse audio-taper response (sin wave)
//#define nonLinearReverseSinAudio                           // uncomment to map the linear audio input signal to a non-linear, audio-taper response (reverse sin wave)
#define nonLinearLogAudio                                   // uncomment to map the linear audio input signal to a log response
//#define nonLinearAvr2                                       // uncomment to average the original input with the non-linear response

//
// overflow settings
//
//#define displayOverflow                                     // display overflow or not
//#define compressOverflowPeaks                               // compress overflow peaks or not
//#define compressOverflowNumOfTimes 2                        // num of times to apply the compressOverflowFactor
//float compressOverflowFactor = .05;                         // factor for compression

//
// uncomment when using high level (non-consumer) inputs
// 
//#define highLevelInput                                      // @EB define for high level inputs

//
// uncomment the definition for the connected strip or ring(s) @EB
//

//#define led_matrix_40
//#define led_ring_60
//#define led_ring_60_ps
#define led_rhombus_160_ps
//#define led_strip_60
//#define led_strip_60_qr
//#define led_strip_30
//#define led_2_rings_24
//#define led_2_rings_30
//#define led_strip_200
//#define led_strip_144
//#define led_2_strip_63
//#define led_2_strip_63_qr

//
// important setting: using potentiometer sensor values or not
// This setting has to be set right or the script will not work correctly:
// - set to true if using potentiometers
// - set to false if not using potentiometers
//

const int useSensorValues = true;                         // @EB

//
// setup pins
//

int leftPin = A0, rightPin = A1;                          // left audio in on analog 0, right on analog 1
int brightnessPin = A4, sensitivityPin = A5;              // potentiometers for brightness and sensitivity on analog 4 and 5
int leftStripPin = 5;                                     // DIN of left led strip on digital pin 5
int rightStripPin = 6;                                    // DIN of right led strip on digital pin 6
int showPeaksPin = 9;                                     // switch to toggle peaks on or off on digital pin 7 (7, 9 for box version)
int showPeaksMomentarySwitch = false;                     // set false for an on/off toggle switch
int reverseShowPeaks = true;                              // reverses the on/off setting in case you made a wiring mistake ;-) @EB
int selectButton1Pin = 8;                                 // push button for changing settings on digital pin 8
int useSelectButton1 = true;                              // set to false if no push button1 for selecting the color scheme is connected  @EB
int selectButton2Pin = 10;                                // push button for changing settings on digital pin 10
int useSelectButton2 = true;                              // set to false if no push button2 is connected  @EB

//
// setup variables for the number of leds and led strip or 2 rings
//

#if defined (led_matrix_40)
  //settings for a 40 led matrix

  int stripNumOfLeds = 40;                                  // the total number of leds
  int stripsOn2Pins = false;                                // set to true if the LED strips or rings are connected to 2 input pins
  uint32_t stripColor[21];                                  // half of the number of leds + 1
  int displayMiddleLed = false;                             // display the middle led (blue). set to true for one strip, false for two strips or rings
  int splitStrip = true;                                    // set to true when using 2 strips or rings, false for one strip
  int middleOffset = 0;                                     // offset for the middle led when using one strip
  int startupAnimationDelay = 6;                            // delay for the startup animation
  int orangeLimitAmount = 0;                                // limit the amount of green of the middle LEDs to make them more orange
  int swapLeftRight = false;                                // swap the left and right input values or not
  
  int dropDelay = 5;                                        // hold time before dropping the leds
  float dropFactor = .94;                                   // value for dropping the leds
  
  int peakTimeNoDropDelay = 250;                            // peak hold time when not dropping the peaks (when droppingPeak is false)
  int peakTimeFirstDropDelay = 150;                         // peak hold time when dropping the first peak
  int peakTimeDropDelay = 7;                                // peak hold time when dropping the rest of the peaks
  float peakDropFactor = .94;                               // value for dropping the peaks
  int droppingPeakFade = false;                             // display the dropping peak fading to black or not
  
  int bouncingPeaksNumOfLeds = 6;                           // how many leds to bounce up (max)
  int bouncingPeaksNumOfLedsMin = 3;                        // how many leds to bounce up (min) when using dynamicBouncingPeaks
  int bouncingPeakDelay = 6;                                // delay between peak bounce updates
  int bouncingPeakCounterInc = 10;                          // increase counter for each bounce update. note: it uses a 0-180 sin function for the bouncing

#elif defined (led_ring_60)
  //settings for a 60 led ring

  int stripNumOfLeds = 60;                                  // the total number of leds
  int stripsOn2Pins = false;                                // set to true if the LED strips or rings are connected to 2 input pins
  uint32_t stripColor[31];                                  // half of the number of leds + 1
  int displayMiddleLed = false;                             // display the middle led (blue). set to true for one strip, false for two strips or rings
  int splitStrip = true;                                    // set to true when using 2 strips or rings, false for one strip
  int middleOffset = 0;                                     // offset for the middle led when using one strip
  int startupAnimationDelay = 6;                            // delay for the startup animation
  int orangeLimitAmount = 0;                                // limit the amount of green of the middle LEDs to make them more orange
  int swapLeftRight = false;                                // swap the left and right input values or not
  
  int dropDelay = 5;                                        // hold time before dropping the leds
  float dropFactor = .94;                                   // value for dropping the leds
  
  int peakTimeNoDropDelay = 250;                            // peak hold time when not dropping the peaks (when droppingPeak is false)
  int peakTimeFirstDropDelay = 70;                         // peak hold time when dropping the first peak
  int peakTimeDropDelay = 7;                                // peak hold time when dropping the rest of the peaks
  float peakDropFactor = .94;                               // value for dropping the peaks
  int droppingPeakFade = false;                             // display the dropping peak fading to black or not
  
  int bouncingPeaksNumOfLeds = 6;                           // how many leds to bounce up (max)
  int bouncingPeaksNumOfLedsMin = 3;                        // how many leds to bounce up (min) when using dynamicBouncingPeaks
  int bouncingPeakDelay = 4;                                // delay between peak bounce updates
  int bouncingPeakCounterInc = 10;                          // increase counter for each bounce update. note: it uses a 0-180 sin function for the bouncing

#elif defined (led_ring_60_ps)
  //settings for a 60 led ring - pulsating and spinning settings

  int stripNumOfLeds = 60;                                  // the total number of leds
  int stripsOn2Pins = false;                                // set to true if the LED strips or rings are connected to 2 input pins
  uint32_t stripColor[31];                                  // half of the number of leds + 1
  int displayMiddleLed = true;                              // display the middle led (blue). set to true for one strip, false for two strips or rings
  int splitStrip = true;                                    // set to true when using 2 strips or rings, false for one strip
  int middleOffset = 0;                                     // offset for the middle led when using one strip
  int startupAnimationDelay = 6;                            // delay for the startup animation
  int orangeLimitAmount = 0;                                // limit the amount of green of the middle LEDs to make them more orange
  int swapLeftRight = false;                                // swap the left and right input values or not
  
  int dropDelay = 5;                                        // hold time before dropping the leds
  float dropFactor = .93;                                   // value for dropping the leds
  
  int peakTimeNoDropDelay = 10;                             // peak hold time when not dropping the peaks (when droppingPeak is false)
  int peakTimeFirstDropDelay = 10;                          // peak hold time when dropping the first peak
  int peakTimeDropDelay = 6;                                // peak hold time when dropping the rest of the peaks
  float peakDropFactor = .92;                               // value for dropping the peaks
  int droppingPeakFade = false;                             // display the dropping peak fading to black or not
  
  int bouncingPeaksNumOfLeds = 6;                           // how many leds to bounce up (max)
  int bouncingPeaksNumOfLedsMin = 3;                        // how many leds to bounce up (min) when using dynamicBouncingPeaks
  int bouncingPeakDelay = 4;                                // delay between peak bounce updates
  int bouncingPeakCounterInc = 10;                          // increase counter for each bounce update. note: it uses a 0-180 sin function for the bouncing

#elif defined (led_rhombus_160_ps)
  //settings for a 160 led rhombus - pulsating and spinning settings

  int stripNumOfLeds = 160;                                 // the total number of leds
  int stripsOn2Pins = false;                                // set to true if the LED strips or rings are connected to 2 input pins
  uint32_t stripColor[81];                                  // half of the number of leds + 1
  int displayMiddleLed = true;                              // display the middle led (blue). set to true for one strip, false for two strips or rings
  int splitStrip = true;                                    // set to true when using 2 strips or rings, false for one strip
  int middleOffset = 0;                                     // offset for the middle led when using one strip
  int startupAnimationDelay = 0;                            // delay for the startup animation
  int orangeLimitAmount = 0;                                // limit the amount of green of the middle LEDs to make them more orange
  int swapLeftRight = false;                                // swap the left and right input values or not
  
  int dropDelay = 4;                                        // hold time before dropping the leds
  float dropFactor = .92;                                   // value for dropping the leds
  
  int peakTimeNoDropDelay = 150;                            // peak hold time when not dropping the peaks (when droppingPeak is false)
  int peakTimeFirstDropDelay = 70;                          // peak hold time when dropping the first peak
  int peakTimeDropDelay = 7;                                // peak hold time when dropping the rest of the peaks
  float peakDropFactor = .94;                               // value for dropping the peaks
  int droppingPeakFade = false;                             // display the dropping peak fading to black or not
  
  int bouncingPeaksNumOfLeds = 10;                          // how many leds to bounce up (max)
  int bouncingPeaksNumOfLedsMin = 5;                        // how many leds to bounce up (min) when using dynamicBouncingPeaks
  int bouncingPeakDelay = 4;                                // delay between peak bounce updates
  int bouncingPeakCounterInc = 6;                           // increase counter for each bounce update. note: it uses a 0-180 sin function for the bouncing

#elif defined (led_strip_60)
  //settings for a 60 led strip

  int stripNumOfLeds = 60;                                  // the total number of leds
  int stripsOn2Pins = false;                                // set to true if the LED strips or rings are connected to 2 input pins
  uint32_t stripColor[31];                                  // half of the number of leds + 1
  int displayMiddleLed = true;                              // display the middle led (blue). set to true for one strip, false for two strips or rings
  int splitStrip = false;                                   // set to true when using 2 strips or rings, false for one strip
  int middleOffset = 1;                                     // offset for the middle led when using one strip
  int startupAnimationDelay = 6;                            // delay for the startup animation
  int orangeLimitAmount = 0;                                // limit the amount of green of the middle LEDs to make them more orange
  int swapLeftRight = false;                                // swap the left and right input values or not
  
  int dropDelay = 5;                                        // hold time before dropping the leds
  float dropFactor = .94;                                   // value for dropping the leds
  
  int peakTimeNoDropDelay = 250;                            // peak hold time when not dropping the peaks (when droppingPeak is false)
  int peakTimeFirstDropDelay = 70;                          // peak hold time when dropping the first peak
  int peakTimeDropDelay = 7;                                // peak hold time when dropping the rest of the peaks
  float peakDropFactor = .94;                               // value for dropping the peaks
  int droppingPeakFade = false;                             // display the dropping peak fading to black or not
  
  int bouncingPeaksNumOfLeds = 6;                           // how many leds to bounce up (max)
  int bouncingPeaksNumOfLedsMin = 3;                        // how many leds to bounce up (min) when using dynamicBouncingPeaks
  int bouncingPeakDelay = 4;                                // delay between peak bounce updates
  int bouncingPeakCounterInc = 10;                          // increase counter for each bounce update. note: it uses a 0-180 sin function for the bouncing

#elif defined (led_strip_60_qr)
  //settings for a 60 led strip - quick response

  int stripNumOfLeds = 60;                                  // the total number of leds
  int stripsOn2Pins = false;                                // set to true if the LED strips or rings are connected to 2 input pins
  uint32_t stripColor[31];                                  // half of the number of leds + 1
  int displayMiddleLed = true;                              // display the middle led (blue). set to true for one strip, false for two strips or rings
  int splitStrip = false;                                   // set to true when using 2 strips or rings, false for one strip
  int middleOffset = 1;                                     // offset for the middle led when using one strip
  int startupAnimationDelay = 6;                            // delay for the startup animation
  int orangeLimitAmount = 0;                                // limit the amount of green of the middle LEDs to make them more orange
  int swapLeftRight = false;                                // swap the left and right input values or not
  
  int dropDelay = 4;                                        // hold time before dropping the leds
  float dropFactor = .92;                                   // value for dropping the leds
  
  int peakTimeNoDropDelay = 0;                              // peak hold time when not dropping the peaks (when droppingPeak is false)
  int peakTimeFirstDropDelay = 0;                           // peak hold time when dropping the first peak
  int peakTimeDropDelay = 0;                                // peak hold time when dropping the rest of the peaks
  float peakDropFactor = 1;                                 // value for dropping the peaks
  int droppingPeakFade = false;                             // display the dropping peak fading to black or not
  
  int bouncingPeaksNumOfLeds = 0;                           // how many leds to bounce up (max)
  int bouncingPeaksNumOfLedsMin = 0;                        // how many leds to bounce up (min) when using dynamicBouncingPeaks
  int bouncingPeakDelay = 0;                                // delay between peak bounce updates
  int bouncingPeakCounterInc = 180;                         // increase counter for each bounce update. note: it uses a 0-180 sin function for the bouncing

#elif defined (led_strip_30)
  //settings for a 30 led strip

  int stripNumOfLeds = 30;                                  // the total number of leds
  int stripsOn2Pins = false;                                // set to true if the LED strips or rings are connected to 2 input pins
  uint32_t stripColor[16];                                  // half of the number of leds + 1
  int displayMiddleLed = true;                              // display the middle led (blue). set to true for one strip, false for two strips or rings
  int splitStrip = false;                                   // set to true when using 2 strips or rings, false for one strip
  int middleOffset = 1;                                     // offset for the middle led when using one strip
  int startupAnimationDelay = 10;                           // delay for the startup animation
  int orangeLimitAmount = 0;                                // limit the amount of green of the middle LEDs to make them more orange
  int swapLeftRight = false;                                // swap the left and right input values or not
  
  int dropDelay = 10;                                       // hold time before dropping the leds
  float dropFactor = .9;                                    // value for dropping the leds
  
  int peakTimeNoDropDelay = 250;                            // peak hold time when not dropping the peaks (set droppingPeak true or false)
  int peakTimeFirstDropDelay = 150;                         // peak hold time when dropping the first peak
  int peakTimeDropDelay = 15;                               // peak hold time when dropping the rest of the peaks
  float peakDropFactor = .94;                               // value for dropping the peaks
  int droppingPeakFade = false;                             // display the dropping peak fading to black or not
  
  int bouncingPeaksNumOfLeds = 4;                           // how many leds to bounce up (max)
  int bouncingPeaksNumOfLedsMin = 2;                        // how many leds to bounce up (min) when using dynamicBouncingPeaks
  int bouncingPeakDelay = 4;                                // delay between peak bounce updates
  int bouncingPeakCounterInc = 9;                           // increase counter for each bounce update. note: it uses a 0-180 sin function for the bouncing

#elif defined (led_2_rings_24)
  //settings for 2 24 led rings

  int stripNumOfLeds = 48;
  int stripsOn2Pins = false;
  uint32_t stripColor[25];
  int displayMiddleLed = false;
  int splitStrip = true;
  int middleOffset = 0;
  int startupAnimationDelay = 5;
  int orangeLimitAmount = 0;
  int swapLeftRight = false;
  
  int dropDelay = 2;
  float dropFactor = .96;
  
  int peakTimeNoDropDelay = 250;
  int peakTimeFirstDropDelay = 100;
  int peakTimeDropDelay = 10;
  float peakDropFactor = .94;
  int droppingPeakFade = false;
  
  int bouncingPeaksNumOfLeds = 4;
  int bouncingPeaksNumOfLedsMin = 2;
  int bouncingPeakDelay = 4;
  int bouncingPeakCounterInc = 9;

#elif defined(led_2_rings_30)
  //settings for 2 30 led rings

  int stripNumOfLeds = 60;
  int stripsOn2Pins = false;
  uint32_t stripColor[31];
  int displayMiddleLed = false;
  int splitStrip = true;
  int middleOffset = 0;
  int startupAnimationDelay = 5;
  int orangeLimitAmount = 0;
  int swapLeftRight = false;
  
  int dropDelay = 2;
  float dropFactor = .96;
  
  int peakTimeNoDropDelay = 250;
  int peakTimeFirstDropDelay = 100;
  int peakTimeDropDelay = 10;
  float peakDropFactor = .94;
  int droppingPeakFade = false;
  
  int bouncingPeaksNumOfLeds = 4;
  int bouncingPeaksNumOfLedsMin = 2;
  int bouncingPeakDelay = 4;
  int bouncingPeakCounterInc = 9;

#elif defined (led_strip_200)
  //settings for a 200 led strip

  int stripNumOfLeds = 200;
  int stripsOn2Pins = false;
  uint32_t stripColor[101];
  int displayMiddleLed = false;
  int splitStrip = true;
  int middleOffset = 0;
  int startupAnimationDelay = 1;
  int orangeLimitAmount = 0;
  int swapLeftRight = false;
  
  int dropDelay = 10;
  float dropFactor = .96;
  
  int peakTimeNoDropDelay = 250;
  int peakTimeFirstDropDelay = 100;
  int peakTimeDropDelay = 30;
  float peakDropFactor = .99;
  int droppingPeakFade = false;
  
  int bouncingPeaksNumOfLeds = 8;
  int bouncingPeaksNumOfLedsMin = 4;
  int bouncingPeakDelay = 4;
  int bouncingPeakCounterInc = 9;

#elif defined (led_strip_144)
  //settings for a 144 led strip

  int stripNumOfLeds = 145;
  int stripsOn2Pins = false;
  uint32_t stripColor[73];
  int displayMiddleLed = true;
  int splitStrip = false;
  int middleOffset = 1;
  int startupAnimationDelay = 1;
  int orangeLimitAmount = 0;
  int swapLeftRight = false;
  
  int dropDelay = 4;
  float dropFactor = .92;
  
  int peakTimeNoDropDelay = 250;
  int peakTimeFirstDropDelay = 100;
  int peakTimeDropDelay = 5;
  float peakDropFactor = .94;
  int droppingPeakFade = false;
  
  int bouncingPeaksNumOfLeds = 10;
  int bouncingPeaksNumOfLedsMin = 4;
  int bouncingPeakDelay = 2;
  int bouncingPeakCounterInc = 10;

#elif defined (led_2_strip_63)
  //settings for 2 63 led strips

  int stripNumOfLeds = 63;
  int stripsOn2Pins = true;
  uint32_t stripColor[64];
  int displayMiddleLed = true;
  int splitStrip = true;
  int middleOffset = 0;
  int startupAnimationDelay = 1;
  int orangeLimitAmount = 0;
  int swapLeftRight = false;
  
  int dropDelay = 5;
  float dropFactor = .94;
  
  int peakTimeNoDropDelay = 250;
  int peakTimeFirstDropDelay = 70;
  int peakTimeDropDelay = 7;
  float peakDropFactor = .94;
  int droppingPeakFade = false;
  
  int bouncingPeaksNumOfLeds = 12;
  int bouncingPeaksNumOfLedsMin = 4;
  int bouncingPeakDelay = 4;
  int bouncingPeakCounterInc = 10;

#elif defined (led_2_strip_63_qr)
  //settings for 2 63 led strips - quick response

  int stripNumOfLeds = 63;
  int stripsOn2Pins = true;
  uint32_t stripColor[64];
  int displayMiddleLed = false;
  int splitStrip = true;
  int middleOffset = 0;
  int startupAnimationDelay = 1;
  int orangeLimitAmount = 0;
  int swapLeftRight = false;
  
  int dropDelay = 4;
  float dropFactor = .92;
  
  int peakTimeNoDropDelay = 200;
  int peakTimeFirstDropDelay = 60;
  int peakTimeDropDelay = 6;
  float peakDropFactor = .92;
  int droppingPeakFade = false;
  
  int bouncingPeaksNumOfLeds = 12;
  int bouncingPeaksNumOfLedsMin = 4;
  int bouncingPeakDelay = 3;
  int bouncingPeakCounterInc = 10;
#endif

//
// setup other user variables
//

// basic settings
int pulsing = true;                                       // pulsing will display from the middle of each strip or ring  @EB

int spinCircle = true;                                    // spin the animation. will not work with stripsOn2Pins  @EB

int animType = 0;                                         // startup animation selection (1 looks nice for 1 ring)  @EB
int colorScheme = 10;                                     // 0: green-red, 1: blue-green, 2: blue-red, 3: red-blue, 4: green-blue, 5: red-green, 6: blue-white-red
                                                          // 7: red-white-blue, 8: green-white-red, 9: green-white-blue, 10: color wheel, 11: spinning color wheel,
	                            						  // 12: as 11 but spread with factor colorScheme12Factor  @EB
int maxColorScheme = 12;                                  // used for looping through the color schemes with the switch button
int colorScheme11SpinDelay = stripNumOfLeds / 4 ;         // delay for spinning scheme 11
int colorScheme12Factor = 3;                              // wheel spread factor for scheme 12 @EB

int minValue = 10;                                        // min analog input value
int sensitivityValue = 110;                               // 0 - 255, initial value (value read from the potentiometer if useSensorValues = true)

#ifdef highLevelInput
  int maxValue = 700;                                     // max analog input value (0-1023 equals 0-5V). try 300 for low level input, 700 for high
  int maxSensitivity = 2 * 255;                           // set to a higher setting to amplify low input levels. try 4 * 255 for low level input, 2 * 255 for high
#else
  int maxValue = 300;                                     // max analog input value (0-1023 equals 0-5V). try 300 for low level input, 700 for high
  int maxSensitivity = 4 * 255;                           // set to a higher setting to amplify low input levels. try 4 * 255 for low level input, 2 * 255 for high
#endif

int ledBrightness = 30;                                   // 0 - 255, initial value (value read from the potentiometer if useSensorValues = true)
int sensorDeviationBrightness = 3;                        // eliminate fluctuating values
int overflowDelay = 10;                                   // overflow hold time

// peak settings @EB
int displayPeaks = false;                                 // value will be set by the switch if useSensorValues = true
int displayTopAsPeak = true;                              // always display the top LED in peak color
int droppingPeak = true;                                  // display dropping peaks or not. note: displayPeaks has to be true 
int bouncingPeaks = false;                                // display bouncing peaks or not. note: displayPeaks has to be true 
int dynamicBouncingPeaks = false;                         // bounce less with lower peaks. note: bouncingPeaks has to be true 

//
// initialize other variables 
//

int numOfSegments, halfNumOfSegments, stripMiddle, maxDisplaySegments;
float sensitivityFactor;
float nonLinearResponseFactor;

int brightnessValue, prevBrightnessValue;
float ledFactor, ledFactor_div_numOfSegments;

uint32_t stripMiddleColor, stripOverflowColor, stripHoldColor;
uint32_t colorValue;

int leftValue = 0, rightValue = 0, maxReadValue = 0;
int leftValueN = 0, rightValueN = 0;
int leftAnalogValue = 0, rightAnalogValue = 0;
float log10MaxDisplaySegments;

int prevLeftValue = 0, prevRightValue = 0;
int prevLeftAnalogValue = 0, prevRightAnalogValue = 0;

int selectButton1PinState = 0, prevSelectButton1PinState = 0;
int selectButton2PinState = 0, prevSelectButton2PinState = 0;

int selectButton1PinSetting = colorScheme;
int selectButton2PinSetting = 0;

int i, j;
int dropLeft, dropRight;
int leftDropTime, rightDropTime;

int leftPeak = 0, rightPeak = 0;
int leftPeakTime = 0, rightPeakTime = 0;
int leftFirstPeak = true, rightFirstPeak = true;
int showPeaksPinSetting, prevShowPeaksPinSetting;

int stripPulseMiddle = 0;
int halfLeftValue, halfRightValue, halfPrevLeftValue, halfPrevRightValue;

int leftPeakBouncing = false, rightPeakBouncing = false;
int leftPeakBounce = 0, rightPeakBounce = 0;
int prevLeftPeakBounce = 0, prevRightPeakBounce = 0;
int leftPeakBounceCounter = 0, rightPeakBounceCounter = 0;
int leftPeakBounceDelayCounter = 0, rightPeakBounceDelayCounter = 0;
int leftBouncingPeaksNumOfLeds = 0, rightBouncingPeaksNumOfLeds = 0;
float bounceFactor;

int colorScheme11SpinValue = 0, colorScheme11SpinDelayValue = 0;
int colorSchemeFactor = 1;
long selectButton1Timer;

int spinDelayCounter = 0, spinCounter = 0, spinTurnsCounter = 0, spinTurnsMax = 0, spinTurnsDelay = 0, spinTurnsDelayMax = 0;
int spinCounterInc = 1;
int spinDelay = 0;
//
// initialize the strip or rings
//

Adafruit_NeoPixel left_strip = Adafruit_NeoPixel(stripNumOfLeds, leftStripPin, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel right_strip = Adafruit_NeoPixel(stripNumOfLeds, rightStripPin, NEO_GRB + NEO_KHZ800);

//
// setup
//

void setup() {
  #ifdef DEBUG
    Serial.begin(9600);
  #endif

  randomSeed(analogRead(2));

  if (stripsOn2Pins) {
    numOfSegments = stripNumOfLeds;
    maxDisplaySegments = numOfSegments - 1;
    
    stripMiddle = stripNumOfLeds;
    stripPulseMiddle = stripMiddle / 2;
    spinCircle = false;
  }
  else {
    numOfSegments = stripNumOfLeds / 2;
    stripMiddle = stripNumOfLeds / 2;
    maxDisplaySegments = stripMiddle - 1;

    stripPulseMiddle = stripMiddle / 2;
  }

  halfNumOfSegments = numOfSegments / 2; 
  bounceFactor = (float) bouncingPeaksNumOfLeds / (maxDisplaySegments - bouncingPeaksNumOfLeds);
  nonLinearResponseFactor = 90 / (float) maxDisplaySegments;
  log10MaxDisplaySegments = log10(maxDisplaySegments);

  pinMode(showPeaksPin, INPUT);    
  
  if (useSelectButton1)
    pinMode(selectButton1Pin, INPUT);  

  left_strip.begin();
  if (stripsOn2Pins) 
    right_strip.begin();

  if (useSensorValues) {
    readSensorValues();
    setInitialDisplayPeaks();
  }
  else {
    setStripColors();
    setSensitivityFactor();
  }

  #ifdef DEBUG_TEST_LEDS
    displayTest();
  #endif

  startupAnimation();
}

//
// main loop
//

void loop() {
  #ifdef DEBUG_PRINT_LOOP_TIME
    long time = millis();
  #endif


  if (useSensorValues) 
    readSensorValues();
  
  readValues();

  #if defined (DEBUG_NO_PEAKS)
    displayPeaks = false;
  #endif

  #if defined (DEBUG_PEAKS)
    displayPeaks = true;
  #endif

  if (pulsing) {
    drawPulsingValues();
  }
  else {
    drawValues();
    if (displayPeaks) {
      getPeaks();
      drawPeaks();
    }
  }

  left_strip.show();
  if (stripsOn2Pins)
    right_strip.show();
    
  storePrevValues();

  checkSpinCircle();

  #ifdef DEBUG_PRINT_LOOP_TIME
    time = millis() - time;
    Serial.println(time);
  #endif
}

// 
// functions
//

void setInitialDisplayPeaks() {
  #if !defined (DEBUG_NO_PEAK_SWITCH)
    showPeaksPinSetting = digitalRead(showPeaksPin);
  
    if (showPeaksPinSetting == HIGH)
      displayPeaks = false;
  #endif 
 
  if (reverseShowPeaks) {
    if (!displayPeaks)
      displayPeaks = true;
    else
      displayPeaks = false;
  }
  
  prevShowPeaksPinSetting = showPeaksPinSetting;
}

void readSensorValues() {
  //
  // peaks pin
  //

  #if !defined (DEBUG_NO_PEAK_SWITCH)
    showPeaksPinSetting = digitalRead(showPeaksPin);
  
    if (showPeaksMomentarySwitch) {
      if (showPeaksPinSetting == LOW && prevShowPeaksPinSetting == HIGH) {
        if (displayPeaks == true) {
          displayPeaks = false;
          clearLeftPeak();
          clearRightPeak();        
          if (showPeaksMomentarySwitch)
            while (digitalRead(showPeaksPin) == LOW) {}
        }
        else {
          displayPeaks = true;
        }
      }
    } 
    else {
      if (reverseShowPeaks) {
        if (showPeaksPinSetting == HIGH && prevShowPeaksPinSetting == LOW) 
          displayPeaks = true;
        else if (showPeaksPinSetting == LOW && prevShowPeaksPinSetting == HIGH) {
          displayPeaks = false;
          clearLeftPeak();
          clearRightPeak();        
        }
      }
      else {    
        if (showPeaksPinSetting == LOW && prevShowPeaksPinSetting == HIGH) 
          displayPeaks = true;
        else if (showPeaksPinSetting == HIGH && prevShowPeaksPinSetting == LOW) {
          displayPeaks = false;
          clearLeftPeak();
          clearRightPeak();        
        }
      }
    }
    if (pulsing) {
      if (displayPeaks)
        displayTopAsPeak = true;
      else
        displayTopAsPeak = false;
    }

    prevShowPeaksPinSetting = showPeaksPinSetting;
  #endif
  

  //
  // selectButtonPin 1 and 2
  //
  if (useSelectButton1) {      
    selectButton1PinState = digitalRead(selectButton1Pin);
    
    if (selectButton1PinState == HIGH && prevSelectButton1PinState == LOW)
      selectButton1Timer = millis();
      
    if (selectButton1PinState == HIGH && prevSelectButton1PinState == HIGH) {
      if ((millis() - selectButton1Timer) > 1000) {
        pulsing = !pulsing;
        setStripColors();
        displayNumber(colorScheme, 250);

        while (digitalRead(selectButton1Pin) == HIGH) {}
        selectButton1PinState = LOW;
        clearValues();
      }
    }
    else if (selectButton1PinState == LOW && prevSelectButton1PinState == HIGH) {
      selectButton1PinSetting++;
      if (selectButton1PinSetting > maxColorScheme) {
        selectButton1PinSetting = 0;
      }
      colorScheme = selectButton1PinSetting;

      if (colorScheme == 12)
        colorScheme11SpinValue = (colorScheme11SpinValue * colorScheme12Factor);

      setStripColors();
      displayNumber(colorScheme, 250);
    }
    prevSelectButton1PinState = selectButton1PinState;
  }

  if (useSelectButton2) {
    selectButton2PinState = digitalRead(selectButton2Pin);
    
    if (selectButton2PinState == HIGH && prevSelectButton2PinState == LOW) {
      selectButton2PinSetting++;
      
      switch(selectButton2PinSetting) {
        case 0:
        case 3: {   
          pulsing = false;
          spinCircle = false;
          selectButton2PinSetting = 0;
          break;
        }
        case 1: {
          pulsing = true;
          spinCircle= false;
          break;
        }
        case 2: {
          pulsing = true;
          spinCircle = true;
          break;
        }
      }
      
      setStripColors();
      displayNumber(colorScheme, 250);
    }
    
    prevSelectButton2PinState = selectButton2PinState;
  }
  
  //
  // brightness
  //
  brightnessValue = analogRead(brightnessPin);
  brightnessValue = map(brightnessValue, 0, 1023, 0, 255);
  
  if (abs(brightnessValue - prevBrightnessValue) > sensorDeviationBrightness) {
    ledBrightness = brightnessValue;
    setStripColors();
    prevBrightnessValue = brightnessValue;
  }

  //
  // colorscheme 11 spinning wheel
  //

  if (colorScheme == 11 || colorScheme == 12) {
    colorScheme11SpinDelayValue++;
    if (colorScheme11SpinDelayValue == colorScheme11SpinDelay) {
      colorScheme11SpinDelayValue = 0;
      colorScheme11SpinValue++;
      if (colorScheme11SpinValue > maxDisplaySegments * colorSchemeFactor)
        colorScheme11SpinValue = 0;
      setStripColors();
    }
  }

  //
  // sensitivity
  //
  sensitivityValue = analogRead(sensitivityPin);
  sensitivityValue = map(sensitivityValue, 0, 1023, 0, 255);
  setSensitivityFactor();
}

void setSensitivityFactor() {
  //sensitivityValue_div_numOfSegments = sensitivityValue / numOfSegments;
  sensitivityFactor = ((float) sensitivityValue / 255 * (float) maxSensitivity / 255);
}

void readValues() {
  #ifdef averageReadings
    leftAnalogValue = 0;
    rightAnalogValue = 0;
    
    for (i = 0; i <= averageNumOfReadings; i++) {
      leftAnalogValue += analogRead(leftPin);
      rightAnalogValue += analogRead(rightPin);
    }

    leftAnalogValue /= averageNumOfReadings;
    rightAnalogValue /= averageNumOfReadings;
    
  #else  
    leftAnalogValue = analogRead(leftPin);
    rightAnalogValue = analogRead(rightPin);
  #endif

  if (swapLeftRight) {
    int tempValue = leftAnalogValue;
    leftAnalogValue = rightAnalogValue;
    rightAnalogValue = tempValue;
  }

  if (leftAnalogValue < prevLeftAnalogValue) {
    leftDropTime++;
    if (leftDropTime > dropDelay) {
      leftAnalogValue = prevLeftAnalogValue * dropFactor;
      leftDropTime = 0;
    }
    else
      leftAnalogValue = prevLeftAnalogValue;
  }
   
  if (rightAnalogValue < prevRightAnalogValue) {
    rightDropTime++;
    if (rightDropTime > dropDelay) {
      rightAnalogValue = prevRightAnalogValue * dropFactor;
      rightDropTime = 0;
    }
    else
      rightAnalogValue = prevRightAnalogValue;
  }

  #ifdef DEBUG_PRINT_ANALOGVALUES
    Serial.print(leftAnalogValue);
    Serial.print(" ");
    Serial.println(rightAnalogValue);
  #endif  

  // map values  
  leftValue = map(leftAnalogValue * sensitivityFactor, minValue, maxValue, 0, maxDisplaySegments);
  rightValue = map(rightAnalogValue * sensitivityFactor, minValue, maxValue, 0, maxDisplaySegments);
  
  // if defined, convert to (reverse) non linear response
  boolean flagNonLinear = false;
  
  #if defined (nonLinearSinAudio)
    flagNonLinear = true;
    leftValueN = ((sin(((leftValue * nonLinearResponseFactor) + 270) * 0.0174533) + 1) * maxDisplaySegments);
    rightValueN = ((sin(((rightValue * nonLinearResponseFactor) + 270) * 0.0174533) + 1) * maxDisplaySegments);
    
  #elif defined (nonLinearReverseSinAudio)
    flagNonLinear = true;
    leftValueN = ((sin(((leftValue * nonLinearResponseFactor)) * 0.0174533)) * maxDisplaySegments);
    rightValueN = ((sin(((rightValue * nonLinearResponseFactor)) * 0.0174533)) * maxDisplaySegments);

  #elif defined (nonLinearLogAudio)
    flagNonLinear = true;
    leftValueN = ((log10(leftValue  + 1) / log10MaxDisplaySegments * maxDisplaySegments));
    rightValueN = ((log10(rightValue  + 1) / log10MaxDisplaySegments * maxDisplaySegments));
  
  #endif
  
  if (flagNonLinear == true) {
    #if defined (nonLinearAvr2)
      leftValue = (leftValue + leftValueN) / 2;
      rightValue = (rightValue + rightValueN) / 2;
    #else
      leftValue = leftValueN;
      rightValue = rightValueN;
    #endif
  }
  
// @EB_DEBUG

  #ifdef displayOverflow
    #ifdef compressOverflowPeaks
      for (i = 1; i <= compressOverflowNumOfTimes; i++) {
        if (leftValue > maxDisplaySegments) {
//          Serial.print(i);    
//          Serial.print("  ");
//          Serial.print(leftValue);    
//          Serial.print("  ");
          leftValue = leftValue - leftValue * compressOverflowFactor * i;
//          Serial.print(leftValue);
//          Serial.print("  ");
//          Serial.println(maxDisplaySegments);
        }
      }
    #endif
  #endif
  
  if (leftValue > maxDisplaySegments) {      
    leftValue = maxDisplaySegments;
    #ifdef displayOverflow
      drawOverflow();
    #endif
  }

  #ifdef displayOverflow
    #ifdef compressOverflowPeaks
      if (rightValue > maxDisplaySegments)
        rightValue = rightValue - rightValue * compressOverflowFactor;
    #endif
  #endif
  
  if (rightValue > maxDisplaySegments) {
    rightValue = maxDisplaySegments;
    #ifdef displayOverflow
      drawOverflow();
    #endif
  }
}

void storePrevValues() {
  prevLeftAnalogValue = leftAnalogValue;
  prevRightAnalogValue = rightAnalogValue;

  prevLeftValue = leftValue;
  prevRightValue = rightValue;
}

void getPeaks() {
  if (leftValue > leftPeak) {
    if (dynamicBouncingPeaks || prevLeftPeakBounce > 0)
      clearLeftBouncePeak();
          
    leftPeak = leftValue;
    leftPeakTime = 0;
    leftFirstPeak = true;

    if (bouncingPeaks) {
      leftPeakBouncing = true;
      leftPeakBounceCounter = 0;
      leftPeakBounceDelayCounter = 0;
      
      if (dynamicBouncingPeaks)
        leftBouncingPeaksNumOfLeds = max(bouncingPeaksNumOfLedsMin, (leftPeak * bounceFactor));
      else
        leftBouncingPeaksNumOfLeds = bouncingPeaksNumOfLeds;
    }
  }
  else {
    leftPeakTime++;
    if (droppingPeak) {
      if (leftFirstPeak) {
        if (leftPeakTime > peakTimeFirstDropDelay) {
          clearLeftPeak();
          leftFirstPeak = false;
        }
      }
      else {
        if (leftPeakTime > peakTimeDropDelay) {
          clearLeftPeak();
        }
      }
    }
    else {
      if (leftPeakTime > peakTimeNoDropDelay) {
        clearLeftPeak();
      }
    }
  }

  if (leftPeakBouncing) {
    if (leftFirstPeak) {
      leftPeakBounceDelayCounter++;
      if (leftPeakBounceDelayCounter >= bouncingPeakDelay) {
        leftPeakBounceDelayCounter = 0;
        leftPeakBounceCounter += bouncingPeakCounterInc;
        if (leftPeakBounceCounter >= 180) {
          clearLeftBouncePeak();
          clearLeftBounce();
        }
        else {        
          leftPeakBounce = min((sin(leftPeakBounceCounter * 0.0174533) * leftBouncingPeaksNumOfLeds), (maxDisplaySegments - leftPeak));
          if (leftPeakBounce != prevLeftPeakBounce) {
            clearLeftBouncePeak();
          }
          prevLeftPeakBounce = leftPeakBounce;
        }
      }
    }
  }

  if (rightValue > rightPeak) {
    if (dynamicBouncingPeaks || prevRightPeakBounce > 0)
      clearRightBouncePeak();

    rightPeak = rightValue;
    rightPeakTime = 0;
    rightFirstPeak = true;

    if (bouncingPeaks) {
      rightPeakBouncing = true;
      rightPeakBounceCounter = 0;
      rightPeakBounceDelayCounter = 0;

      if (dynamicBouncingPeaks)
        rightBouncingPeaksNumOfLeds = max(bouncingPeaksNumOfLedsMin, (rightPeak * bounceFactor));
      else
        rightBouncingPeaksNumOfLeds = bouncingPeaksNumOfLeds;
    }
  }
  else {
    rightPeakTime++;
    if (droppingPeak) {
      if (rightFirstPeak) {
        if (rightPeakTime > peakTimeFirstDropDelay) {
          clearRightPeak();
          rightFirstPeak = false;
        }
      }
      else {
        if (rightPeakTime > peakTimeDropDelay)
          clearRightPeak();
      }
    }
    else {
      if (rightPeakTime > peakTimeNoDropDelay)
        clearRightPeak();
    }
  }

  if (rightPeakBouncing) {
    if (rightFirstPeak) {
      rightPeakBounceDelayCounter++;
      if (rightPeakBounceDelayCounter >= bouncingPeakDelay) {
        rightPeakBounceDelayCounter = 0;
        rightPeakBounceCounter += bouncingPeakCounterInc;
  
        if (rightPeakBounceCounter >= 180) {
          clearRightBouncePeak();
          clearRightBounce();
        }
        else {        
          rightPeakBounce = min((sin(rightPeakBounceCounter * 0.0174533) * rightBouncingPeaksNumOfLeds), (maxDisplaySegments - rightPeak));
          if (rightPeakBounce != prevRightPeakBounce) {
            clearRightBouncePeak();
          }
          prevRightPeakBounce = rightPeakBounce;
        }
      }
    }
  }
}

void checkSpinCircle () {
  if (spinCircle) {
    if (spinTurnsMax == 0) {
      spinTurnsMax = random(stripNumOfLeds / 4, stripNumOfLeds * 3);  // spin at least a quarter turn, max 3 turns
      
      if (random(10) > 4)
        spinCounterInc = -spinCounterInc;
      
      spinTurnsDelayMax = random(100, 1000); // @EB_DEBUG

      spinDelay = random(20, 75); // @EB_DEBUG
    }

    if (spinTurnsCounter == spinTurnsMax) {
      spinTurnsDelay++;
      if (spinTurnsDelay == spinTurnsDelayMax) {
        spinTurnsDelay = 0;
        spinTurnsCounter = 0;
        spinTurnsMax = 0;
      }
    }
    else {
      spinDelayCounter++;
  
      if (spinDelayCounter > spinDelay) {
        clearZeroAndPeaks();

        spinCounter += spinCounterInc;
        if (spinCounter > stripNumOfLeds)
          spinCounter = 0;
        else if (spinCounter < 0)
          spinCounter = stripNumOfLeds;

        spinTurnsCounter++;
        spinDelayCounter = 0;
      }
    }
  }
}

int getSpinCircleValue(int value) {
  if (!spinCircle)
   return value;
  else {
    int calcValue = value + spinCounter;
    if (calcValue >= stripNumOfLeds)
      calcValue -= stripNumOfLeds;
    return calcValue;
  }
}

void drawValues() {
  if (splitStrip) {
    for (i = middleOffset; i < leftValue; i++)
      left_strip.setPixelColor(getSpinCircleValue(i), stripColor[i]);

    if (!displayPeaks && displayTopAsPeak)
      left_strip.setPixelColor(getSpinCircleValue(leftValue), stripHoldColor);

    for (i = prevLeftValue; i >= leftValue; i--)
      left_strip.setPixelColor(getSpinCircleValue(i), 0);

    if (stripsOn2Pins) {
      for (i = middleOffset; i < rightValue; i++) 
        right_strip.setPixelColor(i, stripColor[i]);

      if (!displayPeaks && displayTopAsPeak)
        right_strip.setPixelColor(rightValue, stripHoldColor);

      for (i = prevRightValue; i >= rightValue; i--)
        right_strip.setPixelColor(i, 0);
    }
    else {
      for (i = middleOffset; i < rightValue; i++)
        left_strip.setPixelColor(getSpinCircleValue(stripMiddle + i), stripColor[i]);

      if (!displayPeaks && displayTopAsPeak)
        left_strip.setPixelColor(getSpinCircleValue(stripMiddle + rightValue), stripHoldColor);
        
      for (i = prevRightValue; i >= rightValue; i--)
        left_strip.setPixelColor(getSpinCircleValue(stripMiddle + i), 0);
    }
  }
  else {
    for (i = middleOffset; i < leftValue; i++)
      left_strip.setPixelColor(getSpinCircleValue(stripMiddle + i), stripColor[i]);

    if (!displayPeaks && displayTopAsPeak)
      left_strip.setPixelColor(getSpinCircleValue(stripMiddle + leftValue), stripHoldColor);

    for (i = prevLeftValue; i >= leftValue; i--)
      left_strip.setPixelColor(getSpinCircleValue(stripMiddle + i), 0);
  
    for (i = middleOffset; i < rightValue; i++)
      left_strip.setPixelColor(getSpinCircleValue(stripMiddle - i), stripColor[i]);

    if (!displayPeaks && displayTopAsPeak)
      left_strip.setPixelColor(getSpinCircleValue(stripMiddle - rightValue), stripHoldColor);

    for (i = prevRightValue; i >= rightValue; i--)
      left_strip.setPixelColor(getSpinCircleValue(stripMiddle - i), 0);
  }

  if (displayMiddleLed) 
    left_strip.setPixelColor(getSpinCircleValue(stripMiddle), stripMiddleColor);
}

void drawPulsingValues() {
  halfLeftValue = (leftValue + 1) / 2;
  halfRightValue = (rightValue + 1) / 2;
  halfPrevLeftValue = (prevLeftValue + 1)/ 2;
  halfPrevRightValue = (prevRightValue + 1) / 2;
  
  if (splitStrip) {
    for (i = 0; i < halfLeftValue; i++) {
      colorValue = stripColor[i * 2];
      left_strip.setPixelColor(getSpinCircleValue(stripPulseMiddle + i), colorValue);
      left_strip.setPixelColor(getSpinCircleValue(stripPulseMiddle - i), colorValue);
    }

    if (displayTopAsPeak) {
      left_strip.setPixelColor(getSpinCircleValue(stripPulseMiddle + halfLeftValue), stripHoldColor);
      left_strip.setPixelColor(getSpinCircleValue(stripPulseMiddle - halfLeftValue), stripHoldColor);
    }

    for (i = halfPrevLeftValue; i >= halfLeftValue; i--) {
      left_strip.setPixelColor(getSpinCircleValue(stripPulseMiddle + i), 0);
      left_strip.setPixelColor(getSpinCircleValue(stripPulseMiddle - i), 0);
    }

    if (stripsOn2Pins) {
      for (i = 0; i < halfRightValue; i++) {
        colorValue = stripColor[i * 2];
        right_strip.setPixelColor((stripPulseMiddle + i), colorValue);
        right_strip.setPixelColor((stripPulseMiddle - i), colorValue);
      }

      if (displayTopAsPeak) {
        right_strip.setPixelColor(getSpinCircleValue(stripPulseMiddle + halfRightValue), stripHoldColor);
        right_strip.setPixelColor(getSpinCircleValue(stripPulseMiddle - halfRightValue), stripHoldColor);
      }
      
      for (i = halfPrevRightValue; i >= halfRightValue; i--) {
        right_strip.setPixelColor((stripPulseMiddle + i), 0);
        right_strip.setPixelColor((stripPulseMiddle - i), 0);
      }
    }
    else {
      for (i = 0; i < halfRightValue; i++) {
        colorValue = colorValue = stripColor[i * 2];
        left_strip.setPixelColor(getSpinCircleValue(stripMiddle + stripPulseMiddle + i), colorValue);
        left_strip.setPixelColor(getSpinCircleValue(stripMiddle + stripPulseMiddle - i), colorValue);
      }

      if (displayTopAsPeak) {
        left_strip.setPixelColor(getSpinCircleValue(stripMiddle + stripPulseMiddle + halfRightValue), stripHoldColor);
        left_strip.setPixelColor(getSpinCircleValue(stripMiddle + stripPulseMiddle - halfRightValue), stripHoldColor);
      }

      for (i = halfPrevRightValue; i >= halfRightValue; i--) {
        left_strip.setPixelColor(getSpinCircleValue(stripMiddle + stripPulseMiddle + i), 0);
        left_strip.setPixelColor(getSpinCircleValue(stripMiddle + stripPulseMiddle - i), 0);
      }
    }
  }
  else {
    for (i = 0; i < halfLeftValue; i++) {
      colorValue = colorValue = stripColor[i * 2];
      left_strip.setPixelColor(getSpinCircleValue(stripMiddle + stripPulseMiddle + i), colorValue);
      left_strip.setPixelColor(getSpinCircleValue(stripMiddle + stripPulseMiddle - i), colorValue);
    }

    if (displayTopAsPeak) {
      left_strip.setPixelColor(getSpinCircleValue(stripMiddle + stripPulseMiddle + halfLeftValue), stripHoldColor);
      left_strip.setPixelColor(getSpinCircleValue(stripMiddle + stripPulseMiddle - halfLeftValue), stripHoldColor);
    }
    
    for (i = halfPrevLeftValue; i >= halfLeftValue; i--) {
      left_strip.setPixelColor(getSpinCircleValue(stripMiddle + stripPulseMiddle + i), 0);
      left_strip.setPixelColor(getSpinCircleValue(stripMiddle + stripPulseMiddle - i), 0);
    }
  
    for (i = 0; i < halfRightValue; i++) {
      colorValue = colorValue = stripColor[i * 2];
      left_strip.setPixelColor(getSpinCircleValue(stripMiddle - (stripPulseMiddle + i)), colorValue);
      left_strip.setPixelColor(getSpinCircleValue(stripMiddle - (stripPulseMiddle - i)), colorValue);
    }

    if (displayTopAsPeak) {
      left_strip.setPixelColor(getSpinCircleValue(stripMiddle - (stripPulseMiddle + halfRightValue)), stripHoldColor);
      left_strip.setPixelColor(getSpinCircleValue(stripMiddle - (stripPulseMiddle - halfRightValue)), stripHoldColor);
    }
    
    for (i = halfPrevRightValue; i >= halfRightValue; i--) {
      left_strip.setPixelColor(getSpinCircleValue(stripMiddle - (stripPulseMiddle + i)), 0);
      left_strip.setPixelColor(getSpinCircleValue(stripMiddle - (stripPulseMiddle - i)), 0);
    }
  }

  if (displayMiddleLed) {
    left_strip.setPixelColor(getSpinCircleValue(stripMiddle - stripPulseMiddle), stripMiddleColor);
    left_strip.setPixelColor(getSpinCircleValue(stripMiddle + stripPulseMiddle), stripMiddleColor);
  }
}

void clearZeroAndPeaks() {
  left_strip.setPixelColor(getSpinCircleValue(middleOffset), 0);
  left_strip.setPixelColor(getSpinCircleValue(stripMiddle), 0);

  if (displayTopAsPeak) {
    if (splitStrip) {
      left_strip.setPixelColor(getSpinCircleValue(stripPulseMiddle + halfLeftValue), 0);
      left_strip.setPixelColor(getSpinCircleValue(stripPulseMiddle - halfLeftValue), 0);
      
      left_strip.setPixelColor(getSpinCircleValue(stripMiddle + stripPulseMiddle + halfRightValue), 0);
      left_strip.setPixelColor(getSpinCircleValue(stripMiddle + stripPulseMiddle - halfRightValue), 0);
    }
    else {
      left_strip.setPixelColor(getSpinCircleValue(stripMiddle + stripPulseMiddle + halfLeftValue), 0);
      left_strip.setPixelColor(getSpinCircleValue(stripMiddle + stripPulseMiddle - halfLeftValue), 0);

      left_strip.setPixelColor(getSpinCircleValue(stripMiddle - (stripPulseMiddle + halfRightValue)), 0);
      left_strip.setPixelColor(getSpinCircleValue(stripMiddle - (stripPulseMiddle - halfRightValue)), 0);
    }
  }
}

void drawPeaks() {  
  if (leftPeak > 0) {
    if (droppingPeakFade && leftPeakBouncing == false)
      stripHoldColor = left_strip.Color(max(1, (255 * leftPeak * ledFactor_div_numOfSegments)), 0, 0);
    else
      stripHoldColor = stripColor[numOfSegments];

    if (splitStrip)
      left_strip.setPixelColor(getSpinCircleValue(leftPeak + leftPeakBounce), stripHoldColor);
    else
      left_strip.setPixelColor(getSpinCircleValue(stripMiddle + (leftPeak + leftPeakBounce)), stripHoldColor);
  } 
  
  if (rightPeak > 0) {
    if (droppingPeakFade && rightPeakBouncing == false)
      stripHoldColor = left_strip.Color(max(1, (255 * rightPeak * ledFactor_div_numOfSegments)), 0, 0);    
    else
      stripHoldColor = stripColor[numOfSegments];

    if (splitStrip) {
      if (stripsOn2Pins) {
        right_strip.setPixelColor(getSpinCircleValue(rightPeak + rightPeakBounce), stripHoldColor);
      }
      else {
        left_strip.setPixelColor(getSpinCircleValue(stripMiddle + rightPeak + rightPeakBounce), stripHoldColor);
      }
    }
    else {
      left_strip.setPixelColor(getSpinCircleValue(stripMiddle - (rightPeak + rightPeakBounce)), stripHoldColor);
    }
  }

  //if (leftPeak > 0 || rightPeak > 0)
  //  left_strip.show();    
}

void clearLeftPeak() {  
  if (splitStrip)
    left_strip.setPixelColor(getSpinCircleValue(leftPeak + prevLeftPeakBounce), 0);
  else
    left_strip.setPixelColor(getSpinCircleValue(stripMiddle + (leftPeak + prevLeftPeakBounce)), 0);

  if (droppingPeak)
    leftPeak = leftPeak * peakDropFactor;
  else
    leftPeak = 0;
  leftPeakTime = 0;
}

void clearRightPeak() {
  if (splitStrip) {
    if( stripsOn2Pins) {
      right_strip.setPixelColor(getSpinCircleValue(rightPeak + prevRightPeakBounce), 0);
    }
    else {
      left_strip.setPixelColor(getSpinCircleValue(stripMiddle + rightPeak + prevRightPeakBounce), 0);
    }
  }
  else {
    left_strip.setPixelColor(getSpinCircleValue(stripMiddle - (rightPeak + prevRightPeakBounce)), 0);
  }
  
  if (droppingPeak) 
    rightPeak = rightPeak * peakDropFactor;
  else
    rightPeak = 0;
  rightPeakTime = 0;
}

void clearLeftBouncePeak() {
  if (splitStrip)
    left_strip.setPixelColor(getSpinCircleValue(leftPeak + prevLeftPeakBounce), 0);
  else
    left_strip.setPixelColor(getSpinCircleValue(stripMiddle + (leftPeak + prevLeftPeakBounce)), 0);
}

void clearRightBouncePeak() {
  if (splitStrip) {
    if (stripsOn2Pins) {
      right_strip.setPixelColor(getSpinCircleValue(rightPeak + prevRightPeakBounce), 0);
    }
    else {
      left_strip.setPixelColor(getSpinCircleValue((stripMiddle + rightPeak + prevRightPeakBounce)), 0);
    }
  }
  else {
    left_strip.setPixelColor(getSpinCircleValue(stripMiddle - (rightPeak + prevRightPeakBounce)), 0);
  }
}

void clearLeftBounce() {
  leftPeakBouncing = false;
  leftPeakBounceCounter = 0;
  leftPeakBounce = 0;
  prevLeftPeakBounce = 0;
  leftBouncingPeaksNumOfLeds = 0;
}

void clearRightBounce() {
  rightPeakBouncing = false;
  rightPeakBounceCounter = 0;
  rightPeakBounce = 0;
  prevRightPeakBounce = 0;
  leftBouncingPeaksNumOfLeds = 0;
}

void clearValues() {
  leftAnalogValue = 0;
  rightAnalogValue = 0;
  prevLeftAnalogValue = 0;
  prevRightAnalogValue = 0;
  leftPeak = 0;
  rightPeak = 0;
}


void drawOverflow() {
  for (i = 0; i <= numOfSegments; i++) {
    left_strip.setPixelColor(getSpinCircleValue(stripMiddle - i), stripOverflowColor);
    if (stripsOn2Pins) {
      right_strip.setPixelColor(i, stripOverflowColor);
    }
    else {
      left_strip.setPixelColor(getSpinCircleValue(stripMiddle + i), stripOverflowColor);
    }
  }
  left_strip.show();
  if (stripsOn2Pins)
    right_strip.show();
  
  delay(overflowDelay);

  for (i = 0; i <= numOfSegments; i++) {
    left_strip.setPixelColor(getSpinCircleValue(stripMiddle - i), 0);
    if (stripsOn2Pins) {
      right_strip.setPixelColor(i, 0);
    }
    else {
      left_strip.setPixelColor(getSpinCircleValue(stripMiddle + i), 0);
    }
  }
  left_strip.show();
  if (stripsOn2Pins)
    right_strip.show();
}

void setStripColors() {
  int r, g, b;
  int p1, p2;

  ledFactor = (float) ledBrightness / 255;
  ledFactor_div_numOfSegments = (float) ledFactor / (float) numOfSegments;
  stripMiddleColor = left_strip.Color(0, 0, 255 * ledFactor);
  
  switch (colorScheme) {
    case 0: {      
      int orangeLimit;
      float orangeFactor = orangeLimitAmount / halfNumOfSegments;
    
      for (i = 0; i <= numOfSegments; i++) {
        if (i <= halfNumOfSegments)
          orangeLimit = (i * orangeFactor);
        else
          orangeLimit = ((numOfSegments - i) * orangeFactor);
    
        stripColor[i] = left_strip.Color((255 * i * ledFactor_div_numOfSegments), ((255 - orangeLimit) * (numOfSegments - i) * ledFactor_div_numOfSegments), 0); 
      }
      break;
    }

    case 1: {
      for (i = 0; i <= numOfSegments; i++) {
        stripColor[i] = left_strip.Color(0, (255 * i * ledFactor_div_numOfSegments), (255 * (numOfSegments - i) * ledFactor_div_numOfSegments)); 
      }
      break;
    }

    case 2: {
      for (i = 0; i <= numOfSegments; i++) {
        stripColor[i] = left_strip.Color((255 * i * ledFactor_div_numOfSegments), 0, (255 * (numOfSegments - i) * ledFactor_div_numOfSegments)); 
      }
      break;
    }

    case 3: {
      for (i = 0; i <= numOfSegments; i++) {
        stripColor[i] = left_strip.Color((255 * (numOfSegments - i) * ledFactor_div_numOfSegments), 0, (255 * i * ledFactor_div_numOfSegments)); 
      }
      break;
    }

    case 4: {
      for (i = 0; i <= numOfSegments; i++) {
        stripColor[i] = left_strip.Color(0, (255 * (numOfSegments - i) * ledFactor_div_numOfSegments), (255 * i * ledFactor_div_numOfSegments)); 
      }
      break;
    }

    case 5: {
      for (i = 0; i <= numOfSegments; i++) {
        stripColor[i] = left_strip.Color((255 * (numOfSegments - i) * ledFactor_div_numOfSegments), (255 * i * ledFactor_div_numOfSegments), 0); 
      }
      break;
    }

    case 6: {
      for (i = 0; i <= numOfSegments; i++) {
        r = (255 * i * ledFactor_div_numOfSegments);
        g = (255 * min(i, numOfSegments - i) * ledFactor_div_numOfSegments);
        b = (200 * (numOfSegments - i) * ledFactor_div_numOfSegments); 
        stripColor[i] = left_strip.Color(r, g, b); 
      }
      break;
    }

    case 7: {
      for (i = 0; i <= numOfSegments; i++) {
        b = (255 * i * ledFactor_div_numOfSegments);
        g = (255 * min(i, numOfSegments - i) * ledFactor_div_numOfSegments);
        r = (255 * (numOfSegments - i) * ledFactor_div_numOfSegments); 
        stripColor[i] = left_strip.Color(r, g, b); 
      }
      break;
    }

    case 8: {
      for (i = 0; i <= numOfSegments; i++) {
        r = (255 * i * ledFactor_div_numOfSegments);
        b = (255 * min(i, numOfSegments - i) * ledFactor_div_numOfSegments);
        g = (255 * (numOfSegments - i) * ledFactor_div_numOfSegments); 
        stripColor[i] = left_strip.Color(r, g, b); 
      }
      break;
    }

    case 9: {
      for (i = 0; i <= numOfSegments; i++) {
        b = (255 * i * ledFactor_div_numOfSegments);
        r = (255 * min(i, numOfSegments - i) * ledFactor_div_numOfSegments);
        g = (255 * (numOfSegments - i) * ledFactor_div_numOfSegments); 
        stripColor[i] = left_strip.Color(r, g, b); 
      }
      break;
    }

    case 10: 
      colorScheme11SpinValue = 0;
      
    case 11:     
    
    case 12: {
      p1 = (85 * numOfSegments / 255);
      p2 = (170 * numOfSegments / 255);
      int wheel;

      if (colorScheme == 12)
        colorSchemeFactor = colorScheme12Factor;        
      else
        colorSchemeFactor = 1;
            
      for (i = 0; i <= numOfSegments; i++) {  
        //wheel = int(float(i + colorScheme11SpinValue) / colorSchemeFactor) % numOfSegments;  // reverse wheel
        
        wheel = int(float(i - colorScheme11SpinValue) / colorSchemeFactor + numOfSegments) % numOfSegments;

        if (wheel < p1) {          
          wheel = map(wheel, 0, p1, 0, 255);
          r = (wheel * ledFactor);
          g = ((255 - wheel) * ledFactor);
          b = 0;
        } 
        else if (wheel < p2) {
          wheel = map(wheel, p1, p2, 0, 255);
          r = ((255 - wheel) * ledFactor);
          g = 0;
          b = (wheel * ledFactor);
        } 
        else {
          wheel = map(wheel, p2, numOfSegments, 0, 255);
          r = 0;
          g = (wheel * ledFactor);
          b = ((255 - wheel) * ledFactor);
        }        

        stripColor[i] = left_strip.Color(r, g, b); 
      }
      break;
    }
  }

  if (colorScheme >= 10)
    stripHoldColor = left_strip.Color(255 * ledFactor, 0, 0); // set to red for the color wheels
  else
    stripHoldColor = stripColor[numOfSegments];
    
  stripOverflowColor = stripHoldColor;   // left_strip.Color(min(255, 255 * ledFactor * 1.5), 0, 0);
}

void startupAnimation() {  
  for (j = 0; j < 2; j++) {
    for (i = 0; i <= numOfSegments; i++) {
      if (animType == 1)
        left_strip.setPixelColor(stripMiddle - (numOfSegments - i), stripColor[i]);
      else
        left_strip.setPixelColor(stripMiddle - i, stripColor[i]);
      
      if (stripsOn2Pins)
        right_strip.setPixelColor(i, stripColor[i]);
      else
        left_strip.setPixelColor(stripMiddle + i, stripColor[i]);

      left_strip.show();
      if (stripsOn2Pins)
        right_strip.show();  
      
      delay(startupAnimationDelay);
    }
    
    for (i = 0; i <= numOfSegments; i++) {
      if (animType == 1)
        left_strip.setPixelColor(stripMiddle - (numOfSegments - i), 0);
      else
        left_strip.setPixelColor(stripMiddle - i, 0);
        
      if (stripsOn2Pins)
        right_strip.setPixelColor(i, 0);
      else
        left_strip.setPixelColor(stripMiddle + i, 0);

      left_strip.show();
      if (stripsOn2Pins)
        right_strip.show();  
      
      delay(startupAnimationDelay);
    }
  }
}

void displayNumber (int number, int displayDelay) {
  left_strip.clear();
  if (stripsOn2Pins)
    right_strip.clear();

  number++; // @EB_DEBUG : display value 0 at led 1
  
  for (i = 0; i <= number; i++) {
    if (i % 5 == 0) 
      colorValue = stripMiddleColor;
    else
      colorValue = stripColor[0];

    left_strip.setPixelColor(middleOffset + i, colorValue);

    if (stripsOn2Pins)
      right_strip.setPixelColor(middleOffset + i, colorValue);
    else
      left_strip.setPixelColor(stripMiddle + middleOffset + i, colorValue);

    delay(45 - number * 3); // @EB_DEBUG
    
    left_strip.show();
    if (stripsOn2Pins)
      right_strip.show();  
  }

  if (pulsing) {
    left_strip.setPixelColor(middleOffset + maxDisplaySegments, stripMiddleColor);

    if (stripsOn2Pins)
      right_strip.setPixelColor(maxDisplaySegments, stripMiddleColor);
    else
      left_strip.setPixelColor(stripMiddle + maxDisplaySegments, stripMiddleColor);

    left_strip.show();
    if (stripsOn2Pins)
      right_strip.show();  
  }

  delay(displayDelay);

  left_strip.clear();
  if (stripsOn2Pins)
    right_strip.clear();
}


//
// for debugging
//

#ifdef DEBUG_TEST_LEDS
  void displayTest() {
    for (i = 0; i <= numOfSegments; i++) {
      left_strip.setPixelColor(stripMiddle - i, stripColor[i]);

      if (stripsOn2Pins)
        right_strip.setPixelColor(i, stripColor[i]);
      else
        left_strip.setPixelColor(stripMiddle + i, stripColor[i]);

      left_strip.show();
      if (stripsOn2Pins)
        right_strip.show();  

      delay(50);
    }
    delay(5000);
  
    for (i = 0; i <= numOfSegments; i++) {
      left_strip.setPixelColor(stripMiddle - i, 0);

      if (stripsOn2Pins)
        right_strip.setPixelColor(i, 0);
      else
        left_strip.setPixelColor(stripMiddle + i, 0);

      left_strip.show();
      if (stripsOn2Pins)
        right_strip.show();  
    }
  }
  
  void serialDisplayRGB(int r, int g, int b) {
    Serial.print(i);
    Serial.print(" ");
    Serial.print(r);
    Serial.print(" ");
    Serial.print(g);
    Serial.print(" ");
    Serial.println(b);
  }
#endif
Old LCD, LED and LED strip test version.Arduino
// include the library code:
#include <LiquidCrystal.h>
#include "LedControlMS.h"
#include <Adafruit_NeoPixel.h>

/*
  LiquidCrystal Library

  The circuit:
 * LCD RS pin to digital pin 12
 * LCD Enable pin to digital pin 11
 * LCD D4 pin to digital pin 5
 * LCD D5 pin to digital pin 4
 * LCD D6 pin to digital pin 3
 * LCD D7 pin to digital pin 2
 * LCD R/W pin to ground
 * LCD VSS pin to ground
 * LCD VCC pin to 5V
 * 10K resistor:
 * ends to +5V and ground
 * wiper to LCD VO pin (pin 3)

*/
// initialize the library by associating any needed LCD interface pin
// with the arduino pin number it is connected to
const int rs = 12, en = 11, d4 = 5, d5 = 4, d6 = 3, d7 = 2;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);

// led matrix
// DataIN, CLK, LOAD, # of matrix
#define NUMOFMATRIX 4
LedControl led = LedControl(10,8,9,NUMOFMATRIX);

// led strip
#define PIN 6
#define NUMOFLEDS 31
Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUMOFLEDS, PIN, NEO_GRB + NEO_KHZ800);

// setup values
const int outputType = 1; //  lcd = 0, led = 1, led strip = 2

const int minValue = 20;
const int maxValue = 500;

int updateDelay, maxSegments;
float ledIntensity;

int leftPin = A0, rightPin = A1;
int leftValue = 0, rightValue = 0, averageValue = 0, maxReadValue = 0;
int leftAnalogValue = 0, rightAnalogValue = 0, averageAnalogValue = 0;

int prevLeftValue = 0, prevRightValue = 0, prevAverageValue = 0;
int prevLeftAnalogValue = 0, prevRightAnalogValue = 0, prevAverageAnalogValue = 0;

float dropFactor;

int i, j;

int holdShow = true;
int holdZeroShow = true;
int leftHold = 0, rightHold = 0;
int leftHoldTime = 0, rightHoldTime = 0;
int holdTime;

int stripMiddle;
uint32_t stripRed, stripGreen, stripBlue;
uint32_t stripColor[16];

void setup() {
	switch (outputType) {
    case 0:
  	  // set up the LCD's number of columns and rows:
  	  updateDelay = 50;
  	  maxSegments = 16;
      holdTime = 20;
      dropFactor = .9;
      
  	  lcd.begin(16, 2);
     break;
     
	  case 1:
  	  // set up led
  	  updateDelay = 0;
  	  maxSegments = 7;
      holdTime = 50;
      ledIntensity = 1.2;
      dropFactor = .7;
        
  	  for (i = 0; i < NUMOFMATRIX; i++) {
  		  led.shutdown(i, false);
  		  //led.setIntensity(i, 4);
  		  led.clearDisplay(i);
  	  }
  
  	  // setup: identify left & right matrix
  	  led.writeString(0,"#1 - LEFT");
  	  led.writeString(1,"#2 - RIGHT");
      led.writeString(2,"#3 - THREE");
      led.writeString(3,"#4 - FOUR");
     break;
     
    case 2:
      // set up led strip
      updateDelay = 0;
      maxSegments = NUMOFLEDS / 2;
      stripMiddle = maxSegments;
      holdTime = 250;
      ledIntensity = .1;
      dropFactor = .991;
      
      strip.begin();

      stripRed = strip.Color(255 * ledIntensity, 0, 0);
      stripGreen = strip.Color(0, 255 * ledIntensity, 0);
      stripBlue = strip.Color(0, 0, 255 * ledIntensity);

      // set colors green to fellow to red
      for (i = 0; i <= maxSegments; i++)
        stripColor[i] = strip.Color(255 / maxSegments * i * ledIntensity , 255 / maxSegments * (maxSegments - i) * ledIntensity, 0);

      // startup animation
      for (j = 0; j < 2; j ++) {
        for (i = 0; i <= maxSegments; i++) {
          strip.setPixelColor(stripMiddle - i, stripColor[i]);
          strip.setPixelColor(stripMiddle + i, stripColor[i]);
          strip.show();
          delay(20);
        }
        
        for (i = 0; i <= maxSegments; i++) {
          strip.setPixelColor(stripMiddle + i, 0);
          strip.setPixelColor(stripMiddle - i, 0);
          strip.show();
          delay(20);
  	    }
      }
	}
 
  // for debugging
  Serial.begin(9600);  
}

void loop() {
  readValues();
  if (holdShow) getHolds();

  switch(outputType) {
    case 0:
      LCDdisplayValues();
      if (holdShow) LCDdisplayHolds();
      break;
      
    case 1: 
      LEDdisplayValues();
      if (holdShow) LEDdisplayHolds();
      break;

    case 2:
      STRIPdisplayValues();
      if (holdShow) STRIPdisplayHolds();
  }

  storePrevValues();
  delay(updateDelay);
}

void readValues() {
  leftAnalogValue = analogRead(leftPin);
  rightAnalogValue = analogRead(rightPin);
  //averageAnalogValue = (leftValue + rightValue) / 2;

  if (leftAnalogValue < prevLeftAnalogValue)
    leftAnalogValue = prevLeftAnalogValue * dropFactor;
    
  if (rightAnalogValue < prevRightAnalogValue)
    rightAnalogValue = prevRightAnalogValue * dropFactor;

  //if (averageAnalogValue < prevAverageAnalogValue)
  //  averageAnalogValue = averageAnalogValue * dropFactor;

  // debug to check read values
  /*
  if (leftValue > maxReadValue) maxReadValue = leftValue;
  if (rightValue > maxReadValue) maxReadValue = rightValue;
  Serial.print(maxReadValue);
  Serial.print(" ");
  Serial.print(leftValue);
  Serial.print(" ");
  Serial.println(rightValue);
  */

  // check if left or right value exceeds max and print the value
  if (leftValue > maxValue) Serial.println (leftValue);
  if (rightValue > maxValue) Serial.println (rightValue);

  // map values
  leftValue = map(leftAnalogValue, minValue, maxValue, 0, maxSegments);
  rightValue = map(rightAnalogValue, minValue, maxValue, 0, maxSegments);
  //averageValue = map(averageAnalogValue, minValue, maxValue, 0, maxSegments);

}

void storePrevValues() {
  prevLeftAnalogValue = leftAnalogValue;
  prevRightAnalogValue = rightAnalogValue;
  //prevAverageValue = averageAnalogValue;

  prevLeftValue = leftValue;
  prevRightValue = rightValue;
  //prevAverageValue = averageValue;
}

void LEDdisplayValues() {
  led.clearDisplay(0);
  led.clearDisplay(1);
  
  for (i=0; i <= leftValue; i++)
    for (j=0; j <= leftValue; j++)
      led.setLed(0, maxSegments - i, j, true);
  led.setIntensity(0, leftValue * ledIntensity);

  for (i=0; i <= rightValue; i++) 
    for (j=0; j <= rightValue; j++)
      led.setLed(1, i, j, true);
  led.setIntensity(1, rightValue * ledIntensity);
}

void LEDdisplayHolds() {
  if (leftHold || holdZeroShow) {
    //for (j=0; j <= leftHold; j++)
    //  led.setLed(0, leftHold, j, true);

    //for (j=0; j <= leftHold; j++)
    //  led.setLed(0, j, leftHold, true);
    led.setLed(0, maxSegments - leftHold, leftHold, true);
  }

  if (rightHold || holdZeroShow) {
    //for (j=0; j < rightHold; j++)
    //  led.setLed(1, rightHold, j, true);

    //for (j=0; j <= rightHold; j++)
    //  led.setLed(1, j, rightHold, true);
    led.setLed(1, rightHold, rightHold, true);
  }
}

void LCDdisplayValues() {
  lcd.clear();
  for (i=0; i < leftValue; i++) 
    lcd.print("=");

  lcd.setCursor(0, 1);
  for (i=0; i < rightValue; i++) 
    lcd.print("=");
}

void LCDdisplayHolds() {
  if (leftHold || holdZeroShow) {
    lcd.setCursor(leftHold, 0);
    lcd.print(">");
  }

  if (rightHold || holdZeroShow) {
    lcd.setCursor(rightHold, 1);
    lcd.print(">");
  }
}

void STRIPdisplayValues() {
  
  strip.clear();
  //for (i=0; i <= averageValue; i++)
  //  strip.setPixelColor(i, stripGreen);
  //strip.show();    

  for (i=0; i <= leftValue; i++)
    strip.setPixelColor(stripMiddle + i, stripColor[i]);

  for (i=0; i <= rightValue; i++)
    strip.setPixelColor(stripMiddle - i, stripColor[i]);
  
/*
  for (i=prevLeftValue; i <= leftValue; i++)
    strip.setPixelColor(stripMiddle + i, stripGreen);

  for (i=prevLeftValue; i > leftValue; i--)
    strip.setPixelColor(stripMiddle + i, 0);

  for (i=prevRightValue; i <= rightValue; i++)
    strip.setPixelColor(stripMiddle - i, stripGreen);

  for (i=prevRightValue; i > rightValue; i--)
    strip.setPixelColor(stripMiddle - i, 0);
*/

  strip.show();
}

void STRIPdisplayHolds() {
  //strip.setPixelColor((leftHold + rightHold) / 2, stripRed);

  strip.setPixelColor(stripMiddle + leftHold, stripColor[maxSegments]);
  strip.setPixelColor(stripMiddle - rightHold, stripColor[maxSegments]);
  strip.setPixelColor(stripMiddle, stripBlue);
  strip.show();    
}

void getHolds() {
  if (leftValue > leftHold) {
    leftHold = leftValue;
    leftHoldTime = 0;
  }
  else {
    leftHoldTime++;
    if (leftHoldTime > holdTime) {
      //if (outputType == 2)
      //  strip.setPixelColor(stripMiddle + leftHold, 0);
      leftHold = 0;
      leftHoldTime = 0;
    }
  }

  if (rightValue > rightHold) {
    rightHold = rightValue;
    rightHoldTime = 0;
  }
  else {
    rightHoldTime++;
    if (rightHoldTime > holdTime) {
      //if (outputType == 2)
      //  strip.setPixelColor(stripMiddle - rightHold, 0);
      rightHold = 0;
      rightHoldTime = 0;
    }
  }
}

Schematics

VU meter schematic for code version 20171105
VU meter schematic
Vu meter1 bb oqolvzgauq
VU meter schematic for code version 20180202
Several changes, check the story for details
Vu meter 20180202 bb kyhryohndn

Comments

Similar projects you might like

A Microwave Interface for the IKEA Duktig Kids Kitchen

Project showcase by Myles Eftos

  • 1,371 views
  • 8 comments
  • 9 respects

Servo Signals and Characterization

by 3 developers

  • 1,262 views
  • 4 comments
  • 14 respects

Music Adaptive RGB LED with Arduino and Processing

Project in progress by ounane mohamed elfarouk

  • 1,061 views
  • 6 comments
  • 11 respects

Cellular IoT with Blynk & Hologram

by Moheeb Zara

  • 5,110 views
  • 9 comments
  • 19 respects

Monitoring Temperature Remotely with Blynk for Dummies

Project in progress by Cmtelesann

  • 1,279 views
  • 2 comments
  • 5 respects

How to Make a Customizable Punchable Keyboard Button

Project tutorial by Amal Mathew

  • 1,549 views
  • 4 comments
  • 4 respects
Add projectSign up / Login