MFi認証不要! iPhoneとMIDIで双方向通信できるUSBデバイスを作ろう

15.8K Views

September 03, 23

スライド概要

iOSDC Japan 2023 Day 2 Lightning Talkの発表資料です。
https://fortee.jp/iosdc-japan-2023/proposal/b48dda55-90e2-4da8-a11e-cd21b5e8ebc5

CircuitPythonとSwift Playgroundsのコード
https://github.com/bricklife/MIDI-Servo-Control/tree/main

profile-image

SwiftとLEGOとBluetooth LEが好きなプログラマ

シェア

またはPlayer版

埋め込む »CMSなどでJSが使えない場合

関連スライド

各ページのテキスト
1.

MFi認証不要! iPhoneとMIDIで双方向通信できる USBデバイスを作ろう 大庭 慎一郎 @ooba / @bricklife iOSDC Japan 2023 - Lightning Talk

2.

自己紹介 大庭 慎一郎(おおば しんいちろう) ID: @ooba / @bricklife SwiftとLEGOが好きなプログラマ メルカリ1人目のiOSアプリエンジニア

3.

Scratch専用ブラウザ「Scrub」 https://apps.apple.com/jp/app/scrub-web-browser/id1569777095

4.

Scrubから制御できる 教育向けのUSBデバイス を作りたい

5.

教育向けデバイスといえばBBC micro:bit https://microbit.org/ iPadやScratchとBluetooth 接続をしてプログラミング

6.

Bluetooth接続だとつらいところ ペアリングが必要 電源が必要 複数台あると混乱の元 →トラブルが起きやすい

7.

もしUSB接続できたら USBケーブルで繋げるだけ 電源もUSBから供給 確実に1対1接続できる →トラブルが起きづらい

8.

iPhoneやiPadにUSB接続できるデバイス MFi認証を受けているデバイス MFi認証が不要な一般的なUSBデバイス

9.

MFi認証デバイス シリアル通信(UART)による独 自プロトコルだとMFi認証が必須 認証の費用 Appleデバイス向けの専用実装 # UARTは現在新規申請不可?

10.

MFi認証が不要なUSBデバイス 種類 デバイスの例 HID キーボード、マウス、ゲームパッド、etc UAC マイク、オーディオインターフェイス、etc MSC USBメモリ、HDD、etc UVC Webカメラ、ビデオスイッチャー、etc MIDI 鍵盤、音源、etc 入力 出力 ○ ○ ○ ○ ○ ○ API iOS 17+ ○ ○

11.

MIDIデバイスのフリを すればよさそう!

12.

MIDIメッセージを別の意味とし てやりとりする

13.

ドの音を送信でLED点灯 iPhone /iPad USBデバイス MIDIメッセージ

14.

ピッチベンドでサーボが回転 iPhone /iPad USBデバイス MIDIメッセージ

15.

ボタンが押されたらファの音を受信 iPhone /iPad USBデバイス MIDIメッセージ

16.

MIDIメッセージはたくさんの種類がある チャンネルメッセージ システムメッセージ チャンネルボイスメッ チャンネルモードメッ システムエクスクルー セージ セージ シブメッセージ システムコモンメッ セージ ノートオフ ノートオン MTCクォーターフレー タイミングクロック スタート ムメッセージ ソングポジションポイ コンティニュー ストップ ンタ アクティブセンシング ソングセレクト システムリセット チューンリクエスト オールサウンドオフ SysEx リセットオールコント ローラ ポリフォニック キー ローカルコントロール プレッシャー コントロールチェンジ オールノートオフ MIDIモード設定 プログラムチェンジ チャンネルプレッ シャー ピッチベンド エンドオブエクスク ルーシブ (EOX) システムリアルタイム メッセージ

17.

実際に作ってみた

19.

キリンさんのカタパルト

20.

システム構成 FT90B (3V動作サーボ) iPad Pro Raspberry Pi Pico

21.

Swift Playgroundsによるデモ

23.

作り方

24.

USBデバイス側 最近のマイコンは簡単に USB MIDIデバイスになれる プログラミング環境も色々 今回はRaspberry Pi Picoと CircuitPythonを利用

25.

CircuitPythonのコード import board import usb_midi import adafruit_midi from adafruit_midi.pitch_bend import PitchBend import pwmio from adafruit_motor import servo midi = adafruit_midi.MIDI(midi_in=usb_midi.ports[0], midi_out=usb_midi.ports[1], debug=True) pins = [board.GP15, board.GP16] servos = [] for pin in pins: pwm = pwmio.PWMOut(pin, frequency=50) servos.append(servo.Servo(pwm, actuation_range=180, min_pulse=500, max_pulse=2500)) # FT90B while True: msg = midi.receive() if isinstance(msg, PitchBend): if msg.channel < len(servos) and msg.pitch_bend <= servos[msg.channel].actuation_range: servos[msg.channel].angle = msg.pitch_bend

26.

iOS側 Core MIDIフレームワーク 全Appleデバイスで使える C言語ベースのAPIはつらい

27.

Core MIDIのコード init() { MIDIClientCreateWithBlock("Client" as CFString, &clientRef) { [weak self] _ in Task { @MainActor in self?.updateDestination() } } MIDIOutputPortCreate(clientRef, "Output" as CFString, &outputPortRef) } updateDestination()

28.
[beta]
Core MIDIのコード
func updateDestination() {
let numberOfDestinations = MIDIGetNumberOfDestinations()
for i in 0 ..< numberOfDestinations {
let ref = MIDIGetDestination(i)
var value: Unmanaged<CFString>?
MIDIObjectGetStringProperty(ref, kMIDIPropertyManufacturer, &value)
let manufacturer = value?.takeRetainedValue() as String?
if manufacturer == "Raspberry Pi" {
destinationRef = ref
isConnected = true
return
}
}

}

destinationRef = nil
isConnected = false

29.

Core MIDIのコード func sendPitchBend(channel: UInt, pitchBend: UInt) { guard channel <= 0x0f, pitchBend <= 0x3fff else { return } let message = MIDI1UPPitchBend(0, UInt8(channel), UInt8(pitchBend & 0x7f), UInt8(pitchBend >> 7)) } sendMIDI1Message(message)

30.

Core MIDIのコード func sendMIDI1Message(_ message: MIDIMessage_32) { guard let destinationRef else { return } var packet = MIDIEventPacket() packet.words.0 = message packet.wordCount = 1 var eventList = MIDIEventList(protocol: ._1_0, numPackets: 1, packet: packet) } MIDISendEventList(outputPortRef, destinationRef, &eventList)

31.

これは「MIDIデバイス」か?

32.

Akadako https://akadako.com/

33.

もっと知りたい人のためのキーワード MIDIの規格 - JIS X 6054-1、JIS X 6054-2、IEC63035:2017 Firmata - MIDIメッセージベースのプロトコル SysExメッセージ - 独自の可変長データを送るためのMIDIメッセージ

34.

ありがとうございました