LoginSignup
0
0

More than 1 year has passed since last update.

BLEモジュールを使ってみた

Last updated at Posted at 2022-04-15

使うもの

参考文書

太陽誘電のEYSGJNはファームウエアのソースまで開示されるようなのですが、個人用途だからか入手までたどり着けませんでした。資料は入手できましたが、Confidentialなので、詳しいことは書けません。
MicrochipのRN4020は資料が公開されていますが、ソースは入手できません。ファームのアップデート機能はありますが、ファームを自分でつくることはできません。
資料をざっと見た限りでは、Microchipの方が親切というか、色々できそうな気がします。

Microchip RN4020

RN4020(正確にはRN4020使用モジュール)は5Vを直接つなげられるので、USBで電源供給します。
USB-RN4020.png
USBシリアル変換モジュール (https://akizukidenshi.com/catalog/g/gM-08461/) を使っています。この手の変換ケーブルは結構高くて、何本も買うと思わぬ出費になりますが、これはコスパもよくて非常によいです。ただし、ちょっとだけハンダ付けが必要です。

USBケーブルをPCに挿すと起動します。
Dコマンド(RN4020設定出力コマンド)を実行してみると、
RN4020 Dコマンド.png

意味 対応コマンド
BTA MACアドレス 68271921D57D
Name デバイス名 RND57D
Connected 接続済みデバイス no (なし)
Bonded ボンディング済みデバイス no (なし)
Server Services サーバーロールで
サポートするサービス
80000000
(Device Information)
SS
Features サポート機能(Feature) 00060000
(I/O Capability =
No Input, no output)
SR
TxPower 送信出力 4 (-2.5dBm) SP

Connected,Bondedは現在の状態ですが、設定は対応するコマンドで変更することができます。
I/O Capability = No Input, no output は、私はキーボード(操作パネル)もディスプレイも持たないデバイスだという宣言になります。今回は、PCがキーボードとディスプレイになるので、I/O Capability = Keyboard Display にするのが適切です。

起動が確認できたので、RN4020をペリフェラルとしてスマホから接続してみます。
peripheral.png
参考文書[1]
Chapter 3. アプリケーション例
3.1 スマートデバイスとの接続によるデモ
peripheral demo.png

コマンド 応答 備考
Echo On +コマンドの応答
SF,1 AOK 工場出荷設定にリセット
SS,C0000000 AOK Device InformationとBatteryサービスの有効化
SR,00000000 AOK ペリフェラルに設定
R,1 Reboot 再起動
CMD 起動メッセージ
Echo On +コマンドの応答
LS 180A~END サービス一覧取得
A AOK アドバタイズ開始

LSコマンドは、SSコマンドで設定したサービスの確認です。
180AはDevice Informationサービス、180FはBatteryサービスのUUIDです。
これをスマホで見てみると、
smart phone.png
このBLEモジュールのデバイス名である、RND57Dが表示されています。
smart phone2.png
スマホアプリはnRF Connect for Mobileを使いました。
LSコマンドで表示される2A25,2A27,...は各サービスのキャラクタリスティックのUUIDですが、それぞれの意味はこの画面を見れば一目瞭然です。例えば、2A25はシリアル番号を意味し、その値は68271921D57Dです。

この値はMACアドレスなのですが、それはこのモジュールにおいて、シリアル番号のデフォルト値がMACアドレスであるためです。

参考文書[1] p.24
Serial Number command.png

太陽誘電 EYSGJN

EYSGJNの電源は1.8~3.6Vです。ラズパイの3.3Vから取ってもいいのですが、USBの5Vからレギュレータ (https://akizukidenshi.com/catalog/g/gI-11318/) を使って3Vにしました。
regulator.png
EYSGJN board.jpg
スマホで見てみると、
Scanner EYSGJN.png
TYSA-B 3.0.0が、このモジュールのデバイス名です。

全体

DSC_1847.JPG

EYSGJNをペリフェラル、RN4020をセントラルとして、RN4020から接続します。

F // Start scan
AOK
DCBDD693FA10,1,TYSA-B 3.0.0,1804|180F,-1E
X // Stop scan
E,1,DCBDD693FA10 // Establish connection
AOK
Connected
ConnParam:00A0,0000,01F4

EYSGJNのサービスを取得します。

LC
180F
  2A19,0012,02
  2A19,0013,10
END

180FはBattery serviceのUUIDです。2A19はBattery levelのcharacteristicで、0012,0013はUUIDの代わりに使用できるハンドルです。このハンドルは、UUIDの桁が大きいときに入力の手間を省くためのもので、RN4020のコマンドでのみ使用できます。

Battery levelの値を取得すると、

CHR,0012
R,64.

USB給電だからか、0x64 = 100%でした。この値を任意に変更できると面白いのですが、EYSGJNのマニュアルを見てもよくわかりませんでした。
なお、EYSGJNのコマンドはConfidentialなので、書くことができません。

Battery levelの値を一定周期で何点か取ってグラフにするGUIを、Djangoでつくりました。

Animation3.gif
ソースの一部

ble_serial.py
import re
from serial import Serial

class BleSerialPort:
    def __init__(self) -> None:
        try:
            self.port = Serial("COM6", 115200)
        except:
            self.port = None
        self.scan_list = []
    
    def __del__(self):
        if self.port != None:
            self.port.close()
    
    def start_scan(self):
        if self.port != None:
            self.scan_list = []
            self.send("F", callback=self.scan_callback)

    def send(self, command, timeout=1, callback=None):
        self.port.timeout = timeout

        print(f"> {command}")
        self.port.write(f"{command}\r\n".encode("utf-8"))
        while True:
            line = self.port.readline()
            if line == b"":
                # timeout
                break
            if callback != None:
                callback(line)
            print(line)

    def scan_callback(self, line):
        # <BTADDR>,<PRIVATE>,<BTName>,<UUID>,<RSSI>
        pattern = re.compile("([^,]*),([^,]*),([^,]*),([^,]*),([^,]*)")

        m = pattern.match(line.decode("utf-8"))
        if m != None:
            device = {
                "BTADDR": m.group(1),
                "PRIVATE": m.group(2),
                "BTName": m.group(3),
                "UUID": m.group(4),
                "RSSI": int(m.group(5), 16)
            }
            self.scan_list.append(device)
views.py
from django.shortcuts import render
from .ble_serial import BleSerialPort

def index(request):
    port = BleSerialPort()

    port.start_scan()
    port.stop_scan()

    context = {
        "scan_list": port.scan_list,
    }
    print(context)

    return render(request, 'monitor/index.html', context)
index.html
<table class="table">
    <thead>
        <tr>
            <th>BTADDR</th>
            <th>PRIVATE</th>
            <th>BTName</th>
            <th>UUID</th>
            <th>RSSI</th>
        </tr>
    </thead>
    <tbody>
        {% for device in scan_list %}
        <tr>
            <td>{{ device.BTADDR }}</td>
            <td>{{ device.PRIVATE }}</td>
            <td>{{ device.BTName }}</td>
            <td>{{ device.UUID }}</td>
            <td>{{ device.RSSI }}</td>
        </tr>
        {% endfor %}
    </tbody>
</table>
0
0
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
0
0