今回はBLEに対応したESP32のRSSIをRaspberry Piで検出してみたいと思います
開発環境
ESP32
- micropython
- WSL(Windows Subsystem for Linux)
- ESP32開発ボード
- ESP-idf
- ampy (書き込みツール)
###Raspberry Pi Zero WH(Bluetooth 対応)
- Raspbian
- Python3.7
- pip3
ESP32の設定
今回はWSL内でファイルを書き込みますが,好きな書き込みツールを使用して構いません
対話モードでubluetoothモジュールがあるか確認する
ESP32でBLEを使用するにはubluetoothが必要です.モジュールの有無はhelp('modules')
で確認ができます
>>> help('modules')
__main__ framebuf uasyncio/funcs upip
_boot gc uasyncio/lock upip_utarfile
_onewire inisetup uasyncio/stream urandom
_thread machine ubinascii ure
_uasyncio math ubluetooth uselect
_webrepl micropython ucollections usocket
apa106 neopixel ucryptolib ussl
btree network uctypes ustruct
builtins ntptime uerrno utime
cmath onewire uhashlib utimeq
dht sys uhashlib uwebsocket
ds18x20 uarray uheapq uzlib
esp uasyncio/__init__ uio webrepl
esp32 uasyncio/core ujson webrepl_setup
flashbdev uasyncio/event uos websocket_helper
Plus any modules on the filesystem
もしなければ各自の使用している書き込みツールの方法でubluetoothモジュールをインストールしてください
bluetoothのサンプルプログラムをインストール
''
今回はここからgitにあるmicropythonのソースコードを拝借
git clone https://github.com/micropython/micropython
などでインストール
Bluetoothのサンプルプログラムは/micropython/examples/bluetooth/
にあります.
今回使用するのはble_advertising.py
とble_temperature.py
です
これらをESP32に書き込みます
次にble_temperature.py
を編集します
import bluetooth
import random
import struct
import time
from ble_advertising import advertising_payload
from micropython import const
_IRQ_CENTRAL_CONNECT = const(1)
_IRQ_CENTRAL_DISCONNECT = const(2)
# org.bluetooth.service.environmental_sensing
_ENV_SENSE_UUID = bluetooth.UUID(0x181A)
# org.bluetooth.characteristic.temperature
_TEMP_CHAR = (
bluetooth.UUID(0x2A6E),
bluetooth.FLAG_READ | bluetooth.FLAG_NOTIFY,
)
_ENV_SENSE_SERVICE = (
_ENV_SENSE_UUID,
(_TEMP_CHAR,),
)
# org.bluetooth.characteristic.gap.appearance.xml
_ADV_APPEARANCE_GENERIC_THERMOMETER = const(768)
class BLETemperature:
def __init__(self, ble, name="beacon1"):
self._ble = ble
self._ble.active(True)
self._ble.irq(handler=self._irq)
((self._handle,),) = self._ble.gatts_register_services((_ENV_SENSE_SERVICE,))
self._connections = set()
self._payload = advertising_payload(
name=name, services=[_ENV_SENSE_UUID], appearance=_ADV_APPEARANCE_GENERIC_THERMOMETER
)
self._advertise()
def _irq(self, event, data):
# Track connections so we can send notifications.
if event == _IRQ_CENTRAL_CONNECT:
conn_handle, _, _, = data
self._connections.add(conn_handle)
elif event == _IRQ_CENTRAL_DISCONNECT:
conn_handle, _, _, = data
self._connections.remove(conn_handle)
# Start advertising again to allow a new connection.
self._advertise()
def set_temperature(self, temp_deg_c, notify=False):
# Data is sint16 in degrees Celsius with a resolution of 0.01 degrees Celsius.
# Write the local value, ready for a central to read.
BLETemperatureクラスのdef _init(self, ble, name="mpy-temp")のmpy-tempをbeacon1など分かりやすい名前に変更します
UUIDの指定もこのファイル内でできます
main.pyの編集
ESP32は特に指定のない限り,電源が入るとmain.pyが実行されます
ここにBluetoothの発信し続けるように指定します
import ble_temperature
ble_temperature.demo()
これをESP32に書き込んだら準備完了です
#Raspberry Piの設定
bluepyなどの必要なツールを次のコマンドでインストールします
$ sudo apt install libbluetooth3-dev libglib2.0 libboost-python-dev libboost-thread-dev
$ sudo apt install python3-pip
$ cd /usr/lib/arm-linux-gnueabihf/
$ sudo ln libboost_python-py37.so libboost_python-py34.so
$ sudo pip3 install gattlib
$ sudo pip3 install bluepy
$ sudo systemctl daemon-reload
$ sudo service bluetooth restart
3行目のlibboost_python-py37.so
は自身のデバイス内のPython3のバージョンにより異なります
gatlibのインストールが出来ない場合
Rasberry Pi Zeroの低スペックのRasberry Piではgattlibのインストールがスワップファイルが原因で出来ない場合がある(自分がそうでした)ので対処
free -mでスワップファイルの容量を確認すると100MBしかないのでスワップファイルを編集します
$ free -m
total used free shared buff/cache available
Mem: 875 115 523 8 236 695
Swap: 99 3 96
$ sudo nano /etc/dphys-swapfile
dphys-swapfile
のCONF_SWAPSIZE
を100から800に変更します
次のコマンドでスワップファイルを停止して開始するとスワップファイルが800MBに変更されると思います
$ sudo /etc/init.d/dphys-swapfile stop
$ sudo /etc/init.d/dphys-swapfile start
$ sudo free -m
total used free shared buff/cache available
Mem: 432 37 222 4 172 323
Swap: 799 67 732
これでgatlibのインストールが可能になると思います.
スキャンプログラムでESP32のRSSIの検出
Python3でble_scan.pyを管理者権限で実行
import bluepy
scanner = bluepy.btle.Scanner(0)
device = scanner.scan(5) #5秒間スキャン
for device in device:
print('======================================================')
print('address : %s' % device.addr)
print('addrType: %s' % device.addrType)
print('RSSI : %s' % device.rssi)
print('Adv data:')
for (adtype, desc, value) in device.getScanData():
print(' (%3s) %s : %s ' % (adtype, desc, value))
実行結果
======================================================
address : fc:f5:c4:29:05:4e
addrType: public
RSSI : -60
Adv data:
( 1) Flags : 06
( 9) Complete Local Name : beacon1
( 3) Complete 16b Services : 0000181a-0000-1000-8000-00805f9b34fb
( 25) Appearance : 0003
======================================================
↓以下に他のBluetoothデバイス情報をが表示される
先ほど設定したESP32の情報とRSSIデータなどが表示されていると思います.
おわりに
次はRasberryPiとESP32と距離をメートル表記にして表示できるようにしたいですね
参考サイト
Raspberry Pi で bluepy を使ってmicro:bitをコントロール(https://qiita.com/FiveOne/items/ea04b74271da0f382ed6)
BLE対応のESP32用MicroPythonのビルドと書き込み - Ubuntu (Windows Subsystem for Linux)(https://qiita.com/jp-96/items/f5a18e2d10591849bd3d)