Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
20
Help us understand the problem. What is going on with this article?
@From_F

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

More than 1 year has passed since last update.

今回のゴール

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通信しているサンプルがなかなか見つけづらいので参考になればと思います。

20
Help us understand the problem. What is going on with this article?
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
From_F
iOSアプリやArduinoを使って色々作っています。
code-candy
アプリ開発特化オンラインスクール「CodeCandy」です。

Comments

No comments
Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account Login
20
Help us understand the problem. What is going on with this article?