Audio VU Meter using Arduino
- Biasing AC input using resistor divider and scaling up / down if necessary;
- Sampling fast and accurately using direct access to Control Registers of ADC and Timer1;
- Subtract whatever was added at step #1 from result of Analog / Digital conversion and Square;
- Average / accumulate, filtering following VU specification;
- Sqrt – take square root, Log10 – transform to dB scale;
1. Hope, you follow my advice and hack your cheap USB speakers, to get nice ( pre-assembled ! ) analog “front-end” for this project. If not, than get your soldering iron to work, minimum two resistors and 1 cap would required, assuming you already have display wired up and running.
First things with AC measurements ( audio in this category ) on Atmel microcontroler is to get rid of negative half-wave of the input signal, and this what front-end circuitry should do. There are at least two option: rectifying AC to DC before voltage could reach arduino analog input, or biasing signal with external DC offset. Rectification, could nicely be done with help of specifically design IC, LM3914 / 15 / 16 for example. But in this article, I’d describe second alternative, as it’d be not fare to ask you to hack your speakers and than tell you to solder another board…. Here is my set-up, slightly modified version from last blog:
When AC input signal is mixed with DC offset, so it stays always in positive area, ( think about sine, which defined betseen -1 and +1, if I add +1 it always would be positive ), I only save arduino life, preventing it from destruction by negative voltage. When arduino ADC completes conversion from analog to digital form, I don’t need DC offset anymore, and it should be subtracted.
NOTE: DC voltage was added just to pass audio through arduino ADC.
2. Sampling subroutine is running at 40 kHz, that is more than enough for ANY application. You may decrease sampling rate to lower CPU load, with current settings VU metering consumes more than 50%. Higher sampling rate gives better linearity / precision over wide band, the same time with regular audio content even 10 kHz sampling would provide better than 1 dB accuracy. All input capture process goes in Interruption subroutine, which is configured in setup. Two channels of Timer 1 Configured to run in parallel, “A” is responsible to keep clock at 40 kHz sharp, and “B” fires start conversion event to ADC with the same speed. Restarting new conversion via hardware provides lowest phase noise compare to any other way of doing this.
ADCSRB = ((1<<ADTS2)| // Sets Auto Trigger source – Timer/Counter1 Compare Match B
/* Set up TIMER 1 – ADC sampler */
TCCR1A = ((1<<WGM11) | (1<<WGM10)); // Mode 15, Fast PWM
TCCR1B = ((1<<WGM13) | (1<<WGM12)); // Mode 15, Fast PWM
TCCR1B |= (1<<CS10); // clk/1 prescaling.
OCR1A = SMP_TMR1;
OCR1B = SMP_TMR1;
TIFR1 |= (1<<OCF1B);
TIMSK1 |= (1<<OCIE1B);
3 . As you can see in a code snipped below, adc_Offst is subtracted from new ADC result. Quite simple, value of DC offset ( adc_Offst ) was obtained in setup() during start up, using Arduino IDE “analogRead”. The only problem with this simple solution, is that no audio should be present at this moment ( start up ) at input, otherwise all measurements would be erroneous.
For more detail: Audio VU Meter using Arduino
This Post / Project can also be found using search terms:
- arduino vu meter
- аудиометр ардуино
- Arduino deciBel Meter
- arduino lcd meter