ble_uart.py
The Feather becomes a Bluetooth serial terminal: the NUS (Nordic UART) service advertises, Adafruit Connect connects, and 1 Hz ticks land on the phone. The end of the USB cable for battery-powered builds.
Hardware
An Adafruit Feather nRF52840 Express (nRF52840 Cortex-M4F SoC, BLE 5 / 802.15.4) with on-board NeoPixel, red LED, 2 MB QSPI flash for the CircuitPython filesystem and a LiPo battery connector. Just the Feather; an Android/iOS phone with the free Adafruit Connect app (or any BLE serial client).
Wiring
No wiring: the antenna is on board. USB only serves to charge or edit code.py.
How it works
BLERadio drives the nRF52840 radio; ProvideServicesAdvertisement advertises the UART service; UARTService exposes write/read over a BLE channel. The loop openly switches between waiting and exchanging.
Running it
CircuitPython (feather_nrf52840_express build) installed via the UF2 bootloader (double reset); edit code.py on the CIRCUITPY drive, console in Mu/Thonny.
Variants
Send sensor readings instead of ticks, receive commands to drive a relay, or move to BLE HID (keyboard) for automation.
ble_uart.py
# BLE UART : la console passe dans l'air.
#libs : adafruit_ble (Bundle Adafruit CircuitPython Library).
# Client : app "Adafruit Connect" sur téléphone.
import time
import board
from adafruit_ble import BLERadio
from adafruit_ble.advertising.standard import ProvideServicesAdvertisement
from adafruit_ble.services.nordic import UARTService
ble = BLERadio()
uart = UARTService()
annonce = ProvideServicesAdvertisement(uart)
print("Attente de connexion BLE...")
ble.start_advertising(annonce)
while not ble.connected:
time.sleep(0.2)
print("Connecté !")
compteur = 0
while ble.connected:
compteur += 1
uart.write("tick %d\n" % compteur)
# Entrée du téléphone -> console de la carte
if uart.in_waiting:
print("Reçu:", uart.read(uart.in_waiting))
time.sleep(1)