RaspberryPiPicoWの内蔵温度センサの値を、BLE(Bluetooth Low Energy)で接続してスマホに表示
目的:RaspberryPiPicoWの温度センサとBLE機能を確認する
用意するもの:RaspberryPiPicoW、書き込み用PC、スマホ
1)BLE機能が使える最新ファームウェア.uf2をDL
《 microPythonのサイト 》
ファイル名の例:v1.25.0 (2025-04-15) .uf2 / [Release notes] (latest)
☞ 今回はこのファイルを使用
《 ラズパイ公式サイト 》
ファイル名の例:RPI_PICO_W-20250415-v1.25.0.uf2
2)Bootボタンを押しながらPiPicoWを起動。
3)PiPicoWのフォルダウィンドウに.uf2をドラッグ&ドロップ
ファイルのドロップが完了したら、PicoWのフォルダウィンドウは自動的に閉じる
4)以下の3ファイルを、ThonnyでPicoW内に保存
それぞれのファイルの用途
main.py … 実行ファイル
ble_advertising.py … アドバタイズ用(BLE情報を定期的に発信)
ble_temp_sensor.py … 温度を取得して送信
# ファイル名:main.py
import time
from machine import ADC
from ble_temp_sensor import BLETemperature
import bluetooth
# 温度センサー初期化
sensor_temp = ADC(4)
conversion_factor = 3.3 / 65535
def read_temp():
reading = sensor_temp.read_u16() * conversion_factor
temp_c = 27 - (reading - 0.706)/0.001721
return round(temp_c, 2)
# BLE初期化
ble = bluetooth.BLE()
temp_service = BLETemperature(ble)
print("BLE initialized and advertising...") # ← 追加
while True:
temperature = read_temp()
print("Temp:", temperature)
temp_service.send_temperature(temperature)
time.sleep(2)
# ファイル名:ble_temp_sensor.py
import struct
import bluetooth
from micropython import const
from ble_advertising import advertising_payload
# 短いUUIDに変更(標準定義)
_TEMP_SERVICE_UUID = bluetooth.UUID(0x1809) # Health Thermometer (BLE公式規格)
_TEMP_CHAR_UUID = bluetooth.UUID(0x2A1C) # Temperature Measurement (公式)
# flags
_FLAG_READ = const(0x0002)
_FLAG_NOTIFY = const(0x0010)
_IRQ_CENTRAL_CONNECT = const(1) #bluetoothライブラリ使わなくてよいように追加
_IRQ_CENTRAL_DISCONNECT = const(2) #同上
class BLETemperature:
def __init__(self, ble, name="PicoTemp"):
self._ble = ble
self._ble.active(True)
self._ble.irq(self._irq)
self._connections = set()
# サービス登録
((self._temp_handle,),) = self._ble.gatts_register_services((
(_TEMP_SERVICE_UUID, (
(_TEMP_CHAR_UUID, _FLAG_READ | _FLAG_NOTIFY),
)),
))
# アドバタイズ用データ
self._payload = advertising_payload(name=name, services=[_TEMP_SERVICE_UUID])
self._advertise()
def _irq(self, event, data):
if event == _IRQ_CENTRAL_CONNECT: #変更
conn_handle, _, _ = data
print("Connected:", conn_handle)
self._connections.add(conn_handle)
elif event == _IRQ_CENTRAL_DISCONNECT: #変更
conn_handle, _, _ = data
print("Disconnected:", conn_handle)
self._connections.discard(conn_handle)
self._advertise()
def _advertise(self):
# アドバタイズ間隔を100msに(安定する値)
self._ble.gap_advertise(100_000, adv_data=self._payload)
def send_temperature(self, temp_c):
temp_str = "{:.1f}℃".format(temp_c)
# 元は、temp_bytes = struct.pack("<f", temp_c) # floatをバイト列に変換だった
temp_bytes = temp_str.encode('utf-8')
for conn_handle in self._connections:
self._ble.gatts_notify(conn_handle, self._temp_handle, temp_bytes)
# ファイル名:ble_advertising.py
import struct
import bluetooth
_ADV_TYPE_FLAGS = const(0x01)
_ADV_TYPE_NAME = const(0x09)
_ADV_TYPE_UUID16_COMPLETE = const(0x03)
_ADV_TYPE_UUID32_COMPLETE = const(0x05)
_ADV_TYPE_UUID128_COMPLETE = const(0x07)
def advertising_payload(limited_disc=False, br_edr=False, name=None, services=None):
payload = bytearray()
flags = 0x02 if limited_disc else 0x06
if br_edr:
flags |= 0x18
payload += struct.pack("BB", 2, _ADV_TYPE_FLAGS) + bytes([flags])
if name:
payload += struct.pack("BB", len(name) + 1, _ADV_TYPE_NAME) + name.encode()
if services:
for uuid in services:
b = bytes(uuid)
if len(b) == 2:
payload += struct.pack("BB", len(b) + 1, _ADV_TYPE_UUID16_COMPLETE) + b
elif len(b) == 4:
payload += struct.pack("BB", len(b) + 1, _ADV_TYPE_UUID32_COMPLETE) + b
elif len(b) == 16:
payload += struct.pack("BB", len(b) + 1, _ADV_TYPE_UUID128_COMPLETE) + b
return payload
5)main.pyを実行
Thonnyのシェルに print("Temp:", temperature) の実行結果として温度が表示される
6)スマホにLightBlueをインストール
nRFconnectでもValueの確認は可能
ただ、アプリ側でUTF-8にエンコード表示する設定が見当たらない。
7)PicoWのAdvertisingをLightBlueで確認する
順に赤〇の部分をタップ
[Peripherals] > PicoTemp の [Connect]
PicoTemp が [connected] であるのを確認して、Health Thermometerの項目の[Temperature Measurement]をタップ
Characteristic 内の [Subscribe] をタップ
すると、Read/Notified Values の下に、取得値が更新表示される
値がHEX表示のままの場合、赤〇部分が[HEX]となっていると思うので、タップして[UTF-8 String]に変更する