Pages: [1]   Go Down
Author Topic: Code for LED vu-meter  (Read 4766 times)
0 Members and 1 Guest are viewing this topic.
0
Offline Offline
Newbie
*
Karma: 0
Posts: 3
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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 smiley

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!
Logged

Norway@Oslo
Offline Offline
Edison Member
*
Karma: 12
Posts: 2033
loveArduino(true);
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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.]
« Last Edit: March 26, 2009, 07:42:08 pm by AlphaBeta » Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 3
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

Norway@Oslo
Offline Offline
Edison Member
*
Karma: 12
Posts: 2033
loveArduino(true);
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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

0
Offline Offline
Newbie
*
Karma: 0
Posts: 3
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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 smiley

Logged

Norway@Oslo
Offline Offline
Edison Member
*
Karma: 12
Posts: 2033
loveArduino(true);
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Sorry it is so long, im sticking to the easy way smiley

Nothing to say you're sorry for smiley

Glad you got it working!
Logged

Pages: [1]   Go Up
Jump to: