I'd like to take an audio signal and modulate an LED. I'm using a v1053 shield, so those libraries are referenced in the code below..
Essentially, the challenge is to get a reading from the MP3player within this code and apply it to a scalable PWM number for an LED. It would be great if I could tune this range a bit, but I'm unclear on how to do this.
The audio in this project is human speech, so advanced spectral analysis and/or envelope-following are probably not necessary.
I would greatly appreciate some help...Thank you in advance.
result = sd.begin(SD_SEL, SPI_FULL_SPEED);
result = MP3player.begin();
MP3player.setVolume(20, 20);
randomSeed (millis()); // set a more random seed for the random function
Serial.println("Hello");
}
// loop
void loop() {
MP3player.playTrack(random(5)); // range of tracks to randomly play.
while (MP3player.isPlaying());
{
MP3player.setVUmeter(1);
Serial.println(MP3player.getVUmeter());
}
MP3player.stopTrack();// stop track
}
I edited this post to be a little more coherent, so I'm topping it since it's been a few days. I'm sorry to bug the forum, but I could really use some help.
Hi - sorry, I did read over the guidelines, but I think I messed up on a few things because they're fuzzy for me too.
I would like to use the amplitude of the audio signal (an mp3 of a human voice) to modulate the brightness of an LED. I don't think an envelope will be necessary, but it couldn't hurt.
The Serial.println(MP3player.getVUmeter()); is currently not returning any information.
The Serial.println(MP3player.getVUmeter()); is currently not returning any information.
In that case you are stuffed for the software route.
I would like to use the amplitude of the audio signal (an mp3 of a human voice) to modulate the brightness of an LED.
Because the amplitude of an audio signal varies over a time scale of 10mS to 0.1mS then you are not going to see very much in the way of modulation. The LED will be on at some indeterminate brightness thought the duration of the sound.
In the absence of any software indication of the sound then the next best bet is to connect the audio to the analogue input and read the signal and use that to modulate the LED. Make sure that the audio is biased at 2.5V by using two 10K resistors on the analogue input pulling up and down. Couple in from the audio output of your module using a capacitor.
I don't think an envelope will be necessary,
The video below did this with the sound to make the mouth move. An envelope detector was used to replace the mouth pattern according to the amplitude of the sound. The louder the sound the bigger was the pattern.
The A/D gives values between 0 and 1023, while analogWrite needs 0-255.
You could divide by 4.
Or, maybe better for music, use some sort of log scaling .
Leo..
Make measurements as to what the maximum input value you get. Then use the map function to put that into the range 0 to 255.
Note what you are calling a class is in fact a function, a class is called with a period between the name and the instances.
Hmm.. I made the changes and altered the circuitry as specified... it seems responsive, but it is flickering constantly, instead of smoothly transitioning between values. Is there a way to smooth it out on the code side?
Is it possible that the VS1053 shield uses the analog inputs for other purposes?
No.
but I seem to just be getting a random stream of numbers, uncorrelated to the audio.
That would be expected. What were you expecting?
Have you tried removing the print statement because that slows everything down and you don't see much correlation between the samples because it is a long time between them.
Do you get zero when there is no music?
If you want something to follwo the envelope of the music then play about with the values of the R and C. The R controls the decay from a peak so if you want this to be slower then make this bigger. The C controls the time constant so make this bigger to slow down the changes.
Ah, had no idea about the "Print" slowing things down.
Let me just clarify a few things re:signal flow:
Output from headphone jack -> capacitor, 1uf -> voltage divider, two 10ks (one to +3v, one to grd).
From there, the signal is sent to an envelope follower, built to your specifications above..
This just leaves the light turned on.
Removing the 10k to +3v allows some degree of flickering - though even with the audio signal disconnected, this flickering continues. It's hard to tell if it is correlated to the audio, quite frankly.
I'm not exactly sure what is going on here.
The current code looks like this:
// libraries
#include <SPI.h>
#include <SdFat.h>
#include <SdFatUtil.h>
#include <SFEMP3Shield.h>
// initialize MP3 card
SdFat sd;
SFEMP3Shield MP3player;
int sensorPin = A1;
const int ledPin = 10;
byte result;
// setup
void setup() {
Serial.begin(115200);
result = sd.begin(SD_SEL, SPI_FULL_SPEED);
result = MP3player.begin();
MP3player.setVolume(20, 20);
randomSeed (analogRead(0)); // set a more random seed for the random function
}
// loop
void loop() {
MP3player.playTrack(random(8)); // range of tracks to randomly play.
while (MP3player.isPlaying()){
int val = analogRead(sensorPin);
val = map(val, 0, 100, 0, 255);
analogWrite(ledPin, val);
Serial.println(val);
}
MP3player.stopTrack();// stop track
}
Output from headphone jack -> capacitor, 1uf -> voltage divider, two 10ks (one to +3v, one to grd).
No simply Output from headphone jack -> capacitor, 1uf -> to the circuit I showed you.
Also you need the ground from the headphone jack to the ground of the Arduino if it is not connected elsewhere.
Put in the print statement and remove the map, look at the numbers then remove it and reinstate the map function, put the highest number in the third parameter of the map function call.
By the way
voltage divider, two 10ks (one to +3v, one to grd).
That is not a voltage divider that will bias the signal to 2.5 V meaning you will get a reading of around 512 when there is no sound.
Ok, without any supporting circuitry whatsoever, I get a reading from about 278 to 310.
The next step is to put a 1uf capacitor in place and add the biasing. The signal coming out of the VS1053 is a +/- 1.65v signal. My expectation with the biasing resistors is that it will cut off the negative going signal, giving me something closing to 0-4v - which is what is expected at the AnalogIn.
This capacitor, with biasing, gives me a range from about 490 to 520. Adding a diode from ground gives me an extra +10, equalling about 500-530..
This range seems very, very small for something potentially running on 0-1024. The LED is also violently flickering with these polled values.
Sending the output of this to an envelope follower (100k resistor, 0.22 cap), my range is knocked back down to 470/500..The LED no longer flickers, though.
So, I adjust the code to take a range of 470 to 500 - still less resolution than would be ideal - and scale it from 0-255. Now, it's flickering again. The light never quite shuts off, despite repeatedly re-adjusting the mapping function.
I'm sorry to be annoying about this. I appreciate all of the help, so far..making an LED blink has been quite difficult for me.
Yes but you still seem bent on ignoring most of it.
Do not add ANY biasing, for envelope detection you do not need / want it.
Adding a diode from ground
Who told you to do that? It is a series peak detecting diode.
This range seems very, very small for something potentially running on 0-1024.
The range 0 to 1023 ( not 1024 ) depends on your input voltage. You will only get that with a full 5V signal, do you have that?
If not then you need to add an amplifier to get a greater range.
The light never quite shuts off, despite repeatedly re-adjusting the mapping function.
You need to add a bias or a constraint to make sure your signal is zero when there is no music.