#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
// --- Configuraciones de Hardware ---
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1
#define OLED_ADDR 0x3C
// --- Pines de entrada de Audio para ESP32 ---
#define audioInL 36 // Canal Izquierdo (ADC1_CH0)
#define audioInR 39 // Canal Derecho (ADC1_CH3)
// --- Parámetros de Muestreo ---
// Número de muestras a tomar para encontrar el pico de la señal
#define SAMPLES 256
// --- Parámetros de la Barra de Nivel ---
#define BAR_START_X 18 // Posición X inicial de la barra (deja espacio para la etiqueta 'L'/'R')
#define BAR_MAX_WIDTH 108 // Ancho máximo de la barra en píxeles
#define BAR_HEIGHT 15 // Altura de cada barra
#define BAR_Y_L 12 // Posición Y de la barra superior (Canal L)
#define BAR_Y_R 37 // Posición Y de la barra inferior (Canal R)
// --- Parámetros de los Segmentos de la Barra ---
#define SEGMENT_WIDTH 4 // Ancho de cada segmento
#define SEGMENT_GAP 2 // Espacio entre segmentos
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
void setup() {
Serial.begin(115200); // Opcional, para depuración
// Configurar los pines de audio como entrada
pinMode(audioInL, INPUT);
pinMode(audioInR, INPUT);
// Iniciar la pantalla OLED
if(!display.begin(SSD1306_SWITCHCAPVCC, OLED_ADDR)) {
Serial.println(F("Fallo al iniciar SSD1306"));
for(;;); // No continuar si falla
}
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(WHITE);
display.println("Vumetro 2-CH");
display.display();
delay(2000);
}
// Función para dibujar una barra segmentada
void drawSegmentedBar(int x_start, int y_pos, int bar_width, int bar_height) {
int total_segment_width = SEGMENT_WIDTH + SEGMENT_GAP;
int num_segments = bar_width / total_segment_width;
for (int i = 0; i < num_segments; i++) {
int segment_x = x_start + (i * total_segment_width);
display.fillRect(segment_x, y_pos, SEGMENT_WIDTH, bar_height, WHITE);
}
}
void loop() {
// --- 1. Muestreo para encontrar la amplitud pico a pico ---
unsigned int minSampleL = 4095, maxSampleL = 0;
unsigned int minSampleR = 4095, maxSampleR = 0;
for (int i = 0; i < SAMPLES; i++) {
unsigned int sampleL = analogRead(audioInL);
if (sampleL < minSampleL) minSampleL = sampleL;
if (sampleL > maxSampleL) maxSampleL = sampleL;
unsigned int sampleR = analogRead(audioInR);
if (sampleR < minSampleR) minSampleR = sampleR;
if (sampleR > maxSampleR) maxSampleR = sampleR;
}
// Calcular la amplitud pico a pico (un indicador del "volumen")
unsigned int p2p_L = maxSampleL - minSampleL;
unsigned int p2p_R = maxSampleR - minSampleR;
// --- 2. Mapear la amplitud a la longitud de la barra ---
// El rango del ADC del ESP32 es de 12 bits (0-4095)
// Mapeamos este valor al ancho máximo definido para la barra
int barWidthL = map(p2p_L, 0, 4095, 0, BAR_MAX_WIDTH);
int barWidthR = map(p2p_R, 0, 4095, 0, BAR_MAX_WIDTH);
// --- 3. Visualización en la Pantalla OLED ---
display.clearDisplay();
// Dibujar etiquetas de los canales
display.setTextSize(2);
display.setCursor(0, BAR_Y_L);
display.print("L");
display.setCursor(0, BAR_Y_R);
display.print("R");
// Dibujar el contorno de las barras (opcional, pero mejora la estética)
display.drawRect(BAR_START_X, BAR_Y_L, BAR_MAX_WIDTH, BAR_HEIGHT, WHITE);
display.drawRect(BAR_START_X, BAR_Y_R, BAR_MAX_WIDTH, BAR_HEIGHT, WHITE);
// Dibujar las barras segmentadas basadas en el nivel de la señal
drawSegmentedBar(BAR_START_X, BAR_Y_L, barWidthL, BAR_HEIGHT);
drawSegmentedBar(BAR_START_X, BAR_Y_R, barWidthR, BAR_HEIGHT);
display.display();
}