Close

2. Using USB Host Shield

A project log for MIDI Slide Whistle "MEMIDION"

I tried to make slide whistle move automatically by MIDI signal. This is MEMIDION.

homemadegarbageHomeMadeGarbage 09/26/2018 at 10:300 Comments

MEMIDION can be controlled directly by MIDI controller by using USB host shield.

Structure

Place the Arduino pro mini on the Mini USB Host Shield and connect it to MIDI controller 

Arduino IDE Code

Move the slider of the whistle with the MIDI signal from the MIDI keyboard. The slide amount is controlled by the measurement value of distance sensor VL6180X.

I used the following as a USB MIDI library

https://github.com/felis/USB_Host_Shield_2.0

I programmed with reference to the following

https://github.com/felis/USB_Host_Shield_2.0/tree/master/examples/USBH_MIDI/USBH_MIDI_dump

The library for distance sensor VL6180X is below.

https://github.com/pololu/vl6180x-arduino

#include <usbh_midi.h>
#include <usbhub.h>
#include <SPI.h>

#include <Wire.h>
#include <VL6180X.h>

USB Usb;
USBH_MIDI  Midi(&Usb);

uint8_t Note, oldNote;

VL6180X sensor;

int meas;
int aim = 50;
int diff = 5;

void MIDI_poll();

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

  Wire.begin();

  pinMode(2, OUTPUT);
  pinMode(3, OUTPUT);

  sensor.init();
  sensor.configureDefault();
  sensor.setTimeout(500);

  if (Usb.Init() == -1) {
    while (1); //halt
  }
  
  delay( 200 );
}

void loop() {
  Usb.Task();

  if ( Usb.getUsbTaskState() == USB_STATE_RUNNING ) {
    MIDI_poll();
  }
}

// Poll USB MIDI Controler and drive motor
void MIDI_poll() {
  char buf[20];
  uint8_t bufMidi[64];
  uint16_t  rcvd;

  if (Midi.RecvData( &rcvd,  bufMidi) == 0 ) {
    if(bufMidi[0] == 9){
      Note = bufMidi[2];
      Serial.println(Note);

      //Initial operation of the motor
      if(Note > oldNote){
        digitalWrite(2, HIGH);
        digitalWrite(3, LOW);
      }else{
        digitalWrite(2, LOW);
        digitalWrite(3, HIGH);
      }
      delay(50);

      digitalWrite(2, LOW);
      digitalWrite(3, LOW);
    }
  }

  //Slide distance setting
  if(Note == 57) aim = 22;  //A
  if(Note == 58) aim = 33;  //A#
  if(Note == 59) aim = 41;  //B
  if(Note == 60) aim = 52;  //C
  if(Note == 61) aim = 62;  //C#
  if(Note == 62) aim = 71;  //D
  if(Note == 63) aim = 81;  //D#
  if(Note == 64) aim = 90;  //E
  if(Note == 65) aim = 97; //F
  if(Note == 66) aim = 103; //F#
  if(Note == 67) aim = 109; //G
  if(Note == 68) aim = 116; //G#
  if(Note == 69) aim = 121; //A
  if(Note == 70) aim = 126; //A#
  if(Note == 71) aim = 129; //B
  if(Note == 72) aim = 133; //C

  //Distance sensor measurement
  meas = sensor.readRangeSingleMillimeters();
  //Serial.println(meas);

  //Motor operation
  if(meas > (aim - diff) && meas <  (aim + diff)){
    digitalWrite(2, LOW);
    digitalWrite(3, LOW);
  }else if(meas > aim){
    digitalWrite(2, LOW);
    digitalWrite(3, HIGH);
  }else if(meas < aim){
    digitalWrite(2, HIGH);
    digitalWrite(3, LOW);
  }
  oldNote = Note;
}

Operation

Discussions