Software NEXT firmware
Wireless: BLE & Wi-Fi
The HealthyPi 5 streams to a phone over BLE and to a browser over Wi-Fi. Neither radio is on the main MCU.
The HealthyPi 5’s main MCU is a plain RP2040 — not a Pico W — so it has no Bluetooth and no Wi-Fi silicon. Calling BLEDevice.begin() there would have nothing to talk to.
Wireless is handled by the on-board ESP32-C3, which owns both radios and runs its own firmware. The RP2040 streams to it over a dedicated UART.
The two-chip model
┌──────────────────┐ HealthyBridge ┌──────────────────┐
│ RP2040 │ UART1 @ 921600 │ ESP32-C3 │
│ main MCU │ ───AA55|…|CRC───► │ wireless co-MCU │
│ • sensors (SPI) │ GP24 TX / 25 RX │ • BLE GATT │ ──BLE──► phone
│ • DSP / vitals │ GP27 RTS/26 CTS │ • Wi-Fi AP/STA │ ──WiFi─► browser
│ • USB / SD │ ◄──status/cmds─── │ │
└──────────────────┘ └──────────────────┘
BLE and Wi-Fi are identical from the RP2040’s side. The same frames go out UART1 either way; which radio carries them is decided entirely on the ESP32-C3, and by whatever host connects. That’s why there’s one wireless example, not two.
The two firmwares you flash
| Chip | Firmware | Role |
|---|---|---|
| RP2040 | protocentral_healthypi_5_firmware | Acquire, then stream over HealthyBridge |
| ESP32-C3 | healthybridge-esp32 | Own the BLE / Wi-Fi radios, relay the stream |
You don’t re-implement BLE or Wi-Fi. The ESP32-C3 firmware is reused unchanged — both sides share the HealthyBridge frame format verbatim, so they can’t drift apart.
Enabling it
One line in the RP2040 sketch:
HealthyPi5.enableBridge(); // before begin()
The bridge is a drop-newest sink like any other: if the ESP32 is unflashed, held in reset, or simply not draining the UART, the RP2040 drops frames rather than blocking, and acquisition never stalls. HealthyPi5.bridgeTxDrops() reports the count.
To see the wire protocol built up from nothing, read examples/Tutorials/10_Wireless_Bridge — a plain single-core sketch that sends vitals frames and mirrors them to USB.
Bringing it up
- Flash the RP2040 with the production firmware, or
./extras/scripts/upload.sh wireless --monitorfor the teaching sketch. - Flash the HealthyBridge firmware to the on-board ESP32-C3 — step-by-step in Programming the ESP32-C3. This step is not optional on a board coming from the earlier firmware, whose ESP32-C3 carries a Bluetooth HCI controller image rather than HealthyBridge.
- BLE: open the OpenView 2 mobile app (or any BLE scanner) and connect to the advertised device.
- Wi-Fi: provision the ESP32-C3 through its captive portal, then open
http://healthypi.localin a browser.
The OpenView 2 mobile app
Turn on Bluetooth. On Android, also enable Location — Android requires Location permission for BLE scanning. Open the app, tap Scan, and pick HealthyPi 5 from the discovered list.
Once connected, vitals stream live.
Wireless streaming draws very little power — a LiPo battery runs the kit unattended for hours. USB is needed only for charging, or as a backup supply.
The HealthyBridge link
-
Transport: UART1 (arduino-pico
Serial2), 921600 8N1, RTS/CTS. -
Pins — already routed on the PCB, nothing to wire:
Signal RP2040 GPIO ESP32-C3 side TX GP24 RX RX GP25 TX RTS GP27 CTS CTS GP26 RTS -
Frame (little-endian):
SYNC(0xAA55) | TYPE(1) | FLAGS(1) | LENGTH(2) | SEQ(2) | PAYLOAD | CRC16(2)CRC-16/CCITT (polynomial
0x1021, init0xFFFF) computed overTYPE..PAYLOAD. -
Directions: RP2040 → ESP32 sends
BIOSIG(waveforms),VITALS, andBATTERY. ESP32 → RP2040 sendsSTATUS(BLE/Wi-Fi up) and forwards commands from the phone.
The canonical implementation is src/HPIBridge.h / src/HPIBridge.cpp in the firmware repo.
Troubleshooting
Bluetooth worked before I flashed NEXT, and now the device never appears.
The ESP32-C3 still has the old Bluetooth HCI controller image on it. Under the earlier firmware the RP2040 ran the BLE host and drove advertising through that controller; NEXT has no host stack, so nothing advertises. Flash HealthyBridge onto the ESP32-C3 — this is expected, and it’s a one-command fix.
Frames sent = 0, drops climbing. Watch the hbtx counter on the 1 Hz HPI_INSTR telemetry line (UART0), or the teaching sketch’s [frames= drops=] output. The ESP32 isn’t draining the UART — it’s unflashed, held in reset, or CTS is deasserted. The RP2040 deliberately drops rather than blocking, so acquisition keeps running regardless.
Bench-testing without an ESP32. In 10_Wireless_Bridge, set USE_FLOW_CONTROL 0 and sniff GP24 with a logic analyser or a 921600 USB-UART adapter to confirm the AA 55 … framing.
Board resets when Wi-Fi starts. The ESP32’s SoftAP draws a current spike on the shared rail. A marginal supply can brown out the board when the radio comes up — power from a solid 5 V source.
Next
- Recording Data — capture the stream to SD or to a phone.
- Streaming to OpenView 2 — the wired alternative.



