As a reverse engineer and someone who enjoys dissecting how systems communicate, my interest was recently piqued by the Bluetooth Low Energy (BLE) cycling sensors that integrate with fitness tracking apps like Samsung Health. What began as an investigative dive into what I initially presumed were proprietary connections quickly evolved into a hands-on DIY project with an ESP32, demonstrating the power of open standards.
Proprietary Sensors Only?
My adventure began when I noticed the “Accessories” option in Samsung Health while preparing for an exercise session. Upon clicking, I was presented with a list of sensor devices for biking. My immediate thought was that Samsung Health might only support a specific, limited set of official or licensed sensors. This led me to purchase a second-hand Polar cadence sensor, believing it was the only way to get my cycling data into the app. Here’s a glimpse of what the accessory scanning looked like:
How Bike Sensors Really Work
While my Polar sensor was still in transit, I decided to dive deeper into how these cycling sensors actually function. I quickly learned that most bike sensors, whether for speed or cadence, fall into two main categories:
- Magnet-based sensors: These are simple and reliable. A small magnet is attached to a rotating part (like a wheel spoke for speed, or a crank arm for cadence), and a stationary sensor (often a reed switch) is mounted nearby. Every time the magnet passes the sensor, it registers a “rotation.” My Polar sensor, it turned out, used this exact mechanism for cadence: a magnet on the crank, and the sensor on the bike’s chainstay, counting each crank rotation. In fact, when I looked up the FCC ID (INWY6) for Polar bike sensors, the internal photos readily available online confirmed it was indeed using a magnetic reed sensor for its operation.
- Accelerometer-based sensors: These are more advanced and magnet-less. They use an accelerometer to detect the orientation and rotation of the component they’re attached to (e.g., a wheel hub or crank arm) to infer revolutions.
What truly surprised me was discovering that Bluetooth has an official Cycling Speed and Cadence (CSC) Service. This isn’t a proprietary Samsung thing; it’s a standardized BLE profile that any compatible sensor or app can use. This meant my initial assumption was wrong. Samsung Health, and many other fitness apps, are designed to connect to any sensor that adheres to this standard.
The CSC service is quite clever. It doesn’t send “speed” or “RPM” directly. Instead, it transmits:
- Cumulative Rotation Count: A running total of how many times the wheel or crank has rotated.
- Last Event Time: A timestamp indicating when the last rotation was detected.
The connected app (like Samsung Health) then takes these raw numbers and performs the calculations to give you real-time speed and RPM. For speed, the app typically asks for your wheel circumference, which it then multiplies by the wheel revolutions to get distance, and divides by the time elapsed to get speed.
The DIY Solution: ESP32 + Reed Sensor Emulation
Since I already had an ESP32, a microcontroller with built-in BLE capabilities, I realized I didn’t need to wait for my Polar sensor to arrive to start experimenting. I could build my own “fake” sensor! I grabbed a simple magnetic reed sensor (the same type used in many commercial sensors) and connected it to my ESP32.
My goal was to create an ESP32 BLE server that would emulate a full Cycling Speed and Cadence sensor using just this one reed switch. This meant every time the single reed sensor triggered, I would update both the emulated wheel revolutions and crank revolutions. While not physically accurate (a real bike’s wheel turns many more times than its cranks), it would demonstrate the BLE service functionality perfectly.
Here’s a simplified look at the core ESP32 Arduino code:
1 |
|
Key parts of the code:
SINGLE_REED_SENSOR_PIN = 13
: This is where your single reed sensor is connected.singleReedISR()
: This Interrupt Service Routine is the heart of the emulation. Every time the magnet passes the sensor, this function runs. It increments bothcumulativeWheelRevolutions
andcumulativeCrankRevolutions
and updates theirlastEventTime
with the current timestamp. This makes the single sensor appear as both a speed and cadence sensor.cscFeatures = 0x0003
: In thesetup()
function, this line tells any connecting app that our ESP32 supports both wheel (speed) and crank (cadence) data.pCscMeasurementCharacteristic->setValue(cscData, 11); pCscMeasurementCharacteristic->notify(true);
: In the loop() function, after preparing the cscData packet with the latest revolution counts and times, these lines update the BLE characteristic’s value and send a notification to the connected fitness app.
Connecting to Samsung Health
Once the ESP32 code is uploaded and running, it starts advertising itself as “ESP32_Emulated_CSC”. You can then go into Samsung Health and scan for new devices. After selecting “ESP32_Emulated_CSC” and connecting, Samsung Health will typically ask for some configuration details, especially the wheel size. This is crucial for the app to accurately calculate your speed from the wheel revolution data it receives.
Once configured, you can start your exercise! Every time you trigger the reed sensor (e.g., by waving a magnet past it, or by mounting it on a wheel and spinning it), you’ll see the values update in Samsung Health. The app takes the raw revolution counts and timestamps from the ESP32 and displays your speed and RPM.
This project demonstrates the power of open standards like BLE and how a simple microcontroller like the ESP32 can be used to create custom sensors that integrate seamlessly with existing fitness ecosystems. It’s a fantastic way to learn about BLE, microcontrollers, and even a bit about how your fitness data is collected!
Happy cycling (and emulating)!
Funny Finding
While looking at the Samsung Health APK for the blogpost, I stumbled upon some curious strings related to antioxidant
. My first thought was that it might be some obscure codename for another type of sensor.
However, upon further investigation (and a quick search that led me to this Android Authority blog post published just 12 hours before my discovery!), it turned out to be a real feature. Samsung watches can actually measure an “Antioxidant Index,” and this functionality was introduced in the very patch of Samsung Health that I was reversing. It was a fun, unexpected detour in my exploration!