How do I resolve multiple definition error?

I'm trying to add a library to a sample sketch and when I do I get the error message below.

The library is the Conceptinetics library that's used to control the CQRobot DMX shield. I'm trying to add it to this sketch from CineLights that includes a bunch of addressable LED animations (GitHub - s-marley/Uno_vu_line: Arduino code for a stereo VU meter with lots of patterns).

Any suggestions on how to resolve this?

HardwareSerial0.cpp.o (symbol from plugin): In function Serial': (.text+0x0): multiple definition of __vector_25'
C:\Users[...]\AppData\Local\Temp\arduino\sketches\59320A57133527EC0B514DAAA2112AAF\libraries\Conceptinetics\Conceptinetics.cpp.o (symbol from plugin):(.text+0x0): first defined here
collect2.exe: error: ld returned 1 exit status

exit status 1

Compilation error: exit status 1

Gottcha. Thanks. I've tried a few other DMX libraries with similar results. I've posted an issue to the CineLights GitHub. Fingers crossed he can resolve it.

on a 328P it's for I2C (AVR Interrupt Vectors)

I'm using an Arduino Mega (technically a clone by Elegoo).

I'll try to post the code later tonight. But I've literally only taken the CineLights VU LED sketch and added an include for the Conceptinetics library. Hit compile and it throws the error.

I've tried a few other DMX libraries and got similar errors.

Here's the entire sketch

// --------------------------------
// -- VU Meter - Scott's version --
// --------------------------------


#include <FastLED.h>
#include <EEPROM.h>
#include <JC_Button.h>
#include <Conceptinetics.h>

# define LEFT_OUT_PIN 6             // Left channel data out pin to LEDs [6]
# define RIGHT_OUT_PIN 5            // Right channel data out pin to LEDs [5]
# define LEFT_IN_PIN A5             // Left aux in signal [A5]
# define RIGHT_IN_PIN A4            // Right aux in signal [A4]
# define BTN_PIN 3                  // Push button on this pin [3]
# define DEBOUNCE_MS 20             // Number of ms to debounce the button [20]
# define LONG_PRESS 500             // Number of ms to hold the button to count as long press [500]
# define N_PIXELS 18                // Number of pixels in each string [24]
# define MAX_MILLIAMPS 500          // Maximum current to draw [500]
# define COLOR_ORDER GRB            // Colour order of LED strip [GRB]
# define LED_TYPE WS2812B           // LED string type [WS2812B]
# define DC_OFFSET 0                // DC offset in aux signal [0]
# define NOISE 20                   // Noise/hum/interference in aux signal [10]
# define SAMPLES 60                 // Length of buffer for dynamic level adjustment [60]
# define TOP (N_PIXELS + 2)         // Allow dot to go slightly off scale [(N_PIXELS + 2)]
# define PEAK_FALL 20               // Rate of peak falling dot [20]
# define N_PIXELS_HALF (N_PIXELS / 2)
# define PATTERN_TIME 10            // Seconds to show eaach pattern on auto [10]
# define STEREO true                // If true, L&R channels are independent. If false, both L&R outputs display same data from L audio channel [false]

uint8_t volCountLeft = 0;           // Frame counter for storing past volume data
int volLeft[SAMPLES];               // Collection of prior volume samples
int lvlLeft = 0;                    // Current "dampened" audio level
int minLvlAvgLeft = 0;              // For dynamic adjustment of graph low & high
int maxLvlAvgLeft = 512;

uint8_t volCountRight = 0;          // Frame counter for storing past volume data
int volRight[SAMPLES];              // Collection of prior volume samples
int lvlRight = 0;                   // Current "dampened" audio level
int minLvlAvgRight = 0;             // For dynamic adjustment of graph low & high
int maxLvlAvgRight = 512;

CRGB ledsLeft[N_PIXELS];
CRGB ledsRight[N_PIXELS];

uint8_t myhue = 0;

void vu4(bool is_centered, uint8_t channel);
void vu5(bool is_centered, uint8_t channel);
void vu6(bool is_centered, uint8_t channel);
void vu7(bool show_background);
void vu8();
//void vu9();
void vu10();
void balls();
void fire();
void juggle();
void ripple(boolean show_background);
void sinelon();
void twinkle();
void rainbow(uint8_t rate);

// --------------------
// --- Button Stuff ---
// --------------------
uint8_t state = 0;
int buttonPushCounter = 0;
bool autoChangeVisuals = false;
Button modeBtn(BTN_PIN, DEBOUNCE_MS);


void incrementButtonPushCounter() {
  buttonPushCounter = ++buttonPushCounter %17;
  EEPROM.write(1, buttonPushCounter);
}

void setup() {
  delay(1000); // power-up safety delay

  FastLED.addLeds < LED_TYPE, LEFT_OUT_PIN, COLOR_ORDER > (ledsLeft, N_PIXELS).setCorrection(TypicalLEDStrip);
  FastLED.addLeds < LED_TYPE, RIGHT_OUT_PIN, COLOR_ORDER > (ledsRight, N_PIXELS).setCorrection(TypicalLEDStrip);
  //FastLED.setBrightness(BRIGHTNESS);
  FastLED.setMaxPowerInVoltsAndMilliamps(5, MAX_MILLIAMPS);

  modeBtn.begin();
  Serial.begin(57600);

  buttonPushCounter = (int)EEPROM.read(1); // load previous setting
  buttonPushCounter = 0;
  Serial.print("Starting pattern ");
  Serial.println(buttonPushCounter);
}

void loop() {

  // Read button
  modeBtn.read(); 
  switch (state) {
    case 0:                
      if (modeBtn.wasReleased()) {
        Serial.print("Short press, pattern ");
        Serial.println(buttonPushCounter);
        incrementButtonPushCounter();
        autoChangeVisuals = false;
      }
      else if (modeBtn.pressedFor(LONG_PRESS))
        state = 1;
      break;
    
    case 1:
      if (modeBtn.wasReleased()) {
        state = 0;
        Serial.print("Long press, auto, pattern ");
        Serial.println(buttonPushCounter);
        autoChangeVisuals = true;
      }
      break;
  }
  
  // Switch pattern if on auto
  if(autoChangeVisuals){
    EVERY_N_SECONDS(PATTERN_TIME) { 
      incrementButtonPushCounter();
      Serial.print("Auto, pattern ");
      Serial.println(buttonPushCounter); 
    }
  }

  // Run selected pattern
  switch (buttonPushCounter) {
    case 0:
      vu4(false, 0);
      if (STEREO) vu4(false, 1);
      else copyLeftToRight();
      break;
  
    case 1:
      vu4(true, 0);
      if (STEREO) vu4(true, 1);
      else copyLeftToRight();
      break;
  
    case 2:
      vu5(false, 0);
      if (STEREO) vu5(false, 1);
      else copyLeftToRight();
      break;
  
    case 3:
      vu5(true, 0);
      if (STEREO) vu5(true, 1);
      else copyLeftToRight();
      break;
  
    case 4:
      vu6(false, 0);
      if (STEREO) vu6(false, 1);
      else copyLeftToRight();
      break;
      
    case 5:
      vu7(true);
      copyLeftToRight();
      break;
  
    case 6:
      vu8();
      copyLeftToRight();
      break;
  
    case 7:
      //vu9();
      break;
  
    case 8:
      vu10();
      break;
    
    case 9:
      vu7(false);
      copyLeftToRight();
      break;
  
    case 10:
      twinkle();
      break;
  
    case 11:
      sinelon();
      break;
  
    case 12:
      balls();
      break;
  
    case 13:
      juggle();
      break;
  
    case 14:
      fire();
      break;
  
    case 15:
      ripple(false);
      break;
  
    case 16:
      rainbow(10);
      break;
  }
}

// ------------------
// -- VU functions --
// ------------------

uint16_t auxReading(uint8_t channel) {

  int n = 0;
  uint16_t height = 0;

  if(channel == 0) {
    int n = analogRead(LEFT_IN_PIN); // Raw reading from left line in
    n = abs(n - 512 - DC_OFFSET); // Center on zero
    n = (n <= NOISE) ? 0 : (n - NOISE); // Remove noise/hum
    lvlLeft = ((lvlLeft * 7) + n) >> 3; // "Dampened" reading else looks twitchy (>>3 is divide by 8)
    volLeft[volCountLeft] = n; // Save sample for dynamic leveling
    volCountLeft = ++volCountLeft % SAMPLES;
    // Calculate bar height based on dynamic min/max levels (fixed point):
    height = TOP * (lvlLeft - minLvlAvgLeft) / (long)(maxLvlAvgLeft - minLvlAvgLeft);
  }
  
  else {
    int n = analogRead(RIGHT_IN_PIN); // Raw reading from mic
    n = abs(n - 512 - DC_OFFSET); // Center on zero
    n = (n <= NOISE) ? 0 : (n - NOISE); // Remove noise/hum
    lvlRight = ((lvlRight * 7) + n) >> 3; // "Dampened" reading (else looks twitchy)
    volRight[volCountRight] = n; // Save sample for dynamic leveling
    volCountRight = ++volCountRight % SAMPLES;
    // Calculate bar height based on dynamic min/max levels (fixed point):
    height = TOP * (lvlRight - minLvlAvgRight) / (long)(maxLvlAvgRight - minLvlAvgRight);
  }

  // Calculate bar height based on dynamic min/max levels (fixed point):
  height = constrain(height, 0, TOP);
  return height;
}

void copyLeftToRight() {
  for (uint8_t i = 0; i < N_PIXELS; i++) {
    ledsRight[i] = ledsLeft[i];
  }
}

/*
 * Function for dropping the peak
 */
uint8_t peakLeft, peakRight;
void dropPeak(uint8_t channel) {
  
  static uint8_t dotCountLeft, dotCountRight;
 
  if(channel == 0) {
    if(++dotCountLeft >= PEAK_FALL) { //fall rate 
      if(peakLeft > 0) peakLeft--;
      dotCountLeft = 0;
    }
  } else {
    if(++dotCountRight >= PEAK_FALL) { //fall rate 
      if(peakRight > 0) peakRight--;
      dotCountRight = 0;
    }
  }
}

/*
 * Function for averaging the sample readings
 */
void averageReadings(uint8_t channel) {

  uint16_t minLvl, maxLvl;

  // minLvl and maxLvl indicate the volume range over prior frames, used
  // for vertically scaling the output graph (so it looks interesting
  // regardless of volume level).  If they're too close together though
  // (e.g. at very low volume levels) the graph becomes super coarse
  // and 'jumpy'...so keep some minimum distance between them (this
  // also lets the graph go to zero when no sound is playing):
  if(channel == 0) {
    minLvl = maxLvl = volLeft[0];
    for (int i = 1; i < SAMPLES; i++) {
      if (volLeft[i] < minLvl) minLvl = volLeft[i];
      else if (volLeft[i] > maxLvl) maxLvl = volLeft[i];
    }
    if ((maxLvl - minLvl) < TOP) maxLvl = minLvl + TOP;
    
    minLvlAvgLeft = (minLvlAvgLeft * 63 + minLvl) >> 6; // Dampen min/max levels
    maxLvlAvgLeft = (maxLvlAvgLeft * 63 + maxLvl) >> 6; // (fake rolling average)
  }

  else {
    minLvl = maxLvl = volRight[0];
    for (int i = 1; i < SAMPLES; i++) {
      if (volRight[i] < minLvl) minLvl = volRight[i];
      else if (volRight[i] > maxLvl) maxLvl = volRight[i];
    }
    if ((maxLvl - minLvl) < TOP) maxLvl = minLvl + TOP;
    minLvlAvgRight = (minLvlAvgRight * 63 + minLvl) >> 6; // Dampen min/max levels
    maxLvlAvgRight = (maxLvlAvgRight * 63 + maxLvl) >> 6; // (fake rolling average)
  }
}
/*
 * Standby: Three balls bouncing under gravity
 */

void balls() {

  const float H0 = 0.5;
  const int NUM_BALLS = 3;
  static float h[NUM_BALLS]; // An array of heights
  static float vImpact0 = sqrt(-2 * -9.81 * H0); // Impact velocity of the ball when it hits the ground if "dropped" from the top of the strip
  static float vImpact[NUM_BALLS]; // As time goes on the impact velocity will change, so make an array to store those values
  static float tCycle[NUM_BALLS]; // The time since the last time the ball struck the ground
  static int pos[NUM_BALLS]; // The integer position of the dot on the strip (LED index)
  static long tLast[NUM_BALLS]; // The clock time of the last ground strike
  static float COR[NUM_BALLS]; // Coefficient of Restitution (bounce damping)
  static bool fireFirstRun = true;

  if (fireFirstRun) {
    for (int i = 0; i < NUM_BALLS; i++) { // Initialize variables
      tLast[i] = millis();
      h[i] = H0;
      pos[i] = 0; // Balls start on the ground
      vImpact[i] = vImpact0; // And "pop" up at vImpact0
      tCycle[i] = 0;
      COR[i] = 0.90 - float(i) / pow(NUM_BALLS, 2);
    }
    fireFirstRun = false;
  }

  for (int i = 0; i < NUM_BALLS; i++) {
    tCycle[i] = millis() - tLast[i]; // Calculate the time since the last time the ball was on the ground

    // A little kinematics equation calculates positon as a function of time, acceleration (gravity) and intial velocity
    h[i] = 0.5 * -9.81 * pow(tCycle[i] / 1000, 2.0) + vImpact[i] * tCycle[i] / 1000;

    if (h[i] < 0) {
      h[i] = 0; // If the ball crossed the threshold of the "ground," put it back on the ground
      vImpact[i] = COR[i] * vImpact[i]; // and recalculate its new upward velocity as it's old velocity * COR
      tLast[i] = millis();

      if (vImpact[i] < 0.01) vImpact[i] = vImpact0; // If the ball is barely moving, "pop" it back up at vImpact0
    }
    pos[i] = round(h[i] * (N_PIXELS - 1) / H0); // Map "h" to a "pos" integer index position on the LED strip
  }

  //Choose color of LEDs, then the "pos" LED on
  for (int i = 0; i < NUM_BALLS; i++) ledsLeft[pos[i]] = CHSV(uint8_t(i * 40), 255, 255);

  // Copy left LED array into right LED array
  for (uint8_t i = 0; i < N_PIXELS; i++) {
    ledsRight[i] = ledsLeft[i];
  }
  
  FastLED.show();
  
  //Then off for the next loop around
  for (int i = 0; i < NUM_BALLS; i++) {
    ledsLeft[pos[i]] = CRGB::Black;
    ledsRight[pos[i]] = CRGB::Black;
  }
}
/*
 * Standby: Looks like fire! Both channels are seperate and random
 */

void fire() {
  const uint8_t COOLING = 55;
  const uint8_t SPARKING = 50;
  
  // Array of temperature readings at each simulation cell
  static byte heatLeft[N_PIXELS];
  static byte heatRight[N_PIXELS];

  // Step 1.  Cool down every cell a little
  for (int i = 0; i < N_PIXELS; i++) {
    heatLeft[i] = qsub8(heatLeft[i], random8(0, ((COOLING * 10) / N_PIXELS) + 2));
  }

  // Step 2.  Heat from each cell drifts 'up' and diffuses a little
  for (int k = N_PIXELS - 1; k >= 2; k--) {
    heatLeft[k] = (heatLeft[k - 1] + heatLeft[k - 2] + heatLeft[k - 2]) / 3;
  }

  // Step 3.  Randomly ignite new 'sparks' of heat near the bottom
  if (random8() < SPARKING) {
    int y = random8(7);
    heatLeft[y] = qadd8(heatLeft[y], random8(160, 255));
  }

  // Step 4.  Map from heat cells to LED colors
  for (int j = 0; j < N_PIXELS; j++) {
    // Scale the heat value from 0-255 down to 0-240
    // for best results with color palettes.
    byte colorindex = scale8(heatLeft[j], 240);
    CRGB color = ColorFromPalette(CRGBPalette16(CRGB::Black, CRGB::Red, CRGB::Yellow, CRGB::White), colorindex);
    int pixelnumber = j;
    ledsLeft[pixelnumber] = color;
  }

  // Now do it all again for the right channel
  // Step 1.  Cool down every cell a little
  for (int i = 0; i < N_PIXELS; i++) {
    heatRight[i] = qsub8(heatRight[i], random8(0, ((COOLING * 10) / N_PIXELS) + 2));
  }

  // Step 2.  Heat from each cell drifts 'up' and diffuses a little
  for (int k = N_PIXELS - 1; k >= 2; k--) {
    heatRight[k] = (heatRight[k - 1] + heatRight[k - 2] + heatRight[k - 2]) / 3;
  }

  // Step 3.  Randomly ignite new 'sparks' of heat near the bottom
  if (random8() < SPARKING) {
    int y = random8(7);
    heatRight[y] = qadd8(heatRight[y], random8(160, 255));
  }

  // Step 4.  Map from heat cells to LED colors
  for (int j = 0; j < N_PIXELS; j++) {
    // Scale the heat value from 0-255 down to 0-240
    // for best results with color palettes.
    byte colorindex = scale8(heatRight[j], 240);
    CRGB color = ColorFromPalette(CRGBPalette16(CRGB::Black, CRGB::Red, CRGB::Yellow, CRGB::White), colorindex);
    int pixelnumber = j;
    ledsRight[pixelnumber] = color;
  }
  
  FastLED.show();
}
/*
 * Standby: Several colored dots, weaving in and out of sync with each other
 */

const uint8_t FADE_RATE = 2; // How long should the trails be. Very low value = longer trails.

void juggle() { 
  const uint8_t NUM_DOTS = 4; // Number of dots in use.
  const uint8_t HUE_INC = 16; // Incremental change in hue between each dot.
  static uint8_t thishue = 0; // Starting hue.
  static uint8_t curhue = 0;
  const uint8_t basebeat = 5;
  
  curhue = thishue; // Reset the hue values?
  fadeToBlackBy(ledsLeft, N_PIXELS, FADE_RATE);
  for (int i = 0; i < NUM_DOTS; i++) {
    ledsLeft[beatsin16(basebeat + i + NUM_DOTS, 0, N_PIXELS - 1)] |= CHSV(curhue, 255, 255);
    curhue += HUE_INC;
  }

  // Copy left LED array into right LED array
  copyLeftToRight();
  
  FastLED.show();
}
/*
 * Standby: Rainbow cycling around in clockwise direction
 */

void rainbow(uint8_t rate) {
  static uint8_t leftHue = 0;
  static uint8_t rightHue = 0;
  
  fill_rainbow(ledsLeft, N_PIXELS, leftHue, 7);
  fill_rainbow(ledsRight, N_PIXELS, rightHue, 7);
  
  EVERY_N_MILLISECONDS(20) {
    leftHue = (leftHue + rate) % 255;
    rightHue = (rightHue - rate) % 255;
  }
   
  FastLED.show();
}
/*
 * Standby: Ripple with or without background
 */

void ripple(boolean show_background) {

  const float RIPPLE_FADE_RATE = 0.80;
  const uint8_t MAX_STEPS = 16;
  static uint8_t rippleColor = 0;
  static uint8_t rippleCenter = 0;
  static int rippleStep = -1;

  // -- fill background --
  EVERY_N_MILLISECONDS(10) {
    myhue++;
  }
  if (show_background) {
    fill_solid(ledsLeft, N_PIXELS, CHSV(myhue, 255, 128));
  } else {
    fill_solid(ledsLeft, N_PIXELS, CRGB::Black);
  }

  EVERY_N_MILLISECONDS(50) {
    // -- do ripple --
    if (rippleStep == -1) {
      rippleCenter = random(N_PIXELS);
      rippleColor = myhue + 128;
      rippleStep = 0;
    }

    if (rippleStep == 0) {
      ledsLeft[rippleCenter] = CHSV(rippleColor, 255, 255);
      rippleStep++;
    } else {
      if (rippleStep < MAX_STEPS) {
        ledsLeft[wrap(rippleCenter + rippleStep)] = CHSV(rippleColor, 255, pow(RIPPLE_FADE_RATE, rippleStep) * 255); 
        ledsLeft[wrap(rippleCenter - rippleStep)] = CHSV(rippleColor, 255, pow(RIPPLE_FADE_RATE, rippleStep) * 255);
        if (rippleStep > 3) {
          ledsLeft[wrap(rippleCenter + rippleStep - 3)] = CHSV(rippleColor, 255, pow(RIPPLE_FADE_RATE, rippleStep - 2) * 255);
          ledsLeft[wrap(rippleCenter - rippleStep + 3)] = CHSV(rippleColor, 255, pow(RIPPLE_FADE_RATE, rippleStep - 2) * 255);
        }
        rippleStep++;
      } else {
        rippleStep = -1;
      }
    }
  }

  // Copy left LED array into right LED array
  copyLeftToRight();
  
  FastLED.show();
  delay(50);
}

int wrap(int rippleStep) {
  if (rippleStep < 0) return N_PIXELS + rippleStep;
  if (rippleStep > N_PIXELS - 1) return rippleStep - N_PIXELS;
  return rippleStep;
}
/*
 * Standby: A colored dot sweeping back and forth, with fading trails
 */

void sinelon() {

  const uint8_t THIS_BEAT = 23;
  const uint8_t THAT_BEAT = 28;
  const uint8_t THIS_FADE = 2; // How quickly does it fade? Lower = slower fade rate.

  fadeToBlackBy(ledsLeft, N_PIXELS, THIS_FADE);
  int pos1 = beatsin16(THIS_BEAT, 0, N_PIXELS - 1);
  int pos2 = beatsin16(THAT_BEAT, 0, N_PIXELS - 1);
  ledsLeft[(pos1 + pos2) / 2] += CHSV(myhue, 255, 255);
  EVERY_N_MILLISECONDS(10) {
    myhue++;
  }
  
  // Copy left LED array into right LED array
  copyLeftToRight();
  
  FastLED.show();
}
/*
 * Standby: Twinkling lights of random colours
 */

void twinkle() {
  
  if (random(25) == 1) {
    uint16_t i = random(N_PIXELS);
    ledsLeft[i] = CRGB(random(256), random(256), random(256));
  }
  fadeToBlackBy(ledsLeft, N_PIXELS, FADE_RATE);

  if (random(25) == 1) {
    uint16_t i = random(N_PIXELS);
    ledsRight[i] = CRGB(random(256), random(256), random(256));
  }
  fadeToBlackBy(ledsRight, N_PIXELS, FADE_RATE);
  
  FastLED.show();
  delay(10);
}

void vu4(bool is_centered, uint8_t channel) {
  
  CRGB* leds;
  uint8_t i = 0;
  uint8_t *peak;      // Pointer variable declaration
  uint16_t height = auxReading(channel);

  if(channel == 0) {
    leds = ledsLeft;    // Store address of peakLeft in peak, then use *peak to
    peak = &peakLeft;   // access the value of that address
  }
  else {
    leds = ledsRight;
    peak = &peakRight;
  }
  
  // Draw vu meter part
  fill_solid(leds, N_PIXELS, CRGB::Black);
  if(is_centered) {
    
    // Fill with colour gradient
    fill_gradient(leds, N_PIXELS_HALF  , CHSV(96, 255, 255), N_PIXELS - 1, CHSV(224, 255, 255),SHORTEST_HUES);
    fill_gradient(leds, N_PIXELS_HALF-1, CHSV(96, 255, 255), 0, CHSV(224, 255, 255),LONGEST_HUES);
    
    // Black out ends
    for (i = 0; i < N_PIXELS; i++) {
      uint8_t numBlack = (N_PIXELS - constrain(height, 0, N_PIXELS-1)) / 2;
      if(i <= numBlack -1 || i >= N_PIXELS - numBlack) leds[i] = CRGB::Black;
    }
    
    // Draw peak dot  
    if(height/2 > *peak)
      *peak = height/2; // Keep 'peak' dot at top

    if(*peak > 0 && *peak <= N_PIXELS_HALF-1) {
      leds[N_PIXELS_HALF + *peak]   = CHSV(rainbowHue2(*peak, N_PIXELS_HALF),255,255);
      leds[N_PIXELS_HALF - 1 - *peak] = CHSV(rainbowHue2(*peak, N_PIXELS_HALF),255,255);
    }
  } 
  
  else {
    // Fill with color gradient
    fill_gradient(leds, 0, CHSV(96, 255, 255), N_PIXELS - 1, CHSV(224, 255, 255),SHORTEST_HUES);
    
    //Black out end
    for (i = 0; i < N_PIXELS; i++) {
      if(i >= height) leds[i] = CRGB::Black;
    }
    
    // Draw peak dot  
    if(height > *peak)
      *peak = height; // Keep 'peak' dot at top
      
    if(*peak > 0 && *peak <= N_PIXELS-1)
      leds[*peak] = CHSV(rainbowHue2(*peak, N_PIXELS), 255, 255); // Set peak colour correctly
  }

  dropPeak(channel);
  averageReadings(channel);
  FastLED.show();
}

uint8_t rainbowHue2(uint8_t pixel, uint8_t num_pixels) {
  uint8_t hue = 96 - pixel * (145 / num_pixels);
  return hue;
}

/*
 * VU: Old-skool green and red from bottom or middle
 */

void vu5(bool is_centered, uint8_t channel) {

  CRGB* leds;
  uint8_t i = 0;
  uint8_t *peak;      // Pointer variable declaration
  uint16_t height = auxReading(channel);

  if(channel == 0) {
    leds = ledsLeft;    // Store address of peakLeft in peak, then use *peak to
    peak = &peakLeft;   // access the value of that address
  }
  else {
    leds = ledsRight;
    peak = &peakRight;
  }

  if (height > *peak)
    *peak = height; // Keep 'peak' dot at top

  if(is_centered) {
    // Color pixels based on old school green / red
    for (uint8_t i = 0; i < N_PIXELS_HALF; i++) {
      if (i >= height) {
        // Pixels greater than peak, no light
        leds[N_PIXELS_HALF - i - 1] = CRGB::Black;
        leds[N_PIXELS_HALF + i] = CRGB::Black;
      } else {
        if (i > N_PIXELS_HALF - (N_PIXELS_HALF / 3)){
          leds[N_PIXELS_HALF - i - 1] = CRGB::Red;
          leds[N_PIXELS_HALF + i] = CRGB::Red;
        }
        else {
          leds[N_PIXELS_HALF - i - 1] = CRGB::Green;
          leds[N_PIXELS_HALF + i] = CRGB::Green;
        }
      }
    }
  
    // Draw peak dot
    if (*peak > 0 && *peak <= N_PIXELS_HALF - 1) {
      if (*peak > N_PIXELS_HALF - (N_PIXELS_HALF / 3)){
        leds[N_PIXELS_HALF - *peak - 1] = CRGB::Red;
        leds[N_PIXELS_HALF + *peak] = CRGB::Red;
      } else {
        leds[N_PIXELS_HALF - *peak - 1] = CRGB::Green;
        leds[N_PIXELS_HALF + *peak] = CRGB::Green;
      }
    }
    
  } else {
    // Color pixels based on old school green/red vu
    for (uint8_t i = 0; i < N_PIXELS; i++) {
      if (i >= height) leds[i] = CRGB::Black;
      else if (i > N_PIXELS - (N_PIXELS / 3)) leds[i] = CRGB::Red;
      else leds[i] = CRGB::Green;
    }
  
    // Draw peak dot
    if (*peak > 0 && *peak <= N_PIXELS - 1)
      if (*peak > N_PIXELS - (N_PIXELS / 3)) leds[*peak] = CRGB::Red;
      else leds[*peak] = CRGB::Green;
  }
  
  dropPeak(channel);

  averageReadings(channel);

  FastLED.show();
}
/*
 * VU: Rainbow from bottom or middle with hue cycling
 */

void vu6(bool is_centered, uint8_t channel) {

  const uint8_t SPEED = 10;
  static uint8_t hueOffset = 30;

  CRGB* leds;
  uint8_t i = 0;
  uint8_t *peak;      // Pointer variable declaration
  uint16_t height = auxReading(channel);

  if(channel == 0) {
    leds = ledsLeft;    // Store address of peakLeft in peak, then use *peak to
    peak = &peakLeft;   // access the value of that address
  }
  else {
      leds = ledsRight;
      peak = &peakRight;
  }

  if(height > *peak)
    *peak = height; // Keep 'peak' dot at top
  
  EVERY_N_MILLISECONDS(SPEED) {hueOffset++;}

  if(is_centered) {
    // Color pixels based on rainbow gradient
    for (uint8_t i = 0; i < N_PIXELS_HALF; i++) {
      if (i >= height) {
        leds[N_PIXELS_HALF - i - 1] = CRGB::Black;
        leds[N_PIXELS_HALF + i] = CRGB::Black;
      } else {
        leds[N_PIXELS_HALF - i - 1] = CHSV(hueOffset + (10 * i),255,255);
        leds[N_PIXELS_HALF + i] = CHSV(hueOffset + (10 * i),255,255);
      }
    }

    // Draw peak dot  
    if (*peak > 0 && *peak <= N_PIXELS_HALF - 1) {
      leds[N_PIXELS_HALF - *peak - 1] = CHSV(hueOffset,255,255);
      leds[N_PIXELS_HALF + *peak] = CHSV(hueOffset,255,255);
    }
  }
  
  else {
    // Color pixels based on rainbow gradient
    for (uint8_t i = 0; i < N_PIXELS; i++) {
      if (i >= height) {
        leds[i] = CRGB::Black;
      } else {
        leds[i] = CHSV(hueOffset + (10 * i),255,255);
      }
    }
    // Draw peak dot  
    if (*peak > 0 && *peak <= N_PIXELS - 1)
      leds[*peak] = CHSV(hueOffset, 255, 255);
  
  }
  dropPeak(channel);

  averageReadings(channel);

  FastLED.show();
}
/*
 * VU: Ripple (mono) with or without background
 */
 
int rippleStep = -1;
const float RIPPLE_FADE_RATE = 0.80;
int peakspersec = 0;
int peakcount = 0;
unsigned int sampleavg;
uint8_t rippleHue = 0;
uint8_t bgcol = 0;

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

  soundmems();

  EVERY_N_MILLISECONDS(20) {
    ripple3(show_background);
  }
  
  FastLED.show();
}

void soundmems() { // Rolling average counter - means we don't have to go through an array each time.
  
  static int samplecount;
  static unsigned long samplesum;
  static unsigned long oldtime;
  unsigned long newtime = millis();
  unsigned int sample = abs(analogRead(LEFT_IN_PIN) -512);
  
  samplesum = samplesum + sample - volLeft[samplecount]; // Add the new sample and remove the oldest sample in the array 
  sampleavg = samplesum / SAMPLES; // Get an average
  volLeft[samplecount] = sample; // Update oldest sample in the array with new sample
  samplecount = (samplecount + 1) % SAMPLES; // Update the counter for the array

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

void ripple3(bool show_background) {

  const uint8_t MAX_STEPS = 16;
  static int center = 0;
  
  if(show_background) {
    for (int i = 0; i < N_PIXELS; i++) {
      ledsLeft[i] = CHSV(bgcol, 255, sampleavg * 2); // Set the background colour.
    }
  } else {
    fadeToBlackBy(ledsLeft, N_PIXELS, 64);
  }

  switch (rippleStep) {

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

  case 0:
    ledsLeft[center] = CHSV(rippleHue, 255, 255); // Display the first pixel of the ripple.
    rippleStep++;
    break;

  case MAX_STEPS: // At the end of the ripples.
    break;

  default: // Middle of the ripples.
    ledsLeft[(center + rippleStep + N_PIXELS) % N_PIXELS] += CHSV(rippleHue, 255, 255 / rippleStep * 2); // Simple wrap from Marc Miller.
    ledsLeft[(center - rippleStep + N_PIXELS) % N_PIXELS] += CHSV(rippleHue, 255, 255 / rippleStep * 2);
    rippleStep++; // Next step.
    break;
  }
}
/*
 * VU: Hue cycling, three bars (shatter, mono)
 */

void vu8() {
  const uint8_t DRAW_MAX = 30;
  const uint8_t SEGMENTS = 3;
  
  static int origin = 0;
  static uint8_t scroll_color = 0;
  static int last_intensity = 0;
  static int intensity_max = 0;
  static int origin_at_flip = 0;
  static CHSV draw[DRAW_MAX];
  static bool growing = false;
  static bool fall_from_left = true;
  
  int intensity = auxReading(0);
  
  //// Update Origin ////
  // detect peak change and save origin at curve vertex
  if (growing && intensity < last_intensity) {
    growing = false;
    intensity_max = last_intensity;
    fall_from_left = !fall_from_left;
    origin_at_flip = origin;
  } else if (intensity > last_intensity) {
    growing = true;
    origin_at_flip = origin;
  }
  last_intensity = intensity;
  
  // adjust origin if falling
  if (!growing) {
    if (fall_from_left) {
      origin = origin_at_flip + ((intensity_max - intensity) / 2);
    } else {
      origin = origin_at_flip - ((intensity_max - intensity) / 2);
    }
    // correct for origin out of bounds
    if (origin < 0) {
      origin = DRAW_MAX - abs(origin);
    } else if (origin > DRAW_MAX - 1) {
      origin = origin - DRAW_MAX - 1;
    }
  }
  
  //// Assign draw values ///
  // draw amplitue as 1/2 intensity both directions from origin
  int min_lit = origin - (intensity / 2);
  int max_lit = origin + (intensity / 2);
  if (min_lit < 0) {
    min_lit = min_lit + DRAW_MAX;
  }
  if (max_lit >= DRAW_MAX) {
    max_lit = max_lit - DRAW_MAX;
  }
  for (int i=0; i < DRAW_MAX; i++) {
    // if i is within origin +/- 1/2 intensity
    if (
      (min_lit < max_lit && min_lit < i && i < max_lit) // range is within bounds and i is within range
      || (min_lit > max_lit && (i > min_lit || i < max_lit)) // range wraps out of bounds and i is within that wrap
    ) {
      draw[i] = CHSV(scroll_color,255,255);
    } else {
      draw[i] = CHSV(scroll_color,0,0);
    }
  }

  //// Write Segmented ////
  int seg_len = N_PIXELS / SEGMENTS;

  for (int s = 0; s < SEGMENTS; s++) {
    for (int i = 0; i < seg_len; i++) {
       ledsLeft[i + (s*seg_len)] = draw[map(i, 0, seg_len, 0, DRAW_MAX)];
    }
  }

  FastLED.show();
  
  averageReadings(0);

  EVERY_N_MILLISECONDS(20) {
    scroll_color = ++scroll_color % 255;
  }
}

/*
 * VU: Palette blending demo
 */

CRGBPalette16 currentPalette;
CRGBPalette16 targetPalette;

void vu10() {

  EVERY_N_SECONDS(5) { // Change the target palette to a random one every 5 seconds.
    static uint8_t baseC = random8(); // You can use this as a baseline colour if you want similar hues in the next line.

    for (int i = 0; i < 16; i++) {
      targetPalette[i] = CHSV(random8(), 255, 255);
    }
  }

  EVERY_N_MILLISECONDS(100) {
    uint8_t maxChanges = 24;
    nblendPaletteTowardPalette(currentPalette, targetPalette, maxChanges); // AWESOME palette blending capability.
  }

  EVERY_N_MILLISECONDS(20) { // FastLED based non-blocking delay to update/display the sequence.
    soundtun();

    FastLED.show();
  }
}

void soundtun() {

  int sampleLeft = abs(analogRead(LEFT_IN_PIN) - 512 - DC_OFFSET);
  CRGB newcolourLeft = ColorFromPalette(currentPalette, constrain(sampleLeft, 0, 255), constrain(sampleLeft, 0, 255), LINEARBLEND);
  nblend(ledsLeft[0], newcolourLeft, 128);
  for (int i = N_PIXELS - 1; i > 0; i--) {
    ledsLeft[i] = ledsLeft[i - 1];
  }

  if (STEREO) {
    int sampleRight = abs(analogRead(RIGHT_IN_PIN) - 512 - DC_OFFSET);
    CRGB newcolourRight = ColorFromPalette(currentPalette, constrain(sampleRight, 0, 255), constrain(sampleRight, 0, 255), LINEARBLEND);
    nblend(ledsRight[0], newcolourRight, 128);
    for (int i = N_PIXELS - 1; i > 0; i--) {
      ledsRight[i] = ledsRight[i + 1];
    }
  }
  else {
    copyLeftToRight();
  }

}

Well, through trial/error and dumb luck I found something that seems to work.

The issue with the Conceptinetics library seems to be with the Serial object. If I disable all references to Serial in the sketches, I can use the Conceptinetics library with the Cine Light LED sketch.

It's obviously not ideal. I'd like to be able to use the Serial port to test and debug. But it's workable.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.