/*
Obtener el código Arduino para un ESP32 Dev module, que grafique en una pantalla
oled: SSd1306, el valor: mínimo -80dB y máximo 0dB en pasos de 1 dB y obtenido
de un Rotary encoder KY040 en dB
* Proyecto: Gráfico de dB con Encoder Rotativo en ESP32 y OLED SSD1306
* Descripción: Lee un encoder rotativo KY-040 y mapea su valor a un
* rango de -80 dB a 0 dB. Muestra el valor numérico y una
* barra gráfica en una pantalla OLED.
*
* Hardware:
* - ESP32 Dev Module
* - Pantalla OLED SSD1306 I2C (128x64)
* - Encoder Rotativo KY-040
*
* Conexiones:
* - OLED VCC -> 3.3V
* - OLED GND -> GND
* - OLED SCL -> GPIO 22
* - OLED SDA -> GPIO 21
* - KY-040 VCC -> 3.3V
* - KY-040 GND -> GND
* - KY-040 CLK -> GPIO 19
* - KY-040 DT -> GPIO 18
*/
/*
// Librerías para la pantalla OLED
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
// Librería para el Encoder Rotativo en ESP32
#include <ESP32Encoder.h>
// --- Configuración de la Pantalla ---
#define SCREEN_WIDTH 128 // Ancho en píxeles
#define SCREEN_HEIGHT 64 // Alto en píxeles
#define OLED_RESET -1 // Pin de Reset (-1 si se comparte con el ESP32)
#define SCREEN_ADDRESS 0x3C // Dirección I2C, puede ser 0x3D en algunos modelos
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
// --- Configuración del Encoder ---
#define Vol_Enc_CLK_PIN 19
#define Vol_Enc_DT_PIN 18
ESP32Encoder encoder;
// --- Rango de Decibelios (dB) ---
const int DB_MIN = -80;
const int DB_MAX = 0;
// Variables para controlar el estado
long encoderCount = 0;
long lastEncoderCount = -1; // Usamos -1 para forzar la primera actualización
int currentDB = 0;
void setup() {
Serial.begin(115200); // Inicia el monitor serie para depuración
// --- Inicialización de la pantalla OLED ---
if(!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
Serial.println(F("Fallo al iniciar SSD1306"));
for(;;); // Bucle infinito si falla
}
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
display.setCursor(10, 28);
display.println("Iniciando...");
display.display();
delay(1000);
// --- Inicialización del Encoder ---
// Asociamos los pines al objeto encoder
// Usamos attachHalfQuad para que cada "clic" del encoder cuente como 1 paso
encoder.attachHalfQuad(Vol_Enc_DT_PIN, Vol_Enc_CLK_PIN);
// Establecemos el rango de conteo del encoder.
// El rango es de 0 a 80 (81 pasos en total, incluyendo el -80 y el 0).
encoder.setCount(0); // El valor inicial será 0, que mapearemos a -80 dB
}
void loop() {
// Obtener el conteo actual del encoder
encoderCount = encoder.getCount();
// Limitamos el contador para que no exceda nuestro rango de 81 pasos (de 0 a 80)
if (encoderCount > (DB_MAX - DB_MIN)) {
encoderCount = (DB_MAX - DB_MIN);
encoder.setCount(encoderCount);
}
if (encoderCount < 0) {
encoderCount = 0;
encoder.setCount(encoderCount);
}
// --- Actualizar la pantalla SOLO si el valor ha cambiado ---
// Esto evita parpadeos (flickering) y hace el sistema más eficiente.
if (encoderCount != lastEncoderCount) {
// Mapeamos el conteo del encoder (0 a 80) al rango de dB (-80 a 0)
currentDB = map(encoderCount, 0, (DB_MAX - DB_MIN), DB_MIN, DB_MAX);
// Actualizamos el último valor conocido
lastEncoderCount = encoderCount;
// Imprimimos el valor en el monitor serie (útil para depurar)
Serial.print("Encoder: ");
Serial.print(encoderCount);
Serial.print(" -> dB: ");
Serial.println(currentDB);
// --- Dibujar en la pantalla OLED ---
display.clearDisplay(); // Limpiamos el buffer
// 1. Dibuja el valor numérico en dB
display.setTextSize(2); // Tamaño de texto grande
display.setTextColor(SSD1306_WHITE);
display.setCursor(24, 2); // Posición (x, y)
display.print("VOLUMEN");
display.setCursor(28, 20); // Posición (x, y)
display.print(currentDB);
display.print(" dB");
// 2. Dibuja la barra de progreso/gráfico
// Mapeamos el valor de dB (-80 a 0) al ancho de la pantalla (0 a 128 píxeles)
int barWidth = map(currentDB, DB_MIN, DB_MAX, 0, SCREEN_WIDTH);
// Dibuja el contorno de la barra (para saber el máximo)
display.drawRect(0, 40, SCREEN_WIDTH, 16, SSD1306_WHITE);
// Dibuja el relleno de la barra, representando el valor actual
display.fillRect(0, 40, barWidth, 16, SSD1306_WHITE);
// 3. Muestra todo lo dibujado en la pantalla
display.display();
}
// Pequeña pausa para no saturar el bucle.
delay(50);
}
*/
/* * Proyecto: Mezclador Básico con 6 Encoders en ESP32 y OLED SSD1306
* Descripción: Lee 6 encoders rotativos (Volumen, Gain, High, Mid-High, Mid-Low, Low)
* y muestra en una pantalla OLED el parámetro que se está ajustando en tiempo real.
* Cada parámetro tiene su propio rango de dB y una barra gráfica.
*
* Hardware:
* - ESP32 Dev Module
* - Pantalla OLED SSD1306 I2C (128x64)
* - 6x Encoder Rotativo KY-040
*
* Conexiones (Ejemplo - ¡Puedes cambiarlos!):
* - OLED VCC -> 3.3V
* - OLED GND -> GND
* - OLED SCL -> GPIO 22
* - OLED SDA -> GPIO 21
* --- Encoders ---
* - Todos los VCC -> 3.3V
* - Todos los GND -> GND
* - VOL CLK -> GPIO 19 | VOL DT -> GPIO 18
* - GAIN CLK-> GPIO 17 | GAIN DT -> GPIO 16
* - HIGH CLK-> GPIO 5 | HIGH DT -> GPIO 4
* - MHIGHCLK-> GPIO 2 | MHIGH DT-> GPIO 15
* - MLOW CLK-> GPIO 25 | MLOW DT -> GPIO 26
* - LOW CLK -> GPIO 27 | LOW DT -> GPIO 33
*/
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <ESP32Encoder.h>
// --- Configuración de la Pantalla ---
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1
#define SCREEN_ADDRESS 0x3C
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
// --- Configuración de Pines de Encoders ---
// Volumen
#define VOL_CLK_PIN 19
#define VOL_DT_PIN 18
// Ganancia
#define GAIN_CLK_PIN 17
#define GAIN_DT_PIN 16
// Agudos
#define HIGH_CLK_PIN 5
#define HIGH_DT_PIN 4
// Medios-Agudos
#define MID_HIGH_CLK_PIN 2
#define MID_HIGH_DT_PIN 15
// Medios-Graves
#define MID_LOW_CLK_PIN 25
#define MID_LOW_DT_PIN 26
// Graves
#define LOW_CLK_PIN 27
#define LOW_DT_PIN 33
// --- Rangos de Decibelios (dB) ---
const int VOL_MIN = -80, VOL_MAX = 0;
const int GAIN_MIN = -10, GAIN_MAX = 40;
const int EQ_MIN = -15, EQ_MAX = 15; // Rango para HIGH, MIDs y LOW
// --- Objetos Encoder ---
ESP32Encoder encoderVol;
ESP32Encoder encoderGain;
ESP32Encoder encoderHigh;
ESP32Encoder encoderMidHigh;
ESP32Encoder encoderMidLow;
ESP32Encoder encoderLow;
// --- Variables de estado para cada parámetro ---
long volCount = 0, lastVolCount = -1;
int currentVolDB = 0;
long gainCount = 0, lastGainCount = -1;
int currentGainDB = 0;
long highCount = 0, lastHighCount = -1;
int currentHighDB = 0;
long midHighCount = 0, lastMidHighCount = -1;
int currentMidHighDB = 0;
long midLowCount = 0, lastMidLowCount = -1;
int currentMidLowDB = 0;
long lowCount = 0, lastLowCount = -1;
int currentLowDB = 0;
void setup() {
Serial.begin(115200);
// --- Inicialización de la pantalla OLED ---
if(!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
Serial.println(F("Fallo al iniciar SSD1306"));
for(;;);
}
display.clearDisplay();
display.setTextSize(2);
display.setTextColor(SSD1306_WHITE);
display.setCursor(15, 24);
display.println("PATRO DJ");
display.display();
delay(1000);
// Volumen: Inicia en -80 dB (silencio)
encoderVol.attachHalfQuad(VOL_DT_PIN, VOL_CLK_PIN);
encoderVol.setCount(0); // El contador en 0 se mapea a -80 dB
//delay(200);
// Ganancia: Inicia en 0 dB
encoderGain.attachHalfQuad(GAIN_DT_PIN, GAIN_CLK_PIN);
encoderGain.setCount(GAIN_MAX - 30); // El contador se ajusta para que el valor inicial sea 0 dB
//delay(200);
// Agudos (High): Inicia en 0 dB
encoderHigh.attachHalfQuad(HIGH_DT_PIN, HIGH_CLK_PIN);
encoderHigh.setCount(EQ_MAX - 0);
//delay(200);
// Medios-Agudos (Mid High): Inicia en 0 dB
encoderMidHigh.attachHalfQuad(MID_HIGH_DT_PIN, MID_HIGH_CLK_PIN);
encoderMidHigh.setCount(EQ_MAX - 0);
//delay(200);
// Medios-Graves (Mid Low): Inicia en 0 dB
encoderMidLow.attachHalfQuad(MID_LOW_DT_PIN, MID_LOW_CLK_PIN);
encoderMidLow.setCount(EQ_MAX - 0);
//delay(200);
// Graves (Low): Inicia en 0 dB
encoderLow.attachHalfQuad(LOW_DT_PIN, LOW_CLK_PIN);
encoderLow.setCount(EQ_MAX - 0);
//delay(200);
// Forzar la primera actualización para mostrar el volumen al inicio
actualizarPantalla("VOLUMEN", map(encoderVol.getCount(), 0, (VOL_MAX - VOL_MIN), VOL_MIN, VOL_MAX), VOL_MIN, VOL_MAX);
}
// =================================================================
// FUNCIÓN LOOP
// =================================================================
void loop() {
// --- Leer y procesar cada encoder por separado ---
// 6. Encoder de GAIN
gainCount = encoderGain.getCount();
if (gainCount != lastGainCount) {
if (gainCount > (GAIN_MAX - GAIN_MIN)) { gainCount = (GAIN_MAX - GAIN_MIN); encoderGain.setCount(gainCount); }
if (gainCount < 0) { gainCount = 0; encoderGain.setCount(gainCount); }
currentGainDB = map(gainCount, 0, (GAIN_MAX - GAIN_MIN), GAIN_MIN, GAIN_MAX);
lastGainCount = gainCount;
Serial.printf("GAIN: %d dB\n", currentGainDB);
actualizarPantalla("GAIN", currentGainDB, GAIN_MIN, GAIN_MAX);
}
// 5. Encoder de LOW
lowCount = encoderLow.getCount();
if (lowCount != lastLowCount) {
if (lowCount > (EQ_MAX - EQ_MIN)) { lowCount = (EQ_MAX - EQ_MIN); encoderLow.setCount(lowCount); }
if (lowCount < 0) { lowCount = 0; encoderLow.setCount(lowCount); }
currentLowDB = map(lowCount, 0, (EQ_MAX - EQ_MIN), EQ_MIN, EQ_MAX);
lastLowCount = lowCount;
Serial.printf("LOW: %d dB\n", currentLowDB);
actualizarPantalla("LOW", currentLowDB, EQ_MIN, EQ_MAX);
}
// 4. Encoder de MID LOW
midLowCount = encoderMidLow.getCount();
if (midLowCount != lastMidLowCount) {
if (midLowCount > (EQ_MAX - EQ_MIN)) { midLowCount = (EQ_MAX - EQ_MIN); encoderMidLow.setCount(midLowCount); }
if (midLowCount < 0) { midLowCount = 0; encoderMidLow.setCount(midLowCount); }
currentMidLowDB = map(midLowCount, 0, (EQ_MAX - EQ_MIN), EQ_MIN, EQ_MAX);
lastMidLowCount = midLowCount;
Serial.printf("MID LOW: %d dB\n", currentMidLowDB);
actualizarPantalla("MID LOW", currentMidLowDB, EQ_MIN, EQ_MAX);
}
// 3. Encoder de MID HIGH
midHighCount = encoderMidHigh.getCount();
if (midHighCount != lastMidHighCount) {
if (midHighCount > (EQ_MAX - EQ_MIN)) { midHighCount = (EQ_MAX - EQ_MIN); encoderMidHigh.setCount(midHighCount); }
if (midHighCount < 0) { midHighCount = 0; encoderMidHigh.setCount(midHighCount); }
currentMidHighDB = map(midHighCount, 0, (EQ_MAX - EQ_MIN), EQ_MIN, EQ_MAX);
lastMidHighCount = midHighCount;
Serial.printf("MID HIGH: %d dB\n", currentMidHighDB);
actualizarPantalla("MID HIGH", currentMidHighDB, EQ_MIN, EQ_MAX);
}
// 2. Encoder de HIGH
highCount = encoderHigh.getCount();
if (highCount != lastHighCount) {
if (highCount > (EQ_MAX - EQ_MIN)) { highCount = (EQ_MAX - EQ_MIN); encoderHigh.setCount(highCount); }
if (highCount < 0) { highCount = 0; encoderHigh.setCount(highCount); }
currentHighDB = map(highCount, 0, (EQ_MAX - EQ_MIN), EQ_MIN, EQ_MAX);
lastHighCount = highCount;
Serial.printf("HIGH: %d dB\n", currentHighDB);
actualizarPantalla("HIGH", currentHighDB, EQ_MIN, EQ_MAX);
}
// 1. Encoder de VOLUMEN
volCount = encoderVol.getCount();
if (volCount != lastVolCount) {
if (volCount > (VOL_MAX - VOL_MIN)) { volCount = (VOL_MAX - VOL_MIN); encoderVol.setCount(volCount); }
if (volCount < 0) { volCount = 0; encoderVol.setCount(volCount); }
currentVolDB = map(volCount, 0, (VOL_MAX - VOL_MIN), VOL_MIN, VOL_MAX);
lastVolCount = volCount;
Serial.printf("VOLUMEN: %d dB\n", currentVolDB);
actualizarPantalla("VOLUMEN", currentVolDB, VOL_MIN, VOL_MAX);
}
delay(20); // Pequeña pausa para no saturar el bucle
}
// =================================================================
// FUNCIÓN PARA ACTUALIZAR LA PANTALLA
// Dibuja el nombre del parámetro, su valor y la barra gráfica.
// Esta función se llama solo cuando un valor cambia.
// =================================================================
void actualizarPantalla(const char *paramName, int currentValue, int minValue, int maxValue) {
display.clearDisplay(); // Limpiamos el buffer
// 1. Dibuja el nombre y el valor numérico
display.setTextSize(2);
display.setTextColor(SSD1306_WHITE);
// Centrar el nombre del parámetro
int16_t x1, y1;
uint16_t w, h;
display.getTextBounds(paramName, 0, 0, &x1, &y1, &w, &h);
display.setCursor((SCREEN_WIDTH - w) / 2, 2);
display.println(paramName);
// Formatear y centrar el valor en dB
char dbStr[10];
// Añadir el signo '+' si el valor es positivo o cero para consistencia
sprintf(dbStr, "%+d dB", currentValue);
display.getTextBounds(dbStr, 0, 0, &x1, &y1, &w, &h);
display.setCursor((SCREEN_WIDTH - w) / 2, 20);
display.print(dbStr);
// 2. Dibuja la barra de progreso
// Mapeamos el valor actual al ancho de la pantalla (0 a 128 píxeles)
int barWidth = map(currentValue, minValue, maxValue, 0, SCREEN_WIDTH);
// Dibuja el contorno de la barra
display.drawRect(0, 42, SCREEN_WIDTH, 16, SSD1306_WHITE);
// Si es un control Bipolar (EQ o Gain), dibujamos la barra desde el centro
if (minValue < 0 && maxValue > 0) {
int zeroPoint = map(0, minValue, maxValue, 0, SCREEN_WIDTH); // Posición del 0 dB
display.drawFastVLine(zeroPoint, 40, 20, SSD1306_WHITE); // Línea central en 0 dB
if (barWidth > zeroPoint) { // Valor positivo
display.fillRect(zeroPoint, 42, barWidth - zeroPoint, 16, SSD1306_WHITE);
} else { // Valor negativo
display.fillRect(barWidth, 42, zeroPoint - barWidth, 16, SSD1306_WHITE);
}
} else { // Si es un control Unipolar (como el volumen)
display.fillRect(0, 42, barWidth, 16, SSD1306_WHITE);
}
// 3. Muestra todo lo dibujado en la pantalla
display.display();
}
/*
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <ESP32Encoder.h>
// --- Configuración de la Pantalla ---
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1
#define SCREEN_ADDRESS 0x3C
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
// --- Configuración de Pines de Encoders ---
// Volumen
#define VOL_CLK_PIN 19
#define VOL_DT_PIN 18
// Ganancia
#define GAIN_CLK_PIN 17
#define GAIN_DT_PIN 16
// Agudos
#define HIGH_CLK_PIN 5
#define HIGH_DT_PIN 4
// Medios-Agudos
#define MID_HIGH_CLK_PIN 2
#define MID_HIGH_DT_PIN 15
// Medios-Graves
#define MID_LOW_CLK_PIN 25
#define MID_LOW_DT_PIN 26
// Graves
#define LOW_CLK_PIN 27
#define LOW_DT_PIN 33
// --- Rangos de Decibelios (dB) ---
const int VOL_MIN = -80, VOL_MAX = 0;
const int GAIN_MIN = -10, GAIN_MAX = 40;
const int EQ_MIN = -15, EQ_MAX = 15; // Rango para HIGH, MIDs y LOW
// --- Objetos Encoder ---
ESP32Encoder encoderVol;
ESP32Encoder encoderGain;
ESP32Encoder encoderHigh;
ESP32Encoder encoderMidHigh;
ESP32Encoder encoderMidLow;
ESP32Encoder encoderLow;
// --- Variables de estado para cada parámetro (ahora directamente en dB) ---
int currentVolDB = 0;
int currentGainDB = 0;
int currentHighDB = 0;
int currentMidHighDB = 0;
int currentMidLowDB = 0;
int currentLowDB = 0;
// =================================================================
// FUNCIÓN SETUP
// =================================================================
void setup() {
Serial.begin(115200);
// --- Inicialización de la pantalla OLED ---
if(!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
Serial.println(F("Fallo al iniciar SSD1306"));
for(;;);
}
display.clearDisplay();
display.setTextSize(2);
display.setTextColor(SSD1306_WHITE);
display.setCursor(15, 24);
display.println("PATRO DJ");
display.display();
delay(1500);
// Habilitar interrupciones para los encoders en el ESP32
//ESP32Encoder::useInternalWeakPullResistors=UP;
// --- Inicialización de los Encoders ---
// Se asocian los pines y se establece un valor inicial que es el valor en dB.
// Volumen: Inicia en -80 dB (silencio)
encoderVol.attachHalfQuad(VOL_DT_PIN, VOL_CLK_PIN);
encoderVol.setCount(VOL_MIN); // <-- CAMBIO: Inicia en el valor mínimo de dB
currentVolDB = VOL_MIN;
// Ganancia: Inicia en 0 dB
encoderGain.attachHalfQuad(GAIN_DT_PIN, GAIN_CLK_PIN);
encoderGain.setCount(0); // <-- CAMBIO: Inicia en 0 dB
currentGainDB = 0;
// Agudos (High): Inicia en 0 dB
encoderHigh.attachHalfQuad(HIGH_DT_PIN, HIGH_CLK_PIN);
encoderHigh.setCount(0); // <-- CAMBIO: Inicia en 0 dB
currentHighDB = 0;
// Medios-Agudos (Mid High): Inicia en 0 dB
encoderMidHigh.attachHalfQuad(MID_HIGH_DT_PIN, MID_HIGH_CLK_PIN);
encoderMidHigh.setCount(0); // <-- CAMBIO: Inicia en 0 dB
currentMidHighDB = 0;
// Medios-Graves (Mid Low): Inicia en 0 dB
encoderMidLow.attachHalfQuad(MID_LOW_DT_PIN, MID_LOW_CLK_PIN);
encoderMidLow.setCount(0); // <-- CAMBIO: Inicia en 0 dB
currentMidLowDB = 0;
// Graves (Low): Inicia en 0 dB
encoderLow.attachHalfQuad(LOW_DT_PIN, LOW_CLK_PIN);
encoderLow.setCount(0); // <-- CAMBIO: Inicia en 0 dB
currentLowDB = 0;
// Forzar la primera actualización para mostrar el volumen al inicio
actualizarPantalla("VOLUMEN", currentVolDB, VOL_MIN, VOL_MAX);
}
// =================================================================
// FUNCIÓN LOOP
// =================================================================
void loop() {
// --- Leer y procesar cada encoder por separado ---
// La lógica es la misma para todos: leer, limitar y actualizar si hay cambio.
// 1. Encoder de VOLUMEN
long newVol = encoderVol.getCount();
if (newVol > VOL_MAX) { newVol = VOL_MAX; encoderVol.setCount(newVol); }
if (newVol < VOL_MIN) { newVol = VOL_MIN; encoderVol.setCount(newVol); }
if (newVol != currentVolDB) {
currentVolDB = newVol;
Serial.printf("VOLUMEN: %d dB\n", currentVolDB);
actualizarPantalla("VOLUMEN", currentVolDB, VOL_MIN, VOL_MAX);
}
// 2. Encoder de GAIN
long newGain = encoderGain.getCount();
if (newGain > GAIN_MAX) { newGain = GAIN_MAX; encoderGain.setCount(newGain); }
if (newGain < GAIN_MIN) { newGain = GAIN_MIN; encoderGain.setCount(newGain); }
if (newGain != currentGainDB) {
currentGainDB = newGain;
Serial.printf("GAIN: %d dB\n", currentGainDB);
actualizarPantalla("GAIN", currentGainDB, GAIN_MIN, GAIN_MAX);
}
// 3. Encoder de HIGH
long newHigh = encoderHigh.getCount();
if (newHigh > EQ_MAX) { newHigh = EQ_MAX; encoderHigh.setCount(newHigh); }
if (newHigh < EQ_MIN) { newHigh = EQ_MIN; encoderHigh.setCount(newHigh); }
if (newHigh != currentHighDB) {
currentHighDB = newHigh;
Serial.printf("HIGH: %d dB\n", currentHighDB);
actualizarPantalla("HIGH", currentHighDB, EQ_MIN, EQ_MAX);
}
// 4. Encoder de MID HIGH
long newMidHigh = encoderMidHigh.getCount();
if (newMidHigh > EQ_MAX) { newMidHigh = EQ_MAX; encoderMidHigh.setCount(newMidHigh); }
if (newMidHigh < EQ_MIN) { newMidHigh = EQ_MIN; encoderMidHigh.setCount(newMidHigh); }
if (newMidHigh != currentMidHighDB) {
currentMidHighDB = newMidHigh;
Serial.printf("MID HIGH: %d dB\n", currentMidHighDB);
actualizarPantalla("MID HIGH", currentMidHighDB, EQ_MIN, EQ_MAX);
}
// 5. Encoder de MID LOW
long newMidLow = encoderMidLow.getCount();
if (newMidLow > EQ_MAX) { newMidLow = EQ_MAX; encoderMidLow.setCount(newMidLow); }
if (newMidLow < EQ_MIN) { newMidLow = EQ_MIN; encoderMidLow.setCount(newMidLow); }
if (newMidLow != currentMidLowDB) {
currentMidLowDB = newMidLow;
Serial.printf("MID LOW: %d dB\n", currentMidLowDB);
actualizarPantalla("MID LOW", currentMidLowDB, EQ_MIN, EQ_MAX);
}
// 6. Encoder de LOW
long newLow = encoderLow.getCount();
if (newLow > EQ_MAX) { newLow = EQ_MAX; encoderLow.setCount(newLow); }
if (newLow < EQ_MIN) { newLow = EQ_MIN; encoderLow.setCount(newLow); }
if (newLow != currentLowDB) {
currentLowDB = newLow;
Serial.printf("LOW: %d dB\n", currentLowDB);
actualizarPantalla("LOW", currentLowDB, EQ_MIN, EQ_MAX);
}
delay(20); // Pequeña pausa para no saturar el bucle
}
// =================================================================
// FUNCIÓN PARA ACTUALIZAR LA PANTALLA
// Dibuja el nombre del parámetro, su valor y la barra gráfica.
// Esta función se llama solo cuando un valor cambia.
// (Esta función no necesita cambios)
// =================================================================
void actualizarPantalla(const char *paramName, int currentValue, int minValue, int maxValue) {
display.clearDisplay(); // Limpiamos el buffer
// 1. Dibuja el nombre y el valor numérico
display.setTextSize(2);
display.setTextColor(SSD1306_WHITE);
// Centrar el nombre del parámetro
int16_t x1, y1;
uint16_t w, h;
display.getTextBounds(paramName, 0, 0, &x1, &y1, &w, &h);
display.setCursor((SCREEN_WIDTH - w) / 2, 2);
display.println(paramName);
// Formatear y centrar el valor en dB
char dbStr[10];
// Añadir el signo '+' si el valor es positivo o cero para consistencia
sprintf(dbStr, "%+d dB", currentValue);
display.getTextBounds(dbStr, 0, 0, &x1, &y1, &w, &h);
display.setCursor((SCREEN_WIDTH - w) / 2, 20);
display.print(dbStr);
// 2. Dibuja la barra de progreso
// Mapeamos el valor actual al ancho de la pantalla (0 a 128 píxeles)
int barWidth = map(currentValue, minValue, maxValue, 0, SCREEN_WIDTH);
// Dibuja el contorno de la barra
display.drawRect(0, 42, SCREEN_WIDTH, 16, SSD1306_WHITE);
// Si es un control Bipolar (EQ o Gain), dibujamos la barra desde el centro
if (minValue < 0 && maxValue > 0) {
int zeroPoint = map(0, minValue, maxValue, 0, SCREEN_WIDTH); // Posición del 0 dB
display.drawFastVLine(zeroPoint, 40, 20, SSD1306_WHITE); // Línea central en 0 dB
if (barWidth > zeroPoint) { // Valor positivo
display.fillRect(zeroPoint, 42, barWidth - zeroPoint, 16, SSD1306_WHITE);
} else { // Valor negativo
display.fillRect(barWidth, 42, zeroPoint - barWidth, 16, SSD1306_WHITE);
}
} else { // Si es un control Unipolar (como el volumen)
display.fillRect(0, 42, barWidth, 16, SSD1306_WHITE);
}
// 3. Muestra todo lo dibujado en la pantalla
display.display();
}
*/