How to make simple Arduino RGB Led strip VU Meter

 Despite the many options and customization possibilities, this device is extremely simple to build, and contains a minimal number of components.

 VU meter or volume unit meter is a device intended for visual presentation of the audio signal. It typically consists of a series of LEDs arranged in horizontal bar graph configuration, wictch light up proportionally to the level of the audio signal they receive. In some of my previous videos , I present more different types of such devices.
  This time I will present you a way to make an advanced VU meter witch for indication uses a 5050 type LED strip with a built-in WS2812B chips and the parameters of each diode can be controlled individually. 
 

Thanks to this feature of the led strip, with a minimum number of components and relatively complex code, can be made a VU meter with many functions and visual modes. The project was originally developed by “ericBcreator” and then it was repeatedly made and modified by many self-builders.
 The device is relatively simple to make and contains only a few components:
 - Arduino nano microcontroller board
 - 10K resistors 5 pieces
 - 2 Potentiometers 10K
 - 2 Buttons
 - switch
 - Audio Input Jacks
 - and VS2812B LED strip with 72 LEDs

 This project is sponsored by PCBWay. This year, PCBWay organizes the Seventh Project Design Contest where, in addition to Electronic and Mechanical Project,  also has been added a new category: STM32 Project. Submit your project for participation in this Contest from 2nd, Sep, 2024 to 19th, Jan, 2025. For more details and instructions visit the given page. On the occasion of the upcoming Christmas and New Year holidays, visit PCBWay big Christmas sale where you will find discounts of up to 50% as well as many other prizes and benefits.

 As you can see, the control part and led strips are placed in separate boxes, in order to have a better visibility during the presentation of this device. Otherwise, my original idea is that the control part will be built into the box with the led strips, and the potentiometers and buttons will be on the back of the box, and the width of the box would be standard 19 inches to fit as part of the whole audio system. Based on this dimension, the number of LEDs in the strip would be adjusted.
The code is highly customizable and all important settings are commented out. So we can easily adjust it according to our current conditions.
 Speaking of the number of diodes in the strip, several values are predefined in the code. If the project requires us to have a different number of diodes than those predefined in the code, as in my case, where I have 50 diodes per channel, then we simply cut the strip to the required number, and in the code we uncomment the line where more diodes are defined.

  And now let me explain all the settings and options, as well as see how this device works in real conditions:
  - One potentiometer regulates the sensitivity of the input signal
  - the other potentiometer serves to regulate the light intensity of the LEDs
  - switch for peak hold function
  - a button that can be used to select one of 12 different color schemes
  - and the other button will cycle through spinning and/or pulsing modes. 
  We can also place the box with the LED lights vertically above the control box, so we get a vertical audio visualizer VU meter.

 


Next I would like to show you visually effective and very unusual way of displaying signal strength. Now instead of a led strip we will use a led ring with 60 diodes. Also in the code we need to deselect the line where is defined the VU meter on single LED strip.

  And finally a short conclusion.
   This is probably the most advanced LED VU meter for which you can find detailed documentation. Despite the many options and customization possibilities, it is extremely simple to make and contains a minimal number of components. Device is mounted in a suitable case made of PVC board with a thickness of 5 mm and covered with colored self-adhesive wallpaper.
 

CODE
/*
**********************************************************************
* Stereo VU Meter for 1 or 2 LED rings or strips build by ericBcreator
* Designed to be used with an Arduino UNO, Nano or compatible device.
**********************************************************************
* Notice: search for @EB in the Sketch for important variables to set
* for the Sketch to work with your setup.
**********************************************************************
* Last updated 20180202 by ericBcreator
*
* This code is free for personal use, not for commercial purposes.
* Please leave this header intact.
*
* contact: [email protected]
**********************************************************************
*/
#include <Adafruit_NeoPixel.h>
#define nonLinearLogAudio 

//#define led_strip_60                                    //uncomment this if you are using a single 60 LED strip (Center to sides mode)
#define led_2_strip_60                                  //uncomment this if you are using two 60 LED strips (Left-Right bottom to top mode)

//#define led_strip_30                                    //uncomment this if you are using a single 30 LED strip
//#define led_2_strip_30                                  //uncomment this if you are using two 30 LED strips

//#define led_strip_144                                   //uncomment this if you are using a single 144 LED strip
//#define led_2_strip_144                                 //uncomment this if you are using two 144 LED strips

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 (7, 9 for box version)
int showPeaksMomentarySwitch = false;                     // set false for an on/off toggle switch
int reverseShowPeaks = true;                              // reverses the on/off setting in case you made a wiring mistake ;-) @EB
int selectButton1Pin = 8;                                 // push button for changing settings on digital pin 8
int useSelectButton1 = true;                              // set to false if no push button1 for selecting the color scheme is connected  @EB
int selectButton2Pin = 9;                                 // push button for changing settings on digital pin 9
int useSelectButton2 = true;                              // set to false if no push button2 is connected  @EB


#if 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_2_strip_60)
  //settings for 2 60 led strips

  int stripNumOfLeds = 60;
  int stripsOn2Pins = true;
  uint32_t stripColor[61];
  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_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_strip_30)
  //settings for 2 30 led strips

  int stripNumOfLeds = 30;
  int stripsOn2Pins = true;
  uint32_t stripColor[31];
  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_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_144)
  //settings for 2 144 led strips

  int stripNumOfLeds = 144;
  int stripsOn2Pins = true;
  uint32_t stripColor[145];
  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 user variables
//

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

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

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

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

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

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

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

//
// initialize other variables 
//

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

int brightnessValue, prevBrightnessValue;
float ledFactor, ledFactor_div_numOfSegments;

uint32_t stripMiddleColor, stripOverflowColor, stripHoldColor;
uint32_t colorValue;

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

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

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

int selectButton1PinSetting = colorScheme;
int selectButton2PinSetting = 0;

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

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

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

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

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

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

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

//
// setup
//

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

  randomSeed(analogRead(2));

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

    stripPulseMiddle = stripMiddle / 2;
  }

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

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

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

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

  #ifdef DEBUG_TEST_LEDS
    displayTest();
  #endif

  startupAnimation();
}

//
// main loop
//

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


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

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

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

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

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

  checkSpinCircle();

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

// 
// functions
//

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

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

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

    prevShowPeaksPinSetting = showPeaksPinSetting;
  #endif
  

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

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

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

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

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

  //
  // colorscheme 11 spinning wheel
  //

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

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

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

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

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

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

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

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

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

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

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

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

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

  prevLeftValue = leftValue;
  prevRightValue = rightValue;
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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


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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    left_strip.setPixelColor(middleOffset + i, colorValue);

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

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

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

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

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

  delay(displayDelay);

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


//
// for debugging
//

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

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

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

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

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

      left_strip.show();
      if (stripsOn2Pins)
        right_strip.show();  
    }
  }
  
  void serialDisplayRGB(int r, int g, int b) {
    Serial.print(i);
    Serial.print(" ");
    Serial.print(r);
    Serial.print(" ");
    Serial.print(g);
    Serial.print(" ");
    Serial.println(b);
  }
#endif
License
All Rights
Reserved
licensBg
0