LoginSignup
2
1

More than 1 year has passed since last update.

ESP32のBLEのRSSIを調べてみた

研究の一環として,ESP-WROOM-32を用いてRSSI値の測定をやってみました.

使用機材

環境構築

筆者は日頃Python3を用いてコードを書いているので,今回はmicropythonを使っています.
ESP32でmicropythonを使う場合はこちらを参照してください.

https://micropython-docs-ja.readthedocs.io/ja/latest/esp32/tutorial/intro.html

エディタやIDEはお好みで大丈夫ですが,作成したコードをESP32に焼く際はesp-idfを用いるのが楽だと感じました.
クイックリファレンスがGithubに上がっていますので,興味がある方はぜひ.

https://github.com/espressif/esp-idf

BLEのRSSI取得方法

公式のGithubのコードを参考にさせていただきました.

https://github.com/micropython/micropython

参考にさせていただいたのは,example > bluetooth内のコードです.

送信側の処理

送信側はble_advertising.pyble_temperature.pyをそのまま使用しています.

受信側の処理

まず,ble_advertising.pydemo()を自分の環境に合わせて変更してください.

def demo():
    payload = advertising_payload(
        name="micropython",
        services=[bluetooth.UUID(0x181A), bluetooth.UUID("XXXX")],
    ) #送信側のUUIDに設定

筆者はMongoDBにデータを格納しているので以下のようなコードになりました.
xxxの部分は適時変更してください.

import ubluetooth
import utime
import ubinascii
import urequests
import ujson
import network, urequests, utime
from machine import Pin, RTC
from micropython import const

_IRQ_SCAN_RESULT                     = const(5)
_IRQ_SCAN_DONE                       = const(6)

def send_db(name,addr,rssi):
    url = 'http://xxxxxxx'
    now = get_jst()
    payload = {
        "db": "xxx",
        "collection": "xxx",
        "datetime": now,
        "data": {
            "name": name,
            "addr": ubinascii.hexlify(addr),
            "rssi": rssi,
        }
    }
    header = {
            'Content-Type' : 'application/json'
            }
    res = urequests.post(
        url,
        data = ujson.dumps(payload).encode("utf-8"),
        headers = header
    )
    res.close()

def get_jst():
    rtc = RTC()
    url_jst = "http://worldtimeapi.org/api/timezone/Asia/Tokyo"
    retry_delay = 5000
    response = urequests.get(url_jst)
    parsed = response.json()
    datetime_str = str(parsed["datetime"])
    year = int(datetime_str[0:4])
    month = int(datetime_str[5:7])
    day = int(datetime_str[8:10])
    hour = int(datetime_str[11:13])
    minute = int(datetime_str[14:16])
    second = int(datetime_str[17:19])
    subsecond = int(round(int(datetime_str[20:26]) / 10000))
    rtc.datetime((year, month, day, 0, hour, minute, second, subsecond))
    daysOfTheWeek = "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"
    tm = utime.localtime(utime.mktime(utime.localtime()))
    date_str = "{0:4d}/{1:02d}/{2:02d}".format(*rtc.datetime())
    time_str = "{4:02d}:{5:02d}:{6:02d}".format(*rtc.datetime())
    date_ok = date_str + " " + time_str
    return date_ok

ble=ubluetooth.BLE()

if ble.active()== False:
    ble.active(True)

def bt_irq(event, data):
    if event == _IRQ_SCAN_RESULT:
        addr_type, addr, connectable, rssi, adv_data = data
        name = "xxx"
        addr_hex = ubinascii.hexlify(addr)
        if '{}'.format(ubinascii.hexlify(addr)) == 'b\'xxxxx\'':
            print('addr:{} rssi:{} '.format(ubinascii.hexlify(addr), rssi ))
            send_db(name, str(addr_hex), rssi)
    elif event == _IRQ_SCAN_DONE:
        print('Scan compelete')
        pass

ble.irq(bt_irq)
ble.gap_scan(600000, 30000, 30000)

ble.gap_scan()に関する詳しい説明はubluetoothのリファレンスを読んでみてください.

https://micropython-docs-ja.readthedocs.io/ja/latest/library/ubluetooth.html

RSSIの測定

受信側,送信側それぞれをESP32に焼き,実行してみましょう.
筆者はWebREPLを使用しています.
Screen Shot 2021-07-25 at 22.21.45.png

WebREPLの使用手順

①左上のIPアドレスを変更し,Connect!
②右上からファイルを選択し,Send to device!
③以下のコマンドを実行!

>>> execfile("xxx.py")

3つのビーコンで測定

各ビーコンで1mの時をそれぞれ測定すると以下のような分布になりました!
なお,縦軸は取得回数,横軸はRSSI値です.
Picture1.png
Picture2.png
Picture3.png

しっかり測定はできましたが,それぞれで誤差がかなりありそうですね...

おわりに

ESP32は機器ごとにも誤差が大きいようで,しっかりとした基準値をうまく決めないと使えないようですね...
位置精度の改善や座標の特定など色々な用途に使用できそうですね!

2
1
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
2
1