Płytka STM32 NUCLEO-WB15CC to jeden z tańszych sposobów na wejście w świat Bluetooth Low Energy z mikrokontrolerami STM32. Kupiłem ją z myślą o projekcie, który od dawna chodził mi po głowie: czujnik obecności BLE zintegrowany z Home Assistant, który nie opiera się na ruchu, ale naprawdę wie, czy ktoś jest w pomieszczeniu. Połączenie STM32WB15CC z Home Assistant okazało się zaskakująco proste — i bardzo niezawodne.

Czym jest STM32 NUCLEO-WB15CC i dlaczego wybrałem właśnie tę płytkę

NUCLEO-WB15CC to płytka Nucleo-64 oparta na mikrokontrolerze STM32WB15CC. W środku pracują dwa rdzenie: ARM Cortex-M4 taktowany do 64 MHz (rdzeń aplikacyjny) oraz ARM Cortex-M0+ (rdzeń sieciowy obsługujący stos BLE). Oba rdzenie działają niezależnie — Cortex-M0+ zarządza komunikacją Bluetooth 5.0, podczas gdy M4 wykonuje logikę aplikacji.

Z punktu widzenia projektu IoT to istotne: nie tracę cykli CPU na obsługę BLE i mam pełną kontrolę nad logiką czujnika po stronie M4.

Parametry, które miały znaczenie przy wyborze:

  • Bluetooth 5.0 LE z obsługą trybu skanowania pasywnego
  • 320 KB Flash + 48 KB RAM — wystarczająco na stos BLE i własny kod
  • Niski pobór prądu — tryby Stop i Standby z aktywnym budzikiem RTC
  • Zgodność z Arduino Uno — piny kompatybilne, łatwy montaż modułów
  • Wbudowany ST-Link/V3 — programowanie i debugowanie bez dodatkowego sprzętu
  • Cena — znacznie poniżej płytek z Wi-Fi + BLE

Jak działa czujnik obecności BLE

Standardowe czujniki PIR wykrywają ruch. Jeśli siedzisz nieruchomo przez kilkanaście minut — dla PIR jesteś niewidoczny. To generuje fałszywe „opuszczenia” pokoju i niepotrzebne wyłączanie świateł czy ogrzewania.

Czujnik obecności BLE oparty na NUCLEO-WB15CC działa inaczej. Smartfony i inne urządzenia BLE co kilkaset milisekund rozgłaszają pakiety advertisingu — nawet gdy ekran jest wygaszony i telefon leży w kieszeni. STM32WB15CC skanuje te pakiety pasywnie, identyfikuje znane urządzenia po adresie MAC i na tej podstawie wnioskuje, czy domownik jest w zasięgu.

Zaletą jest to, że obecność jest wykrywana stale, bez konieczności ruchu. Wadą — zasięg BLE obejmuje całe mieszkanie, więc dokładna lokalizacja (który pokój) wymaga kilku węzłów lub użycia RSSI do szacowania odległości.

Schemat projektu STM32WB15CC i Home Assistant

[Smartfon / zegarek / tag BLE]
        │  BLE advertising
        ▼
[NUCLEO-WB15CC]
  Cortex-M0+: skanowanie BLE
  Cortex-M4:  logika obecności + UART
        │  UART/USB
        ▼
[Raspberry Pi / serwer lokalny]
  MQTT broker (Mosquitto)
        │  MQTT
        ▼
[Home Assistant]
  binary_sensor: presence

Płytka łączy się z Raspberry Pi przez USB (UART wirtualny). Pi pełni rolę pośrednika: odbiera dane z NUCLEO, publikuje je do brokera MQTT, a Home Assistant subskrybuje i podejmuje automatyzacje.

Konfiguracja środowiska

Do pracy z STM32WB15CC potrzebujesz:

  1. STM32CubeMX — generowanie konfiguracji projektu i inicjalizacja stosu BLE (WPAN middleware)
  2. STM32CubeIDE lub VS Code + CMake + arm-none-eabi-gcc — kompilacja
  3. STM32CubeProgrammer — wgrywanie firmware stosu BLE (tzw. FUS + wireless stack)

Ważny krok, który często pomijają tutoriale: przed pierwszym programowaniem musisz wgrać najnowszy Firmware Upgrade Service (FUS) oraz BLE wireless stack przez STM32CubeProgrammer. Bez tego rdzeń M0+ nie uruchomi BLE. Pliki znajdziesz w pakiecie STM32CubeWB.

Implementacja skanowania BLE

Po wygenerowaniu projektu w CubeMX z włączonym middleware STM32WPAN i wybranym przykładem BLE_Scan, główna logika skanowania wygląda następująco:

Rdzeń M4 inicjalizuje stos przez SHCI_C2_BLE_Init(), następnie wywołuje aci_gap_set_scan_parameters() z trybem pasywnym (LE_SCAN_PASSIVE). Skanowanie pasywne oznacza, że płytka nasłuchuje pakietów advertisingu, ale sama nie wysyła żadnych zapytań — to ważne dla niskiego poboru prądu.

Gdy pojawi się pakiet od śledzonego urządzenia, callback hci_le_advertising_report_event() dostarcza adres MAC i poziom sygnału RSSI. Na tej podstawie M4 aktualizuje stan obecności i wysyła przez UART komunikat JSON:

{"device":"phone_rudner","rssi":-62,"present":true,"ts":1710000000}

Próg RSSI przyjąłem na poziomie -85 dBm — przy słabszym sygnale uznajemy urządzenie za poza zasięgiem (wyszło z domu lub zasięg budynku).

Filtrowanie i debouncowanie

Samo RSSI zmienia się dynamicznie. Żeby uniknąć migotania stanu „obecny/nieobecny”, implementuję prosty licznik:

  • Urządzenie uznajemy za obecne, gdy przez ostatnie 30 sekund odebraliśmy co najmniej 3 pakiety z RSSI powyżej progu
  • Urządzenie uznajemy za nieobecne, gdy przez 5 minut nie odebraliśmy żadnego pakietu z RSSI powyżej progu

Histereza czasowa eliminuje fałszywe alarmy, gdy ktoś wychodzi na chwilę pod drzwi.

Integracja STM32WB15CC z Home Assistant przez MQTT

Na Raspberry Pi działa Mosquitto. Integracja MQTT w Home Assistant subskrybuje temat home/presence/nucleo i mapuje dane na encję binary_sensor:

# configuration.yaml
mqtt:
  binary_sensor:
    - name: "Obecność w domu"
      state_topic: "home/presence/nucleo"
      value_template: "{{ value_json.present }}"
      payload_on: "true"
      payload_off: "false"
      device_class: presence
      off_delay: 300

off_delay: 300 to dodatkowe 5 minut opóźnienia po stronie HA — zabezpieczenie na wypadek chwilowej przerwy w BLE. Po zapisaniu konfiguracji czujnik obecności BLE pojawia się w Home Assistant natychmiast i jest gotowy do użycia w automatyzacjach.

Pobór prądu i zasilanie

W trybie ciągłego skanowania płytka pobiera około 8–12 mA (rdzeń M0+ aktywny, M4 w trybie Sleep między callbackami). To pozwala zasilać projekt z dowolnej ładowarki USB lub powerbanku.

Jeśli zależy Ci na baterii, możesz zaimplementować skanowanie z interwałem (np. 10 sekund skanowania, 50 sekund uśpienia) — pobór spada do ok. 1–2 mA średnio, ale czas reakcji na wykrycie obecności wzrasta.

Co dalej — możliwe rozszerzenia

Projekt STM32WB15CC z Home Assistant działa stabilnie od kilku tygodni. Kilka kierunków, które planuję sprawdzić:

  • Triangulacja RSSI z kilku węzłów — dwa lub trzy NUCLEO rozmieszczone w mieszkaniu pozwoliłyby określić, w którym pomieszczeniu jest dana osoba
  • Obsługa tagów BLE — zamiast polegać na smartfonie (który może wyłączyć BLE), można użyć małego tagu przypiętego do kluczy
  • Hybrydowy czujnik obecności BLE + PIR — BLE do długoterminowej obecności, PIR do natychmiastowej reakcji na ruch
  • OTA przez BLE — STM32WB15CC obsługuje aktualizacje firmware over-the-air, co przy kilku węzłach w mieszkaniu znacznie ułatwia utrzymanie

FAQ

Czy NUCLEO-WB15CC obsługuje Wi-Fi? Nie. STM32WB15CC ma tylko Bluetooth 5.0 LE. Do komunikacji z Home Assistant potrzebny jest pośrednik — Raspberry Pi, ESP32 lub inny serwer lokalny z MQTT.

Czy można wykrywać obecność bez znanych adresów MAC? Tak, ale z ograniczeniami. Można zliczać wszystkie unikalne urządzenia BLE w zasięgu, ale nowoczesne smartfony rotują adresy MAC co kilkanaście minut (MAC randomization), co utrudnia identyfikację. Najlepiej działa lista zaufanych adresów lub sparowane tagi BLE.

Jakie jest maksymalne opóźnienie wykrycia w Home Assistant? Przy interwale skanowania 100 ms pierwsze pakiety są odbierane w ciągu 1–3 sekund. Debouncowanie po stronie firmware dodaje kilka sekund, a off_delay w Home Assistant — do 5 minut przy wyjeździe.

Czy projekt działa z Apple Watch lub AirTagami? Apple Watch rozgłasza BLE — jest wykrywalny przez czujnik obecności BLE. AirTagi używają protokołu FindMy, który nie jest standardowym BLE advertisingiem i nie będzie widoczny bez reverse-engineeringu protokołu Apple.