📘

iPad Swift PlaygroundsでBluetooth LE アプリを作成してPicoW搭載ロボットをリモート操作

2024/01/08に公開

はじめに

iPadとiPhoneは使っていますが、macを持たないWindowsユーザーです。
iPadのSwift Playgroundsでアプリを作成してみました。
Javascript、Pythonを使ってきました。Swiftは全くの初心者です。
まだ出来上がったものには考慮不足がいっぱいあるでしょうが、
プログラミングを楽しむ道が一つ開けたように思っています。
iPadだけでもできるんだ・・という参考になればと思い紹介します。
(注1)keyboardとmouseは必要と思います(無しでは試していません)
(注2)完成アプリをインストールするには有料年間サブスクリプションが必要です


iPad Swift Playgrounds プログラミング環境
LiveViewパネルから2足歩行ロボットをリモート操作

iOSアプリへ Bluetooth LE UART 実装 今回のポイント

Bluetooth LE UARTの接続、送受信 実装の要点は以下です。
iOSDC Japan 2022で大庭さんが発表されている資料の24ページ目が一番参考になりました。接続からデータ送信までをコンパクトにまとめられています。LEGO-Remote-Playgroundsをひな型に活用させていただきました。受信は使用するライブラリAsyncBluetoothのREADMEに記載されているSubscribe to a characteristicの方法を使用しました。
今回紹介するのは、その実装例です。
Peripheral側のPico WはMicro PythonでBluetooth LE UARTを実装しています。

システム構成

構成

Bluetooth Low Energy UARTで通信します

  • BLE Central: iPad - Swift Playgrounds
  • BLE Peripheral: Pico W - Micro Python


UI

  • PANEL/ADJUSTの2画面をタブで切り替えます。

  • コントロールパネル (PANEL)
    connectボタンをタップすると接続を開始
      Scanning...表示中にタップすると接続を停止
      接続するとデバイス名を表示
      デバイス名前の✖をタップすると接続を解除
    方向を示すボタンで動作を指示します。
      左前進、前進、右前進
      左回転、停止、右回転
      左後進、後進、右後進
    ボタンをタップし続けることで連続動作、ボタンを離すと停止

  • 調整 (ADJUST)
    ロボットの部品ばらつき、組み立てばらつきによる角度ズレを補正
    スライドバーを変更してUPDATEボタンをタップすことで更新
    脚の角度をTop Viewで、足の角度をFront Viewで調整
    調整値をPico Wでファイルに保存してバックアップ


UART通信定義


UART通信定義


BLE central: Swift Playgrounds 2足歩行ロボットリモコン

プロジェクトファイル

GitHubのpicow_robo2/SwiftPlaygrounds_BLE/に保存してあります。
 ・MyApp.swift ------------ main ひな型のまま
 ・ContentView.swift ------ Tab切り替え
 ・PagePanelView.swift ---- PANEL画面
 ・PageAdjustView.swift --- ADJUST画面
 ・ViewModel.swift -------- BLE uart接続、送受信、ロボット制御コマンド処理

Swift Playgrounds へ組み込み方

各ソースファイルをiPadにダウンロードしておいてください。

新規プロジェクトを作成してダウンロードしたソースを反映する手順を示します。

Capture conditions: iPadOS 16.7.2, Swift Playgrounds 4.4.1, iPad Pro (10.5 inch)

  1. Playgroundsを起動し画面左下のボタン[+]をタップしてプロジェクトを追加します。
  2. 追加されたアプリアイコンをタップしてプロジェクトを開きます。
    ※アプリアイコンを長押しすると名前変更することができます。
  3. 左上のマークをタップしてコードリストを開きます。
    ※コードリストの上の"App設定"を開くとアプリ名、アイコン変更など設定できます。
  4. コードファイル名を長押ししてファイルを全て削除します。
  5. ⊕マークの付いたアイコンをタップして追加メニューを開きます。
  6. "挿入元..."をタップします。
  7. 読み込むファイルを全て選択して"開く"をタップします。
  8. ⊕マークの付いたアイコンをタップして追加メニューを開きます。
  9. "Swiftパッケージ"をタップします。
  10. AsyncBluetoothのurl "https://github.com/manolofdez/AsyncBluetooth" を入力し⏎
  11. "Appプレイグランドに追加"をタップします。
  12. 左上のマークをタップしてコードリストを閉じます。
  13. マークをタップするとLiveViewが表示されます。
  14. マークをタップするとprint出力をモニターできます。
    以上、簡単にプロジェクトファイルを作成し反映することができます。

拡張子.swiftpmのプロジェクトファイルの中身をWindowsでも確認できればいいのですが、方法を見つけることができませんでした。中身を把握できていないものをgitに上げることはできないので、全てのソース内容を別のエディタにコピペしてファイルを作成しました。macを持たない状態では外部との連携を取りにくいです。

現状の私の運用方法は下記です。
・Windowsでソースファイルを管理、最終のソース編集もWindowsで行う
・iPadにプロジェクトひな型を作成しWindowsからソースを読み込んで差し替え確認する
・iPadでの変更量が多いときはファイルにコピペ、Windowsへアップロードして反映する

ソース説明

・MyApp.swift --- Playgroundsが自動作成するひな型からの変更はありません。
https://github.com/ha864git/picow_robo2/blob/main/SwiftPlaygrounds_BLE/MyApp.swift

・ContentView.swift --- Tab切り替え
 PANEL/ADJUSTの2画面をタブで切り替えています。
 ADJUST画面への切り替え時に調整値要求('get angles_init')を送信しています。
https://github.com/ha864git/picow_robo2/blob/main/SwiftPlaygrounds_BLE/ContentView.swift

・PagePanelView.swift --- PANEL画面
 LEGO-Remote-PlaygroundsのContentView.swiftをひな型に活用させていただきました。
https://github.com/ha864git/picow_robo2/blob/main/SwiftPlaygrounds_BLE/PagePanelView.swift
 タップ開始onTouchDownGestureと離したときonTouchUpGesturを拡張しています。
 OnTouchDownGestureModifierは下記を引用しました。TouchUpはその変形です。
https://stackoverflow.com/questions/58784684/how-do-you-detect-a-swiftui-touchdown-event-with-no-movement-or-duration

・PageAdjustView.swift --- ADJUST画面
 ADJUST画面への切り替え時の送信('get angles_init')に対する
 応答('ri xx,xx,xx,xx')を受信してSliderの位置に反映されています。
 UPDATEボタンをタップするとslider内容を反映して
 調整値設定コマンド('si xx,xx,xx,xx')を送信します。
https://github.com/ha864git/picow_robo2/blob/main/SwiftPlaygrounds_BLE/PageAdjustView.swift

・ViewModel.swift -------- BLE uart接続、送受信、ロボット制御コマンド処理
 LEGO-Remote-PlaygroundsのViewModel.swiftをひな型に活用させていただきました。
https://github.com/ha864git/picow_robo2/blob/main/SwiftPlaygrounds_BLE/ViewModel.swift
 UART受信はAsyncBluetoothのREADMEに従い、下記のようなコードとしました。

    peripheral?.characteristicValueUpdatedPublisher
      .filter { $0.uuid == rx_char_uuid }
      .map { try? $0.parsedValue() as String? }
      .sink { value in
        self.checkCommand(cmd: (value ?? ""))
      }
      .store(in: &cancellables)
    try await peripheral?.setNotifyValue(true, forCharacteristicWithCBUUID: rx_char_uuid, ofServiceWithCBUUID: uart_service_uuid)

参考

大庭さんのプログラムを参考にさせていただきました。
https://github.com/bricklife/LEGO-Remote-Playgrounds

YouTube iOSDC Japan 2022: Bluetoothでレゴをリモートプログラミングしよう / 大庭 慎一郎
特に発表資料の24ページ目(↓リンク)が大変参考になりました。ありがとうございます。
https://www.docswell.com/s/bricklife/ZDXYL5-lego-bluetooth-programming#p24


BLE peripheral: Pico W 2足歩行ロボット Program

- BLE peripheral - Pico W版 bipedal robot
※タイトルとの関連性が低いのでBOOK参照に変更しました(2024/1/15)

Hardware: Pico W版 2足歩行ロボットの作り方

bipedal robot Hard - Pico W版
※タイトルとの関連性が低いのでBOOK参照に変更しました(2024/1/15)

Discussion