Introduction: Controlador MIDI Theremin Ultrasónico
En este proyecto, hemos creado un controlador MIDI Theremin utilizando Arduino y sensores ultrasónicos. Inspirados en el icónico instrumento electrónico de Leon Theremin, hemos combinado la creatividad musical con la innovación tecnológica para ofrecer una experiencia única.
Nuestro dispositivo utiliza sensores ultrasónicos para detectar la posición de las manos, permitiendo a los usuarios controlar la altura y el volumen del sonido en tiempo real. Con Arduino como base, hemos desarrollado un sistema que convierte estos movimientos en señales MIDI, lo que proporciona una interfaz versátil y adaptable para la creación musical.
Lo mejor de todo es que hemos integrado este controlador MIDI Theremin con el software Ableton Live. Esta conexión nos permite no solo controlar la altura y el volumen, sino también explorar una amplia gama de sonidos y efectos disponibles en Ableton Live. Desde sintetizadores hasta instrumentos de percusión, la combinación de nuestro controlador con Ableton Live desbloquea un mundo de posibilidades musicales.
A través de este tutorial, te guiaremos paso a paso en la construcción de tu propio controlador MIDI Theremin, desde la configuración de los componentes hasta la programación del Arduino y la integración con Ableton Live.
Supplies
Hardware
1 Arduino Uno R3
1 Led Rojo
1 Led Azul
1 Led Verde
3 resistencias de 330 ohm
6 resistencias de 1k ohm
2 sensores de distancia ultrasónico
6 pulsadores
Software
Arduino IDE 2.2.1 (Software | Arduino)
loopMIDI (loopMIDI | Tobias Erichsen (tobias-erichsen.de))
Hairless MIDI (The Hairless MIDI<->Serial Bridge (projectgus.github.io))
Ableton Live 11 Lite (Creative tools for music makers | Ableton)
Step 1: Montaje Del Circuito
Montaje del Circuito para el Theremin Musical Interactivo
En la siguiente sección, presentamos un esquemático detallado que ilustra cómo ensamblar el circuito completo. Para facilitar la comprensión, dividimos el montaje en tres partes principales: el sensor de control de volumen, los pulsadores y LEDs, y finalmente, los sensores que modulan las notas musicales.
1. Sensor de Control de Volumen:
Situado a la izquierda del circuito, empleamos un sensor ultrasónico característico de Arduino que emite y recibe pulsos para calcular la distancia. Hemos programado este sensor de manera que puedas ajustar el volumen de tu pista de audio según la proximidad de tu mano al sensor.
2. Sensor de Notas Musicales:
El segundo sensor ultrasónico, ubicado en el circuito, se encarga de modular las notas musicales del instrumento programado. Al igual que el sensor de volumen, responde a la distancia de tu mano, permitiéndote controlar de manera intuitiva las melodías generadas.
3. Pulsadores y LEDs:
- Primer Pulsador: Controla la grabación y reproducción de tu sesión. Asociado a dos LEDs, el rojo indica la grabación en curso y el azul señala la reproducción de la canción.
- Segundo Pulsador: Activa el sensor ultrasónico de las notas, replicando el funcionamiento del theremin original. Un LED verde indica su estado activo.
- Tercer Pulsador: Gestiona los efectos aplicados al instrumento musical, como reverb o ecualización. En nuestro caso, lo utilizamos para activar un arpegiador.
4. Pulsadores de Pistas:
- Cuarto Pulsador: Asociado a la pista 1.
- Quinto Pulsador: Asociado a la pista 2.
- Sexto Pulsador: Asociado a la pista 3.
Cada pulsador de pista se asigna a un instrumento específico para componer la canción deseada. Este diseño modular y su programación intuitiva hacen que nuestro Theremin Musical Interactivo sea accesible para músicos y entusiastas, permitiéndote explorar y expresarte de maneras únicas.
Step 2: Código
int ledPinGrabacion = 7; // LED ROJO DE GRABACION
int ledPinReprod = 6; // LED AZUL DE REPRODUCCION
int ledPinON = 5; // LED VERDE DE ENCENDIDO
int rec_boton = A0; // BOTON GRABACION
int effect_boton = A1; // BOTON EFECTOS
int P1_boton = A2; // BOTON PISTA 1
int P2_boton = A3; // BOTON PISTA 2
int P3_boton = A4; // BOTON PISTA 3
int ON_boton = A5; // BOTON ENCENDIDO
int Echo_TV = 10; // ECHO THEREMIN VOLUMEN
int Trigger_TV = 11; // TRIGGER THEREMIN VOLUMEN
int Echo_TN = 8; // ECHO THEREMIN NOTAS
int Trigger_TN = 9; // TRIGGER THEREMIN NOTAS
int ledStateG = 0; // ESTADO DEL LED GRABACION
int ledStateE = 0; // ESTADO DEL LED EFECTO
int ledState1 = 0; // ESTADO DEL LED PISTA 1
int ledState2 = 0; // ESTADO DEL LED PISTA 2
int ledState3 = 0; // ESTADO DEL LED PISTA 3
int ledStateON = 0; // ESTADO DEL LED ENCENDIDO
int buttonOldG = 1; // ESTADO DEL BOTON GRABACION
int buttonOldE = 1; // ESTADO DEL BOTON EFECTO
int buttonOld1 = 1; // ESTADO DEL BOTON PISTA 1
int buttonOld2 = 1; // ESTADO DEL BOTON PISTA 2
int buttonOld3 = 1; // ESTADO DEL BOTON PISTA 3
int buttonOldON = 1; // ESTADO DEL BOTON ENCENDIDO
int buttonNewG,buttonNewE,buttonNew1,buttonNew2,buttonNew3, buttonNewON; // DIGITAL READ DE LOS BOTONES
int CCG = 0; // NOTAS CONTROL MIDI GRABACION
int CCE = 1; // NOTAS CONTROL MIDI EFECTOS
int CC1 = 2; // NOTAS CONTROL MIDI PISTA 1
int CC2 = 3; // NOTAS CONTROL MIDI PISTA 2
int CC3 = 4; // NOTAS CONTROL MIDI PISTA 3
int CCTV = 30; // NOTAS CONTROL MIDI THEREMIN VOLUMEN
const int aMin = 5; // ALTURA MINIMA A MAPEAR THEREMIN VOLUMEN
const int aMax = 50; // ALTURA MAXIMA A MAPEAR THEREMIN VOLUMEN
float distanciaTV; // DISTANCIA THEREMIN VOLUMEN
float distanciaAnteriorTV; // DISTANCIA ANTERIOR THEREMIN VOLUMEN
int distanciaTN; // DISTANCIA THEREMIN NOTAS
int nota; // NOTAS DEL THEREMIN
long tiempoTV; // TIEMPO DE DURACION DEL PULSO (THEREMIN VOLUMEN)
long tiempoTN; // TIEMPO DE DURACION DEL PULSO (THEREMIN NOTAS)
int valorTV; // VALOR DE LA ALTURA DEL VOLUMEN
int dt = 100; // DELAY
int dt1 = 5; // DELAY
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
pinMode(ledPinGrabacion, OUTPUT);
pinMode(ledPinReprod, OUTPUT);
pinMode(rec_boton, INPUT);
pinMode(effect_boton, INPUT);
pinMode(P1_boton, INPUT);
pinMode(P2_boton, INPUT);
pinMode(P3_boton, INPUT);
pinMode(Echo_TV, INPUT);
pinMode(Trigger_TV, OUTPUT);
pinMode(Echo_TN, INPUT);
pinMode(Trigger_TN, OUTPUT);
}
void loop() {
// put your main code here, to run repeatedly:
buttonNewG = digitalRead(rec_boton);
buttonNewE = digitalRead(effect_boton);
buttonNew1 = digitalRead(P1_boton);
buttonNew2 = digitalRead(P2_boton);
buttonNew3 = digitalRead(P3_boton);
buttonNewON = digitalRead(ON_boton);
delay(dt);
////////////////////////////// GRABACION /////////////////////////////////
if(buttonNewG == 0 && buttonOldG == 1){
if (ledStateG == 0){
digitalWrite(ledPinGrabacion, 1);
digitalWrite(ledPinReprod, 0);
ledStateG = 1;
Serial.write(176);
Serial.write(CCG);
Serial.write(127);
}
else {
digitalWrite (ledPinGrabacion,0);
digitalWrite (ledPinReprod,1);
Serial.write(176);
Serial.write(CCG);
Serial.write(127);
ledStateG = 0;
}
}
buttonOldG=buttonNewG;
////////////////////////////// EFECTOS /////////////////////////////////
if(buttonNewE == 0 && buttonOldE == 1){
if (ledStateE == 0){
ledStateE = 1;
Serial.write(176);
Serial.write(CCE);
Serial.write(127);
}
else {
Serial.write(176);
Serial.write(CCE);
Serial.write(0);
ledStateE = 0;
}
}
buttonOldE=buttonNewE;
////////////////////////////// PISTA 1 /////////////////////////////////
if(buttonNew1 == 0 && buttonOld1 == 1){
if (ledState1 == 0){
ledState1 = 1;
Serial.write(176);
Serial.write(CC1);
Serial.write(127);
}
else {
Serial.write(176);
Serial.write(CC1);
Serial.write(127);
ledState1 = 0;
}
}
buttonOld1=buttonNew1;
////////////////////////////// PISTA 2 /////////////////////////////////
if(buttonNew2 == 0 && buttonOld2 == 1){
if (ledState2 == 0){
ledState2 = 1;
Serial.write(176);
Serial.write(CC2);
Serial.write(127);
}
else {
Serial.write(176);
Serial.write(CC2);
Serial.write(127);
ledState2 = 0;
}
}
buttonOld2=buttonNew2;
////////////////////////////// PISTA 3 /////////////////////////////////
if(buttonNew3 == 0 && buttonOld3 == 1){
if (ledState3 == 0){
ledState3 = 1;
Serial.write(176);
Serial.write(CC3);
Serial.write(127);
}
else {
Serial.write(176);
Serial.write(CC3);
Serial.write(127);
ledState3 = 0;
}
}
buttonOld3=buttonNew3;
////////////////////////////// THEREMIN NOTAS /////////////////////////////////
if(buttonNewON == 0 && buttonOldON == 1){
if (ledStateON == 0){
digitalWrite(ledPinON, 1);
ledStateON = 1;
}
else {
digitalWrite(ledPinON, 0);
ledStateON = 0;
}
}
buttonOldON=buttonNewON;
if(ledStateON == 1) {
digitalWrite(Trigger_TN,LOW);
delayMicroseconds(5);
digitalWrite(Trigger_TN, HIGH); //envio del pulso para iniciar medicion
delayMicroseconds(10); //arduino espera 10 micro segundos
tiempoTN = pulseIn(Echo_TN, HIGH); //se mide la duración del pulso
distanciaTN = int(0.0177 * tiempoTN); //multiplicamos el tiempo para convertirlo en dista
nota = map(distanciaTN, 5, 60, 36, 60);
if (nota > 127) nota = 127; // limiter
if (nota < 0) nota = 0; // limiter para los negativos
Serial.write(144);
Serial.write(nota);
Serial.write(100);
delay(100);
Serial.write(144);
Serial.write(nota);
Serial.write(0);
delay(50);
}
////////////////////////////// THEREMIN VOLUMEN ///////////////////////////////
digitalWrite(Trigger_TV,LOW);
delayMicroseconds(5);
digitalWrite(Trigger_TV, HIGH); //envio del pulso para iniciar medicion
delayMicroseconds(10); //arduino espera 10 micro segundos
tiempoTV = pulseIn(Echo_TV, HIGH); //se mide la duración del pulso
distanciaTV = 0.0177 * tiempoTV; //multiplicamos el tiempo para convertirlo en distancia
if (abs(distanciaAnteriorTV - distanciaTV) > 0.8) { //resolución de 8 mm.
if (distanciaTV <= aMax + 2) {
valorTV = map(distanciaTV, aMin, aMax, 0, 127); //mapear alturas mínima y máxima a valores de 0 a 127
if (valorTV > 127) valorTV = 127; // limiter
if (valorTV < 0) valorTV = 0; // limiter para los negativos
Serial.write(176);
Serial.write(CCTV);
Serial.write(valorTV);
}
distanciaAnteriorTV = distanciaTV;
}
delay(dt1);
}
Attachments
Step 3: Funcionamiento
Aquí os dejamos un vídeo explicativo que muestra como funciona nuestro controlador MIDI theremín.
Por orden:
El primer video explica como funciona el pulsador de grabación y reproducción.
El segundo y el tercero explican como funcionan los sensores ultrasónicos que controlan el volumen y las notas.
El cuarto vídeo enseña el funcionamiento del pulsador de efectos.
Y por último se muestra como funcionan los pulsadores de las pistas.