New to the forum and new to Arduino in general,
I just wanted to get some help or if someone can shoot me in the right direction if this project has already been made.
I'm using an Arduino nano.
What I'm after is essentially making an LED get brighter to the volume of a guitar.
So the analog side of it would be the guitar signal going through an op amp to boost it up to a signal that the Arduino can read a little better which i can map to 0 to 1023 in the analog input.
So when i strum the guitar it will be picked up by the Arduino Nano and output a PWM to an LED to the same velocity/voltage as the guitar, (So if i strum quieter it will be softer, and louder it will be brighter).
Is this something that already exists in code i can see and deconstruct/alter?
Its essentially a envelope follower, and seems like something that exists already i just can’t seem to find anything as I’m having trouble on getting this code started off.
Here is the code ive got so far, but the problem is that because guitar is an AC signal it goes positive and negative due to the frequency of the signal, which turns the led on and off really fast, is there a way to make it just be on and fade off, not stutter off due to reading ac negative voltages.
Here is the code ive got so far:
const int envelopeInPin = A5;
const int envelopeOutPin = 6;
const int envelopeInPin2 = A4;
int envelopeVoltage;
You actually need one of the breakout board with a microphone and amplifier on the board. Get one with an analog output based on volume and you are ready to go.
You seem to be using an electronic guitar signal output, which is not what you want, unless you rectify it and use a capacitor to sum the voltages to indicate volume.
Paul
@paulpaulson Sorry i should correct, i did say voltage but i meant volume, a smooth ramping up and ramping down of the led when playing guitar based on volume.
@Paul_KD7HB I was hoping to do it without any breakout boards but using analog components on a breadboard. I'll try adding a rectifier circuit before hand, i was just hoping its possible in code.
You can "rectify" in your program - just track the highest vMax and lowest vMin values you read. The difference between them is the size (ie volume).
You will need to reset Vmax on the "negative " half cycle, and VMin on the positive half cycle
vAv is the average input - the reading you get with no input signal.
Having given it a bit of thought I'll not write the code for you - its not difficult, but a rather fun challenge.
Draw a sine wave and figure out how to measure its size.
You need a diode and capacitor to give peak amplitude and also a resistor in parallel with the capacitor so the capacitor discharges when the amplitude reduces. The product of resistance (in ohms) times the capacitance (in Farads) needs to be roughly 0.05 (that's seconds).
As subjective volume has a logarithmic relationship to acoustic sound pressure, I suggest trying if it's better if (in your code) you take the logarithm of the voltage from your peak detector (relative to the DC voltage of your signal earth) before feeding that to the PWM modulation of LED intensity.
Hey @johnerrington if i bias the analog input of the arduino with a voltage divider 10k resistors from 5v and gnd.
And if i map the input from 0, 1023, 0, 255.
When i am not playing guitar it will be at roughly 128, and when im playing with the highest positive voltage being 255, and the lowest negative voltage being 0 in arduino.
Would these be the steps to then rectify it? Im unsure what you mean by Vmax, Vmin, vAv
Can you expand a little further?
As the average input value with no input is "roughly" 512 you can VERY EASILY find the size of the signal.
Forget about mapping, work with the raw values as they have better resolution.
envelopeVoltage = analogRead(envelopeInPin);
For each reading
subtract 512. (envelopeVoltage is declared as a int so neg values will be OK)
envelopeVoltage = envelopeVoltage - 512;
get rid of neg values - or any less than a threshold to allow for noise
if (envelopeVoltage<5) {
its the end of a cycle - so .. take the sum of the input values for this cycle and divide by the count;
record the result as the signal size; then
reset the count and the sum to start again.
}
This definitely is seeming for like what i'm after, and making a little bit more sense.
I'm just having trouble with what you mean by:
"take the sum of the input values for this cycle and divide by the count;
record the result as the signal size; then
reset the count and the sum to start again."
I'm still super new to Arduino but is that similar to the "smoothing" program in the examples sketches?
No; however there is a way to do it using that basic idea.
const int envelopeInPin = A5;
const int envelopeOutPin = 6;
const int envelopeInPin2 = A4;
float vol = 128;
int vout;
int sample;
int rate = 50; // controls the time between samples; a sample is 1 measurement of your incoming signal.
float filter = 0.01; //you may need to play with this to get the results you want
float nfilter;
void setup() {
pinMode(envelopeInPin, INPUT);
pinMode(envelopeOutPin, OUTPUT);
nfilter = 1 - filter;
}
void loop() {
sample = analogRead(envelopeInPin);
sample -= 512;
if (sample < 0) { sample = -sample }; //or sample = abs(sample);
//sample will now be in the range 0 - 512; smooth it
vol = (vol * nfilter) + (sample * filter); // in one instruction!
vout = int ( vol / 2); //change the range to be between 0 and 255
analogWrite(envelopeOutPin, vout);
delayMicroseconds(rate);
}
I havent tried it out so you may need to correct the odd typo.
Hey @johnerrington
Thank you, this is almost perfect, i had to do a few changes to match the preamp i had, but its only values. And setting a min and max threshold.