Code for LED vu-meter

First i will introduce myself! I am currently studying avionics in montreal, i know the basics but still have a lot to learn. My main trouble will be the programing, but i think i am coming along well :slight_smile:

One of my first projects is a vu-meter. i got it working, but i would like to smooth out the edges.

I would like to calculate a average over a certain amout of time (a few ms) and then process it to make the leds light up.

Here is the code i have for the moment:

int val = 0;

void setup() {
pinMode(13, OUTPUT);
pinMode(12, OUTPUT);
pinMode(11, OUTPUT);
pinMode(10, OUTPUT);
pinMode(9, OUTPUT);
pinMode(8, OUTPUT);
}

void loop(){
val = analogRead(0);
if(analogRead(2) > val){
digitalWrite(13, HIGH);
} else{
digitalWrite(13, LOW);
}
delay(10);
if(analogRead(2) > val+10){
digitalWrite(12, HIGH);
digitalWrite(13, HIGH);
} else{
digitalWrite(12, LOW);
digitalWrite(13, LOW);
}
delay(10);
if(analogRead(2) > val+30){
digitalWrite(11, HIGH);
digitalWrite(12, HIGH);
digitalWrite(13, HIGH);
} else{
digitalWrite(11, LOW);
digitalWrite(12, LOW);
digitalWrite(13, LOW);
}
delay(10);
if(analogRead(2) > val+55){
digitalWrite(10, HIGH);
digitalWrite(11, HIGH);
digitalWrite(12, HIGH);
digitalWrite(13, HIGH);
} else{
digitalWrite(10, LOW);
digitalWrite(11, LOW);
digitalWrite(12, LOW);
digitalWrite(13, LOW);
}
delay(10);
if(analogRead(2) > val+80){
digitalWrite(9, HIGH);
digitalWrite(10, HIGH);
digitalWrite(11, HIGH);
digitalWrite(12, HIGH);
digitalWrite(13, HIGH);
} else{
digitalWrite(9, LOW);
digitalWrite(10, LOW);
digitalWrite(11, LOW);
digitalWrite(12, LOW);
digitalWrite(13, LOW);
}
delay(10);
if(analogRead(2) > val+100){
digitalWrite(8, HIGH);
digitalWrite(9, HIGH);
digitalWrite(10, HIGH);
digitalWrite(11, HIGH);
digitalWrite(12, HIGH);
digitalWrite(13, HIGH);
} else{
digitalWrite(8, LOW);
digitalWrite(9, LOW);
digitalWrite(10, LOW);
digitalWrite(11, LOW);
digitalWrite(12, LOW);
digitalWrite(13, LOW);
}
delay(10);

}

Thanks in advance for you help!

I started to tweak your code and ended up with this snippet:

[PSEUDOTESTED CODE] (seems to be working with potentiometers and serial console as output)

/*
|| A simple VU meter using arduino with analog input smoothing
||
|| Contributed:
|| Alexander Brevig
*/

//defines
#define NUMBER_OF_LEDS 6
#define NUMBER_OF_SAMPLES 20

#define DEBUG true

#define VU_METER_DISPLAY_DELAY 10

//analog in pins
byte voltageReferencePin = 0;
byte voltagePin = 2;

//digital out pins
//store the leds in an array, this way changing them later wont be a hazzle
byte ledPins[NUMBER_OF_LEDS] = { 8 , 9 , 10 , 11 , 12 , 13 };

//convert analogRead to VU ledscale
byte voltageComparisonThresholds[] = { 0 , 10 , 30 , 55 , 80 , 100 };

int voltageReference = 0; //contain analogRead(voltageReferencePin);

//sample variables
int samples[NUMBER_OF_SAMPLES] = {0};
int sample = 0;
int sampleTotal = 0;
byte sampleIndex = 0;

void setup() {
for (byte i=0; i<NUMBER_OF_LEDS; i++){
pinMode(ledPins*,OUTPUT);*

  • }*

  • pinMode(voltageReferencePin,INPUT);*

  • pinMode(voltagePin,INPUT);*

  • if(DEBUG){Serial.begin(9600);}*
    }
    void loop(){

  • //SMOOTH See Examples->Analog->Smoothing*

  • sampleTotal -= samples[sampleIndex];*

  • samples[sampleIndex] = analogRead(voltageReferencePin);//read value*

  • sampleTotal += samples[sampleIndex++]; *

  • if (sampleIndex >= NUMBER_OF_SAMPLES) {sampleIndex = 0;}*

  • sample = sampleTotal / NUMBER_OF_SAMPLES;*

  • if(DEBUG){Serial.print("virtual vu: ");}*

  • //DISPLAY_RESULT*

  • //see Examples->Digital->Loop*

  • for (byte i=0; i<NUMBER_OF_LEDS; i++){*
    _ if ( analogRead(voltagePin) >= voltageReference + voltageComparisonThresholds ) {_
    _ digitalWrite(ledPins*,HIGH); if(DEBUG){Serial.print("|");}
    }else{
    digitalWrite(ledPins,LOW); if(DEBUG){Serial.print(" ");}
    }_

    delay(VU_METER_DISPLAY_DELAY);
    _ }
    if(DEBUG){ Serial.println(" "); }*_

}[/quote]
I almost feel guilty, steling all the coding fun. :expressionless:
[I will test when I have the chance.]

Wow i wasn't expecting such a detailed answer! It's very nice of you but it dosent seem to work, all the leds stay on at all times. I tried to see where the problem was, but i barely understand that kind of code.

Maybe just a way to make a average (over a few ms) of analogread(2) ?

Hello!

For analog smoothing see: Smoothing

About the code; it seem to function here, using the serial console, I get a nice bar. But! Beware that the thresholds are wery low, and you'll get a very limited reponse per voltage difference.

Try changing:

byte voltageComparisonThresholds[] = { 0 , 10 , 30 , 55 , 80 , 100 };

to

byte voltageComparisonThresholds[] = { 0 , 100 , 300 , 550 , 800 , 1000 };

If you think the code looks complex, you should take a look at Loop. They make things loog a bit wierd, but makes code much more compact. Eventually you'll see that it actually i simple:)

OK i got it working quite nicely now! I simply copy/pasted the smoothing technique, But i sticked to my longer version of the code because i understand it better.

Next step will be to vary the steps between each led proportionaly with a potentiometer, instead of simply rising/lowering the reference.

Here is the code:

int val = 0;

#define NUMREADINGS 10

int readings[NUMREADINGS];
int index = 0;
int total = 0;
int average = 0;

void setup() {
for (int i = 0; i < NUMREADINGS; i++)
readings *= 0; *
pinMode(13, OUTPUT);
pinMode(12, OUTPUT);
pinMode(11, OUTPUT);
pinMode(10, OUTPUT);
pinMode(9, OUTPUT);
pinMode(8, OUTPUT);
}
void loop(){
*total -= readings[index]; *
readings[index] = analogRead(2);
*total += readings[index]; *
*index = (index + 1); *
*if (index >= NUMREADINGS) *
*index = 0; *
*average = total / NUMREADINGS; *
val = analogRead(0);
if(average > val){
digitalWrite(13, HIGH);
} else{
digitalWrite(13, LOW);
}
if(average > val+10){
digitalWrite(12, HIGH);
digitalWrite(13, HIGH);
} else{
digitalWrite(12, LOW);
digitalWrite(13, LOW);
}
if(average > val+30){
digitalWrite(11, HIGH);
digitalWrite(12, HIGH);
digitalWrite(13, HIGH);
} else{
digitalWrite(11, LOW);
digitalWrite(12, LOW);
digitalWrite(13, LOW);
}
if(average > val+55){
digitalWrite(10, HIGH);
digitalWrite(11, HIGH);
digitalWrite(12, HIGH);
digitalWrite(13, HIGH);
} else{
digitalWrite(10, LOW);
digitalWrite(11, LOW);
digitalWrite(12, LOW);
digitalWrite(13, LOW);
}
if(average > val+80){
digitalWrite(9, HIGH);
digitalWrite(10, HIGH);
digitalWrite(11, HIGH);
digitalWrite(12, HIGH);
digitalWrite(13, HIGH);
} else{
digitalWrite(9, LOW);
digitalWrite(10, LOW);
digitalWrite(11, LOW);
digitalWrite(12, LOW);
digitalWrite(13, LOW);
}
if(average > val+100){
digitalWrite(8, HIGH);
digitalWrite(9, HIGH);
digitalWrite(10, HIGH);
digitalWrite(11, HIGH);
digitalWrite(12, HIGH);
digitalWrite(13, HIGH);
} else{
digitalWrite(8, LOW);
digitalWrite(9, LOW);
digitalWrite(10, LOW);
digitalWrite(11, LOW);
digitalWrite(12, LOW);
digitalWrite(13, LOW);
}
}
Sorry it is so long, im sticking to the easy way :slight_smile:

Sorry it is so long, im sticking to the easy way :slight_smile:

Nothing to say you're sorry for :slight_smile:

Glad you got it working!