XIAOをMIDIインターフェースにしてみる:その2 PCからのMIDI受信テスト

Arduino/SAMDMIDI,Seeeduino,XIAO,インターフェース,フォトカプラ

前回はXIAOをPCに繋ぎ、XIAOがMIDI機器としてPCにMIDI信号を送信できるかどうかのチェックを行いました。

今回は、逆にPCからXIAOにMIDI信号を送り正しく受信できるかどうかのチェックを行います。

PCからのMIDI信号をXIAOで受け取る

前回使ったライブラリのMIDIUSBですが、これを更にラップした「Arduino USB-MIDI」という派生ライブラリがあり、こちらの方は更によく纏められている様子。

examplesを見ると、「MIDI_DIN2USB.ino」なんてすばらしいものがありました。

MIDIポートから入って来る信号をまんまUSBに送り、USBからの信号をまんまMIDIポートに送り出す

これこそMIDIインターフェースではないですか。

というわけで、これがちゃんと動作するかをチェックしてみます。

実際のMIDIケーブルの信号を出したり受けたりする回路をまだ作っていませんので、ここではPCからのメッセージが簡単に拾えるかどうかをチェックしてみます。

#include <Arduino.h>

#include <USB-MIDI.h>
USING_NAMESPACE_MIDI;

typedef USBMIDI_NAMESPACE::usbMidiTransport __umt;
typedef MIDI_NAMESPACE::MidiInterface<__umt> __ss;
__umt usbMIDI(0); // cableNr
__ss MIDICoreUSB((__umt &)usbMIDI);

typedef Message<MIDI_NAMESPACE::DefaultSettings::SysExMaxSize> MidiMessage;

MIDI_CREATE_INSTANCE(HardwareSerial, Serial1, MIDICoreSerial);

// OLEDライブラリ
#include <U8g2lib.h> // グラフィックライブラリ
//====================================================================================
// OLED LCD(I2C)
// I2Cアドレス
volatile const uint8_t ADDRES_OLED = 0x3C; // volatile
// 通信速度
const uint32_t I2C_HIGH = 400000UL; // I2C 周波数
// U8g2
U8G2_SSD1306_128X64_NONAME_F_HW_I2C display(U8G2_R0, /* reset=*/U8X8_PIN_NONE);
//====================================================================================

// -----------------------------------------------------------------------------
// MIDIメッセージコールバック
// -----------------------------------------------------------------------------
// USB
void onUsbMessage(const MidiMessage &message)
{
	// とりあえずコメントアウト
	//	MIDICoreSerial.send(message);

	// LCDに表示させる
	if (message.type ==
			0x8 ||
		0x9 || 0xA)
	{
		switch (message.channel)
		{
		case 1:
			// 削除
			display.setDrawColor(0);
			display.drawBox(0, 16, 127, 33);
			display.setDrawColor(255);
			// 表示
			display.setCursor(0, 31);
			display.println("CH1: " + String(message.channel) + "," + String(message.data1) + "," + String(message.data2));
			display.sendBuffer();
			break;
		case 2:
			// 削除
			display.setDrawColor(0);
			display.drawBox(0, 33, 127, 49);
			display.setDrawColor(255);
			// 表示
			display.setCursor(0, 47);
			display.println("CH2: " + String(message.channel) + "," + String(message.data1) + "," + String(message.data2));
			display.sendBuffer();
			break;
		default:
			break;
		}
	}

	// メッセージタイプ
	// 削除
	display.setDrawColor(0);
	display.drawBox(0, 48, 127, 65);
	display.setDrawColor(255);
	// 表示
	display.setCursor(0, 63);
	display.printf("Type: 0x%x", message.type);
	display.sendBuffer();
}
// MIDIポート
void onSerialMessage(const MidiMessage &message)
{
	MIDICoreUSB.send(message);
}

// -----------------------------------------------------------------------------
//
// -----------------------------------------------------------------------------
void setup()
{
	//------------------------------------------------------------------
	// OLED LCD
	display.begin();

	// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
	// I2Cアドレスを設定
	display.setI2CAddress(ADDRES_OLED * 2);
	// I2Cバスクロック U8g2はなんかクロックスピードあんま出ない?I2Cだからか
	display.setBusClock(I2C_HIGH);
	// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

	// 日本語UTF8フォントを有効化
	display.enableUTF8Print();

	// タイトル出力
	display.setFont(u8g2_font_b16_b_t_japanese1);
	display.setFontDirection(0);
	display.clearBuffer();
	display.setCursor(0, 15);
	display.print("- XIAO MIDI IF -");
	display.sendBuffer();
	//------------------------------------------------------------------

	// Midiメッセージハンドラを設定
	MIDICoreUSB.setHandleMessage(onUsbMessage);
	MIDICoreSerial.setHandleMessage(onSerialMessage);

	// MIDIチャンネル設定 1-16
	//	ここでは全て(MIDI_CHANNEL_OMNI = 0)を指定。
	MIDICoreUSB.begin(MIDI_CHANNEL_OMNI);
	MIDICoreSerial.begin(MIDI_CHANNEL_OMNI);
}

// -----------------------------------------------------------------------------
//
// -----------------------------------------------------------------------------
void loop()
{
	MIDICoreUSB.read();
	MIDICoreSerial.read();
}

このラッパーライブラリは、ポートに到着したMIDIメッセージを受けて動作するイベントハンドラを設置し、好きに料理していいよという非常に使いやすいラッパーです。

examplesのベースは各MIDIポート(USBと外部MIDIポート)に来たMIDIメッセージを相互に送り付けるだけというシンプルなもの。

好きに料理してくれって感じでしたので、ここではPCから受け取るメッセージを外部MIDIポートに送らずにLCDに表示させる様にしました。

思った通りの動きをしてくれて、大変嬉しく思います。

捗りますね。。。

MIDI機器との接続部分を設計

さてPCからのMIDIメッセージもうまく解釈出来ている様子でしたので、MIDI-IN MIDI-OUT端子を作ろうと思います。

MIDI規格では、デバイス間のグランドループを回避する為に、入力はフォトカプラで受ける必要があるとの事。

また、出力は一応5Vとなっていた様ですが、フォトカプラで受ける仕様の為か、十分な電流値(5mA)があれば3.3Vでも良いらしい。

そして余計な線を結線しない事、とある。

とりあえず回路を書いてみます。

こんな感じでよかですかね。

MIDIの規格を調べてみると、グランドループしない様に受けはフォトカプラで受け、出す時は5mAで出すらしい。

フォトカプラもPC817みたいな汎用のでなくて、信号用の高速なものが必要なんだとか。

そういえばPC817でもトランジスタで引いてやって高速化するみたいな記事を読みましたが、ちょっと大変そうなのでパス。

しかし高速なフォトカプラの構成図を見ると、同じ様な事をしてますね。

PC817の例ではカレントミラー、高速フォトカプラの方はプッシュプルとかトーテムポールとかいうやつみたいです。

うん、なんだかサッパリ判りませんがっ

もしかしたらPC817の入力をカレントミラーして、それをプッシュプルしたらだいぶ綺麗な波形になるんじゃなかろうか・・・

部品点数がてんこ盛りになって遅延が益々酷くなるんじゃまいかとかとか

などと妄想しつつ、放置。

そして取り出したるは、もっと詳しく無かった頃に注文してあったTLP2366(の、多分コピー品)。

一応データシートではスレッドショルドが3.5mA(最大)となっているので、、

多分、、、動作するだろう。

電流が少ないとそれだけ遅くなるらしいですが、とりあえず使ってみようと思います。

駄菓子菓子

sop6。

老眼にはゲフンゲフン・・・

もちろんsop6の変換基板も持ってません。

ですのでここは、必殺の空中配線で挑もうかと・・・

まぁ、、、動けば!

そして出力は3.3Vを抵抗を堕として出す感じで。

MIDI端子を作る

さてフォトカプラの他に、MIDI楽器からの出入力を担うMIDI端子を作る必要があるのですが

5DINのメスとか持ってませんし、どうせ繋ぐ先は近場ですからMIDIケーブルをぶった切って使おうかと。

そんなわけでもう10年以上も昔に押し入れの奥にしまい込んだ、手持ちのMIDIケーブルを引っ張り出して来ると、、

お前はもう、氏んでいる

ハードオフでも行って来ましょうかね・・・

ひとまず

頓挫!