quarta-feira, 4 de novembro de 2015

Programando Arduíno com Sensor Ultrassom para enviar notas musicais MIDI

Programando Arduíno com Sensor Ultrassom para enviar notas musicais MIDI

Para a disciplina Projeto Interdisciplinar de Engenharia II (UCL - Serra - ES), foi requisitado fazer um instrumento musical utilizando Arduíno.

Optei por fazer uma "Sanfona Ultrassônica", com dois sensores Ultrassom HCSR04. Utilizei um Arduíno MEGA 2560.

-- Medição das distâncias --

Comecei a pesquisar em vários sites sobre como medir a distância usando Arduíno e sensores ultrassom. Consegui informações relevantes no post "HC-SR04 com Arduíno: Colocando o ultrassom para funcionar", do seguinte blog: http://blog.repeatdomiau.com.br/miadas/arduino-com-ultrassom-hcsr04.
Enfim, cheguei ao seguinte código para medir as distâncias utilizando os dois sensores ultrassom:

Código Arduíno para medir as distâncias usando dois sensores ultrassom (entre aspas - retirar as aspas se for utilizar):
"
#define echoPin1 13 //Pino 13 recebe o pulso do echo
#define trigPin1 12 //Pino 12 envia o pulso para gerar o echo
#define echoPin2 9 //Pino 9 recebe o pulso do echo
#define trigPin2 8 //Pino 8 envia o pulso para gerar o echo

void setup()
{
   Serial.begin(9600); //inicia a porta serial
   pinMode(echoPin1, INPUT); // define o pino 13 como entrada (recebe)
   pinMode(trigPin1, OUTPUT); // define o pino 12 como saida (envia)
   pinMode(echoPin2, INPUT); // define o pino 9 como entrada (recebe)
   pinMode(trigPin2, OUTPUT); // define o pino 8 como saida (envia)
}

void loop()
{
  //seta o pino 12 com um pulso baixo "LOW" ou desligado ou ainda 0
    digitalWrite(trigPin1, LOW);

  //delay de 2 microssegundos
    delayMicroseconds(2);
 
  //seta o pino 12 com pulso alto "HIGH" ou ligado ou ainda 1
    digitalWrite(trigPin1, HIGH);

  //delay de 10 microssegundos
    delayMicroseconds(10);

  //seta o pino 12 com pulso baixo novamente
    digitalWrite(trigPin1, LOW);

  //pulseIn lê o tempo entre a chamada e o pino entrar em high
    long duration1 = pulseIn(echoPin1,HIGH);

  //Esse calculo é baseado em s = v . t, lembrando que o tempo vem dobrado
  //porque é o tempo de ida e volta do ultrassom
    long distancia1 = duration1 /29 / 2 ;
 
Serial.print("Distancia sensor 1 em CM: ");
Serial.println(distancia1);
delay(1000); //espera 1 segundo para fazer a leitura novamente

  //seta o pino 8 com um pulso baixo "LOW" ou desligado ou ainda 0
    digitalWrite(trigPin2, LOW);
  //delay de 2 microssegundos
    delayMicroseconds(2);
 
  //seta o pino 8 com pulso alto "HIGH" ou ligado ou ainda 1
    digitalWrite(trigPin2, HIGH);
  //delay de 10 microssegundos
    delayMicroseconds(10);

  //seta o pino 8 com pulso baixo novamente
    digitalWrite(trigPin2, LOW);

  //pulseIn lê o tempo entre a chamada e o pino entrar em high
    long duration2 = pulseIn(echoPin2,HIGH);

  //Esse calculo é baseado em s = v . t, lembrando que o tempo vem dobrado
  //porque é o tempo de ida e volta do ultrassom
    long distancia2 = duration2 /29 / 2 ;

Serial.print("Distancia sensor 2 em CM: ");
Serial.println(distancia2);
delay(1000); //espera 1 segundo para fazer a leitura novamente
}
"

Os sensores ultrassom HCSR04 tem quatro conexões: 5V, GND, Trigger e ECHO. As conexões 5V e GND são para alimentação de energia. A conexão Trigger (gatilho) é para a emissão do sinal ultrassom. A conexão ECHO detecta o sinal ultrassom após ser refletido em alguma superfície.
Como o sinal vai e volta, é necessário dividir a distância por dois. Os demais ajustes para chegar à distância em centímetros estão descritos no código acima.

O código acima utilizou a porta serial 9600 e os valores de medições podem ser visualizados utilizando-se o "Monitor Serial" do Arduíno (Arduíno - Ferramentas - Monitor Serial // ou pressionando Ctrl + Shift + M).

Para a medição das distâncias, é necessário utilizar o programa do Arduíno (gratuito, disponível em https://www.arduino.cc/), o Arduíno (placa - utilizei o Arduíno MEGA 2560), o cabo USB que vem com o Arduíno, os dois sensores ultrassom e o computador. A função "Monitor Serial" do programa do Arduíno mostra as distâncias em cm (conforme o código acima).

-- Emitindo as notas MIDI com um sensor ultrassom --

Com as medições prontas, resolvi inserir a emissão de notas musicais MIDI conforme as distâncias medidas pelos sensores ultrassom. Voltei a estudar vários sites. Aqui vão alguns links para ajudar quem queira fazer um instrumento musical (encontrei de baterias, xilofones, instrumentos para música eletrônica):
Analisando tudo, foram necessários os seguintes programas para o som sair:

Uma nota importante é que a porta Serial para usar o Hairless usa o número 115200. Gastei muito tempo tentando fazer as notas MIDI saírem usando outros números de portas e não consegui. É possível trocar o número Baud rate (115200) no Hairless: Hairless >> File >> Preferences >> Baud rate.

Olhando os códigos que encontrei, consegui fazer o som funcionar com várias notas utilizando o código abaixo. Utilizei as notas de 68 a 91, para uma distância de 50 cm. Coloquei a nota 68 para os primeiros 2 cm. A cada 2 cm a mais de distância do ultrassom, a nota aumenta em 1 número. Utilizei a função "if" e "else if" para delimitar as distâncias. Caso alguém queira tentar, acredito que seja possível fazer a variação de notas conforme a distância utilizando a função "for".

Segue abaixo o código que funcionou para um sensor Ultrassom. O som do instrumento musical pode ser escolhido no programa que executa as notas MIDI (como o VMPK MIDI piano Keyboard, por exemplo).

Código Arduíno que funcionou com um sensor ultrassom (entre aspas - retirar as aspas se for utilizar):
"
#define echoPin 13 //Pino 13 recebe o pulso do echo
#define trigPin 12 //Pino 12 envia o pulso para gerar o echo

const byte noteOffCommand = 0;
const byte noteOnCommand = 1;

byte channel = 0;  // Channel 1  (0-15 selects channel 1-16)

//byte pitchByte = 69;  // A4 = Middle A = 440 Hz (Piano keyboard runs from 21/A0 to 108/C8)
//byte velocityByte = 127;  // Medium Velocity/Volume (value from 0 to 127)

void setup()
{
   Serial.begin(115200); //inicia a porta serial  115200 para o HairLess
   pinMode(echoPin, INPUT); // define o pino 13 como entrada (recebe)
   pinMode(trigPin, OUTPUT); // define o pino 12 como saida (envia)
}

void loop()
{
  //seta o pino 12 com um pulso baixo "LOW" ou desligado ou ainda 0
    digitalWrite(trigPin, LOW);
  // delay de 2 microssegundos
    delayMicroseconds(2);
  //seta o pino 12 com pulso alto "HIGH" ou ligado ou ainda 1
    digitalWrite(trigPin, HIGH);
  //delay de 10 microssegundos
    delayMicroseconds(10);
  //seta o pino 12 com pulso baixo novamente
    digitalWrite(trigPin, LOW);
  //pulseInt lê o tempo entre a chamada e o pino entrar em high
    long duration = pulseIn(echoPin,HIGH);
  //Esse calculo é baseado em s = v . t, lembrando que o tempo vem dobrado
  //porque é o tempo de ida e volta do ultrassom
    long distancia = duration /29 / 2 ;

if (distancia >= 50){

delay(1000); // Tempo de espera duration

}
else if (distancia <= 2){
Serial.write(0x80 + (noteOnCommand << 4) + (byte(channel)));
Serial.write(byte(68));
Serial.write(byte(127));

delay(300); // Note duration

Serial.write(0x80 + (noteOffCommand << 4) + (byte(channel)));
Serial.write(byte(68));
Serial.write(byte(0));
}
else if ((distancia > 2) && (distancia <= 4)){
Serial.write(0x80 + (noteOnCommand << 4) + (byte(channel)));
Serial.write(byte(69));
Serial.write(byte(127));

delay(300); // Note duration

Serial.write(0x80 + (noteOffCommand << 4) + (byte(channel)));
Serial.write(byte(69));
Serial.write(byte(0));
}
else if ((distancia > 4) && (distancia <= 6)){
Serial.write(0x80 + (noteOnCommand << 4) + (byte(channel)));
Serial.write(byte(70));
Serial.write(byte(127));

delay(300); // Note duration

Serial.write(0x80 + (noteOffCommand << 4) + (byte(channel)));
Serial.write(byte(70));
Serial.write(byte(0));
}
else if ((distancia > 6) && (distancia <= 8)){
Serial.write(0x80 + (noteOnCommand << 4) + (byte(channel)));
Serial.write(byte(71));
Serial.write(byte(127));

delay(300); // Note duration

Serial.write(0x80 + (noteOffCommand << 4) + (byte(channel)));
Serial.write(byte(71));
Serial.write(byte(0));
}
else if ((distancia > 8) && (distancia <= 10)){
Serial.write(0x80 + (noteOnCommand << 4) + (byte(channel)));
Serial.write(byte(72));
Serial.write(byte(127));

delay(300); // Note duration

Serial.write(0x80 + (noteOffCommand << 4) + (byte(channel)));
Serial.write(byte(72));
Serial.write(byte(0));
}
else if ((distancia > 12) && (distancia < 14)){
Serial.write(0x80 + (noteOnCommand << 4) + (byte(channel)));
Serial.write(byte(73));
Serial.write(byte(127));

delay(300); // Note duration

Serial.write(0x80 + (noteOffCommand << 4) + (byte(channel)));
Serial.write(byte(73));
Serial.write(byte(0));
}
else if ((distancia > 14) && (distancia <= 16)){
Serial.write(0x80 + (noteOnCommand << 4) + (byte(channel)));
Serial.write(byte(74));
Serial.write(byte(127));

delay(300); // Note duration

Serial.write(0x80 + (noteOffCommand << 4) + (byte(channel)));
Serial.write(byte(74));
Serial.write(byte(0));
}
else if ((distancia > 16) && (distancia <= 18)){
Serial.write(0x80 + (noteOnCommand << 4) + (byte(channel)));
Serial.write(byte(75));
Serial.write(byte(127));

delay(300); // Note duration

Serial.write(0x80 + (noteOffCommand << 4) + (byte(channel)));
Serial.write(byte(75));
Serial.write(byte(0));
}
else if ((distancia > 18) && (distancia <= 20)){
Serial.write(0x80 + (noteOnCommand << 4) + (byte(channel)));
Serial.write(byte(76));
Serial.write(byte(127));

delay(300); // Note duration

Serial.write(0x80 + (noteOffCommand << 4) + (byte(channel)));
Serial.write(byte(76));
Serial.write(byte(0));
}
else if ((distancia > 20) && (distancia <= 22)){
Serial.write(0x80 + (noteOnCommand << 4) + (byte(channel)));
Serial.write(byte(77));
Serial.write(byte(127));

delay(300); // Note duration

Serial.write(0x80 + (noteOffCommand << 4) + (byte(channel)));
Serial.write(byte(77));
Serial.write(byte(0));
}
else if ((distancia > 22) && (distancia <= 24)){
Serial.write(0x80 + (noteOnCommand << 4) + (byte(channel)));
Serial.write(byte(78));
Serial.write(byte(127));

delay(300); // Note duration

Serial.write(0x80 + (noteOffCommand << 4) + (byte(channel)));
Serial.write(byte(78));
Serial.write(byte(0));
}
else if ((distancia > 24) && (distancia <= 26)){
Serial.write(0x80 + (noteOnCommand << 4) + (byte(channel)));
Serial.write(byte(79));
Serial.write(byte(127));

delay(300); // Note duration

Serial.write(0x80 + (noteOffCommand << 4) + (byte(channel)));
Serial.write(byte(79));
Serial.write(byte(0));
}
else if ((distancia > 26) && (distancia <= 28)){
Serial.write(0x80 + (noteOnCommand << 4) + (byte(channel)));
Serial.write(byte(80));
Serial.write(byte(127));

delay(300); // Note duration

Serial.write(0x80 + (noteOffCommand << 4) + (byte(channel)));
Serial.write(byte(80));
Serial.write(byte(0));
}
else if ((distancia > 28) && (distancia <= 30)){
Serial.write(0x80 + (noteOnCommand << 4) + (byte(channel)));
Serial.write(byte(81));
Serial.write(byte(127));

delay(300); // Note duration

Serial.write(0x80 + (noteOffCommand << 4) + (byte(channel)));
Serial.write(byte(81));
Serial.write(byte(0));
}
else if ((distancia > 30) && (distancia <= 32)){
Serial.write(0x80 + (noteOnCommand << 4) + (byte(channel)));
Serial.write(byte(82));
Serial.write(byte(127));

delay(300); // Note duration

Serial.write(0x80 + (noteOffCommand << 4) + (byte(channel)));
Serial.write(byte(82));
Serial.write(byte(0));
}
else if ((distancia > 32) && (distancia <= 34)){
Serial.write(0x80 + (noteOnCommand << 4) + (byte(channel)));
Serial.write(byte(83));
Serial.write(byte(127));

delay(300); // Note duration

Serial.write(0x80 + (noteOffCommand << 4) + (byte(channel)));
Serial.write(byte(83));
Serial.write(byte(0));
}
else if ((distancia > 34) && (distancia <= 36)){
Serial.write(0x80 + (noteOnCommand << 4) + (byte(channel)));
Serial.write(byte(84));
Serial.write(byte(127));

delay(300); // Note duration

Serial.write(0x80 + (noteOffCommand << 4) + (byte(channel)));
Serial.write(byte(84));
Serial.write(byte(0));
}
else if ((distancia > 36) && (distancia <= 38)){
Serial.write(0x80 + (noteOnCommand << 4) + (byte(channel)));
Serial.write(byte(85));
Serial.write(byte(127));

delay(300); // Note duration

Serial.write(0x80 + (noteOffCommand << 4) + (byte(channel)));
Serial.write(byte(85));
Serial.write(byte(0));
}
else if ((distancia > 38) && (distancia <= 40)){
Serial.write(0x80 + (noteOnCommand << 4) + (byte(channel)));
Serial.write(byte(86));
Serial.write(byte(127));

delay(300); // Note duration

Serial.write(0x80 + (noteOffCommand << 4) + (byte(channel)));
Serial.write(byte(86));
Serial.write(byte(0));
}
else if ((distancia > 40) && (distancia <= 42)){
Serial.write(0x80 + (noteOnCommand << 4) + (byte(channel)));
Serial.write(byte(87));
Serial.write(byte(127));

delay(300); // Note duration

Serial.write(0x80 + (noteOffCommand << 4) + (byte(channel)));
Serial.write(byte(87));
Serial.write(byte(0));
}
else if ((distancia > 42) && (distancia <= 44)){
Serial.write(0x80 + (noteOnCommand << 4) + (byte(channel)));
Serial.write(byte(88));
Serial.write(byte(127));

delay(300); // Note duration

Serial.write(0x80 + (noteOffCommand << 4) + (byte(channel)));
Serial.write(byte(88));
Serial.write(byte(0));
}
else if ((distancia > 44) && (distancia <= 46)){
Serial.write(0x80 + (noteOnCommand << 4) + (byte(channel)));
Serial.write(byte(89));
Serial.write(byte(127));

delay(300); // Note duration

Serial.write(0x80 + (noteOffCommand << 4) + (byte(channel)));
Serial.write(byte(89));
Serial.write(byte(0));
}
else if ((distancia > 46) && (distancia <= 48)){
Serial.write(0x80 + (noteOnCommand << 4) + (byte(channel)));
Serial.write(byte(90));
Serial.write(byte(127));

delay(300); // Note duration

Serial.write(0x80 + (noteOffCommand << 4) + (byte(channel)));
Serial.write(byte(90));
Serial.write(byte(0));
}
else if ((distancia > 48) && (distancia < 50)){
Serial.write(0x80 + (noteOnCommand << 4) + (byte(channel)));
Serial.write(byte(91));
Serial.write(byte(127));

delay(300); // Note duration

Serial.write(0x80 + (noteOffCommand << 4) + (byte(channel)));
Serial.write(byte(91));
Serial.write(byte(0));
}
//delay(200); //espera 200 milissegundos para fazer a leitura novamente
}
"

-- Emitindo as notas MIDI com dois sensores ultrassom --

Após fazer as notas MIDI funcionarem com um sensor ultrassom, consegui colocar os dois sensores ultrassom para funcionar. No código abaixo está um sensor relacionado com o canal 1 e o outro com o canal 2, ou seja, podem ser ligados dois tipos de sons instrumentos musicais, um em cada canal.
Para o primeiro sensor, as notas variam de 68 a 91. Para o segundo sensor, as notas variam de 68 a 45.
Travei a distância máxima de cada sensor ultrassom em 50 cm para a emissão de notas.
Conforme a necessidade de cada projeto, o código poderá ser alterado.

Código Arduíno que funcionou com dois sensores ultrassom (entre aspas - retirar as aspas se for utilizar):

"
#define echoPin2 9 //Pino 9 recebe o pulso do echo
#define trigPin2 8 //Pino 8 envia o pulso para gerar o echo
#define echoPin 13 //Pino 13 recebe o pulso do echo
#define trigPin 12 //Pino 12 envia o pulso para gerar o echo

const byte noteOffCommand = 0;
const byte noteOnCommand = 1;

byte channel = 0;  // Channel 1  (0-15 selects channel 1-16)
byte channel2 = 1; // Channel 2  (0-15 selects channel 1-16)

//byte pitchByte = 69;  // A4 = Middle A = 440 Hz (Piano keyboard runs from 21/A0 to 108/C8)
//byte velocityByte = 127;  // Medium Velocity/Volume (value from 0 to 127)

void setup()
{
   Serial.begin(115200); //inicia a porta serial  115200 para o HairLess
   pinMode(echoPin, INPUT); // define o pino 13 como entrada (recebe)
   pinMode(trigPin, OUTPUT); // define o pino 12 como saida (envia)
   pinMode(echoPin2, INPUT); // define o pino 9 como entrada (recebe)
   pinMode(trigPin2, OUTPUT); // define o pino 8 como saida (envia)
}

void loop()
{
  // -- ULTRASSOM SENSOR 1 -- Medição --
  //seta o pino 12 com um pulso baixo "LOW" ou desligado ou ainda 0
    digitalWrite(trigPin, LOW);
  // delay de 2 microssegundos
    delayMicroseconds(2);
  //seta o pino 12 com pulso alto "HIGH" ou ligado ou ainda 1
    digitalWrite(trigPin, HIGH);
  //delay de 10 microssegundos
    delayMicroseconds(10);
  //seta o pino 12 com pulso baixo novamente
    digitalWrite(trigPin, LOW);
  //pulseInt lê o tempo entre a chamada e o pino entrar em high
    long duration = pulseIn(echoPin,HIGH);
  //Esse calculo é baseado em s = v . t, lembrando que o tempo vem dobrado
  //porque é o tempo de ida e volta do ultrassom
    long distancia = duration /29 / 2 ;

   // -- NOTAS MIDI -- ULTRASSOM SENSOR 1 --
if (distancia >= 50){

delay(300); // Tempo de espera 300 milissegundos

}
else if (distancia <= 2){
Serial.write(0x80 + (noteOnCommand << 4) + (byte(channel)));
Serial.write(byte(68));
Serial.write(byte(127));

delay(300); // Note duration

Serial.write(0x80 + (noteOffCommand << 4) + (byte(channel)));
Serial.write(byte(68));
Serial.write(byte(0));
}
else if ((distancia > 2) && (distancia <= 4)){
Serial.write(0x80 + (noteOnCommand << 4) + (byte(channel)));
Serial.write(byte(69));
Serial.write(byte(127));

delay(300); // Note duration

Serial.write(0x80 + (noteOffCommand << 4) + (byte(channel)));
Serial.write(byte(69));
Serial.write(byte(0));
}
else if ((distancia > 4) && (distancia <= 6)){
Serial.write(0x80 + (noteOnCommand << 4) + (byte(channel)));
Serial.write(byte(70));
Serial.write(byte(127));

delay(300); // Note duration

Serial.write(0x80 + (noteOffCommand << 4) + (byte(channel)));
Serial.write(byte(70));
Serial.write(byte(0));
}
else if ((distancia > 6) && (distancia <= 8)){
Serial.write(0x80 + (noteOnCommand << 4) + (byte(channel)));
Serial.write(byte(71));
Serial.write(byte(127));

delay(300); // Note duration

Serial.write(0x80 + (noteOffCommand << 4) + (byte(channel)));
Serial.write(byte(71));
Serial.write(byte(0));
}
else if ((distancia > 8) && (distancia <= 10)){
Serial.write(0x80 + (noteOnCommand << 4) + (byte(channel)));
Serial.write(byte(72));
Serial.write(byte(127));

delay(300); // Note duration

Serial.write(0x80 + (noteOffCommand << 4) + (byte(channel)));
Serial.write(byte(72));
Serial.write(byte(0));
}
else if ((distancia > 12) && (distancia < 14)){
Serial.write(0x80 + (noteOnCommand << 4) + (byte(channel)));
Serial.write(byte(73));
Serial.write(byte(127));

delay(300); // Note duration

Serial.write(0x80 + (noteOffCommand << 4) + (byte(channel)));
Serial.write(byte(73));
Serial.write(byte(0));
}
else if ((distancia > 14) && (distancia <= 16)){
Serial.write(0x80 + (noteOnCommand << 4) + (byte(channel)));
Serial.write(byte(74));
Serial.write(byte(127));

delay(300); // Note duration

Serial.write(0x80 + (noteOffCommand << 4) + (byte(channel)));
Serial.write(byte(74));
Serial.write(byte(0));
}
else if ((distancia > 16) && (distancia <= 18)){
Serial.write(0x80 + (noteOnCommand << 4) + (byte(channel)));
Serial.write(byte(75));
Serial.write(byte(127));

delay(300); // Note duration

Serial.write(0x80 + (noteOffCommand << 4) + (byte(channel)));
Serial.write(byte(75));
Serial.write(byte(0));
}
else if ((distancia > 18) && (distancia <= 20)){
Serial.write(0x80 + (noteOnCommand << 4) + (byte(channel)));
Serial.write(byte(76));
Serial.write(byte(127));

delay(300); // Note duration

Serial.write(0x80 + (noteOffCommand << 4) + (byte(channel)));
Serial.write(byte(76));
Serial.write(byte(0));
}
else if ((distancia > 20) && (distancia <= 22)){
Serial.write(0x80 + (noteOnCommand << 4) + (byte(channel)));
Serial.write(byte(77));
Serial.write(byte(127));

delay(300); // Note duration

Serial.write(0x80 + (noteOffCommand << 4) + (byte(channel)));
Serial.write(byte(77));
Serial.write(byte(0));
}
else if ((distancia > 22) && (distancia <= 24)){
Serial.write(0x80 + (noteOnCommand << 4) + (byte(channel)));
Serial.write(byte(78));
Serial.write(byte(127));

delay(300); // Note duration

Serial.write(0x80 + (noteOffCommand << 4) + (byte(channel)));
Serial.write(byte(78));
Serial.write(byte(0));
}
else if ((distancia > 24) && (distancia <= 26)){
Serial.write(0x80 + (noteOnCommand << 4) + (byte(channel)));
Serial.write(byte(79));
Serial.write(byte(127));

delay(300); // Note duration

Serial.write(0x80 + (noteOffCommand << 4) + (byte(channel)));
Serial.write(byte(79));
Serial.write(byte(0));
}
else if ((distancia > 26) && (distancia <= 28)){
Serial.write(0x80 + (noteOnCommand << 4) + (byte(channel)));
Serial.write(byte(80));
Serial.write(byte(127));

delay(300); // Note duration

Serial.write(0x80 + (noteOffCommand << 4) + (byte(channel)));
Serial.write(byte(80));
Serial.write(byte(0));
}
else if ((distancia > 28) && (distancia <= 30)){
Serial.write(0x80 + (noteOnCommand << 4) + (byte(channel)));
Serial.write(byte(81));
Serial.write(byte(127));

delay(300); // Note duration

Serial.write(0x80 + (noteOffCommand << 4) + (byte(channel)));
Serial.write(byte(81));
Serial.write(byte(0));
}
else if ((distancia > 30) && (distancia <= 32)){
Serial.write(0x80 + (noteOnCommand << 4) + (byte(channel)));
Serial.write(byte(82));
Serial.write(byte(127));

delay(300); // Note duration

Serial.write(0x80 + (noteOffCommand << 4) + (byte(channel)));
Serial.write(byte(82));
Serial.write(byte(0));
}
else if ((distancia > 32) && (distancia <= 34)){
Serial.write(0x80 + (noteOnCommand << 4) + (byte(channel)));
Serial.write(byte(83));
Serial.write(byte(127));

delay(300); // Note duration

Serial.write(0x80 + (noteOffCommand << 4) + (byte(channel)));
Serial.write(byte(83));
Serial.write(byte(0));
}
else if ((distancia > 34) && (distancia <= 36)){
Serial.write(0x80 + (noteOnCommand << 4) + (byte(channel)));
Serial.write(byte(84));
Serial.write(byte(127));

delay(300); // Note duration

Serial.write(0x80 + (noteOffCommand << 4) + (byte(channel)));
Serial.write(byte(84));
Serial.write(byte(0));
}
else if ((distancia > 36) && (distancia <= 38)){
Serial.write(0x80 + (noteOnCommand << 4) + (byte(channel)));
Serial.write(byte(85));
Serial.write(byte(127));

delay(300); // Note duration

Serial.write(0x80 + (noteOffCommand << 4) + (byte(channel)));
Serial.write(byte(85));
Serial.write(byte(0));
}
else if ((distancia > 38) && (distancia <= 40)){
Serial.write(0x80 + (noteOnCommand << 4) + (byte(channel)));
Serial.write(byte(86));
Serial.write(byte(127));

delay(300); // Note duration

Serial.write(0x80 + (noteOffCommand << 4) + (byte(channel)));
Serial.write(byte(86));
Serial.write(byte(0));
}
else if ((distancia > 40) && (distancia <= 42)){
Serial.write(0x80 + (noteOnCommand << 4) + (byte(channel)));
Serial.write(byte(87));
Serial.write(byte(127));

delay(300); // Note duration

Serial.write(0x80 + (noteOffCommand << 4) + (byte(channel)));
Serial.write(byte(87));
Serial.write(byte(0));
}
else if ((distancia > 42) && (distancia <= 44)){
Serial.write(0x80 + (noteOnCommand << 4) + (byte(channel)));
Serial.write(byte(88));
Serial.write(byte(127));

delay(300); // Note duration

Serial.write(0x80 + (noteOffCommand << 4) + (byte(channel)));
Serial.write(byte(88));
Serial.write(byte(0));
}
else if ((distancia > 44) && (distancia <= 46)){
Serial.write(0x80 + (noteOnCommand << 4) + (byte(channel)));
Serial.write(byte(89));
Serial.write(byte(127));

delay(300); // Note duration

Serial.write(0x80 + (noteOffCommand << 4) + (byte(channel)));
Serial.write(byte(89));
Serial.write(byte(0));
}
else if ((distancia > 46) && (distancia <= 48)){
Serial.write(0x80 + (noteOnCommand << 4) + (byte(channel)));
Serial.write(byte(90));
Serial.write(byte(127));

delay(300); // Note duration

Serial.write(0x80 + (noteOffCommand << 4) + (byte(channel)));
Serial.write(byte(90));
Serial.write(byte(0));
}
else if ((distancia > 48) && (distancia < 50)){
Serial.write(0x80 + (noteOnCommand << 4) + (byte(channel)));
Serial.write(byte(91));
Serial.write(byte(127));

delay(300); // Note duration

Serial.write(0x80 + (noteOffCommand << 4) + (byte(channel)));
Serial.write(byte(91));
Serial.write(byte(0));
}

// -- ULTRASSOM SENSOR 2 -- Medição --
  //seta o pino 8 com um pulso baixo "LOW" ou desligado ou ainda 0
    digitalWrite(trigPin2, LOW);
  //delay de 2 microssegundos
    delayMicroseconds(2);
 
  //seta o pino 8 com pulso alto "HIGH" ou ligado ou ainda 1
    digitalWrite(trigPin2, HIGH);
  //delay de 10 microssegundos
    delayMicroseconds(10);

  //seta o pino 8 com pulso baixo novamente
    digitalWrite(trigPin2, LOW);

  //pulseIn lê o tempo entre a chamada e o pino entrar em high
    long duration2 = pulseIn(echoPin2,HIGH);

  //Esse calculo é baseado em s = v . t, lembrando que o tempo vem dobrado
  //porque é o tempo de ida e volta do ultrassom
    long distancia2 = duration2 /29 / 2 ;

   // -- NOTAS MIDI -- ULTRASSOM SENSOR 2 --
if (distancia2 >= 50){

delay(300); // Tempo de espera 300 milissegundos

}

else if (distancia2 <= 2){
Serial.write(0x80 + (noteOnCommand << 4) + (byte(channel2)));
Serial.write(byte(68));
Serial.write(byte(127));

delay(300); // Note duration

Serial.write(0x80 + (noteOffCommand << 4) + (byte(channel2)));
Serial.write(byte(68));
Serial.write(byte(0));
}
else if ((distancia2 > 2) && (distancia2 <= 4)){
Serial.write(0x80 + (noteOnCommand << 4) + (byte(channel2)));
Serial.write(byte(67));
Serial.write(byte(127));

delay(300); // Note duration

Serial.write(0x80 + (noteOffCommand << 4) + (byte(channel2)));
Serial.write(byte(67));
Serial.write(byte(0));
}
else if ((distancia2 > 4) && (distancia2 <= 6)){
Serial.write(0x80 + (noteOnCommand << 4) + (byte(channel2)));
Serial.write(byte(66));
Serial.write(byte(127));

delay(300); // Note duration

Serial.write(0x80 + (noteOffCommand << 4) + (byte(channel2)));
Serial.write(byte(66));
Serial.write(byte(0));
}
else if ((distancia2 > 6) && (distancia2 <= 8)){
Serial.write(0x80 + (noteOnCommand << 4) + (byte(channel2)));
Serial.write(byte(65));
Serial.write(byte(127));

delay(300); // Note duration

Serial.write(0x80 + (noteOffCommand << 4) + (byte(channel2)));
Serial.write(byte(65));
Serial.write(byte(0));
}
else if ((distancia2 > 8) && (distancia2 <= 10)){
Serial.write(0x80 + (noteOnCommand << 4) + (byte(channel2)));
Serial.write(byte(64));
Serial.write(byte(127));

delay(300); // Note duration

Serial.write(0x80 + (noteOffCommand << 4) + (byte(channel2)));
Serial.write(byte(64));
Serial.write(byte(0));
}
else if ((distancia2 > 12) && (distancia2 < 14)){
Serial.write(0x80 + (noteOnCommand << 4) + (byte(channel2)));
Serial.write(byte(63));
Serial.write(byte(127));

delay(300); // Note duration

Serial.write(0x80 + (noteOffCommand << 4) + (byte(channel2)));
Serial.write(byte(63));
Serial.write(byte(0));
}
else if ((distancia2 > 14) && (distancia2 <= 16)){
Serial.write(0x80 + (noteOnCommand << 4) + (byte(channel2)));
Serial.write(byte(62));
Serial.write(byte(127));

delay(300); // Note duration

Serial.write(0x80 + (noteOffCommand << 4) + (byte(channel2)));
Serial.write(byte(62));
Serial.write(byte(0));
}
else if ((distancia2 > 16) && (distancia2 <= 18)){
Serial.write(0x80 + (noteOnCommand << 4) + (byte(channel2)));
Serial.write(byte(61));
Serial.write(byte(127));

delay(300); // Note duration

Serial.write(0x80 + (noteOffCommand << 4) + (byte(channel2)));
Serial.write(byte(61));
Serial.write(byte(0));
}
else if ((distancia2 > 18) && (distancia2 <= 20)){
Serial.write(0x80 + (noteOnCommand << 4) + (byte(channel2)));
Serial.write(byte(60));
Serial.write(byte(127));

delay(300); // Note duration

Serial.write(0x80 + (noteOffCommand << 4) + (byte(channel2)));
Serial.write(byte(60));
Serial.write(byte(0));
}
else if ((distancia2 > 20) && (distancia2 <= 22)){
Serial.write(0x80 + (noteOnCommand << 4) + (byte(channel2)));
Serial.write(byte(59));
Serial.write(byte(127));

delay(300); // Note duration

Serial.write(0x80 + (noteOffCommand << 4) + (byte(channel2)));
Serial.write(byte(59));
Serial.write(byte(0));
}
else if ((distancia2 > 22) && (distancia2 <= 24)){
Serial.write(0x80 + (noteOnCommand << 4) + (byte(channel2)));
Serial.write(byte(58));
Serial.write(byte(127));

delay(300); // Note duration

Serial.write(0x80 + (noteOffCommand << 4) + (byte(channel2)));
Serial.write(byte(58));
Serial.write(byte(0));
}
else if ((distancia2 > 24) && (distancia2 <= 26)){
Serial.write(0x80 + (noteOnCommand << 4) + (byte(channel2)));
Serial.write(byte(57));
Serial.write(byte(127));

delay(300); // Note duration

Serial.write(0x80 + (noteOffCommand << 4) + (byte(channel2)));
Serial.write(byte(57));
Serial.write(byte(0));
}
else if ((distancia2 > 26) && (distancia2 <= 28)){
Serial.write(0x80 + (noteOnCommand << 4) + (byte(channel2)));
Serial.write(byte(56));
Serial.write(byte(127));

delay(300); // Note duration

Serial.write(0x80 + (noteOffCommand << 4) + (byte(channel2)));
Serial.write(byte(56));
Serial.write(byte(0));
}
else if ((distancia2 > 28) && (distancia2 <= 30)){
Serial.write(0x80 + (noteOnCommand << 4) + (byte(channel2)));
Serial.write(byte(55));
Serial.write(byte(127));

delay(300); // Note duration

Serial.write(0x80 + (noteOffCommand << 4) + (byte(channel2)));
Serial.write(byte(55));
Serial.write(byte(0));
}
else if ((distancia2 > 30) && (distancia2 <= 32)){
Serial.write(0x80 + (noteOnCommand << 4) + (byte(channel2)));
Serial.write(byte(54));
Serial.write(byte(127));

delay(300); // Note duration

Serial.write(0x80 + (noteOffCommand << 4) + (byte(channel2)));
Serial.write(byte(54));
Serial.write(byte(0));
}
else if ((distancia2 > 32) && (distancia2 <= 34)){
Serial.write(0x80 + (noteOnCommand << 4) + (byte(channel2)));
Serial.write(byte(53));
Serial.write(byte(127));

delay(300); // Note duration

Serial.write(0x80 + (noteOffCommand << 4) + (byte(channel2)));
Serial.write(byte(53));
Serial.write(byte(0));
}
else if ((distancia2 > 34) && (distancia2 <= 36)){
Serial.write(0x80 + (noteOnCommand << 4) + (byte(channel2)));
Serial.write(byte(52));
Serial.write(byte(127));

delay(300); // Note duration

Serial.write(0x80 + (noteOffCommand << 4) + (byte(channel2)));
Serial.write(byte(52));
Serial.write(byte(0));
}
else if ((distancia2 > 36) && (distancia2 <= 38)){
Serial.write(0x80 + (noteOnCommand << 4) + (byte(channel2)));
Serial.write(byte(51));
Serial.write(byte(127));

delay(300); // Note duration

Serial.write(0x80 + (noteOffCommand << 4) + (byte(channel2)));
Serial.write(byte(51));
Serial.write(byte(0));
}
else if ((distancia2 > 38) && (distancia2 <= 40)){
Serial.write(0x80 + (noteOnCommand << 4) + (byte(channel2)));
Serial.write(byte(50));
Serial.write(byte(127));

delay(300); // Note duration

Serial.write(0x80 + (noteOffCommand << 4) + (byte(channel2)));
Serial.write(byte(50));
Serial.write(byte(0));
}
else if ((distancia2 > 40) && (distancia2 <= 42)){
Serial.write(0x80 + (noteOnCommand << 4) + (byte(channel2)));
Serial.write(byte(49));
Serial.write(byte(127));

delay(300); // Note duration

Serial.write(0x80 + (noteOffCommand << 4) + (byte(channel2)));
Serial.write(byte(49));
Serial.write(byte(0));
}
else if ((distancia2 > 42) && (distancia2 <= 44)){
Serial.write(0x80 + (noteOnCommand << 4) + (byte(channel2)));
Serial.write(byte(48));
Serial.write(byte(127));

delay(300); // Note duration

Serial.write(0x80 + (noteOffCommand << 4) + (byte(channel2)));
Serial.write(byte(48));
Serial.write(byte(0));
}
else if ((distancia2 > 44) && (distancia2 <= 46)){
Serial.write(0x80 + (noteOnCommand << 4) + (byte(channel2)));
Serial.write(byte(47));
Serial.write(byte(127));

delay(300); // Note duration

Serial.write(0x80 + (noteOffCommand << 4) + (byte(channel2)));
Serial.write(byte(47));
Serial.write(byte(0));
}
else if ((distancia2 > 46) && (distancia2 <= 48)){
Serial.write(0x80 + (noteOnCommand << 4) + (byte(channel2)));
Serial.write(byte(46));
Serial.write(byte(127));

delay(300); // Note duration

Serial.write(0x80 + (noteOffCommand << 4) + (byte(channel2)));
Serial.write(byte(46));
Serial.write(byte(0));
}
else if ((distancia2 > 48) && (distancia2 < 50)){
Serial.write(0x80 + (noteOnCommand << 4) + (byte(channel2)));
Serial.write(byte(45));
Serial.write(byte(127));

delay(300); // Note duration

Serial.write(0x80 + (noteOffCommand << 4) + (byte(channel2)));
Serial.write(byte(45));
Serial.write(byte(0));
}
//delay(200); //espera 200 milissegundos para fazer a leitura novamente
}
"

-- Emitindo as notas MIDI com dois sensores ultrassom -- Código resumido --

Uma outra lógica mais curta do que utilizar várias funções "if" e "else if" pode ser feita se atrelarmos a variação de distância com a formação da nota. Abaixo segue um código mais curto seguindo a ideia. Cada sensor está relacionado com um canal de emissão de notas MIDI: um sensor com o canal 1 e o outro com o canal 2.

Código Arduíno mais curto que funcionou com dois sensores ultrassom (entre aspas - retirar as aspas se for utilizar):

"
#define echoPin2 9 //Pino 9 recebe o pulso do echo
#define trigPin2 8 //Pino 8 envia o pulso para gerar o echo
#define echoPin 13 //Pino 13 recebe o pulso do echo
#define trigPin 12 //Pino 12 envia o pulso para gerar o echo

const byte noteOffCommand = 0;
const byte noteOnCommand = 1;

byte channel = 0;  // Channel 1  (0-15 selects channel 1-16)
byte channel2 = 1; // Channel 2  (0-15 selects channel 1-16)

//byte pitchByte = 69;  // A4 = Middle A = 440 Hz (Piano keyboard runs from 21/A0 to 108/C8)
//byte velocityByte = 127;  // Medium Velocity/Volume (value from 0 to 127)

void setup()
{
   Serial.begin(115200); //inicia a porta serial  115200 para o HairLess
   pinMode(echoPin, INPUT); // define o pino 13 como entrada (recebe)
   pinMode(trigPin, OUTPUT); // define o pino 12 como saida (envia)
   pinMode(echoPin2, INPUT); // define o pino 9 como entrada (recebe)
   pinMode(trigPin2, OUTPUT); // define o pino 8 como saida (envia)
}

void loop()
{
  // -- ULTRASSOM SENSOR 1 -- Medição --
  //seta o pino 12 com um pulso baixo "LOW" ou desligado ou ainda 0
    digitalWrite(trigPin, LOW);
  // delay de 2 microssegundos
    delayMicroseconds(2);
  //seta o pino 12 com pulso alto "HIGH" ou ligado ou ainda 1
    digitalWrite(trigPin, HIGH);
  //delay de 10 microssegundos
    delayMicroseconds(10);
  //seta o pino 12 com pulso baixo novamente
    digitalWrite(trigPin, LOW);
  //pulseInt lê o tempo entre a chamada e o pino entrar em high
    long duration = pulseIn(echoPin,HIGH);
  //Esse calculo é baseado em s = v . t, lembrando que o tempo vem dobrado
  //porque é o tempo de ida e volta do ultrassom
    long distancia = duration /29 / 2 ;

  // -- ULTRASSOM SENSOR 2 -- Medição --
  //seta o pino 8 com um pulso baixo "LOW" ou desligado ou ainda 0
    digitalWrite(trigPin2, LOW);
  //delay de 2 microssegundos
    delayMicroseconds(2);
 
  //seta o pino 8 com pulso alto "HIGH" ou ligado ou ainda 1
    digitalWrite(trigPin2, HIGH);
  //delay de 10 microssegundos
    delayMicroseconds(10);

  //seta o pino 8 com pulso baixo novamente
    digitalWrite(trigPin2, LOW);

  //pulseIn lê o tempo entre a chamada e o pino entrar em high
    long duration2 = pulseIn(echoPin2,HIGH);

  //Esse calculo é baseado em s = v . t, lembrando que o tempo vem dobrado
  //porque é o tempo de ida e volta do ultrassom
    long distancia2 = duration2 /29 / 2 ;
 
   // -- NOTAS MIDI -- ULTRASSOM SENSOR 1 --
if (distancia >= 50){
delay(300); // Tempo de espera 300 milissegundos
}

else {
int nota = distancia + 68;
Serial.write(0x80 + (noteOnCommand << 4) + (byte(channel)));
Serial.write(byte(nota)); //
Serial.write(byte(127));

delay(300); // Note duration

Serial.write(0x80 + (noteOffCommand << 4) + (byte(channel)));
Serial.write(byte(nota));
Serial.write(byte(0));
}

   // -- NOTAS MIDI -- ULTRASSOM SENSOR 2 --
if (distancia2 >= 50){
delay(300); // Tempo de espera 300 milissegundos
}

else {
int nota2 = 68 - distancia2;
Serial.write(0x80 + (noteOnCommand << 4) + (byte(channel2)));
Serial.write(byte(nota2));
Serial.write(byte(127));

delay(300); // Note duration

Serial.write(0x80 + (noteOffCommand << 4) + (byte(channel2)));
Serial.write(byte(nota2));
Serial.write(byte(0));
}

}
//delay(200); //espera 200 milissegundos para fazer a leitura novamente
"

Lucas T R Freitas

2 comentários:

Roge disse...

muito bom estava a procura de algo parecido so um detalhe que não sei como ficaria
se eu quisesse definir uma distancia fixa e cada vez que o sensor for acionado como HIGH tocasse uma nota seguinte e assim por diante e ao termino retornasse a primeira nota
como seria possível fazer isso?

obrigado por compartilhar vossos conhecimentos

Lucas T R Freitas, M.Sc. disse...

Obrigado. Sugestão: fazer uma iteração do tipo "i + 1" até um determinado número. Checar quando o número chegar ao máximo desejado e zerar a contagem, para reiniciar.