So, I'll try to keep this short. I have been working on some code to get a 1x8 strip of Neo Pixel (ws2812B) working as a VU meter. Here is my code so far:
What it does is just displays on the top most 4 LEDs and kind of fidgets around a bit. Can some one take a gander and see what I did wrong? It is late and I'm tired, Might sort it out tomorrow, but the more eyes on it the better. And yes it only needs to be red. This is a prototype code so it isn't even close to being finished yet. Just ran in to this snag and been banging away at it for hours now.
First things first. Are you damaging your Arduino? No point fixing your code if the hardware is already damaged or about to fail.
Connecting an audio signal directly to an Arduino analog pin can damage it. Audio signals contain negative voltages and arduino analog pins cannot tolerate that.
For your vu meter project you need a circuit which will take the audio signals, remove the negative parts and create a signal which follows the "envelope" of the sound.
You have only 8 LEDs (numbered 0 to 7) but led can take the value 8, and there is no led #8 in your strip.
No need to set this each time you update a pixel. The .setBrightness() method affects the whole strip, not individual LEDs. If you plan to change the brightness dynamically, use .setBrightness() just before you call .show(). Right now, you never change the brightness, so I suggest you use .setBrightness() one time in setup().
No need to call .show() after each pixel is updated. Do it once per call of loop(), after all the pixels have been updated.
Huh? You definitely need to review your entire code with a fresh set of eyes in the morning!
Thank you for the reply paulRB. I know better than to hook the audio directly to the Arduino board I'm using two resistors as a voltage divider. Then a decoupling capacitor between the audio input from the line level to the arduino pin. Also I have a pulldown resistor hooked to the audio input, which I don't think I need at this point. I'll check in to the bits of code that you have pointed out and see what is the matter. Reply is much appreciated, thank you.
So I did as you suggested and the results are a bit worse now. So now the last 5 LEDs on the strip (3 - 7 (starting at 0)) are lit and fidgeting around and when I stop the music LEDs 3 & 4 stay lit. Here is the modified code:
Ok, but how does that protect the Arduino input from negative voltages and create an envelope waveform? I think you should post a schematic. We can ask @Grumpy_Mike to take a look at it, he is really good with that kind of thing.
Here you go. Just bashed it out in paint real quick. Hope this helps. I also have information on the ranges I'm getting in the serial plotter. I made a piece of code to detect the audio and spill it out into the serial plotter:
int vol = 0;
void setup()
{
Serial.begin(9600); //Begin the Serial Monitor
}
void loop()
{
vol = analogRead(A4);
vol = map(vol, 0, 1023, 0, 255);
Serial.println(vol);
//delay(50);
}
Here are the results:
All tests are done with PC volume set to 75% at Line Level ONLY!
All tests are done with EDM and Vocal ONLY playing in certain instances!
Values will appear to be above and below 127. This is common becasue we are dealing with a voltage divider to get the full range out of the line level :)
Idle information:
127 - 133 is the idle state for "noise"
This is using a voltage divider and a map function: (0, 1023, 0, 255)
Vocal Tests (My Mate Vince youtube Chanel using his voice)
85 - 180 peak to peak (same result with Vince clanging things around whilst talking.)
Using the same setup as Idle.
EDM (No Mana Proximity AV Set on youtube using the Lows as a referance)
Quiet bits are 120 - 136
Quite bits with vocals are 80 - 160 (Female Vocals)
Lows only are 105 - 160
Lows with Vocals 100 - 165 (Male Vocals)
Using the same setup as Idle.
Remove the pull up and pull down biasing resistors and put this circuit after the 100nF capacitor in your diagram.
For the theory see:-
This will give you a zero reading for a zero audio input and an increasing voltage to measure as it gets louder. Which is what a VU meter does.
Yes that is exactly what the circuit you are using will produce. Nothing wrong with your software, it is just that the signal your hardware is getting is wrong.
Oooooooooooohhhhh, Okay I get it now. Let me go to my bench and grab some parts real quick and stick them in to my breadboard and see the results. Thank, I'll report back in a moment.
By the way this piece of code is doing the same thing with the starting 5 LEDs being constantly lit. I'm going to built the correct hardware real quick and see what that will do LOL.
Ah, I see. You put the results in code tags as though they had come exactly like that from serial monitor, which fooled me, because I could see that code would not produce that analysis!
LOL, no worries. @Grumpy_Mike All I can find is an electrolytic .47uF and a 1n4148 diode, would this do just for a test run so I can get the proper parts when I put this in to production?
Well given that a 1N4148 is a small signal diode it fits into the class of any small signal diode.
As the the capacitor, it is fine to run with any value, the size of that capacitor coupled with the size of that 100K pull down resistor determine the responsiveness of you VU meter. That is all, you adjust them to taste.
Have you tried some NeoPixel sample code? You need to be able to control the LEDs with software-only before you start trying to make it react to audio.
Are you powering the LED strip with a 5V power supply? (You shouldn't power them through the Arduino.) There's lots of information on the Adafruit site.
Then you need to work on your analog input. I haven't really "studied" your code but it's not clear what you're doing with maxi. And you never reset it...
...Typically, you want to subtract-out the bias (which should be about 512) and find the peak over a period of time (50ms or more to "capture the peak of the lowest frequencies) or you can find the average of the positive values, or an average of the absolute values.
That's correct. The bias should be 2.5V and the raw reading of about 512 (before mapping).
That's may not be enough range between idle and loud but it will probably be better once you subtract-out the bias.
Your bias circuit is OK for a headphone output but the 1K load is too low for a line-level signal. (Line level audio is about the same voltage but the inputs are typically 10K or more.)
With Mike's envelope detector you don't have to find the peaks in software, but it has a "weakness" - The signal has to overcome the diode's forward voltage (~0.7v for a regular diode or ~0.3V for a Schottky). At lower levels you won't read anything. I use an op-amp Op-amp peak detector (envelope follower) for my lighting effects but that's something you can think about later.
Here is an alternative to the bias circuit. It's NOT a peak detector so you have to find the peaks or average in software. It "kills" the negative half of the signal. Without the bias you can use the optional 1.1V analog reference for more sensitivity.
@DVDdoug yes I have run some example code, whiten code to just have a rainbow, I've worked with Neo Pixel matrix as well for making a basketball game. But for this project, I just ran my rainbow code to ensure that everything is working correctly and the wiring was fine on the breadboard.
I am not running a separate PSU yet because I'm just in the testing phases of this project and need to sort out all the code blocks first for what I need this thing to do. I do things in phases, for instance with the basketball game I made, it has 6 8x32 matrices, so I started by making text show up then made it change colours, them made graphics, then added the other matrices and made it four player then scrolling text, then points system then timer, then made the timer settable, and so on, pretty sure you get the idea
I purposely have the brightness set really low right now and only have 8 LEDs on the circuit so nothing is getting hot or pulling above 250mA As for the diagram you posted, I don't believe that I have any more shotkey diodes in my invintory or opamp chips sadly so I can't try what you suggested at the moment. You do bring up a lot of good points though, thank you.
Got ya. I seem to have an issue though. I have checked several times now if I have the circuit built correctly and I do. In my example audio test code, I'm running the serial plotter again and when I have the 100nF cap installed I don't really get much but a flat line starting at 3. When I bypass it, I get peaks and valleys, however it "grows". For instance, it will go up to around 12, then it will set the new flatline at 12 after audio is removed (unplug the jack or pause the music) If I keep doing this, it grows to the point where it won't grow anymore.
P.S. A couple more thoughts for possible "'software enhancements" in the future...
I assume this is a VU meter effect, not actually a meter to measure "loudness"?
Red may get boring, so you may want the ability to change colors, maybe randomly, and maybe make a "background" color instead of "off".
I made a "giant VU meter effect". It uses regular red LEDs (spaced at about 4-inches to make it about 8-feet tall) so I can't do any "color tricks" , (I may change that.)
To keep it interesting, it randomly reverses (going down instead of up with loudness), it inverts (more LEDs going off when it gets louder) and it "mirrors" with the LEDs "moving" out from the center, or in toward the center when reversed. It also switches between bar-graph and dot modes.
...It has 6 other sequencing/blinking effects, with similar random variations. I have two switches - One to "hold" the current effect with all the variations and one "hold all" switch, if for example, I want to lock-in the regular bar-graph VU meter (which is how it always starts).
Since my effect is not any kind of "meter" and it's not measuring dB or anything meaningful, the sensitivity is continuously-automatically adjusted based on a circular buffer that stores the (approximate) 20-second peak and moving average.
The "top" of the meter is "calibrated" to the recent peak so it's almost always reaching the top.
The "bottom" of the meter is is the average level instead of near-silence. That gives lots of "meter action" with most music.