Go Down

Topic: Code for LED vu-meter (Read 5612 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