工具還在附近嗎?阿明博士用 ESP32-S3 做 BLE 存在提醒
內容整理:台灣智能感測科技|導讀角色:阿明博士
常用的工具箱放在工作室,想知道它最近還有沒有出現在接收範圍內,可以從 BLE 信標開始。這一篇,阿明博士用兩塊 ESP32-S3 做一個簡單的存在提醒:一塊發送信標,另一塊接收,再把狀態放到網頁。
用兩塊 ESP32-S3,一塊發送 iBeacon,另一塊透過 ESPHome 接收,再把「最近是否收到」放到 Wi-Fi 網頁,就能做 BLE 存在提醒。這個案例判斷能否接收到指定信標,不用來換算精準距離。
- 用第二塊 S3 建立容易操作的 BLE 信標
- 在網頁一起查看工具存在狀態與溫濕度
- 理解接收不到與精準定位之間的差別
先做一個能重複操作的小案例
第一塊主板放在查看資料的位置,接上 SHT20,負責顯示環境與接收 BLE。第二塊主板放在工具箱附近,只接 USB 供電,定期發送一組指定的信標識別碼。兩邊的完整 YAML 都附在本文。
這樣做的好處,是不必先處理手機的背景廣播與隨機位址。等兩塊板子的流程熟悉了,再考慮換成合適的電池信標或其他裝置。
有收到,和確定在幾公尺內,不是一樣的事
接收端最近有收到符合識別碼的廣播時,Nearby 狀態為 true;超過 60 秒沒有再收到,才會轉成 false。你可以把它理解為「最近還聽得到這個信標嗎」。
人體遮擋、金屬工具箱、擺放方向、干擾或信標斷電,都可能影響結果。因此這適合作為「可能離開了,請確認」的提醒,不能直接當成精準距離、門禁授權或失竊判定。
一台主板,同時照顧有線感測與無線接收
SHT20 的溫濕度是由接收板上的有線 I²C 取得;BLE 這邊只提供信標的存在狀態。兩種資料最後透過 Wi-Fi 放到同一頁,這就是本課要示範的分工。
如果之後想讀其他藍牙感測器的溫度,還需要知道它使用的廣播格式、是否加密,以及對應的元件。不能因為本課收得到信標,就假設所有藍牙裝置都會自動變成可用的數值。
想調整接收表現,可以從哪裡開始?
範例採被動掃描,interval 320ms、window 30ms,作為調整起點。Wi-Fi 和 BLE 共用無線資源,擴大掃描視窗不一定在每個場域都更好;先固定擺放位置,再觀察漏收與回復的情形。
信標 UUID、major、minor 要在兩邊對應。新增另一個工具箱時,可以替它設定不同識別值;相同識別值的多顆信標,會讓接收端難以分辨是哪一個。
先準備這些材料
| 材料 | 準備重點 |
|---|---|
| ESP32-S3 N16R8 | 主板、資料 USB 線、2.4GHz Wi-Fi |
| SHT20 I²C 模組 | 商品 6129,使用 3.3V 供電 |
| 另一塊 ESP32-S3 | 作為 BLE 信標,只需 USB 供電 |
主板請確認為 WROOM-1-N16R8,範例使用 16MB Flash 與 Octal PSRAM。接線先斷電,表格中的 GPIO 是腳位名稱,不是排針從上往下數的位置。
照著圖,把線一條條接好
依名稱逐條對照接線

| 感測器接腳 | ESP32-S3/電源 | 核對事項 |
|---|---|---|
| SHT20 VCC | 主板 3V3 | 本課限 3.3V I²C 模組,先核對實物 |
| SHT20 GND | 主板 GND | 所有訊號參考共地 |
| SHT20 SDA | GPIO8 | 上拉至 3.3V |
| SHT20 SCL | GPIO9 | 100kHz;先用短線 |
所有模組都要與主板共地。若使用外接電源,不要把外接 5V 和 USB 5V 直接並接,也不要把獨立 3.3V 穩壓器的輸出接到主板 3V3 輸出。先量好電壓,再接入訊號線。
把設定放進主板
- 下載整個 examples 資料夾,保留 components;把 secrets.yaml.example 複製成 secrets.yaml,填入自己的 Wi-Fi 與密碼。
- 依照Windows 燒錄指南安裝 ESPHome 2026.10.1,選擇本課 YAML,先檢查設定、再編譯與 USB 燒錄。
- 在 USB 日誌或路由器裝置清單找到主板 IP,瀏覽器輸入該 IP,再用 secrets 裡的網頁帳密登入。
以下命令在 examples 資料夾執行,COM5 請換成自己的埠號。USB 接頭、日誌與後續 OTA 更新的操作,都整理在共用指南。
..\.venv\Scripts\python.exe -m esphome config 05-ble.yaml
..\.venv\Scripts\python.exe -m esphome compile 05-ble.yaml
..\.venv\Scripts\python.exe -m esphome upload 05-ble.yaml --device COM5
下載完整範例(含 05-ble.yaml) · 下載完整範例(含 secrets.yaml.example)
完整 YAML:點此展開
esphome:
name: course-05-ble
friendly_name: "BLE 設備存在偵測"
min_version: 2026.10.1
compile_process_limit: 1
esp32:
board: esp32-s3-devkitc-1
flash_size: 16MB
framework:
type: esp-idf
psram:
mode: octal
speed: 80MHz
logger:
hardware_uart: USB_SERIAL_JTAG
level: DEBUG
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
power_save_mode: none
reboot_timeout: 0s
ota:
- platform: esphome
password: !secret ota_password
web_server:
port: 80
version: 3
local: true
auth:
type: digest
username: !secret web_username
password: !secret web_password
i2c:
id: sensor_bus
sda: GPIO8
scl: GPIO9
scan: true
frequency: 100kHz
external_components:
- source:
type: local
path: components
components: [sht20_local]
sensor:
- platform: sht20_local
id: sht20_driver
address: 0x40
update_interval: 10s
temperature:
id: sht_temperature
name: "SHT20 Temperature"
on_value:
then:
- lambda: |-
id(last_sht_ms) = millis();
id(sht_seen) = true;
humidity:
id: sht_humidity
name: "SHT20 Humidity"
on_value:
then:
- lambda: |-
id(last_rh_ms) = millis();
id(rh_seen) = true;
globals:
- id: last_sht_ms
type: uint32_t
restore_value: false
initial_value: '0'
- id: sht_seen
type: bool
restore_value: false
initial_value: 'false'
- id: last_rh_ms
type: uint32_t
restore_value: false
initial_value: '0'
- id: rh_seen
type: bool
restore_value: false
initial_value: 'false'
binary_sensor:
- platform: template
name: "SHT20 Temperature Fresh"
lambda: |-
return id(sht_seen) && (uint32_t)(millis() - id(last_sht_ms)) < 35000;
- platform: template
name: "SHT20 Humidity Fresh"
lambda: |-
return id(rh_seen) && (uint32_t)(millis() - id(last_rh_ms)) < 35000;
- platform: ble_presence
name: "Demo Beacon Nearby"
id: beacon_nearby
ibeacon_uuid: "730eb196-4033-4c32-a7da-c8cf68e8ff01"
ibeacon_major: 1
ibeacon_minor: 1
timeout: 60s
esp32_ble_tracker:
scan_parameters:
active: false
interval: 320ms
window: 30ms
另一塊主板請使用下載完整範例(含 05-beacon.yaml),同樣填妥 secrets 後燒錄。接收端和信標端的識別碼要一致。
信標端完整 YAML
esphome:
name: course-beacon
friendly_name: "BLE 示範信標"
min_version: 2026.10.1
compile_process_limit: 1
esp32:
board: esp32-s3-devkitc-1
flash_size: 16MB
framework:
type: esp-idf
psram:
mode: octal
speed: 80MHz
logger:
hardware_uart: USB_SERIAL_JTAG
level: DEBUG
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
power_save_mode: none
reboot_timeout: 0s
ota:
- platform: esphome
password: !secret ota_password
web_server:
port: 80
version: 3
local: true
auth:
type: digest
username: !secret web_username
password: !secret web_password
esp32_ble_beacon:
type: iBeacon
uuid: "730eb196-4033-4c32-a7da-c8cf68e8ff01"
major: 1
minor: 1
min_interval: 500ms
max_interval: 700ms
接好後,先試這幾件事
先從正常顯示開始,再試一次拔除、恢復或更換環境條件。這些小步驟有助於確認你看到的資料,確實來自現在的接線與位置。
| 測試項目 | 應觀察的結果 |
|---|---|
| 信標與接收端近距離上電 | Nearby 轉為真;兩邊識別碼一致 |
| 關閉信標 | 最後一次廣播後約 60 秒轉為假 |
| 恢復信標 | 重新收到廣播後轉為真;記錄實際延遲 |
| Wi-Fi 流量與遮蔽 | 觀察誤報與延遲,記錄現場條件,不宣稱固定距離 |
遇到問題時,從這裡開始找
先查供電和共地,再核對端子名稱與訊號方向。I²C 裝置可看掃描位址;PMS5003T 走 UART,不會出現在 I²C 清單。接著確認設定的型號與最後一次更新時間,最後才檢查網頁或後端。資料停住時,不要先把它當成環境一直沒變。
材料與延伸閱讀
ESP32-S3 N16R8 主板 · SHT20 I²C 模組。依實際用途選擇所需感測器即可。
想看原廠文件與元件說明
常見問題
可以直接把手機當成本課的工具信標嗎?
不應直接假設可以。手機的背景廣播、隨機位址與作業系統限制都可能影響接收;本課用第二塊 ESP32-S3 發送固定 iBeacon,先把流程做清楚,再評估其他信標。

發佈留言
很抱歉,必須登入網站才能發佈留言。