Self-built VU meter

Self-built VU meter

 

Hello and welcome to a new and exciting blog. Today we go into the low-frequency world and build our own VU meter. For all those who no longer know the measuring instrument known from the 80s: A VU meter (vu stands for English terms Volume Units, i.e. in terms of "volume units") is a control meter, i.e. a measuring instrument for assessing the signal strength in sound technology. The signal strength of a fed audio signal is measured in its electrical equivalent.

We need the following hardware parts from the shop to be able to build the VU meter:


In order to measure an audio signal with our Arduino, we first have to make some preliminary considerations. The most important first: The audio signal is an arbitrary alternating voltage in the KHz range that vibrates around the zero point. Therefore, no digital input is suitable for measuring this signal. Also an analog input Our Microcontrollers for the measurement of the music low frequency signal is only partially suitable without external connection, since it can only measure positive voltage values in the range of 0 to 5 volts at a resolution of 10 bits. To visualize this, I show audio NF vibrations recorded with the oscilloscope below, just as they are attached to a loudspeaker.

Debinding: NF signal at the speaker input, unfiltered

Debinding: NF signal at the speaker input, unfiltered

 

In the first step, we therefore prepare our analog NF music signal using a small external resistance capacitor circuit so that it is lifted into the positive voltage range with an offset of 2.5 volts. The zero passage into the negative area is thus avoided:

 

Binding: Same NF signal with a DC offset.Binding: Same NF signal with a DC offset.

 

 

We do this with the two 10 KOhm resistors shown in the circuit diagram and a 10uF 63 volt electrolytic capacitor, whose cathode points to our microcontroller. Now let's completely build the VU meter as seen on the following picture:

 

VU Meter Set-up plug-in board

 

Important is that the 64 Led Panel obtains its power supply through the MB102 power module and Not by the Arduino Nano, as up to 2.5 A are consumed in operation by the U64 LED panel in the tip. This current, if provided by the Arduino, would inevitably cause the voltage to collapse or damage the voltage regulator on the nano. The dimensioning of the power supply should also be chosen accordingly.

 

#include <Adafruit_NeoPixel.H>

Which pin on the Arduino is connected to the NeoPixels?
On a Trinket or Gemma we suggest changing this to 1:
#define LED_PIN     13
How many NeoPixels are attached to the Arduino?
#define LED_COUNT  64

NeoPixel brightness, 0 (min) to 255 (max)
#define BRIGHTNESS 100

Declare our NeoPixel strip object:
Adafruit_NeoPixel Strip(LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800);
Argument 1 = Number of pixels in NeoPixel strip
Argument 2 = Arduino pin number (most are valid)
Argument 3 = Pixel type flags, add together as needed:
NEO_KHZ800 800 KHz bitstream (most NeoPixel products w/WS2812 LEDs)
NEO_KHZ400 400 KHz (classic 'v1' (not v2) FLORA pixels, WS2811 drivers)
NEO_GRB Pixels are wired for GRB bitstream (most NeoPixel products)
//   NEO_RGB     Pixels are wired for RGB bitstream (v1 FLORA pixels, not v2)
//   NEO_RGBW    Pixels are wired for RGBW bitstream (NeoPixel RGBW products)

#define analogPinLeft A5 // Left Audio Channel, connected to analog pin A5

int val_left_old = 0;  // variable to store the value read from Channel Left
int Base_Left = 0;   // 0 Basis

void setup()
{   strip.begin();           // INITIALIZE NeoPixel strip object (REQUIRED)   strip.show();            // Turn OFF all pixels ASAP   strip.setBrightness(BRIGHTNESS); // Set BRIGHTNESS to about 1/5 (max = 255)   Base_Left = analogRead(analogPinLeft);   Base_Left += analogRead(analogPinLeft);   Base_Left += analogRead(analogPinLeft);   Base_Left += analogRead(analogPinLeft);   Base_Left = Base_Left / 4;   colorWipe(strip.Color(255, 0, 0), 5); // Red   colorWipe(strip.Color(255, 255, 0), 5); // yellow   colorWipe(strip.Color(0, 255, 0), 5); // Green   rainbowFade2White(1, 1, 1);
}

void loop()
{   Left_VU_Meter(64, 100);   delay(40);
}

void Left_VU_Meter(byte Level_Max_Pixels, int sensitivity)
{   int val_left = 0;   val_left = analogRead(analogPinLeft);  // read the input pin   val_left += analogRead(analogPinLeft);  // read the input pin   val_left += analogRead(analogPinLeft);  // read the input pin   val_left += analogRead(analogPinLeft);  // read the input pin   val_left = val_left / 4;   int Signal_Strength = val_left - Base_Left;   if (Signal_Strength < 0) {     Signal_Strength = - Signal_Strength;   }   byte VU_Led_Level =  map(Signal_Strength, 0, sensitivity , 0, Level_Max_Pixels);   for (int i = 0; i < Level_Max_Pixels; i++) {     strip.setPixelColor(i, 0, 0, 0);  // Clear pixel's color (in RAM)   }   for (int i = 0; i < VU_Led_Level; i++) { // For each pixel in strip...     uint32_t hue = map(i, Level_Max_Pixels - 1, 0, 0, 21800);     uint32_t rgbcolor = strip.ColorHSV(hue, 255, BRIGHTNESS); // Hue to RGB Conversation     strip.setPixelColor(i, rgbcolor);         //  Set pixel's color (in RAM)   }   strip.show();   //  Update strip to match
}

void colorWipe(uint32_t color, int wait) {   for (int i = 0; i < strip.numPixels(); i++) { // For each pixel in strip...     strip.setPixelColor(i, color);         //  Set pixel's color (in RAM)     strip.show();                          //  Update strip to match     delay(wait);                           //  Pause for a moment   }
}

void rainbowFade2White(int wait, int rainbowLoops, int whiteLoops) {   int fadeVal = 0, fadeMax = 100;   // Hue of first pixel runs 'rainbowLoops' complete loops through the color   // wheel. Color wheel has a range of 65536 but it's OK if we roll over, so   // just count from 0 to rainbowLoops*65536, using steps of 256 so we   // advance around the wheel at a decent clip.   for (uint32_t firstPixelHue = 0; firstPixelHue < rainbowLoops * 65536;        firstPixelHue += 256) {     for (int i = 0; i < strip.numPixels(); i++) { // For each pixel in strip...       // Offset pixel hue by an amount to make one full revolution of the       // color wheel (range of 65536) along the length of the strip       // (strip.numPixels() steps):       uint32_t pixelHue = firstPixelHue + (i * 65536L / strip.numPixels());       // strip. ColorHSV() can take 1 or 3 arguments: a hue (0 to 65535) or       // optionally add saturation and value (brightness) (each 0 to 255).       // Here we're using just the three-argument variant, though the       // second value (saturation) is a constant 255.       strip.setPixelColor(i, strip.gamma32(strip.ColorHSV(pixelHue, 255,                                            255 * fadeVal / fadeMax)));     }     strip.show();     delay(wait);     if (firstPixelHue < 65536) {                             // First loop,       if (fadeVal < fadeMax) fadeVal++;                      // fade in     } else if (firstPixelHue >= ((rainbowLoops - 1) * 65536)) { // Last loop,       if (fadeVal > 0) fadeVal--;                            // fade out     } else {       fadeVal = fadeMax; // Interim loop, make sure fade is at max     }   }   for (int k = 0; k < whiteLoops; k++) {     for (int j = 0; j < 256; j++) { // Ramp up 0 to 255       // Fill entire strip with white at gamma-corrected brightness level 'j':       strip.fill(Strip.Color(0, 0, 0, Strip.gamma8(J)));       Strip.Show();     }     for (Int J = 255; J >= 0; J--) { Ramp down 255 to 0       Strip.Fill(Strip.Color(0, 0, 0, Strip.gamma8(J)));       Strip.Show();     }   }
}

 

 

Now we can connect an NF analog signal of a speaker to the audio jack. Line-In Level is NOT sufficient to operate our VU meter. The audio input is therefore connected directly to the output of the audio source (max 30 Watt Peak).


In the next two parts of this series, we build a second channel to display stereo signals with the VU meter, and add some settings, such as sensitivity and brightness.
Write your questions or wishes in the comments as always.

I wish you a lot of fun with replica of the VU meter and until the next time.

For arduinoProjects for advanced

8 comments

Tobias

Tobias

Hallo Nils,
Du liegst richtig, die virtuelle Nullinie wird zum Startzeitpunkt des Arduinos eingelesen. Zu diesem Zeitpunkt sollte demnach noch kein Signal anliegen, da diese sonst ggf. verfälscht werden könnte. Dies ist nötig, da die Toleranzen der Bauteile selbst bei nur 1% Abweichung dazu führen könnten, das nach dem Start die eine oder andere VU Led dauerhaft leuchtet. Dies sieht sehr unschön aus. Daher diese Lösung der virtuellen Nullinie. Man könnte aber auch alternativ einmalig die Nullinie beim ersten Start einlesen, und ins EEPRom schreiben, wenn einen das stört.

Tobias

Tobias

Hallo Heiko,

Eine berechtigter Punkt. Jedoch steckt bei der Wahl der MB102 Breadboard Spannungsversorgung die Überlegung dahinter, das das VU Meter zunächst als auf dem Breadboard als TEST aufgebaut wird und später im festen Dauerbetrieb noch mal neu dauerhaft auf eine Platine gelötet wird. Für den festen und gelöteten Einsatz als Modul sollte dann passend dimensioniertes externes 5 Volt-Netzteil verwendet werden. Die MB102 Breadboard Spannungsversorgung ist, wie der Name schon vermuten lässt für den Breadboardeinsatz konzipiert.
Dennoch reicht die MB102 Breadboard Spannungsversorgung für den ersten Aufbau und Test der hier vorgestellten Schaltung aus, denn die 2,5 Ampere beziehen sich auf eine Helligkeitsaussteuerung von 100 % und eine Aussteuerung der LED’s von 100%. Bei dem og. Aufbau ist jedoch die Helligkeit der LED’s auf 39% der maximalen Helligkeit beschränkt, was den Stromverbrauch entsprechend reduziert. 39% von 2,5 A = 0,97 A bei Vollaussteuerung. Im mittleren Betrieb sollen darüber hinaus nur 50% der LED’s aktiv sein, d.h 0,97 A / 2 = 0,48 A. Somit unter den 0,7 Ampere des Moduls.
Zum testen der Schaltung also ausreichend. Im Festbetrieb sollte das Modul, wie du schon schreibst, durch ein normales Netzteil ersetzt werden.
Viele Grüße
Tobias

niko_at

niko_at

Meiner Meinung nach ist der Elko falsch gepolt, d.h. Kathode (Minus) muss an die Lautsprecherbuchse. And der LS-Buchse haben wir im Mittel 0V und am Mikrocontroller (Widerstandsteiler 2x 10kOhm) haben wir U/2 => +2,5V

Zudem fehlen Schutzdioden, dass am Mikrocontroller Eingang nicht Spannungen weit über Ub (5V) und nicht weit unter 0V gehen können!
Z.B: Mikrocontrollereingang über 10 kOhm (ggf. auch kleiner) und 2 Dioden (1N4148) jeweils in Sperrichtung gegen V und 0V. So kann die SPannung max. 0,7V üver V+ und 0,7V unter 0V gehen.

Nils

Nils

Moin,
cooles Projekt! Verstehe ich das richtig, dass im Setup der Base_Left eingelesen wird, um das virtuelle Null-Niveau (Nulllinie) zu ermitteln. Das funktioniert aber nur richtig, wenn beim Einschalten noch kein Audio Signal am Analog-Pin anliegt. Alternativ könnte man 2 1% Widerstände zum Teilen der Spannung nehmen und dann die Nullinie einfach mit 2.5V (also 512) definieren.
Eingangsspannungen kleiner 0V oder größer 5V am analogen Pin werden nicht richtig gemessen, können eventuell den Arduino sogar beschädigen? Vielleicht mit 2 Dioden das Signal auf GND und +5V klemmen?

Dirk

Dirk

Hi, cooles Projekt, da ich im Moment ein VU Meter suche.
Kann man die LED Module hintereinanderschalten? Ich stelle mir vor, 3 Module zu nehmen.
Oder gleich eine komplette LED Matrix 64×32.
Ein Modul mit den 8 LED’s sind zu wenig Auflösung.
Und natürlich muss das mit den Line IN/OUT Signalen funktionieren.
Mann sollte das VU Meter auch kalibrieren können.
Am Lautsprecherausgang macht es für mich keinen Sinn, da sich da die Laustärke ständig ändert.
Danke und Grüße

Heiko Schütz

Heiko Schütz

Frage: Im Beitrag steht, dass “im Betrieb bis zu 2,5 A durch den U64-LED Panel in der Spitze verbraucht werden”. Laut Datenblatt ist die MB102-Spannungsversorgung bis 700 mA ausgelegt. Hält die Spannungsversorgung diese Spitzen von 2,5 A ohne Schaden zu nehmen aus – das ist ja keine Dauerbelastung? Oder wäre es nicht besser (sicherer), gleich ein passend dimensioniertes externes 5 Volt-Netzteil zu verwenden (wie man es z.B. auch zum Betrieb von längeren Neopixel-Streifen benötigt)?

(Datenblatt: https://cdn.shopify.com/s/files/1/1509/1638/files/MB102_Breadboard_Kit_Datenblatt.pdf)

Gerrit

Gerrit

Es wäre schön das VU-Meter einmal in einem kurzen Video im Betrieb zu sehen, um entscheiden zu können ob sich der Nachbau für einen persönlich lohnt.

Gerhard Langner

Gerhard Langner

Hallo. Nicht neu aber cooles projekt. Ich denke eine leicht abgeänderte Vorschaltung wäre auch für die leute wie mich interesant die sowas lieber im linepegel haben möchten.

Leave a comment

All comments are moderated before being published

Recommended blog posts

  1. Install ESP32 now from the board manager
  2. Lüftersteuerung Raspberry Pi
  3. Arduino IDE - Programmieren für Einsteiger - Teil 1
  4. ESP32 - das Multitalent
  5. OTA - Over the Air - ESP programming via WLAN