/*
Controlador DJ Básico con ESP32 y BLE-MIDI
===========================================
Este código convierte un ESP32 en un controlador DJ inalámbrico
compatible con la mayoría de software de DJ que soporta MIDI sobre Bluetooth.
Funcionalidad:
- Un botón para Play/Pause (envía mensajes MIDI Note On/Off).
- Un potenciómetro para el Crossfader (envía mensajes MIDI Control Change).
Librería necesaria:
- "BLE-MIDI" de lathoub (instalar desde el Gestor de Librerías del IDE de Arduino).
Circuito:
- Potenciómetro (pin central) -> GPIO 34
- Pulsador -> GPIO 23 y GND
Hardware Necesario
Un ESP32 Dev Kit (cualquier variante funcionará).
Un pulsador (botón).
Un potenciómetro (por ejemplo, de 10kΩ).
Una protoboard y cables de conexión (jumpers).
Software y Librerías
Arduino IDE: Asegúrate de tenerlo instalado y configurado para tu placa ESP32.
Librería BLE-MIDI:
En el Arduino IDE, ve a Herramientas > Administrar Bibliotecas....
En el buscador, escribe BLE-MIDI.
Instala la librería de lathoub.
Montaje del Circuito
Potenciómetro (Crossfader):
Pin izquierdo -> GND del ESP32.
Pin derecho -> 3V3 del ESP32.
Pin central (Wiper) -> Pin 34 del ESP32 (es un pin de solo entrada analógica, perfecto para esto)
Botón (Play/Pause):
Un pin del botón -> GND del ESP32.
El otro pin del botón -> Pin 23 del ESP32. (Usaremos la resistencia pull-up interna del ESP32).
Cómo Usarlo
Carga el Código: Con el circuito montado, conecta tu ESP32 al ordenador y sube el código desde el Arduino IDE.
Abre tu Software de DJ: Ve a la configuración de Audio/MIDI de tu programa (ej. Preferences > Controller Manager en Traktor, Setup > MIDI en Virtual DJ).
Busca Dispositivos MIDI Bluetooth: Debería haber una opción para "Añadir Dispositivo Bluetooth" o similar.
Conecta tu Controlador: Busca y selecciona el dispositivo llamado "ESP32 DJ Controller". Una vez conectado, el ESP32 debería aparecer como un controlador MIDI genérico.
Mapea los Controles:
La mayoría de los programas tienen un modo de "aprendizaje" MIDI (MIDI Learn). Actívalo.
Para el Play/Pause: Haz clic en el botón de Play en la pantalla del software y luego presiona el botón físico de tu circuito. El software debería asignar automáticamente la nota MIDI 36 a esa función.
Para el Crossfader: Haz clic en el crossfader de la pantalla y luego mueve el potenciómetro de tu circuito. El software debería asignar el CC 8 a esa función.
Sal del modo de aprendizaje y ¡listo!
Cómo Expandirlo
Este es solo el comienzo. Puedes expandir tu controlador fácilmente:
Más Botones: Añade más botones para CUE, SYNC, Hot Cues, etc. Solo necesitas asignarles un pin diferente y una nota MIDI única en el código.
Más Faders/Perillas: Añade más potenciómetros para el volumen de los canales, ecualizadores (EQs), efectos (FX), etc. Asígnales un pin analógico diferente y un número de CC único.
Encoders Rotativos (Jog Wheels): Esto es un poco más avanzado. Necesitarías encoders rotatorios y una lógica para interpretar los giros y enviar mensajes CC o Pitch Bend.
LEDs de Feedback: Puedes hacer que el ESP32 reciba mensajes MIDI del software (por ejemplo, para que un LED se encienda cuando una canción está en play) usando la función BLEMidi.setHandleNoteOn().
*/
// Incluimos la librería mágica para MIDI sobre Bluetooth Low Energy
#include <BLEMidi.h>
// --- Definición de Pines ---
const int PLAY_BUTTON_PIN = 23; // Pin para el botón de Play/Pause
const int CROSSFADER_POT_PIN = 34; // Pin para el potenciómetro del Crossfader (ADC1_CH6)
// --- Definición de Parámetros MIDI ---
// Cada control en un controlador MIDI tiene un número y un canal.
// Puedes encontrar listas de "MIDI Mapping" para tu software DJ específico.
const int MIDI_CHANNEL = 1; // Canal MIDI (1-16). El 1 es el más común.
const int PLAY_NOTE = 36; // Nota MIDI para Play (C2). Un valor común.
const int CROSSFADER_CC = 8; // Número de Control Change (CC) para el Crossfader.
// --- Variables para guardar el estado anterior ---
// Esto es para no enviar datos MIDI constantemente si no hay cambios.
int lastButtonState = HIGH; // El botón está en HIGH cuando no se presiona (INPUT_PULLUP)
int lastCrossfaderValue = -1; // Un valor inicial imposible para forzar el primer envío
// --- Función de configuración (se ejecuta una vez) ---
void setup() {
Serial.begin(115200); // Inicia el monitor serie para depuración
// Configurar los pines de entrada
pinMode(PLAY_BUTTON_PIN, INPUT_PULLUP); // Usamos la resistencia pull-up interna del ESP32
Serial.println("Inicializando Controlador DJ Bluetooth MIDI...");
// Inicia el servicio BLE-MIDI con un nombre que aparecerá en tu software de DJ
BLEMidi.begin("ESP32 DJ Controller");
Serial.println("Esperando conexión Bluetooth MIDI...");
}
// --- Función de bucle principal (se ejecuta repetidamente) ---
void loop() {
// Solo procesamos los controles si hay un dispositivo conectado
if (BLEMidi.isConnected()) {
// --- Lógica del Botón de Play/Pause ---
int currentButtonState = digitalRead(PLAY_BUTTON_PIN);
// Comprobar si el estado del botón ha cambiado (fue presionado o soltado)
if (currentButtonState != lastButtonState) {
if (currentButtonState == LOW) { // Botón presionado (LOW por el PULLUP)
Serial.println("Botón Play PRESIONADO - Enviando Note On");
// Enviamos un mensaje "Note On"
// Formato: (nota, velocidad, canal)
// La velocidad (velocity) 127 es la máxima (como presionar una tecla con fuerza)
BLEMidi.sendNoteOn(PLAY_NOTE, 127, MIDI_CHANNEL);
} else { // Botón soltado
Serial.println("Botón Play SOLTADO - Enviando Note Off");
// Enviamos un mensaje "Note Off"
// Formato: (nota, velocidad, canal)
// La velocidad 0 indica que la nota se ha soltado
BLEMidi.sendNoteOff(PLAY_NOTE, 0, MIDI_CHANNEL);
}
lastButtonState = currentButtonState; // Actualizamos el último estado
delay(50); // Pequeño delay para evitar "rebotes" (debounce)
}
// --- Lógica del Potenciómetro (Crossfader) ---
int potValue = analogRead(CROSSFADER_POT_PIN); // Leer el valor analógico (0-4095 en ESP32)
// Mapeamos el valor del potenciómetro (0-4095) al rango MIDI (0-127)
int midiValue = map(potValue, 0, 4095, 0, 127);
// Comprobar si el valor del fader ha cambiado para no saturar la conexión
if (midiValue != lastCrossfaderValue) {
Serial.print("Crossfader movido a: ");
Serial.println(midiValue);
// Enviamos un mensaje "Control Change" (CC)
// Formato: (número de control, valor, canal)
BLEMidi.sendControlChange(CROSSFADER_CC, midiValue, MIDI_CHANNEL);
lastCrossfaderValue = midiValue; // Actualizamos el último valor
}
}
// Pequeña pausa para dar estabilidad al sistema
delay(10);
}