vu meter with arduino and hl1606 led strip

hey folks

i have some problems with the way how the vu meter acts like. i never thought it would be that hard to make it look nice :expressionless:
i even dont know if its a hardware or software problem... its never doing that what i want it like. its acting tooo fast and more like a strobo or its to slow and has nothing to do with the music.

the hardware:
my hw setup is, an audio source which is going to an lm386 (gain 20) and then to the analog in from the arduino. it has a offset of 2.5V so the voltage the arduino is reading is between 0V and 5V. i also connected the hl1606 led strip (cutted down to 38 leds). everything is powered by a labor power supply.
btw.. tried a few rc filters (cutted off, everything above 15khz or let it react just with the bass)

the software:
yaa... i tried everything i know... first i modded the bargraph sketch but its too fast. then tried this average code but its still not doing what it should. some say it has to be log. other say linear. i have really nooo idea how to make it look nice..

would be very thankfull if someone knows how to do it.

IMHO, to satisfy both requirements, fast reaction to audio / music and not "too fast" same time to be visually pleasant , you need to do "averaging" smoothing effect on the falling edge only. Actually what any VU meter doing in it's core.
http://arduino.cc/forum/index.php/topic,63746.0.html
and blog with this technics:
http://fftarduino.blogspot.com/2011/02/color-organ-spectrum-analyzer-on.html

thank you!!

i tried to use it but..i think i used it wrong.

  int soundn = analogRead(ain);
  sound = soundn;
  
 soundn = 0;
  
if (soundn < (sound * f))
 soundn = (sound * f);
  
  if (soundn > (sound * fn))
 soundn = (sound * fn);

fn is for example 1.1 and f is 0.9 right? now, how can i "map" it to my leds? i have 38 of them.. dunno if the map function is the right thing for it. later in the code im working with the soundn value right?

another question is, how can i take the offset out? if its in idle, the half of the bar is glowing and with the music it goes down...

  sound = soundn; // <- keep previous value in variable sound, to compare with new later 
  soundn = 0;        //  <- this is not necessary, just for logic

  soundn = analogRead(ain); // <- have you declared ain? if not:  int soundn = analogRead(A0);
                                             // A0 is connected to LM386, no DC blocking capacitor  
  if ( soundn < (sound * f))    //<-   f should be declared as:  float f = 0.99 ( or 0.999 for slower   response) 
   soundn = (sound * f);
  
//  if (soundn > (sound * fn)) // <- insert  this two line only if you'd like to control rising edge as 
// well, with different time constant,  float fn = 1.01 (try to experiment 1.10 or 1. 20, for faster 
// reaction), better to do it after you finish with falling edge.
//  soundn = (sound * fn);

All would works with audio envelope detector. Usually, envelope of AC input created by "rectification" process using diode or diode bridge. So there is option for you: modify hardware in a way to rectify AC before applying to A0 input or do it in software:

  int soundn = abs( analogRead(A0) - 512 ); // adjust constant 512 to your real DC  offset ( 2.5 V = 512 )

How to map with 38 led look into barGraph example.

ahh!! i forgot to declare the f as float :blush:

thank you very much!!! i will try it next morning.

=(

when i touch the in of the amp with my finger to the beat ;D it seems to be working nice! if i connect it to the amp, it starts flickering very fast. does it need a delay in your code? i tried it everyhwere and in every size. seems like this effect appears just with high freq like music.

Did you make "envelope detector" in hardware or software?
What is your f and fn coefficients? How big your code in the loop?

did it in software.. but now when u said it, i should try it without the offset part.
f and fn.. yaa i tried everything nothing fix now.. but it seemed to look nice with 0.99 and 1.5.

and here the code in the loop:

void loop() {
  //soundn = analogRead(A0);
  soundn = abs( analogRead(A0) - 400);

  sound = soundn;

  soundn = 0;

  //int soundn=analogRead(A0);
    
if (soundn < (sound * f))
soundn = (sound * f);
  
  if (soundn > (sound * fn))
 soundn = (sound * fn);
  
//int lvl = soundn / 28;
int lvl = map(soundn, 0, 700, 0, 38);

for (int thisLed = 0; thisLed < 38; thisLed+=1)

{ 
    if (lvl > thisLed) {
      strip.setLEDcolor(thisLed, RED);  
    }
    
    else {
            strip.setLEDcolor(thisLed,GREEN);
    }
  }
  strip.writeStrip();
}

There is a logical mistake in the code:

  soundn = abs( analogRead(A0) - 400);
  sound = soundn; // <<< you store variable that just was OVER written in previous command....
  soundn = 0;

//     Try this:

  sound = soundn;
  soundn = abs( analogRead(A0) - 400);

yes, but its not working at all if i do it like u posted. analogRead has to be before the sound=soundn part...

Check out this link:
http://docs.macetech.com/doku.php/rusty_vu

thx. its worked with the sound = soundn thing before the analogRead! no idea why and how but i sent it to the arduino and it worked. another problem appeared!!
i cant set the #lvl = map(soundn, 0, 1024, 0, 38);#

after that

if (soundn < (sound * f))

soundn = (sound * f);#

when i put it after this, it makes no reaction.. i dunno why this shouldnt work.
another question..
when i do this

soundn = (sound * f);

and f is lets say 1.3. shouldnt i change then the 1024 in the map function to a value thats 1.3 x higher than 1024 = 1331?