Go Down

Topic: Code for LED vu-meter (Read 6102 times) previous topic - next topic

stef.l

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 :)

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!

AlphaBeta

#1
Mar 27, 2009, 12:09 am Last Edit: Mar 27, 2009, 01:42 am by AlphaBeta Reason: 1
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)
Quote

/*
|| 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(" "); }
 
}


I almost feel guilty, steling all the coding fun. :|

[I will test when I have the chance.]

stef.l

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) ?

AlphaBeta

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:)

stef.l

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 :)


AlphaBeta

Quote

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


Nothing to say you're sorry for :)

Glad you got it working!

Go Up
 


Please enter a valid email to subscribe

Confirm your email address

We need to confirm your email address.
To complete the subscription, please click the link in the email we just sent you.

Thank you for subscribing!

Arduino
via Egeo 16
Torino, 10131
Italy