Sound Reactive Neopixel Strip?

Hey! So, I’m doing a project for my design course at university and only have a beginner’s knowledge of Arduino, unfortunately.

In brief, I’m making a sound-responsive ‘cloud’ lamp. I’m using a metre strip of Adafruit RGBW Neopixels, an Adafruit sound sensor and a bunch of other things. They seem to be working just great right now, but I’m a little stuck - I hope someone will be able to advise me in some way! :slight_smile:

Right now I feel a little clueless. Currently, the Neopixels change colour in time to the music (roughly! - See the video HERE), but I want a smoother transition. I’m looking toward the Adafruit strand test and looking for effects to copy over, but it doesn’t seem to work.

Ideally, I’d want to include more colours than displayed at the moment (I only get around 5/6) - and perhaps for the Neopixels to change colours based on what’s next in the spectrum, not just a random colour, as shown in the video. I’m not exactly sure where in the code this is, however.

If I’m able to conquer this, my next step is to have a “lightning mode” - where a user places their hand over an LDR and the cloud stops reacting to sound and instead flashes on and off rapidly, like thunder/lightning. But that’s not the concern right now, I can research that once this is done!

I hope I’m making sense and that someone will be kind enough/have the time to help me, I understand that I’m asking a lot - but I’ve done a lot of research and feel quite lost right now!

I’ve attached the code too, of course.

Thanks everyone! (Especially for your patience - sorry if my terminology is incorrect anywhere or I seem a little slow)

(Bonus question: sometimes the lights start flashing even when it’s silent (I think it’s to do with a SLIGHT change in sound - any suggestions on how to fix this?)

// Sound activated LEDs with the Trinket and NeoPixels
#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
  #include <avr/power.h>
#endif

#define MIC_PIN A0 // Microphone
#define LED_PIN 6 // NeoPixel LED strand
#define N_PIXELS 60 // number of pixels in LED strand
#define N 110 // Number of samples to take each time readSamples is called
#define fadeDelay 35 // delay time for each fade amount
#define noiseLevel 10 // slope level of average mic noise without sound

Adafruit_NeoPixel strip = Adafruit_NeoPixel(N_PIXELS, LED_PIN, NEO_GRB + NEO_KHZ800);

int samples[N]; // storage for a sample collection set
int periodFactor = 0; // keep track of number of ms for period calculation
int t1 = -1; // times of slope > 100 detected.
int T; // period between times scaled to milliseconds
int slope; // the slope of two collected data sample points
byte periodChanged = 0;

// Arduino setup Method
void setup() {
  strip.begin();
  ledsOff();
  delay(500);
  displayColor(Wheel(100));
  strip.show();
  delay(500);
}

// Arduino loop Method
void loop() {
  readSamples();
}

// Read and Process Sample Data from Mic
void readSamples() {
  for(int i=0; i<N; i++) {
    samples[i] = analogRead(0);
    if(i>0) {
      slope = samples[i] - samples[i-1];
    }
    else {
      slope = samples[i] - samples[N-1];
    }
    // Check if Slope greater than noiseLevel - sound that is not at noise level detected
    if(abs(slope) > noiseLevel) {
      if(slope < 0) {
        calculatePeriod(i);
        if(periodChanged == 1) {
          displayColor(getColor(T));
        }
      }
    }
    else {
      ledsOff();
    }
    periodFactor += 1;
    delay(1);
  }
}

void calculatePeriod(int i) {
  if(t1 == -1) {
    // t1 has not been set
    t1 = i;
  }
  else {
    // t1 was set so calc period
    int period = periodFactor*(i - t1);
    periodChanged = T==period ? 0 : 1;
    T = period;
    //Serial.println(T);
    // reset t1 to new i value
    t1 = i;
    periodFactor = 0;
  }
}

uint32_t getColor(int period) {
  if(period == -1)
    return Wheel(0);
  else if(period > 400)
    return Wheel(5);
  else
    return Wheel(map(-1*period, -400, -1, 50, 255));
}

void fadeOut()
{
  for(int i=0; i<5; i++) {
    strip.setBrightness(110 - i*20);
    strip.show(); // Update strip
    delay(fadeDelay);
    periodFactor +=fadeDelay;
  }
}

void fadeIn() {
  strip.setBrightness(100);
  strip.show(); // Update strip
  // fade color in
  for(int i=0; i<5; i++) {
    //strip.setBrightness(20*i + 30);
    //strip.show(); // Update strip
    delay(fadeDelay);
    periodFactor+=fadeDelay;
  }
}

void ledsOff() {
  fadeOut();
  for(int i=0; i<N_PIXELS; i++) {
    strip.setPixelColor(i, 0, 0, 0);
  }
}

void displayColor(uint32_t color) {
  for(int i=0; i<N_PIXELS; i++) {
    strip.setPixelColor(i, color);
  }
  fadeIn();
}

// Input a value 0 to 255 to get a color value.
// The colors are a transition r - g - b - back to r.
uint32_t Wheel(byte WheelPos) {
  if(WheelPos < 85) {
    return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
  } 
  else if(WheelPos < 170) {
    WheelPos -= 85;
    return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3);
  } 
  else {
    WheelPos -= 170;
    return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3);
  }
}

Bump.

eosa: Bump.

Don't bump. Forum rules

displayColor(getColor(T));

Looks like the colour is based on this "T" value which I suspect is an estimate of the tempo of the music. Much of the sketch is designed to calculate that value. So if you don't need that value, you could simplify the sketch a lot.