sábado, 20 de setembro de 2014

Protótipo DIY E-Drum

    A facilidade que é trabalhar com Arduíno e aplicação dele em interfaces voltadas para música são muito interessantes. Há algum tempo tenho vontade de montar uma bateria eletrônica, agora estou executando esse projeto. Os objetivos são:

  • Seja MIDI - Isso é para ser usado com softwares de VST ou DAW;
  • Leia a intensidade da batida - Traduza a força da pancada no parâmetro MIDI velocity;
  • Utilizar um Arduíno UNO ou Duemilanove - Este hardware só tem 6 saídas analógidas, logo é necessário utilizar um Multiplexador;
  • Pads "bacanas" - Existem muitas ideias legais na construção de pads para e-drums. Uma delas é transformar um pandeiro em caixa, seja por conta do rebote da pele ou para detecção da batida no aro (Dual Zone).
    Eu utilizei como referência:


   O material utilizado até o momento para montar o protótipo:
  • Pads feitos de EVA de um tatame velho;
  • Piezos 27mm ;
  • Diodo Zener 5V1 1W
  • Resistor de 1M Carbono 5% 1/4W
  • Multiplexador HC4851n
  • Breadboard, cabos, ferramentas, computador e etc.
  • Software Ezdrummer 2, que transforma as mensagens MIDIS em som

Ligação do Protótipo

Ligação do Multiplexador
Ligação Arduíno

Plataforma de Testes

O código utilizado para ligação de 4 pads. Neste caso só estou lendo o Pino analógico 0 (um pad qualquer) e o 1 (Ligado no Multiplexador). No Mux, estou lendo aos três primeiros pinos (0,1 e 2). É importante não percorrer todos os pinos se não estiverem sendo utilizados pois geram notas fantasmas.

//*******************************************************************************************************************
// Variáveis de Definição do Usuário.
//*******************************************************************************************************************
unsigned char PadNote[6] = {51}; // Notas MIDI - 0 a 127
int PadCutOff[6] = {100,100,100,100,100,100}; // Valor Mínimo do Sensor para causar o som
int MaxPlayTime[6] = {90,90,90,90,90,90}; // Ciclos a passar antes da Segunda Batida ser acionada.
//variaveis Mux
unsigned char PadNoteMux[6] = {38,36,46}; // Notas MIDI - 0 a 127
int PadCutOffMux[6] = {100,100,100,100,100,100}; // Valor Mínimo do Sensor para causar o som
int MaxPlayTimeMux[6] = {90,90,90,90,90,90}; // Ciclos a passar antes da Segunda Batida ser acionada.
#define midichannel 0; // Canal Midi
boolean VelocityFlag = true; // Se o som será de acordo com a intensidade da Batida.
// Variaveis MUX
int r0 = 0; //value of select pin at the 4051 (s0)
int r1 = 0; //value of select pin at the 4051 (s1)
int r2 = 0; //value of select pin at the 4051 (s2)
int pinMux = 0;
//*******************************************************************************************************************
// Variáveis de uso Interno
//*******************************************************************************************************************
boolean activePad[6] = {0,0,0,0,0,0}; // Salva se os pads estao ativos ou nao.
int PinPlayTime[6] = {0,0,0,0,0,0}; // Contador dos ciclos desde que o pad foi acionado.
boolean activePadMux[6] = {0,0,0,0,0,0}; // Salva se os pads estao ativos ou nao.
int PinPlayTimeMux[6] = {0,0,0,0,0,0};
unsigned char status;
int pin = 0;
int hitavg = 0;
//*******************************************************************************************************************
// Setup
//*******************************************************************************************************************
void setup()
{
Serial.begin(57600);
//Pinos para o MUX
pinMode(2, OUTPUT); // s0
pinMode(3, OUTPUT); // s1
pinMode(4, OUTPUT); // s2
}
//*******************************************************************************************************************
// Main Program
//*******************************************************************************************************************
void loop()
{
for(int pin=0; pin < 2; pin++) // Percorre os Pinos Analógicos
{
if (pin == 1) //Pino de entrada do muxMUX
{
for (pinMux=0; pinMux<3; pinMux++) { //Percorre os pinos do Mux
r0 = bitRead(pinMux,0); // use this with arduino 0013 (and newer versions)
r1 = bitRead(pinMux,1); // use this with arduino 0013 (and newer versions)
r2 = bitRead(pinMux,2); // use this with arduino 0013 (and newer versions)
digitalWrite(2, r0);
digitalWrite(3, r1);
digitalWrite(4, r2);
hitavg = analogRead(pin); // Lê o Valor do Sensor
if((hitavg > PadCutOffMux[pinMux])) // Verifica se o valor pego pelo sensor é maior que o Valor minimo para causar o Som
{
if((activePadMux[pinMux] == false)) // Verifica se o Pad já está sendo executado.
{
if(VelocityFlag == true) // Verifica se o som será de acordo com a Intensidade da Batida, para gerar o Sinal Midi.
{
// hitavg = 127 / ((1023 - PadCutOffMux[pinMux]) / (hitavg - PadCutOffMux[pinMux])); // With full range (Too sensitive ?)
hitavg = (hitavg / 8) -1 ; // Upper range
}
else
{
hitavg = 127;
}
MIDI_TX(144,PadNoteMux[pinMux],hitavg); // Joga o SInal MIDI
PinPlayTimeMux[pinMux] = 0; //Seta o Ciclo para '0'
activePadMux[pinMux] = true; // Altera o Pad para Ativo.
}
else
{
PinPlayTimeMux[pinMux] = PinPlayTimeMux[pinMux] + 1; // Caso o Pad ja esteja ativo, incrementa 1 Ciclo.
}
}
else if((activePadMux[pinMux] == true)) // ESTA SEGUNDA PARTE É RESPONSÁVEL APENAS POR INCREMENTAR OS CICLOS E ATIVAR/DESATIVAR OS PADS.
{
PinPlayTimeMux[pinMux] = PinPlayTimeMux[pinMux] + 1;
if(PinPlayTimeMux[pinMux] > MaxPlayTimeMux[pinMux])
{
activePadMux[pinMux] = false;
MIDI_TX(128,PadNoteMux[pinMux],127);
}
}
}
}
else
{
hitavg = analogRead(pin); // Lê o Valor do Sensor
if((hitavg > PadCutOff[pin])) // Verifica se o valor pego pelo sensor é maior que o Valor minimo para causar o Som
{
if((activePad[pin] == false)) // Verifica se o Pad já está sendo executado.
{
if(VelocityFlag == true) // Verifica se o som será de acordo com a Intensidade da Batida, para gerar o Sinal Midi.
{
// hitavg = 127 / ((1023 - PadCutOff[pin]) / (hitavg - PadCutOff[pin])); // With full range (Too sensitive ?)
hitavg = (hitavg / 8) -1 ; // Upper range
}
else
{
hitavg = 127;
}
MIDI_TX(144,PadNote[pin],hitavg); // Joga o SInal MIDI
PinPlayTime[pin] = 0; //Seta o Ciclo para '0'
activePad[pin] = true; // Altera o Pad para Ativo.
}
else
{
PinPlayTime[pin] = PinPlayTime[pin] + 1; // Caso o Pad ja esteja ativo, incrementa 1 Ciclo.
}
}
else if((activePad[pin] == true)) // ESTA SEGUNDA PARTE É RESPONSÁVEL APENAS POR INCREMENTAR OS CICLOS E ATIVAR/DESATIVAR OS PADS.
{
PinPlayTime[pin] = PinPlayTime[pin] + 1;
if(PinPlayTime[pin] > MaxPlayTime[pin])
{
activePad[pin] = false;
MIDI_TX(128,PadNote[pin],127);
}
}
}
}
}
//*******************************************************************************************************************
// Função que transmite o MIDI
//*******************************************************************************************************************
void MIDI_TX(unsigned char MESSAGE, unsigned char PITCH, unsigned char VELOCITY)
{
status = MESSAGE + midichannel;
Serial.write(status);
Serial.write(PITCH);
Serial.write(VELOCITY);
}
view raw gistfile1.c hosted with ❤ by GitHub

    Uma amostra do estágio atual pode ser conferida neste vídeo :


Falta muito ajuste, principalmente na sensibilidade dos pads que estão falhando.... O positivo é que já está saindo som! :D