System Overview
┌─────────────────┐ BLE ┌──────────────┐
│ nRF52840 │◄────────────────►│ Zwift │
│ Fitness Sensor │ HR & Power │ App │
└────────┬────────┘ └──────────────┘
│
│ Matter/Thread
│
┌────────▼────────┐
│ Thread Border │ (HomePod mini, Apple TV)
│ Router │
└────────┬────────┘
│
│ Thread Network
│
┌────────▼────────┐
│ iPhone with │
│ Control App │
└─────────────────┘
What You Get
🔵 BLE Broadcasting
Zwift sees your sensor as:
- Heart Rate Monitor
- Cycling Power Meter
🌐 Matter Control
Your iPhone can:
- Turn sensor on/off remotely
- Adjust workout intensity
- Monitor connection status
🏠 Smart Home
Works with:
- Apple Home automations
- Siri voice commands
- HomeKit scenes
Complete Setup Process
Phase 1: Hardware Setup (15 minutes)
1. Flash nRF52840 Firmware
# Navigate to firmware directory
cd fitness-sensor-matter
# Build firmware
west build -b nrf52840dk_nrf52840
# Flash to device
west flash
# Verify it's running
screen /dev/ttyACM0 115200
Expected output:
nRF52840 BLE & Matter Fitness Sensor Emulator
============================================
Bluetooth initialized
BLE advertising started
Matter initialized
Ready for commissioning!
2. Verify BLE Broadcasting
- Open BLE scanner app (nRF Connect)
- Look for "Bike Sensor Matter"
- Verify services: Heart Rate (0x180D), Cycling Power (0x1818)
Phase 2: iOS App Setup (10 minutes)
1. Build iOS App
- Open Xcode
- Create new project with provided code
- Add Info.plist and Entitlements
- Build and run on your iPhone
2. Setup HomeKit
- App opens → Tap "Get Started"
- Grants HomeKit permission
- Creates home if needed
Phase 3: Pairing Device (5 minutes)
Method A: Via iOS App
- In app, tap "+" button
- Tap "Open Home Settings"
- Settings app opens
- Tap "Add Accessory"
- Scan QR code OR enter code:
20202021-3840 - Wait for commissioning (30-60 seconds)
- Name device: "Bike Sensor"
- Assign to room: "Home Gym"
- ✅ Green checkmark in Home app
- ✅ Device appears in control app
- ✅ Status shows "Connected"
Phase 4: Connect to Zwift (5 minutes)
1. Ensure Sensor is Active
- Open control app
- Verify sensor is ON (green heart)
- Check status: "Broadcasting to Zwift"
2. Pair in Zwift
- Open Zwift
- Go to Settings → Devices
- Search for sensors:
- Heart Rate: "Bike Sensor Matter"
- Power Meter: "Bike Sensor Matter"
- Tap to pair each sensor
- Wait for connection (blue icon)
3. Verify Data Flow
- Start a ride in Zwift
- Check your avatar moves
- Verify HR and power display
- Values should update every second
Phase 5: Test Control (5 minutes)
1. Basic On/Off
In control app:
- Toggle sensor OFF
- Check Zwift: sensors disconnect
- Toggle sensor ON
- Check Zwift: sensors reconnect
2. Intensity Control
In control app:
- Set intensity to 50 (low) → ~105 BPM, ~118W
- Set intensity to 150 (medium) → ~143 BPM, ~255W
- Set intensity to 200 (high) → ~171 BPM, ~327W
Watch Zwift display update!
Daily Use Workflows
Option 1: Manual Control
- Power on nRF52840
- Open control app → Turn ON
- Open Zwift → Pair devices
- Adjust intensity as needed
- After workout → Turn OFF
Option 2: Automated (with Shortcuts)
Create a "Start Cycling" shortcut:
1. Turn on Bike Sensor
2. Set intensity to 127
3. Wait 5 seconds
4. Open Zwift
Activate with:
- "Hey Siri, start cycling"
- Home screen widget
- Automation at specific time
Option 3: Advanced Automation
Morning Routine:
Time: 6:00 AM (Weekdays)
Actions:
- Turn on Bike Sensor
- Set intensity to 100
- Play workout playlist
- Turn on HomeKit lights
Testing Scenarios
Test 1: Variable Intensity Workout
Simulate interval training:
| Time | Intensity | Expected Power | Expected HR |
|---|---|---|---|
| 0:00 | 50 | ~118W | ~105 BPM |
| 5:00 | 200 | ~327W | ~171 BPM (SPRINT!) |
| 8:00 | 100 | ~187W | ~138 BPM (recover) |
| 13:00 | 200 | ~327W | ~171 BPM (SPRINT!) |
| 16:00 | 50 | ~118W | ~105 BPM (cool down) |
Adjust via app while riding!
Test 2: Endurance Ride
Set intensity to 127 and let it auto-vary:
- Power: 220-230W (±10W natural variation)
- HR: 127-133 BPM (±3 BPM variation)
- Cadence: 78-82 RPM (±2 RPM variation)
Test 3: Recovery Ride
Low intensity for app testing:
- Intensity: 30
- Power: ~91W
- HR: ~76 BPM
- Perfect for debugging!
Troubleshooting Common Issues
| Issue | Check | Fix |
|---|---|---|
| Zwift Not Seeing Sensor |
✓ Sensor is ON in control app ✓ Bluetooth enabled ✓ No other apps using sensor ✓ Device within BLE range (~10m) |
- Close Zwift completely - Toggle sensor OFF then ON - Reopen Zwift - Search for sensors again |
| Control App Shows "Offline" |
✓ nRF52840 has power ✓ Thread border router active ✓ Both on same network |
- Check nRF52840 serial output - Restart Thread border router - Re-commission device |
| Values Don't Update | Check serial console for:HR: 120 BPM | Power: 150 W | Enabled: 1
|
If Enabled: 0:- Turn sensor ON in app If values frozen: - Check BLE connection - Restart nRF52840 |
| Can't Commission Device |
1. Reset nRF52840 (power cycle) 2. Remove old accessory from Home app 3. Reset HomeKit: Settings → Home → Reset 4. Try commissioning again 5. Use manual code if QR fails: 20202021-3840 |
Performance Optimization
Battery Life (if using battery)
| Mode | Current Draw | Runtime (1000mAh) |
|---|---|---|
| BLE active | ~15mA | ~66 hours |
| Thread active | ~8mA | ~125 hours |
| Both active | ~23mA | ~43 hours |
Update Rate Tuning
Modify in firmware (main.cpp):
// Faster updates (0.5 seconds)
k_sleep(K_MSEC(500));
// Slower updates (2 seconds) - save power
k_sleep(K_SECONDS(2));
Advanced Features
Custom Training Plans
Create preset intensity profiles in iOS app:
// Tabata Protocol
func startTabata() {
// 20 sec high intensity
setIntensity(220)
wait(20)
// 10 sec rest
setIntensity(50)
wait(10)
// Repeat 8 times
}
Multiple Sensors
Connect multiple nRF52840 devices:
- Sensor 1: Your data
- Sensor 2: Training partner's data
- Test different profiles simultaneously
Security Notes
Network Security
- Matter uses Thread protocol
- End-to-end encrypted
- Local network only
- No cloud connection needed
Privacy
- No data collected
- No telemetry sent
- All processing local
- HomeKit sandboxed
FAQ
Q: Can I use this with other fitness apps?
A: Yes! Any app that supports BLE Heart Rate and Power sensors (TrainerRoad, Rouvy, Sufferfest, etc.)
Q: Does it work without the iOS app?
A: Yes! BLE works independently. iOS app is just for remote control.
Q: Can I control it from Android?
A: Not with this app, but you could build an Android Matter controller.
Q: What's the range?
A: BLE: ~10m, Thread: ~30m through border router
Q: Can multiple phones control it?
A: Yes! All phones with Home access can control it.
Q: Does it affect Zwift performance?
A: No impact. Zwift only uses BLE, not Thread.
Quick Reference Card
| Action | Command/Steps |
|---|---|
| Power On | Plug in nRF52840 → Wait 5 seconds |
| Start Workout | Open app → Toggle ON → Open Zwift → Pair |
| Adjust Intensity | Open app → Slide intensity bar → Watch Zwift |
| End Workout | Finish in Zwift → Toggle OFF → Power down |
| Emergency Reset | Unplug → Hold button → Plug in → Re-commission |
🎉 You're all set! Happy training! 🚴♂️💪
For more details, check out: