Spectrum Analyzer using Adafruit NeoPixel Strips & Arduino Mega

Whandall:
If you use a zig-zag connection* between the "bars" you have much less and shorter wiring.

Every second "bar" will have the leds in reverse direction, but that can easily be hidden in software.

  • connect bar1 and bar2 on top, bar2 and bar3 on the bottom, ...

This is exactly what I was thinking after I created the schematic. Thanks! Good point.

After digging into the internet more and doing some more reading, I actually found a similar project. See link below:

The author/designer, Max's cool beans, created a Audio Spectrum analyzer using two MSGEQ7 chips. Using this project, I have finished my wiring schematic. (See attachment). The following items are shown in my schematic:

  1. 14 strips of LEDs. (7 for the left channel and 7 for the right channel with each strip having 20 LEDs)
  2. Arduino Mega
  3. MSGEQ7 - Qty 2
  4. 5VDC 10A AC/DC Power Converter (To Power the LEDs)
  5. 9 Capacitors (Different Values)
  6. 5 Resistors (Different Values)
  7. 3.5mm PCB Audio Jack

If you take a look at the project that Max's cool beans created, he only had 14 regular LEDs while I have 280 programmable LEDs. I have the following questions I'm still trying to answer:

  1. How do I figure out my resistor & capacitor values that are interfacing with the MSGEQ7 chips? Of course they can't be the same as the similar project I mentioned. I am still reading up on how to do this.

  2. The similar project uses multiple Pulse Width Modulation (PWM) pins to interface with the LEDs. 1 pin per LED, but since I have these programmable LED strips, do I only need to use one pin (PWM Pin 0) for my project?

Any help is greatly appreciated. The ball is rolling now :slight_smile:

LED Audio Spectrum Analyzer - 14 Band (07-26-2017).pdf (43 KB)

You don't need any PWM outputs to drive a NeoPixel strip.

What R & C values are you looking to change?

Grumpy_Mike:
You don't need any PWM outputs to drive a NeoPixel strip.

What R & C values are you looking to change?

So should I be using a Digital Pin to talk to the LED strips?

I was looking at the R & C values at Pins 1,5,6, & 8 on the MSGEQ7 chips, but I think the values that are called out int he spreadsheet should be fine. I assumed I had to play with these values....

So should I be using a Digital Pin to talk to the LED strips?

Yes, and a libiary to drive it. It is not the sort of thing you can program yourself.

It is only the R between Pin 1 and 8 you need to consider if you want to make the bands interleave. All other components should be left as they are for a 14 band system. You are best using a 180K fixed resistor in series with a 47K pot wired as a variable resistor, for one chip and leave the other at 200K. Adjust the pot until you get the correct overlap between any two bands. All the others will fall into place.

Grumpy_Mike:
Yes, and a libiary to drive it. It is not the sort of thing you can program yourself.

It is only the R between Pin 1 and 8 you need to consider if you want to make the bands interleave. All other components should be left as they are for a 14 band system. You are best using a 180K fixed resistor in series with a 47K pot wired as a variable resistor, for one chip and leave the other at 200K. Adjust the pot until you get the correct overlap between any two bands. All the others will fall into place.

That's right. I have to have a library. I'll use the NeoPixel library. I got my board today so I'll play with it.

Just to be sure, are you talking about the Resistor that's in parallel with the 33pF capacitor? I see why you are referencing Pin 8 and 1 because they both interfacing with VDD (5 V). I can do what you're mentioning . I'm guessing in order to see the correct overlap between any two bands, I have to see that in the output of my code, correct? Or what would be the way to verify this when I start playing with the pot?

are you talking about the Resistor that's in parallel with the 33pF capacitor?

No. I am talking about the resistor in series with the 33pF capacitor.

I have to see that in the output of my code,

Well that is what the LED strip does for you. You set your frequency generator to one of the the peaks of the none tuneable filter. Then move it half way to the next peak, and adjust the other EQU chip so the same output peaks.

Grumpy_Mike:
No. I am talking about the resistor in series with the 33pF capacitor.
Well that is what the LED strip does for you. You set your frequency generator to one of the the peaks of the none tuneable filter. Then move it half way to the next peak, and adjust the other EQU chip so the same output peaks.

Gotcha. Thanks Mike. You've been extremely helpful.

Another project that may be interesting for you to look into is Lumazoid.

They use software FFT AND drive up to 180 Neopixel on a UNO-comparable custom board and have open-sourced the code (link at the very end of the page).

Check out the video: They also have the nicest "pulse" effect I have seen in any project, open source or closed. Looks very fast to me.

A lot of cues about band binning, assigning weights etc. in there.
I plan to do something similar some day but with microphone input. We'll see...

Good luck with your project.

Just an updated:

Circuit & Code are working correctly. Now it's time to constructing the housing for these LEDs. I recently bought a good size picture frame where I can tape down the LEDs strips into 14 bands using foam double side tape, run all the wiring in the back and then have the arduino board close by.

Had a question if anyone wants to put their two cents in:

These LEDs strips come with weatherproofing on them. Is it better to remove this or leave it on there when I start constructing my layout? I'm trying to decide what's best. Thoughts?

FYI:
If someone is interested in creating something similar, please direct message me. I can provide steps on what I did :slight_smile:

Well I would have got the type without the waterproofing as they are cheaper.

But if you are using them in a picture frame indoors, then I would take them out to get better cooling of the LEDs.

Grumpy_Mike:
Well I would have got the type without the waterproofing as they are cheaper.

But if you are using them in a picture frame indoors, then I would take them out to get better cooling of the LEDs.

I was looking at Adafruit's website and they don't sell it without the weatherproofing. I'll see how difficult it is to take them out. If its too much hassle, I'll probably leave the weatherproofing on. The frame I have is not super enclosed so i'm not supper worried about cooling.

Thanks Mike!

Welp...was doing some testing of my code tonight and noticed that the first LED wasn't lighting up on my strip. Ran into my first problem (bittersweet). Seems like I may have burned the first LED but I have a 1000 uF cap in parallel with the power rails on my 5VDC 10amp pwr supply and put a 470 ohm resistor in series on my data-in wire between the arduino and LED strip.

I have to look at the strip again to make sure I'm not seeing things but what could have cause my first LED to burn out? I followed the instruction from adafruit so I'm confused. I did do a continuity check between 5VAC and ground and of course I hear a small quick beep due to the caps charging but not an actual short.

Any ideas anyone?

The first LED is mainly working, because if it were not then none of the other LEDs would light up. This is because the LEDs regenerate the data signal and if the first one were not working then the signal would never reach the others.

That said the first led is vulnerable to the signal you put into it. That is part of the reasons you put a seriese resistor in the signal line. If the Arduino is powered and feeding into a strip that is not powered then that input looks like a diode connected to ground. Without a resistor that can cause the Arduino's output to burn it out. Even with a resistor it could damage it. What value did you use? Always power up the LED strip first.

Make sure you are addressing the first LED as 0 instead of 1.

Grumpy_Mike:
The first LED is mainly working, because if it were not then none of the other LEDs would light up. This is because the LEDs regenerate the data signal and if the first one were not working then the signal would never reach the others.

That said the first led is vulnerable to the signal you put into it. That is part of the reasons you put a seriese resistor in the signal line. If the Arduino is powered and feeding into a strip that is not powered then that input looks like a diode connected to ground. Without a resistor that can cause the Arduino's output to burn it out. Even with a resistor it could damage it. What value did you use? Always power up the LED strip first.

The morning after I posted my latest post, it came into mind that the LED wasn't dead since the others worked. So your response is dead on.

I used a 470ohm resistor for the data_in signal. I need to check my code (haven't got the chance). Glad I didn't burn it out. Learning as I go here. This is turning out into a great project :slight_smile:

I haven't tested this yet, since I'm still waiting for my 100 LEDs to come in, but is one data-in signal for 280 LEDs fine? 140 LEDs are for the Left Channel 7 band while the other 140 LEDs are for the right channel. Can one data line control all of these or do I need another digital output? I was trying to find the specs online, but no luck.

is one data-in signal for 280 LEDs fine?

Yes it is fine.

Mike/or anyone else,

Do anyone know how to test to see if your Digital Input is flowing through all the LEDs? I cut up my LEDs strips by 20 LEDs and bought these jumpers to tie them together. Every other LED strip (Starting with the 2nd one) is flipped in order for the LEDs strips to reach. Before I cut them up, I ran my code and most of my LEDs were lighting up but for some reason this is not happening anymore. Only the first strip is working and I'm not sure how to test out the other lights. Ideas?

I've done a continuity check on the 5VDC and GND and they're good so this is why I'm saying it might be the digital input. I've also attached a picture for reference.

Ignore my comment avoid. With a little help from a friend, I have it work.

Have another question though. The following is my code just for the left handle channel which is lighting up 7 bands.

#include <MSGEQ7.h>

#include <Adafruit_NeoPixel.h>
//#define A0
//#define A1
#define pinReset 27
#define pinStrobe 26

#define LEDs 140 //total number of LEDs
#define PIN 22
#define OnColor 0x0000FF // BLUE
#define OffColor 0x000000 // OFF
int SpectrumLeft[7];
int SpectrumRight[7];

int SpectrumGraphLeft[7][20];

Adafruit_NeoPixel Strip = Adafruit_NeoPixel(LEDs, PIN, NEO_GRB + NEO_KHZ800);

//#define MSGEQ7_INTERVAL ReadsPerSecond(50)
//#define MSGEQ7_SMOOTH 191 // Range: 0-255

//CMSGEQ7<MSGEQ7_SMOOTH, pinReset, pinStrobe, pinAnalogleft> MSGEQ7;

// Choose a PWM pin!
#define pinLed 22

void setup()
{

Serial.begin(9600);

//pinMode(pinAnalogleft, INPUT);
pinMode(pinStrobe, OUTPUT);
pinMode(pinReset, OUTPUT);
//analogReference(DEFAULT);

digitalWrite(pinStrobe,LOW);
digitalWrite(pinReset,HIGH);
digitalWrite(pinStrobe,HIGH);
digitalWrite(pinStrobe,LOW); //Strobe pin on the shield (go to next Band)
digitalWrite(pinReset,LOW);

// Assign pixels to graph array
for (byte bar = 0 ; bar < 7 ; bar++)
{
for (byte pixel = 0 ; pixel < 20 ; pixel ++)
{
SpectrumGraphLeft[bar][pixel] = (bar * 20) + pixel;
} // end for
} // end for

Strip.begin();
Strip.show(); // Initialize all pixels to 'off'

}

void loop()
{

readSpectrum(); // Get values from spectrum shield
mapSpectrum(); // Color pixels according to spectrum values
//delay(30);
}

void readSpectrum()
{
// Band 0 = Lowest Frequencies.
byte Band;
for(Band=0;Band <7; Band++)
{
SpectrumLeft[Band] = analogRead(A0); //left
//SpectrumRight[Band] = analogRead(1); //right

digitalWrite(pinStrobe,HIGH);
digitalWrite(pinStrobe,LOW);

}

}

void mapSpectrum() // map spectrum to pixel strips
{
for(byte Band=0 ; Band <7 ; Band++)
{ // remap the analogRead values to fit our 30-pixel segments/'bars'
SpectrumLeft[Band] = map(SpectrumLeft[Band], 0, 1023, 0, 19);

for (byte Pixel = 0 ; Pixel < SpectrumLeft[Band] ; Pixel++)
{ // Turn appropriate pixels ON!
Strip.setPixelColor(SpectrumGraphLeft[Band][Pixel], OnColor);
} // end for (Pixel
for (byte Pixel = SpectrumLeft[Band] ; Pixel < 20 ; Pixel++)
{ // Turn the rest OFF!
Strip.setPixelColor(SpectrumGraphLeft[Band][Pixel], OffColor);
} // end for (Pixel

} // end for (Band
Strip.show();

} // end mapSpectrum()

How do I code to have certain individual LEDs a certain colors? Lets say I want to make the first 5 LEDs on my first band a dark color and as I go up by 5, it turns into a more lighter and brighter color. Confused here.

Also, since I flipped every other strip, how do I "flip" my code so my LEDs are moving upwards in the same direction.

Thanks!
Eddie