Stereo VU Meter - AZ-Delivery

Hola y bienvenidos a una nueva parte de la serie "VU-Meter".

¡La gran respuesta a la primera parte de la serie es abrumadora! Por supuesto, asumiremos el desafío y en el siguiente paso agregaremos otro canal a nuestro medidor de VU. El segundo canal se muestra negativamente en el panel U64. ¡Ya tenemos un excelente medidor de VU estéreo con un impresionante efecto de contrarrotación!

Por supuesto, también hay algunas extensiones de hardware y optimizaciones a bordo. Como escribí en la primera parte, el panel U64 consume bastante energía. Por lo tanto, nuestro primer cambio de hardware es un intercambio del módulo de suministro de placa de pruebas por una fuente de alimentación estable de 5 voltios / 2.6 A. Ahora podemos aumentar el brillo de los LED del panel del 39% al 100% sin ningún problema de electricidad. La pantalla hace un poco más. Sin embargo, el código inicialmente limita este brillo al 60% de brillo. Esta limitación caerá en la siguiente parte de la serie sin cambiar la fuente de alimentación.

Por supuesto, el módulo de suministro de la placa de pruebas no es basura, pero se puede usar para todas las demás superestructuras seguimiento  Se pueden seguir utilizando proyectos igualmente interesantes. Las otras partes adicionales, a saber, los dos 680 ohmios Resistencias  y los dos diodos Zener de 5.1 voltios realizan funciones de protección de circuito para el Arduino. Esto da como resultado la siguiente lista parcial para la parte actual de la serie:

 

  • 1x Arduino Nano (con FTDI)
  • 1x Panel LED U64
  • 2x 10 KOhm Resistencias 1%
  • 2x 680 ohmios Resistencias 5%
  • 1x 5 voltios, fuente de alimentación mínima de 2.6 amperios
  • 1x 10 uF condensador electrolítico de 64 voltios
  • 1x conector jack estéreo de 3,5 mm
  • 2x diodo zener de 5.1 voltios

 

Conectamos los componentes al siguiente diagrama de circuito:

Diagrama de circuito fritzing

 

Después de haber construido o actualizado completamente el circuito, ahora podemos cargar el código actualizado y expandido en nuestro Arduino:

 

#include <Adafruit_NeoPixel.h>

// ¿Qué pin del Arduino está conectado a los NeoPixels?
// En un Trinket o Gemma sugerimos cambiar esto a 1:
#definir LED_PIN     13
// ¿Cuántos NeoPixels están conectados al Arduino?
#definir LED_COUNT  64

// Declara nuestro objeto de tira NeoPixel:
Adafruit_NeoPixel tira(LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800);
// Argumento 1 = Número de píxeles en la tira NeoPixel
// argumento 2 = número de pin Arduino (la mayoría son válidos)
// Argumento 3 = Indicadores de tipo píxel, sumar según sea necesario:
// NEO_KHZ800 800 KHz bitstream (la mayoría de los productos NeoPixel con LED WS2812)
// NEO_KHZ400 400 KHz (píxeles de FLORA clásicos 'v1' (no v2), controladores WS2811)
// NEO_GRB Los píxeles están cableados para GRB bitstream (la mayoría de los productos NeoPixel)
// NEO_RGB Los píxeles están cableados para flujo de bits RGB (v1 píxeles FLORA, no v2)
// NEO_RGBW Los píxeles están cableados para flujo de bits RGBW (productos NeoPixel RGBW)

#definir analogPinLeft A5 // Canal de audio izquierdo, conectado al pin analógico A5
#definir analogPinRight A4 // Canal de audio derecho, conectado al pin analógico A4
#definir Left_Channel_Deviation  5
#definir Right_Channel_Deviation 5

int val_left_old = 0;  // variable para almacenar el valor leído del canal izquierdo
int Base_Izquierda = 0;   // 0 base
int val_right_old = 0;  // variable para almacenar el valor leído del canal izquierdo
int Base_Right = 0;   // 0 base

int leftDropTime, rightDropTime;
int dropDelay = 4;                                        // espera antes de soltar los leds
// Brillo NeoPixel, 0 (min) a 255 (max)
byte Brillo = 153;  // 60% de brillo

flotar dropFactor = .98;

nulo configuración()
{   tira.comenzar();           // INICIALIZAR el objeto de tira NeoPixel (REQUERIDO)   tira.mostrar();            // APAGA todos los píxeles lo antes posible   tira.conjuntoBrillo(Brillo); // Establezca BRILLO en aproximadamente 1/5 (máx = 255)   Base_Izquierda = analogRead(analogPinLeft);   Base_Izquierda += analogRead(analogPinLeft);   Base_Izquierda += analogRead(analogPinLeft);   Base_Izquierda += analogRead(analogPinLeft);   Base_Izquierda = Base_Izquierda / 4;   Base_Right = analogRead(analogPinRight);   Base_Right += analogRead(analogPinRight);   Base_Right += analogRead(analogPinRight);   Base_Right += analogRead(analogPinRight);   Base_Right = Base_Right / 4;   De serie.empezar(9600);   colorWipe(tira.Color(255, 0, 0), 5); // Rojo   colorWipe(tira.Color(255, 255, 0), 5); // amarillo   colorWipe(tira.Color(0, 255, 0), 5); // Verde   rainbowFade2White(1, 1, 1);
}

vacío lazo()
{   Left_VU_Meter(LED_COUNT / 2, 512);   Right_VU_Meter(LED_COUNT / 2, 511);   tira.espectáculo();   // Actualizar tira para que coincida
}





vacío Left_VU_Meter(byte Level_Max_Pixels, En t sensibilidad)
{   En t val_left = 0;   bool Sobrecargar = falso;   uint32_t rgbcolor;   uint32_t matiz;   En t Intensidad de señal = 0;   byte VU_Led_Level = 0;   val_left = analogRead(analogPinLeft);  // lee el pin de entrada   val_left += analogRead(analogPinLeft);  // lee el pin de entrada   val_left += analogRead(analogPinLeft);  // lee el pin de entrada   val_left += analogRead(analogPinLeft);  // lee el pin de entrada   val_left = val_left / 4;   Si (!(abdominales(val_left - val_left_old) > Left_Channel_Deviation)) {     val_left = val_left_old;   }   Si (val_left < val_left_old)   {     leftDropTime++;     Si (leftDropTime > dropDelay)     {       val_left = val_left_old * dropFactor;       leftDropTime = 0;     }     más     {       val_left = val_left_old;     }   }   val_left_old = val_left;   Intensidad de señal = val_left - Base_Izquierda;   Si (Intensidad de señal < 0) {     Intensidad de señal = - Intensidad de señal;   }   VU_Led_Level =  mapa(Intensidad de señal, 0, sensibilidad , 0, Level_Max_Pixels);   Si (VU_Led_Level > Level_Max_Pixels)   {     Sobrecargar = cierto;     VU_Led_Level = Level_Max_Pixels;   } más {     Sobrecargar = falso;   }   para (En t yo = 0; yo < Level_Max_Pixels; yo++) {     tira.setPixelColor(yo, 0, 0, 0);  // Borrar el color del píxel (en RAM)   }   para (En t yo = 0; yo < VU_Led_Level; yo++) { // Por cada píxel en la tira ...     matiz = mapa(yo, Level_Max_Pixels - 1, 0, 0, 21800);     Si (Sobrecargar) {       rgbcolor = tira.Color(255, 0, 0);   // Conversación de tono a RGB     } más {       rgbcolor = tira.ColorHSV(matiz, 255, BRILLO);     }     tira.setPixelColor(yo, rgbcolor);         // Establecer el color del píxel (en RAM)   }   // strip.show (); // Actualizar tira para que coincida
}

vacío colorWipe(uint32_t color, En t Espere) {   para (En t yo = 0; yo < tira.numPixels(); yo++) { // Por cada píxel en la tira ...     tira.setPixelColor(yo, color);         // Establecer el color del píxel (en RAM)     tira.espectáculo();                          // Actualizar tira para que coincida     retrasar(Espere);                           // Pausa por un momento   }
}

vacío Right_VU_Meter(byte Level_Max_Pixels, En t sensibilidad)
{   En t val_right = 0;   bool Sobrecargar = falso;   uint32_t rgbcolor;   uint32_t matiz;   En t Intensidad de señal = 0;   byte VU_Led_Level = 0;   val_right  = analogRead(analogPinRight);  // lee el pin de entrada   val_right  += analogRead(analogPinRight);  // lee el pin de entrada   val_right  += analogRead(analogPinRight);  // lee el pin de entrada   val_right  += analogRead(analogPinRight);  // lee el pin de entrada   val_right  = val_right / 4;   Si (!(abdominales(val_right - val_right_old) > Right_Channel_Deviation)) {     val_right = val_right_old;   }   Si (val_right < val_right_old)   {     rightDropTime++;     Si (rightDropTime > dropDelay)     {       val_right = val_right_old * dropFactor;       rightDropTime = 0;     }     más     {       val_right = val_right_old;     }   }   val_right_old = val_right;   Intensidad de señal = val_right - Base_Right;   Si (Intensidad de señal < 0) {     Intensidad de señal = - Intensidad de señal;   }   VU_Led_Level =  mapa(Intensidad de señal, 0, sensibilidad , 0, Level_Max_Pixels);   Si (VU_Led_Level > Level_Max_Pixels)   {     Sobrecargar = cierto;     VU_Led_Level = Level_Max_Pixels;   } más {     Sobrecargar = falso;   }   En t ColorVector = 0;   para (En t yo = LED_COUNT - Level_Max_Pixels; yo < LED_COUNT; yo++) {     tira.setPixelColor(yo, 0, 0, 0);  // Borrar el color del píxel (en RAM)   }   En t StartVector = LED_COUNT - VU_Led_Level;   para (En t yo = LED_COUNT - Level_Max_Pixels; yo < LED_COUNT; yo++) { // Por cada píxel en la tira ...     matiz = mapa(ColorVector, Level_Max_Pixels - 1, 0, 21800, 0);     ColorVector++;     Si ( yo >= StartVector)     {       Si (Sobrecargar) {         rgbcolor = tira.Color(255, 0, 0);   // Conversación de tono a RGB       } más {         rgbcolor = tira.ColorHSV(matiz, 255, BRILLO);       }       tira.setPixelColor(yo, rgbcolor);         // Establecer el color del píxel (en RAM)     }   }
}

vacío rainbowFade2White(En t Espere, En t rainbowLoops, En t whiteLoops) {   En t fadeVal = 0, fadeMax = 100;   // Hue del primer píxel ejecuta bucles completos 'rainbowLoops' a través del color   // rueda. La rueda de colores tiene un rango de 65536 pero está bien si nos damos la vuelta, así que   // solo cuenta de 0 a rainbowLoops * 65536, usando pasos de 256 para que podamos   // avanza alrededor de la rueda con un clip decente.   para (uint32_t firstPixelHue = 0; firstPixelHue < rainbowLoops * 65536;        firstPixelHue += 256) {     para (En t yo = 0; yo < tira.numPixels(); yo++) { // Por cada píxel en la tira ...       // Compense el tono del píxel en una cantidad para hacer una revolución completa de       // rueda de colores (rango de 65536) a lo largo de la tira       // (pasos de strip.numPixels ()):       uint32_t pixelHue = firstPixelHue + (yo * 65536L / tira.numPixels());       // strip.ColorHSV () puede tomar 1 o 3 argumentos: un tono (0 a 65535) o       // opcionalmente agregue saturación y valor (brillo) (cada uno de 0 a 255).       // Aquí estamos usando solo la variante de tres argumentos, aunque el       // segundo valor (saturación) es una constante 255.       tira.setPixelColor(yo, tira.gamma32(tira.ColorHSV(pixelHue, 255,                                            255 * fadeVal / fadeMax)));     }     tira.espectáculo();     retrasar(Espere);     Si (firstPixelHue < 65536) {                             // primer bucle,       Si (fadeVal < fadeMax) fadeVal++;                      // fundirse     } más Si (firstPixelHue >= ((rainbowLoops - 1) * 65536)) { // Último bucle,       Si (fadeVal > 0) fadeVal--;                            // desaparecer     } más {       fadeVal = fadeMax; // Bucle intermedio, asegúrese de que el desvanecimiento esté al máximo     }   }   para (En t k = 0; k < whiteLoops; k++) {     para (En t j = 0; j < 256; j++) { // Incrementa de 0 a 255       // Rellene toda la tira de blanco con el nivel de brillo con corrección gamma 'j':       tira.llenar(tira.Color(0, 0, 0, tira.gamma8(j)));       tira.espectáculo();     }     para (En t j = 255; j >= 0; j--) { // Disminuye 255 a 0       tira.llenar(tira.Color(0, 0, 0, tira.gamma8(j)));       tira.espectáculo();     }   }
}

 

Es ist beim Betrieb zu beachten, das während des Einschaltens des VU Meters und dem Abspielen des Intros die virtuelle Nulllinie eingelesen wird. Damit diese Kalibrierung korrekt ablaufen kann, ist es wichtig, während der Einschaltphase noch kein Audio Signal anzulegen. La primera vez que se inició la animación se inició, y se celebró la señal analógica.

Ich wünsche viel Spaß beim Nachbauen bis zum nächsten Mal

 

 

Für arduinoProjekte für fortgeschrittene

2 comentarios

Tobias

Tobias

Hallo Niko,
Die Polung der Elkos bei Wechselspannung ist immer so eine Sache der Perspektive ;)
Dennoch ist die Polung hier Richtig, da der Bezug zur Masse des Audiosignals !über den 10 KOhm Wiederstand hergestellt wird.
Viele Grüße

Niko

Niko

Hallo Tobias,

ich will ja nicht lästig sein, aber bitte noch einmal die Polung der Elkos prüfen. Ich denke, die sollten andersrum gesteckt werden. Minus in Richtung Audiobuchse.

Schöne Grüße
und vielen Dank für die vielen Ideen und Vorschläge in deinem Blog!

Deja un comentario

Todos los comentarios son moderados antes de ser publicados