Project showcase

Stereo NeoPixel Ring VU Meter © GPL3+

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

  • 4,732 views
  • 49 comments
  • 16 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.

The finished VU meter

VU meter in action

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

Update November 11

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

19" rack version Arduino VU meter

Update December 2

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

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

Although a breadboard for testing is fine, I decided to build an Arduino Nano in a box as a controller for connecting LED rings or strips:

License

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

You can contact me at ericBcreator@gmail.com.

Schematics

VU meter schematic
VU meter schematic
Vu meter1 bb oqolvzgauq

Code

20171105 Updated code with optional dropping and bouncing peaks and some other settingsArduino
/*
**********************************************************************
* 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);
    }
  }
}
20171202 Updated code with multiple color schemes and option to connect 2 strips or ringsArduino
Note: the left strip is connected to pin 5 and the right strip to pin 6
/*
**********************************************************************
* 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 20171202 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_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
#define averageNumOfReadings 5

//
// 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_strip_60
//#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

//
// 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 = 7;                                     // switch to toggle peaks on or off on digital pin 7
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 selectButtonPin = 8;                                  // push button for changing settings on digital pin 8
int useSelectButton = true;                               // set to false if no push button for selecting the color scheme 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 (set droppingPeak true or 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 (set droppingPeak true or 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_strip_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 = 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 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_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 = false;
  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;
#endif

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

// basic settings
int animType = 0;                                         // startup animation selection (1 looks nice for 1 ring)  @EB
int colorScheme = 12;                                     // 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;                                  // for used for looping through the color schemes with the switch button
int colorScheme11SpinDelay = 30;                          // delay for spinning scheme 11
int colorScheme12Factor = 5;                              // wheel spread factor for scheme 12

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
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 
int dynamicBouncingPeaks = true;                          // bounce less with lower peaks. note: bouncingPeaks has to be true 

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

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

int brightnessValue, prevBrightnessValue;
float ledFactor, ledFactor_div_numOfSegments;

uint32_t stripMiddleColor, stripOverflowColor, stripHoldColor;

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

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

int selectButtonPinState = 0, prevSelectButtonPinState = 0;
int selectButtonPinSetting = colorScheme;

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 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;

//
// 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

  if (stripsOn2Pins) {
    numOfSegments = stripNumOfLeds;
    stripMiddle = stripNumOfLeds;
  }
  else {
    numOfSegments = stripNumOfLeds / 2;
    stripMiddle = stripNumOfLeds / 2;
  }
  
  halfNumOfSegments = numOfSegments / 2; 
  maxDisplaySegments = numOfSegments - 1;
  bounceFactor = (float) bouncingPeaksNumOfLeds / (maxDisplaySegments - bouncingPeaksNumOfLeds);

  pinMode(showPeaksPin, INPUT);  
  if (useSelectButton)
    pinMode(selectButtonPin, 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();
  drawValues();

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

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

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

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

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

// 
// functions
//

void setInitialDisplayPeaks() {
  showPeaksPinSetting = digitalRead(showPeaksPin);

  if (showPeaksPinSetting == HIGH)
    displayPeaks = false;
 
  if (reverseShowPeaks && !displayPeaks)
    displayPeaks = true;
  else
    displayPeaks = false;

  prevShowPeaksPinSetting = showPeaksPinSetting;
}

void readSensorValues() {
  //
  // peaks pin
  //
  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();        
      }
    }
  }
  prevShowPeaksPinSetting = showPeaksPinSetting;

  //
  // selectButtonPin
  //
  if (useSelectButton) {      
    selectButtonPinState = digitalRead(selectButtonPin);
    
    if (selectButtonPinState == LOW && prevSelectButtonPinState == HIGH) {
      selectButtonPinSetting++;
   
      if (selectButtonPinSetting > maxColorScheme)
        selectButtonPinSetting = 0;
      colorScheme = selectButtonPinSetting;

      if (colorScheme == 12)
        colorScheme11SpinValue = (colorScheme11SpinValue * colorScheme12Factor);
              
      setStripColors();
      displayNumber(colorScheme, 500);
    }
  
    prevSelectButtonPinState = selectButtonPinState;
  }
    
  //
  // 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 (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) {
    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.0174532925) * 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.0174532925) * rightBouncingPeaksNumOfLeds), (maxDisplaySegments - rightPeak));
          if (rightPeakBounce != prevRightPeakBounce) {
            clearRightBouncePeak();
          }
          prevRightPeakBounce = rightPeakBounce;
        }
      }
    }
  }
}

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

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

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

void drawPeaks() {
  #ifdef DEBUG
    Serial.print("Draw peaks");
  #endif
  
  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((leftPeak + leftPeakBounce), stripHoldColor);
    else
      left_strip.setPixelColor(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(rightPeak + prevRightPeakBounce, stripHoldColor);
      }
      else {
        left_strip.setPixelColor(stripMiddle + rightPeak + prevRightPeakBounce, stripHoldColor);
      }
    }
    else {
      left_strip.setPixelColor(stripMiddle - (rightPeak + prevRightPeakBounce), stripHoldColor);
    }
  }

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

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

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

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

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

void clearRightBouncePeak() {
  if (splitStrip) {
    if (stripsOn2Pins) {
      right_strip.setPixelColor((rightPeak + prevRightPeakBounce), 0);
    }
    else {
      left_strip.setPixelColor((stripMiddle + rightPeak + prevRightPeakBounce), 0);
    }
  }
  else {
    left_strip.setPixelColor(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 drawOverflow() {
  for (i = 0; i <= numOfSegments; i++) {
    left_strip.setPixelColor(stripMiddle - i, stripOverflowColor);
    if (stripsOn2Pins) {
      right_strip.setPixelColor(i, stripOverflowColor);
    }
    else {
      left_strip.setPixelColor(stripMiddle + i, stripOverflowColor);
    }
  }
  left_strip.show();
  if (stripsOn2Pins)
    right_strip.show();
  
  delay(overflowDelay);

  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 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: 
      
    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 = ((i + colorScheme11SpinValue) / colorSchemeFactor) & 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, p1, numOfSegments, 0, 255);
          r = 0;
          g = (wheel * ledFactor);
          b = ((255 - wheel) * ledFactor);
        }
        stripColor[i] = left_strip.Color(r, g, b); 
      }
      break;
    }
  }

  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();
  
  for (i = middleOffset; i <= number; i++) {
    left_strip.setPixelColor(i, stripColor[i]);

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

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

  delay(displayDelay);

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


//
// for debugging
//

#ifdef DEBUG
  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
20171206 Updated code with pulsing and spinning optionArduino
/*
**********************************************************************
* 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 20171206 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
#define averageNumOfReadings 5

//
// 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_strip_60
//#define led_strip_60_p
//#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_p

//
// 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 = 7;                                     // switch to toggle peaks on or off on digital pin 7
int showPeaksMomentarySwitch = false;                     // set false for an on/off toggle switch
int reverseShowPeaks = false;                             // reverses the on/off setting in case you made a wiring mistake ;-) @EB
int selectButtonPin = 8;                                  // push button for changing settings on digital pin 8
int useSelectButton = false;                              // set to false if no push button for selecting the color scheme 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 strip - pulsing 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 = .94;                                   // 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_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_p)
  //settings for a 60 led strip - pulsating

  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 = false;
  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_p)
  //settings for 2 63 led strips - pulsating

  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 = 2;
  float dropFactor = .9;
  
  int peakTimeNoDropDelay = 7;
  int peakTimeFirstDropDelay = 0;
  int peakTimeDropDelay = 0;
  float peakDropFactor = 1;
  int droppingPeakFade = false;
  
  int bouncingPeaksNumOfLeds = 0;
  int bouncingPeaksNumOfLedsMin = 0;
  int bouncingPeakDelay = 0;
  int bouncingPeakCounterInc = 180;
#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 = 1;                                         // startup animation selection (1 looks nice for 1 ring)  @EB
int colorScheme = 0;                                      // 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 = 30;                          // delay for spinning scheme 11
int colorScheme12Factor = 5;                              // 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
int displayPeaks = true;                                  // value will be set by the switch if useSensorValues = true
int displayTopAsPeak = false;                             // always display the top LED in peak color
int droppingPeak = false;                                 // 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 = true;                          // bounce less with lower peaks. note: bouncingPeaks has to be true 

//
// initialize other variables 
//

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

int brightnessValue, prevBrightnessValue;
float ledFactor, ledFactor_div_numOfSegments;

uint32_t stripMiddleColor, stripOverflowColor, stripHoldColor;
uint32_t colorValue;

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

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

int selectButtonPinState = 0, prevSelectButtonPinState = 0;
int selectButtonPinSetting = colorScheme;

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 selectButtonTimer;

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);

  pinMode(showPeaksPin, INPUT);  
  
  if (useSelectButton)
    pinMode(selectButtonPin, 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
  //
  if (useSelectButton) {      
    selectButtonPinState = digitalRead(selectButtonPin);
    
    if (selectButtonPinState == HIGH && prevSelectButtonPinState == LOW)
      selectButtonTimer = millis();
      
    if (selectButtonPinState == HIGH && prevSelectButtonPinState == HIGH) {
      if ((millis() - selectButtonTimer) > 1000) {
        pulsing = !pulsing;
        setStripColors();
        displayNumber(colorScheme, 250);

        while (digitalRead(selectButtonPin) == HIGH) {}
      
        selectButtonPinSetting--;  // @EB_DEBUG
        millis() = 0;
        
      }
    }
    else if (selectButtonPinState == LOW && prevSelectButtonPinState == HIGH) {
      selectButtonPinSetting++;
      if (selectButtonPinSetting > maxColorScheme) {
        selectButtonPinSetting = 0;
      }
      colorScheme = selectButtonPinSetting;

      if (colorScheme == 12)
        colorScheme11SpinValue = (colorScheme11SpinValue * colorScheme12Factor);
              
      setStripColors();
      displayNumber(colorScheme, 250);
    }
  }
  prevSelectButtonPinState = selectButtonPinState;
    
  //
  // 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 (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) {
    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.0174) * 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.0174532925) * 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]);

    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]);

      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]);
        
      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]);

    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]);

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


  if (!displayPeaks && displayTopAsPeak) {
    if (splitStrip) {
      left_strip.setPixelColor(getSpinCircleValue(middleOffset + (leftValue - 1)), stripHoldColor);  //@EB_DEBUG
      
      if (stripsOn2Pins)
        right_strip.setPixelColor(getSpinCircleValue(middleOffset + (rightValue - 1)), stripHoldColor);
      else
        left_strip.setPixelColor(getSpinCircleValue(stripMiddle + middleOffset + (rightValue - 1)), stripHoldColor);
    }
    else {
      left_strip.setPixelColor(getSpinCircleValue(stripMiddle + middleOffset + (leftValue - 1)), stripHoldColor);
      left_strip.setPixelColor(getSpinCircleValue(stripMiddle - (middleOffset + (rightValue - 1))), stripHoldColor);
    }
  }

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

void drawPulsingValues() {
  halfLeftValue = leftValue / 2;
  halfRightValue = rightValue / 2;
  halfPrevLeftValue = prevLeftValue / 2;
  halfPrevRightValue = prevRightValue / 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 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: 
      
    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 = ((i + colorScheme11SpinValue) / colorSchemeFactor) & 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, p1, 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();
  
  for (i = middleOffset; i <= number; i++) {
    left_strip.setPixelColor(i, stripColor[i]);

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

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


  if (pulsing) {
    left_strip.setPixelColor(middleOffset + maxDisplaySegments, stripColor[i]);

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

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

  delay(displayDelay);

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


//
// for debugging
//

#ifdef DEBUG
  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;
    }
  }
}

Comments

Similar projects you might like

Magic Lamp

by Nekhil ravi

  • 772 views
  • 2 comments
  • 8 respects

Arduino MKR GSM 1400 and DTMF

by Arduino_Genuino

  • 3,343 views
  • 0 comments
  • 9 respects

Love You Pillow

Project tutorial by Arduino

  • 1,746 views
  • 0 comments
  • 4 respects

Infrared Replicator

Project tutorial by Gustavo Gonnet

  • 3,541 views
  • 6 comments
  • 26 respects

Rural Hack Kit

by Officine Innesto

  • 3,762 views
  • 0 comments
  • 6 respects

A Model Lighthouse Using an Adafruit NeoPixel Ring

Project tutorial by Jeremy Lindsay

  • 282 views
  • 0 comments
  • 4 respects
Add projectSign up / Login