LoginSignup
35
28

More than 1 year has passed since last update.

M5StackとiOS端末と通信してみた

Last updated at Posted at 2019-04-10

今回のゴール

M5StackとiPhoneの間でBluetooth LE通信する。
今回作るプロジェクトは、下記の通り。

  • M5Stackのボタンを押すと液晶を赤・黄・青に変わる
  • iPhoneも同じように3色のボタンをつけてボタンを押すと色が変わる
  • BluetoothLEで相互に接続し、M5Stackで色を変化させると連動してiPhoneの画面も変わる。その逆もできるようにする

って感じです。

ソースはGithubに公開されています。

demo.gif

BluetoothLEの基礎知識

簡単ですが、BluetoothLEでは以下のことを理解しておくと便利です。

  • デバイスの役割として、ペリフェラルとセントラルがある
  • ペリフェラルは、発信する側 → 親機
  • セントラルは、受信する側 → 子機
  • GATT → 通信のベースとなるプロファイル
  • write、read、notifyの3つがある
  • writeは、セントラル→ペリフェラルにデータを渡す
  • readは、セントラル→ペリフェラルに読み込みデータを要求する
  • notifyは、ペリフェラル→セントラルに通知する

BluetoothLEのサービスUUIDを取得する

Online UUID Generatorで3つのUUIDを作成します。
Bulk Version 1 UUID GenerationHow Many?3 と入力して GENERATE してください。
スクリーンショット 2019-04-10 22.47.42.png
生成された3つのUUIDはあとで使いますので控えてください。(赤枠のところ)

M5StackのBluetoothLE周りの解説

今回は、M5Stackをペリフェラルとして、writeとnotifyを使います。
まずUUIDを3つ定義します。

  • サービスUUID→writeとnotifyが使えますよとiPhoneに通知するために使います
  • write→iPhoneからのデータを受診するために使います。
  • notify→iPhoneにデータを送るために使います。

setup()時に初期化するに必要なinitBLE()にまとめてあります。
loop()で必要な処理はloopBLE()にまとめています。

ボタンを押した時にloopLCDcolor()内に実装されている下記コードでiPhoneにデータを送信しています。

if (deviceConnected) {
  char sendMessage[10];
  lastColor.toCharArray(sendMessage, 10);
  pNotifyCharacteristic->setValue(sendMessage);
  pNotifyCharacteristic->notify();
}

iOSアプリ側の実装

まずM5Stackを検索するためにペリフェラルスキャンをします。
まずCoreBluetoothのCentralManagerのインスタンス取得します。

centralManager = CBCentralManager(delegate: self, queue: nil, options: nil)

Bluetoothデバイスの電源など入るとfunc centralManagerDidUpdateState(_ central: CBCentralManager)が呼ばれます。
central.state.poweredOnならばペリフェラルスキャンを開始します。

centralManager.scanForPeripherals(withServices: nil, options: nil)

ペリフェラルを発見するとfunc centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber)が呼ばれます。
M5Stackで設定したローカルネームと一致するか確認し一緒ならばペリフェラルスキャンを停止し、そのペリフェラルと接続します。

centralManager.stopScan()
centralManager.connect(connectToPeripheral, options: nil)

ペリフェラルを接続完了するとfunc centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral)を呼ばれるので対応しているサービスを取得します。

connectToPeripheral.delegate = self
connectToPeripheral.discoverServices(nil)

サービスを取得できるとfunc peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?)が呼ばれます。1サービスごとに呼ばれます。

サービスがnotifyの場合、M5Stackからデータが送信されるので待ち受けします。

connectToPeripheral.setNotifyValue(true, for: characteristic)

実際に、M5Stackからデータが送られてくるとfunc peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?)が呼ばれます。

最後に

ベタ書きコードで恥ずかしいですが、M5Stack(ESP32にも使える)とiOSデバイスでBluetoothLE通信しているサンプルがなかなか見つけづらいので参考になればと思います。

35
28
4

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
35
28