Un controller MIDI DIY con Arduino

Reading Time: 4 minutes


Un semplice tutorial per realizzare passo dopo passo il tuo controller MIDI DIY con Arduino per controllare i tuoi software synth preferiti.

Questa guida presenta Deep1: un prototipo di controller MIDI DIY basato su Arduino realizzato da Artis Lab a partire dall’inverno 2018. Per questo prototipo si è scelto di utilizzare un Arduino Leonardo poiché questa scheda differisce dalle altre della famiglia Arduino. La scheda Leonardo, infatti, monta un microcontrollore denominato ATmega32u4 che ha una particolarità molto interessante.

Un controller MIDI DIY con ArduinoIl microcontrollore ATmega32u4

Il microcontrollore ATmega32u4 ha il modulo di comunicazione USB integrato nel chip. Questa opportunità elimina la necessità di utilizzare un chip FTDI USB-to-serial per la comunicazione tra la scheda e il PC. In tal modo, la scheda Leonardo, dopo essere stata collegata ad un PC, può essere riconosciuta come una periferica generica USB. Dunque Arduino Leonardo, al pari di un mouse, di una tastiera o di un controller MIDI, viene riconosciuto dal computer come un normale dispositivo di input.

Programmando opportunamente la scheda Leonardo si può fare in modo che venga riconosciuta dal computer come un controller MIDI capace di inviare eventi Control Change per manipolare in tempo reale i parametri di sintetizzatori software. L’uso della scheda Leonardo evita, quindi, il bisogno di realizzare la conversione dei dati sul calcolatore da seriale a MIDI che è, invece, necessaria nel caso in cui si usino le schede dotate di microcontrollori diversi dall’ATmega32u4. In alternativa, è anche possibile programmare opportunamente il chip FTDI USB-to-serial delle schede Arduino perché venga riconosciuto come una periferica MIDI dai computer. Ma questa è una strada un po’ più complessa che proveremo a realizzare in qualche altra guida futura.Un controller MIDI DIY con Arduino
Per realizzare la connessione dei potenziometri alla scheda Arduino si può utilizzare lo schema proposto per il prototipo PDSynth-00.

La struttura del programma per inviare gli eventi Control Change

Poiché la scheda Leonardo viene riconosciuta dai computer come un dispositivo seriale USB al pari di una testiera, un mouse o di un controller MIDI, mediante la libreria MIDIUSB.h è possibile realizzare dei semplici programmi per inviare eventi e dati MIDI al computer. In tal modo è piuttosto semplice costruire dei dispositivi DIY da utilizzare come controller MIDI. Il frammento di codice riportato di seguito mostra come realizzare l’invio di messaggi MIDI Control Change in risposta al cambiamento dei valori del potenziometro connesso sull’ingresso analogico A0.

#include "MIDIUSB.h"

int CC1=0;
float alpha=0.5;

//This function sends Control Change events
void controlChange(byte channel, byte control, byte value) {
  // First parameter is the event type (0x0B = control change).
  // Second parameter: event type, combined with the channel.
  // Third parameter is the control number number (0-119).
  // Fourth parameter is the control value (0-127).
  midiEventPacket_t event={0x0B, 0xB0 | channel, control, value};
  MidiUSB.sendMIDI(event);
}

void setup() {
  Serial.begin(115200);
}

void loop() {
  int newCC1=analogRead(A0);
  if(abs(newCC1-CC1)>=4){//If the value is changed
    //We use an average filter to smooth the readings
    CC1=alpha*newCC1+(1.-alpha)*CC1;
    controlChange(0, 1, map(CC1,0,1023,0,128)); 
    //map data from 10bit to 7bit
    // Set the value of controller 1 on channel 0 to CC1
    MidiUSB.flush(); //send all the data!
  }
} 

La funzione controlChange(channel, control, value) consente di trasmettere gli eventi MIDI Control Change al computer. Nella funzione si crea un nuovo evento MIDI con i dati forniti come argomento alla funzione. In seguito, la funzione MidiUSB.sendMIDI(event) consente di inviare il nuovo evento MIDI appena creato. All’interno della funzione loop(), ogni qual volta si ha un cambiamento della posizione del potenziometro, si invoca la funzione controlChange() per aggiornare opportunamente il valore del Control Change. Per calcolare il valore da inviare come argomento del Control Change si utilizza la funzione map(CC1,0,1023,0,128). In tal modo è possibile convertire in maniera semplice il numero ottenuto dalla lettura del convertitore analogico-digitale di Arduino (un numero a 10bit – compreso nell’intervallo [0,1023]) in un numero coerente con lo standard MIDI (un numero a 7bit – compreso nell’intervallo [0, 127]). Infine, si invoca la funzione MidiUSB.flush() per svuotare la coda dei messaggi MIDI e inviare l’evento Control Change.

Il programma Arduino per realizzare il controller MIDI DIY

Qui di seguito si trova il codice sviluppato per gestire i sei potenziometri del prototipo Deep1:

#include "MIDIUSB.h"

int CC1=0;
int CC2=0;
int CC3=0;
int CC4=0;
int CC5=0;
int CC6=0;
float alpha=0.5;

//This function sends Control Change events
void controlChange(byte channel, byte control, byte value) {
  // First parameter is the event type (0x0B = control change).
  // Second parameter: event type, combined with the channel.
  // Third parameter is the control number number (0-119).
  // Fourth parameter is the control value (0-127).
  midiEventPacket_t event={0x0B, 0xB0 | channel, control, value};
  MidiUSB.sendMIDI(event);
}

void setup() {
  Serial.begin(115200);
}

void loop() {
  int newCC1=analogRead(A0);
  if(abs(newCC1-CC1)>=4){//If the value is changed
    //We use an average filter to smooth the readings
    CC1=alpha*newCC1+(1.-alpha)*CC1;
    controlChange(0, 1, map(CC1,0,1023,0,128)); 
    //map data from 10bit to 7bit
    // Set the value of controller 1 on channel 0 to CC1
    MidiUSB.flush(); //send all the data!
    }
  
  int newCC2=analogRead(A1);
  if(abs(newCC2-CC2)>=4){//If the value is changed
    //We use a running average filter to smooth the readings
    CC2=alpha*newCC2+(1.-alpha)*CC2;
    controlChange(0, 2, map(CC2,0,1023,0,128)); 
    // Set the value of controller 2 on channel 0 to CC2
    MidiUSB.flush();
    }

  int newCC3=analogRead(A2);
  if(abs(newCC3-CC3)>=4){//If the value is changed
    //We use a running average filter to smooth the readings
    CC3=alpha*newCC3+(1.-alpha)*CC3;
    controlChange(0, 3, map(CC3,0,1023,0,128)); 
    // Set the value of controller 3 on channel 0 to CC3
    MidiUSB.flush();
    }
  
  int newCC4=analogRead(A3);
  if(abs(newCC4-CC4)>=4){//If the value is changed
    //We use a running average filter to smooth the readings
    CC4=alpha*newCC4+(1.-alpha)*CC4;
    controlChange(0, 4, map(CC4,0,1023,0,128)); 
    // Set the value of controller 4 on channel 0 to CC4
    MidiUSB.flush();
    }

  int newCC5=analogRead(A4);
  if(abs(newCC5-CC5)>=4){//If the value is changed
    //We use a running average filter to smooth the readings
    CC5=alpha*newCC5+(1.-alpha)*CC5;
    controlChange(0, 5, map(CC5,0,1023,0,128)); 
    // Set the value of controller 5 on channel 0 to CC5
    MidiUSB.flush();
    }
      
  int newCC6=analogRead(A5);
  if(abs(newCC6-CC6)>=4){//If the value is changed
    //We use a running average filter to smooth the readings
    CC6=alpha*newCC6+(1.-alpha)*CC6;
    controlChange(0, 6, map(CC6,0,1023,0,128)); 
    // Set the value of controller 6 on channel 0 to CC6
    MidiUSB.flush();
    }
} 

Perché non dai anche uno sguardo ai nostri prodotti su tindie.com?

I sell on Tindie

Se ti piace questo progetto e vuoi provare a realizzarlo per problemi, curiosità oppure suggerimenti scrivici qui di seguito:

Codice di sicurezza:
security code
Inserire un codice di sicurezza.:

Invia

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *