Arduino UnoのUSB-MIDIデバイス化については別ページで書きましたが、 ここではArduino MicroをUSB-MIDIデバイス化する方法を記載します。Arduinoのライブラリを使います。 Arduino をUSB-MIDI化するライブラリは2種類あります。微妙に違う2種類です。
これらのライブラリは、Arduino Micro 以外でもこの表に示したArduinoであれば使えるはずです。 全部試したわけではありませんが…
Arduino IDE 2.3.2を使って説明します。IDEを立ち上げて、1) 左のアイコンが並んでいるところから本立てのアイコンをクリックします。 2) ライブラリマネジャー(Library Manager)というメニューが表示されます。3) 一番上のテキストボックスに"MIDIUSB"と入力します。 4) MIDIUSB by Gray Grawal, Arduino というライブラリが表示されますので、Install をクリックします。
インストールの途中と、インストール結果がIDEの右下に表示されます。
インストールされたことを確認するにはスケッチの例として、MIDIUSBのスケッチが表示されるかを確認します。
1) 左のアイコンが並んでいるところから本立てのアイコンをクリックします。 2) ライブラリマネジャー(Library Manager)というメニューが表示されます。3) 一番上のテキストボックスに"USBMIDI"と入力します。 4) USBMIDI by Blokas というライブラリが表示されますので、Install をクリックします。
インストールできたことを確認する意味で、USBMIDIのスケッチ例を確認しておきます。
このプログラムはArduinoがMIDIメッセージを受信し、 そのまま同じメッセージを送り返します。 プログラムを見てみると、プログラムの先頭でMIDIUSB.hが先頭でインクルードされています。
このヘッダーをインクルードすることで、MIDIUSB.cppが自動的にリンクされます。 MIDIUSB.cの中でMIDI送受信のクラス、MidiUSBのインスタンスが作られています。 私のインストールしたバージョンでは、MIDIUSB.cppの37業目で MIDI_ というクラスをMidiUSBという名前で生成しています。
MIDI_ MidiUSB;これにより、それぞれのスケッチのsetup()の中では何もしなくても、MidiUSB.read(), MidiUSB.sendMIDI()といったメンバー関数を使うことができます。
MIDIUSBの特徴として、MIDIメッセージを構造体midiEventPacket_tでやり取りします。 この構造体は、MIDIUSB_Defs.hに定義されています。
typedef struct { uint8_t header; uint8_t byte1; uint8_t byte2; uint8_t byte3; } midiEventPacket_t;
loop()関数で、MidiUSB.read()でMIDIを取り込みます。rxのヘッダーを見て MIDIメッセージが届いているかどうかを判断しています。もし、MIDIを受信していなければ、rx.header=0 となります。MIDIが受信できれば、MIDIデータをMidiUSB.sendMIDI(rx)で出力します。
MidiUSB.flush()は、送信バッファーに溜まっているメッセージを実際に転送路に流しています。
void loop() { midiEventPacket_t rx; do { rx = MidiUSB.read(); if (rx.header != 0) { //send back the received MIDI command MidiUSB.sendMIDI(rx); MidiUSB.flush(); } } while (rx.header != 0); }
実際に動作を確認します。USBケーブルでPCとArduino Microを繋ぎます。 IDE の上部で送信先のデバイスをArduino Microと選択します。 IDEの上部の右矢印をクリックすることで、MIDIUSB_loopをArduino Microに書き込みます(Uploadします)。 Arduino Microは書き込んだ後にリセットがかかり、USB MIDIデバイスとして再起動します。
MIDIメッセージを送信してみます。 ブラウザでSend And Receive MIDIを開きます。MIDI Portの設定ダウンロードメニュー、Input Device, Output DeviceにArduino Microが表示されています。 表示されていない場合は、それぞれのプルダウンメニューをクリックしてArduino Microを選択します。
Output MIDIの欄に適当なMIDIメッセージを記入します。ここでは90 60 7F 80 60 00と記入しています。 Sendボタンをクリックします。MIDIメッセージがArduino Microに送信されます。 Arduino Microは受け取ったMIDIメッセージをそのまま送り返します。 Arduino Microから戻ってきたMIDIメッセージがInout Monitorの欄に表示されます。
なを、midiEventPacket_tの詳細はこちらを参照下さい。
USBMIDIはUSBのインターフェースにV-USBというライブラリを使っています。 USBMIDIがインストールされているフォルダー、Arduino/Library/USBMIDI、を見ると以下のようにv-usbがインストールされています。
── USBMIDI ├── LICENSE ├── README.md ├── examples ├── keywords.txt ├── library.properties ├── src └── vusb └── usbdrv
UsbMidiLoopbackのプログラムを見ると先頭で、usbmidi.hがインクルードされています。
このヘッダーがインクルードされていることで、usbmidi_vusb.cpp他のプログラムがリンクされます。 このファイルの中で、298行目で以下のようにUSBMIDI_のクラスが、USBMIDIという名前で生成されています。
USBMIDI_ USBMIDI;
これにより、それぞれのスケッチのsetup()の中では何もしなくても、 USBMIDI.read(), USBMIDI.write()といったメンバー関数を使うことができます。
USBMIDIとMIDIUSBの違いは、USBMIDIではMIDIメッセージを1バイトごとに受信しています。 MIDIUSBは構造体midiEventPacket_tで受信していました。Arduino のloop関数は以下のようになっています。
void loop() { //Handle USB communication USBMIDI.poll(); // While there's MIDI USB input available... while (USBMIDI.available()) { u8 b = USBMIDI.read(); // Output the byte to the Serial interface. Serial.print(b >> 4, HEX); Serial.print(b & 0xf, HEX); Serial.print('\n'); // Echo the byte back to the MIDI USB output. USBMIDI.write(b); USBMIDI.flush(); } }
USBMIDI.available()で受信するMIDIメッセージ(1バイト)が受信バッファーにあるかどうかを調べます。 もし、メッセージがあればb=USBMIDI.read()で1バイト受信します。この1バイトをそのままUSBMIDI.write(b)で 送信バッファーに書き込みます。
このプログラムでは、送信と同時にSerialに書き込んでいますので、 IDEのSerial Monitorでも受信したMIDIメッセージを確認することができます。
ブラウザでSend And Receive MIDIを開きます。と同時に、IDEでSerial Monitorを開きます。 Send And ReceiveのMIDIのInput/Output DeviceのプロフダウンメニューでArduino Microを選択します。 適当なMIDIメッセージをOutput MIDI:のボックスに書き込みます。ここでは、90 40 7F 80 40 00を書き込んでいます。 Sendをクリックします。Serial Montor に1バイトづつMIDIメッセージが表示されています。 また、同時にInput Monitorにも受信したメッセージとして表示されます。
最初のF0 F7は中身の無いSystem Exclusiveです。なぜ、表示されるのかはよくわかりません。 USBMIDIの受信バッファーに起動時に溜まっていたものかもしれません。特に害はありません。