Compteur STÉRÉO VU

Bonjour et bienvenue dans une nouvelle partie de la série "VU-Meter".

La grande réponse à la première partie de la série est écrasante! Nous allons bien sûr relever le défi et dans la prochaine étape, nous ajouterons un autre canal à notre VU-mètre. Le deuxième canal est affiché négativement sur le panneau U64. Nous avons déjà un excellent VU-mètre stéréo avec un effet contrarotatif impressionnant!

Bien sûr, il y a aussi quelques extensions et optimisations matérielles à bord. Comme je l'ai écrit dans la première partie, le panneau U64 est assez gourmand en énergie. Par conséquent, notre premier changement de matériel est un échange du module d'alimentation de la maquette pour une alimentation stable de 5 volts / 2,6 A. Nous pouvons maintenant augmenter la luminosité des LED du panneau de 39% à 100% sans aucun problème d'électricité. L'affichage fait un peu plus. Cependant, le code limite initialement cette luminosité à 60% de luminosité. Cette limitation diminuera alors dans la prochaine partie de la série sans changer l'alimentation.

Le module d'alimentation de la planche à pain n'est bien sûr pas un déchet, mais peut être utilisé pour toutes les autres superstructures suivi  des projets tout aussi passionnants peuvent continuer à être utilisés. Les autres pièces supplémentaires, à savoir les deux 680 ohms Résistances  et les deux diodes Zener 5,1 volts remplissent des fonctions de protection de circuit pour l'Arduino. Il en résulte la liste partielle suivante pour la partie d'aujourd'hui de la série:

 

  • 1x Arduino Nano (avec FTDI)
  • 1x Panneau LED U64
  • 2x 10 KOhm Résistances 1%
  • 2x 680 ohms Résistances 5%
  • 1x alimentation 5 V, min 2,6 A
  • 1 condensateur électrolytique 10 uF 64 volts
  • 1x connecteur jack stéréo prise 3,5 mm
  • 2x diode zener 5,1 volts

 

Nous câblons les composants au schéma de circuit suivant:

Schéma du circuit Fritzing

 

Après avoir complètement construit ou mis à jour le circuit, nous pouvons maintenant télécharger le code mis à jour et développé sur notre Arduino:

 

#include <Adafruit_NeoPixel.h>

// Quelle broche de l'Arduino est connectée aux NeoPixels?
// Sur un bijou ou Gemma, nous suggérons de changer cela en 1:
#define LED_PIN     13
// Combien de NeoPixels sont attachés à l'Arduino?
#define LED_COUNT  64

// Déclarez notre objet bande NeoPixel:
Adafruit_NeoPixel bande(LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800);
// Argument 1 = Nombre de pixels dans la bande NeoPixel
// argument 2 = numéro de broche Arduino (la plupart sont valides)
// Argument 3 = drapeaux de type pixel, additionnez au besoin:
// NEO_KHZ800 800 KHz bitstream (la plupart des produits NeoPixel avec LED WS2812)
// NEO_KHZ400 400 KHz (pixels FLORA classiques 'v1' (pas v2), pilotes WS2811)
// Les pixels NEO_GRB sont câblés pour le flux binaire GRB (la plupart des produits NeoPixel)
// Les pixels NEO_RGB sont câblés pour le flux binaire RVB (v1 pixels FLORA, pas v2)
// Les pixels NEO_RGBW sont câblés pour le flux binaire RGBW (produits NeoPixel RGBW)

#define analogPinLeft A5 // Canal audio gauche, connecté à la broche analogique A5
#define analogPinRight A4 // Canal audio droit, connecté à la broche analogique A4
#define Left_Channel_Deviation  5
#define Right_Channel_Deviation 5

int val_left_old = 0;  // variable pour stocker la valeur lue depuis le canal gauche
int Base_Left = 0;   // 0 base
int val_right_old = 0;  // variable pour stocker la valeur lue depuis le canal gauche
int Base_Right = 0;   // 0 base

int leftDropTime, rightDropTime;
int dropDelay = 4;                                        // attente avant de laisser tomber les leds
// Luminosité NeoPixel, 0 (min) à 255 (max)
octet LUMINOSITÉ = 153;  // 60% de luminosité

flotter dropFactor = .98;

nul configuration()
{   bande.commencer();           // INITIALIZE NeoPixel strip object (REQUIS)   bande.montrer();            // Désactiver tous les pixels dès que possible   bande.setBrightness(LUMINOSITÉ); // Réglez la LUMINOSITÉ à environ 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;   Base_Right = analogRead(analogPinRight);   Base_Right += analogRead(analogPinRight);   Base_Right += analogRead(analogPinRight);   Base_Right += analogRead(analogPinRight);   Base_Right = Base_Right / 4;   En série.commencer(9600);   colorWipe(bande.Couleur(255, 0, 0), 5); // Rouge   colorWipe(bande.Couleur(255, 255, 0), 5); // Jaune   colorWipe(bande.Couleur(0, 255, 0), 5); // Vert   rainbowFade2White(1, 1, 1);
}

néant boucle()
{   Left_VU_Meter(LED_COUNT / 2, 512);   Right_VU_Meter(LED_COUNT / 2, 511);   bande.spectacle();   // Mettre à jour la bande pour correspondre
}





néant Left_VU_Meter(octet Level_Max_Pixels, int sensibilité)
{   int val_left = 0;   bool Surcharge = faux;   uint32_t rgbcolor;   uint32_t teinte;   int Force du signal = 0;   octet VU_Led_Level = 0;   val_left = analogRead(analogPinLeft);  // lire la broche d'entrée   val_left += analogRead(analogPinLeft);  // lire la broche d'entrée   val_left += analogRead(analogPinLeft);  // lire la broche d'entrée   val_left += analogRead(analogPinLeft);  // lire la broche d'entrée   val_left = val_left / 4;   si (!(abdos(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;     }     autre     {       val_left = val_left_old;     }   }   val_left_old = val_left;   Force du signal = val_left - Base_Left;   si (Force du signal < 0) {     Force du signal = - Force du signal;   }   VU_Led_Level =  carte(Force du signal, 0, sensibilité , 0, Level_Max_Pixels);   si (VU_Led_Level > Level_Max_Pixels)   {     Surcharge = vrai;     VU_Led_Level = Level_Max_Pixels;   } autre {     Surcharge = faux;   }   pour (int je = 0; je < Level_Max_Pixels; je++) {     bande.setPixelColor(je, 0, 0, 0);  // Effacer la couleur du pixel (en RAM)   }   pour (int je = 0; je < VU_Led_Level; je++) { // Pour chaque pixel de la bande ...     teinte = carte(je, Level_Max_Pixels - 1, 0, 0, 21800);     si (Surcharge) {       rgbcolor = bande.Couleur(255, 0, 0);   // Conversation de teinte à RVB     } autre {       rgbcolor = bande.CouleurHSV(teinte, 255, LUMINOSITÉ);     }     bande.setPixelColor(je, rgbcolor);         // Définit la couleur du pixel (en RAM)   }   // strip.show (); // Mettre à jour la bande pour correspondre
}

néant colorWipe(uint32_t Couleur, int attendez) {   pour (int je = 0; je < bande.numPixels(); je++) { // Pour chaque pixel de la bande ...     bande.setPixelColor(je, Couleur);         // Définit la couleur du pixel (en RAM)     bande.spectacle();                          // Mettre à jour la bande pour correspondre     retard(attendez);                           // Pause un instant   }
}

néant Right_VU_Meter(octet Level_Max_Pixels, int sensibilité)
{   int val_right = 0;   bool Surcharge = faux;   uint32_t rgbcolor;   uint32_t teinte;   int Force du signal = 0;   octet VU_Led_Level = 0;   val_right  = analogRead(analogPinRight);  // lire la broche d'entrée   val_right  += analogRead(analogPinRight);  // lire la broche d'entrée   val_right  += analogRead(analogPinRight);  // lire la broche d'entrée   val_right  += analogRead(analogPinRight);  // lire la broche d'entrée   val_right  = val_right / 4;   si (!(abdos(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;     }     autre     {       val_right = val_right_old;     }   }   val_right_old = val_right;   Force du signal = val_right - Base_Right;   si (Force du signal < 0) {     Force du signal = - Force du signal;   }   VU_Led_Level =  carte(Force du signal, 0, sensibilité , 0, Level_Max_Pixels);   si (VU_Led_Level > Level_Max_Pixels)   {     Surcharge = vrai;     VU_Led_Level = Level_Max_Pixels;   } autre {     Surcharge = faux;   }   int ColorVector = 0;   pour (int je = LED_COUNT - Level_Max_Pixels; je < LED_COUNT; je++) {     bande.setPixelColor(je, 0, 0, 0);  // Effacer la couleur du pixel (en RAM)   }   int StartVector = LED_COUNT - VU_Led_Level;   pour (int je = LED_COUNT - Level_Max_Pixels; je < LED_COUNT; je++) { // Pour chaque pixel de la bande ...     teinte = carte(ColorVector, Level_Max_Pixels - 1, 0, 21800, 0);     ColorVector++;     si ( je >= StartVector)     {       si (Surcharge) {         rgbcolor = bande.Couleur(255, 0, 0);   // Conversation de teinte à RVB       } autre {         rgbcolor = bande.CouleurHSV(teinte, 255, LUMINOSITÉ);       }       bande.setPixelColor(je, rgbcolor);         // Définit la couleur du pixel (en RAM)     }   }
}

néant rainbowFade2White(int attendez, int arc-en-ciel, int whiteLoops) {   int fadeVal = 0, fadeMax = 100;   // La teinte du premier pixel exécute des boucles complètes 'rainbowLoops' à travers la couleur   // roue. La roue chromatique a une plage de 65536, mais ce n'est pas grave si nous retournons, donc   // il suffit de compter de 0 à rainbowLoops * 65536, en utilisant des pas de 256 pour que nous   // avance autour de la roue à un clip décent.   pour (uint32_t firstPixelHue = 0; firstPixelHue < arc-en-ciel * 65536;        firstPixelHue += 256) {     pour (int je = 0; je < bande.numPixels(); je++) { // Pour chaque pixel de la bande ...       // Décalage de la teinte des pixels d'une quantité pour effectuer une révolution complète du       // roue chromatique (gamme 65536) sur toute la longueur de la bande       // (étapes strip.numPixels ()):       uint32_t pixelHue = firstPixelHue + (je * 65536L / bande.numPixels());       // strip.ColorHSV () peut prendre 1 ou 3 arguments: une teinte (0 à 65535) ou       // ajoutez éventuellement la saturation et la valeur (luminosité) (de 0 à 255 chacune).       // Ici, nous utilisons uniquement la variante à trois arguments, bien que le       // la seconde valeur (saturation) est une constante 255.       bande.setPixelColor(je, bande.gamma32(bande.CouleurHSV(pixelHue, 255,                                            255 * fadeVal / fadeMax)));     }     bande.spectacle();     retard(attendez);     si (firstPixelHue < 65536) {                             // Première boucle,       si (fadeVal < fadeMax) fadeVal++;                      // fondu     } autre si (firstPixelHue >= ((arc-en-ciel - 1) * 65536)) { // Dernière boucle,       si (fadeVal > 0) fadeVal--;                            // disparaître     } autre {       fadeVal = fadeMax; // Boucle intermédiaire, assurez-vous que le fondu est au maximum     }   }   pour (int k = 0; k < whiteLoops; k++) {     pour (int j = 0; j < 256; j++) { // Passez de 0 à 255       // Remplissez la bande entière de blanc au niveau de luminosité corrigé gamma 'j':       bande.remplir(bande.Couleur(0, 0, 0, bande.gamma8(j)));       bande.spectacle();     }     pour (int j = 255; j >= 0; j--) { // Descendre de 255 à 0       bande.remplir(bande.Couleur(0, 0, 0, bande.gamma8(j)));       bande.spectacle();     }   }
}

 

Es ist beim Betrieb zu beachten, das während des Einschaltens des VU Meters und dem Abspielen des Intros die virtual Nulllinie eingelesen wird. Damit diese Kalibrierung korrekt ablaufen kann, ist es wichtig, während der Einschaltphase noch kein Audio Signal anzulegen. Erst wenn die Startanimationen beendet sind, kann ein Analogsignal angelegt werden.

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

 

 

Für arduinoProjekte für fortgeschrittene

2 commentaires

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!

Laisser un commentaire

Tous les commentaires sont modérés avant d'être publiés