3
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

MicroPythonのBluetoothについて調べてみた

Last updated at Posted at 2022-07-07

はじめに

MicroPythonのBluetooth通信について気になったのでまとめてみます

Bluetoothとは

Bluetoothは近距離 無線通信規格の一つです

Bluetoothの利点

  • 省電力
  • アップグレードが容易
  • 赤外線通信よりも広範囲
  • 音声とデータの転送ができる
  • 使用できるデバイスが安価

Bluetoothの欠点

  • Wi-Fiに比べて帯域幅が狭い
  • デバイス間の短距離通信のみ可能
  • 屋内環境において電波の減衰が起こる

BLE(Bluetooth Low Energy)とは

Bluetoothの一部で,バージョン4.0から追加された低消費電力の通信規格です.電池寿命の延長を目的として,無線部分の消費電力削減がされています.このおかげでボタン電池で複数年稼働するため,IoTデバイスの通信方式で注目されています.

MicroPythonのBluetooth

Bluetoothモジュールはボード上のBluetoothコントローラーへのインターフェースを提供していて,Bluetooth Low Energy(BLE)をサポートしています.セントラル(Central),ペリフェラル(Peripheral),ブロードキャスター(Broadcaster),オブザーバー(Observer)のロールがあり,GATTサーバ/クライアントロール,L2CAP connection-oriented-channelsもあります.

  • セントラルとペリフェラルの関係qiita.png

クラスBLE

コンストラクタ

class bluetooth.BLE

  • BLEオブジェクトを返す

設定

BLE.active( [active,] /)

  • オプションでBLE無線のアクティブ状態を変更し,現在の状態を返す

BLE.config('param'./)

BLE.config(*,param=value,...)

  • BLEインターフェイスの設定値を取得or設定
  • パラメーター名を文字列として一度に1つだけ指定する
  • 値を設定する場合には,キーワード構文を使って,一度に1つ以上のパラメーターを設定できる
使える値 'addr_mode' 'mac' 'gap_name'
出来る事 アドレスモードを設定 現在利用中のアドレスを取得 サービス0x1800,キャラクタリスティック0x2a00で利用するGAPデバイス名を取得/設定
戻り値 (addr_type, addr)

ブロードキャスターロール(アドバタイザー):送信側

BLE.gap_advertise(interval_us,adv_data=None,*,resp_data=None,connectable=True)

  • 指定された間隔(マイクロ秒単位)でアドバタイジング(Advertising)を開始する
  • アドバタイジングを停止するにはinterval_usをNoneに設定する
  • adv_data,resp_dataはバッファプロトコルを実装する任意のタイプにできる(bytes,bytearray,str)
  • adv_dataはすべてのブロードキャストに含まれ,resp_dataはアクティブスキャンへの返信として送信される

オブザーバ―ロール(スキャナー):受信側

BLE.gap_scan(duration_ms,interval_us=1280000,window_us=11250,active=False,/)

  • 指定された期間(ミリ 秒単位)持続するスキャン操作を実行する

  • 時間していないしでスキャンするときはduration_msを0に設定する

  • スキャンを停止するにduration_msをNoneに設定する

  • スキャン結果毎に_IRQ_SCAN_RESULTイベントが発生する,イベントデータは(addr_type, addr, adv_type, rssi, adv_data)

  • addr_typeの値はPUBLICまたはRANDOMアドレスであるかを示す

    • 0x00 - PUBLIC
    • 0x01 - RANDOM(RANDOM,RPA,NRPAのいずれかで,どれであるかはアドレス自体にエンコードされている)
  • 'adv_type' の値は次のBluetooth仕様に対応している

    • 0x00 - ADV_IND - 接続/スキャン可能な無向アドバタイジング
    • 0x01 - ADV_DIRECT_IND - 接続可能な有向アドバタイジング
    • 0x02 - ADV_SCAN_IND - スキャン可能な無向アドバタイジング
    • 0x03 - ADV_NONCONN_IND - 接続不可能な無向アドバタイジング
    • 0x04 - SCAN_RSP - スキャン応答
  • スキャンの応答を結果として受け取りたい場合は,activeをTrueにする

セントラルロール

セントラルデバイスは,オブザーバーロールを使うか,既知のアドレスで検出したペリフェラルに接続できる

BLE.gap_connect(addr_type,addr,scan_duration_ms=2000,min_conn_interval_us=None,max_conn_interval_us=None,/)

  • ペリフェラルに接続する
  • 未処理の接続試行を早期にキャンセルするにはgap_connect(None)を呼び出す
  • 接続に成功すると_IRQ_PERIPHERAL_CONNECTイベントが発生する.接続の試行をキャンセルすると_IRQ_PERIPHERAL_DISCONNECTイベントが発生する
  • デバイスからのアドバタイジングペイロードを受信するまでscan_duration_msまで待機する
  • 接続間隔はmin_conn_interval_usおよびmax_conn_interval_usのいずれかまたは両方を使ってマイクロ秒単位で設定できる.それ以外の場合は,通常30000~50000マイクロ秒の間でデフォルトの間隔が選択される.間隔を短くするとスループットが向上するが消費電力は増加する

ペリフェラルロール

ペリフェラルデバイスは,接続可能なアドバタイズを送信することできる.通常はgatts_register_servecesを用いて最初に登録されたサービスとキャラクタリスティックを持つGATTサーバとして動作する.
セントラルが接続すると`_IRQ_CENTRAL_CONNECT'イベントが発生する

セントラル&ペリフェラルロール

BLE.gap_disconnect(conn_handle,/)

  • 指定した接続ハンドル(接続の識別)を切断する
  • (ペリフェラルとして動作している)このデバイスに接続したセントラル,または(セントラルとして動作している)このデバイスに以前に接続されていたペリフェラルのいずれかになる
  • 切断に成功すると_IRQ_PERIPHERAL_DISCONNECTまたは_IRQ_CENTRAL_DISCONNECTイベントが発生する
  • 接続ハンドルが接続されていない場合はFalseを,そうでない場合はTrueを返す

GATTサーバ

  • GATTサーバには登録されたサービスのセットがある
  • 各サービスにはキャラクタリスティックが含まれていることがあり,各キャラクタリスティックは値を持つ
  • キャラクタリスティックには,それ自体に値を持つディスクリプタを含めることもできる
  • 値はローカルに保存され,サービス登録中に精製される「値ハンドル(value handle)」によってアクセスされる.また,リモートのクライアントデバイスから読み書きすることもできる.さらに,ペリフェラルは接続ハンドルを介して接続されたクライアントにキャラクタリスティックを「通知」できる.
  • セントラルまたはペリフェラルのいずれかのロールを持つデバイスがGATTサーバとして機能するが,ペリフェラルがサーバとして機能するのが一般的
  • キャラクタリスティックとディスクリプタのデフォルト最大サイズは20バイト
キャラクタリスティックとは
  • ペリフェラル機器がセントラル機器に公開して共有するデータ構造
  • ペリフェラル機器とセントラル機器はこのキャラクタリスティックを介してデータのやり取りを行う

BLE.gatts_register_services(services_definition,/)

  • 指定したサービスでサーバを構成し,既存サービスを置換する
  • services_definitionはサービスのリストであり,各サービスはUUIDとキャラクタリスティックのリストを含む2項目のタプル
  • 各キャラクタリスティックは,UUID,フラグ値,およびオプションのディスクリプタのリストを含む2または3項目のタプル
  • 各ディスクリプタはUUIDとフラグ値を含む2項目のタプル

BLE.gatts_read(value_handle,/)

  • このハンドルのためのローカル値(gatts_writeかリモートクライアントで書き込まれたもの)を読み取る

BLE.gatts_write(value_handle,data,send_update=False,/)

  • このハンドルのローカル値を書き込む.クライアントによって読み取ることができる
  • send_updateがTrueの場合,サブスクライブしているクライアントにこの書き込みいついて通知される

BLE.gatts_indicate(conn_handle,value_handle,/)

  • キャラクタリスティックの現在の値を含む指示(indication)要求を接続中のクライアントに送信する
  • acknowledgment(あるいはタイムアウトなどの失敗)があった場合,_IRQ_GATTS_INDICATE_DONEイベントが発生する

BLE.gatts_set_buffer(value_handle,len,append=False,/)

  • 値の内部バッファサイズをバイト数で設定.受信可能な最大の書き込みが制限される.デフォルトは20
  • appendをTrueに設定すると,すべてのリモート書き込みが現在の値に置き換えられるのではなく,追加される
  • gatts_readを使用すると,読み取り後に値がクリアされる.

GATTクライアント

GATTクライアントは,リモートのGATTサーバ上のキャラクタリスティックを発見し,読み書きできる
セントラルロールを持つデバイスがGATTクライアントとして動作するのが一般的ですが,接続したセントラルについての情報を発見するためにペリフェラルがクライアントとして動作することも可能

BLE.gattc_discover_servives(conn_handle,uuid=None,/)

  • サービスについて接続されたサーバを問い合わせる
  • オプションで照会するサービスのUUIDを指定できる
  • 検出された各サービスについて_IRQ_GATTC_SERVICE_RESULTイベントが発生し,検索が完了すると_IRQ_GATTC_SERVICE_DONEになる

BLE.gattc_discover_characteristics(conn_handle,start_handle,end_handle,uuid=None,/)

  • 指定した範囲のキャラクタリスティックについて接続されたサーバを問い合わせる
  • オプションで照会するキャラクタリスティックのUUIDを指定できる
  • 任意のサービスのキャラクタリスティックを検索するにはstart_handle_=1,end_handle=0xffffとする
  • 検出された各キャラクタリスティックについて_IRQ_GATTC_CHARACTERISTIC_RESULTイベントが発生し,検索が完了すると_IRQ_GATTC_CHARCTERISIC_DONEになる

BLE.gattc_discover_descriptors(conn_handle,start_handle,end_handle,/)

  • 指定した範囲のディスクリプタについて接続されたサーバを問い合わせる
  • 検出された各ディスクリプタについて_IRQ_GATTC_DESCRIPTOR_RESULTイベントが発生し,検索が完了すると_IRQ_GATTC_DESCRIPTOR_DONEになる

BLE.gattc_write(conn_handle,value_handle,data,mode=0,/)

  • 指定したキャラクタリスティックあるいはディスクリプタについて接続されたサーバにリモート書き込みを発行する
  • 引数modeは書き込み動作を指定する.現在サポートされているのは以下
    • mode=0(デフォルト)は応答なしの書き込み.書き込みはリモートサーバに送信されるが,確認は返されず,イベントは発生しない
    • mode=1は応答付きの書き込み.リモートサーバはデータを受信したという応答/承認を送信するように要求される

BLE.gattc_exchange_mtu(conn_handle,/)

  • BLE.config(mtu=value)で設定した優先MTUを使って,接続されているサーバとのMTU交換を開始する
  • MTU交換が完了すると_IRQ_MTU_EXCHANGEDイベント発生する

L2CAP connection-oriented-channels

2つのBLEデバイス間でのソケットのようなデータ交換が可能になる.デバイスがGAPを介して接続されると,どちらかのデバイスは他方のデバイスがPSM(Protoclo/Service Multiplexer)番号でリスンできる.

アクティブなL2CAPチャネルは,確率された接続ハンドルとCID(チャネルID)によって識別される.

BLE.l2cap_listen(psm,mtu,/)

  • 指定のpsmmtuに指定のローカルMTUで,L2CAPチャネル要求の着信のためのリスンを開始する
  • リモートデバイスが接続を開始すると_IRQ_L2CAP_ACCEPTイベントが発生し,リスン中のサーバに着信接続を(0以外の整数を返すことで)拒否する機会が与えられる
  • 接続が受け入れられると_IRQ_L2CAP_CONNECTイベントが発生し,サーバがチャネルID(CID)とローカルおよびリモートのMTUを取得できるようになる

BLE.l2cap_connect(conn_handle,psm,mtu,/)

  • mtuに設定したローカルMTUで,指定したpsm上のリスニングピアに接続する
  • 接続に成功すると_IRQ_L2CAP_CONNECTイベントが発生し,クライアントはCID
  • CIDとローカルおよびリモートの(ピア)MTUを取得できるようになる
  • 接続に失敗すると_IRQ_L2CAP_DISCONNECTイベントが発生し,ステータスは0以外になる

BLE.l2cap_disconnect(conn_handle,cid,/)

  • 指定したconn_handlecidを持つアクティブなL2CAPチャネルを切断する

BLE.l2cap_send(conn_handle,cid,buf,/)

  • conn_handlecidで識別されるL2CAPチャネル上で,指定したbuf(バッファプロトコルをサポートしている必要アリ)を送信する
  • 指定されたバッファは,リモート(ピア)MTUよりも大きく,ローカルMTUの2倍以下のサイズにすることはできない
  • これはチャネルがストールしている場合に,Falseを返す.この状態では_IRQ_L2CAP_SEND_READYイベントを受信するまで(リモートデバイスがより多くのクレジットを付与したとき,通常はデータ受信して処理した後に発生する),l2cap_sendを再度呼び出してはならない

BLE.l2cap_recvinto(conn_handle,cid,buf,/)

  • 指定したconn_handleおよびcidから,指定したbufにデータを受信する
  • チャネルから読み込んだバイト数を返す
  • bufがNoneの場合,利用可能なバイト数を返す

まとめ

MicropythonでBluetoothやろうとするといろいろできそうです.Bluetooth通信に関する用語が全然わかりませんでしたが,少しだけ理解することが出来ました.

参考にしたサイト

3
4
0

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
3
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?