codedesign
codedesign

Reputation: 11

What is the supported range of Indoor Bike Simulation Parameters in the FTMS spec?

I am looking at the FTMS (Bluetooth) spec and can't figure out how to get the range of supported values in the Set Indoor Bike Simulation Parameters Procedure (section 4.16.2.18).

Basic use case would be displaying the message: 'Your Trainer supports simulation of grades up to 20%.'

A Smart Bike Trainer would support the setting of Power Target, Resistance Level and Indoor Bike Simulation Parameters, under 0x2AD9 Fitness Machine Control Point. The first 2 have dedicated charactersitics under 0x1826 Fitness Machine Service:

from which you can read the minimum, maximum value, and increment unit supported by the particular hardware device.

Bike Trainers also support different levels of grade simulation, which is also a big marketing differentiator. It can be up to 5%, 10%, 20%, and more or anything in between.

EDIT: For this case specifically Ifor 's comment has been most helpful. Indeed those values are speed dependent.

When I am setting this value with the Set Indoor Bike Simulation Parameters which is defined in section 4.16.2.18., I would like know what is the maximum value supported by the Bike Trainer. Is there a standard way to figure that out as there is for Power Target and Resistance Level setting? And while we are on it what about the other 3 params: wind speed, rolling resistance and wind resistance coefficient?

I am asking about this part of the FTMS spec document: FTMS section 4.16.2.18

EDIT: My main worry is how the trainer reacts when you write a value above the maximum. For Resistance Target it overflows and goes into very undesirable behavior. For Power Target it just ignores the value and stays at the maximum. I want to be sure that the trainer won't suddenly set the grade, or other simulation params to 0 when I write a value too high as it does with Resistance Target.

Also do you write negative values for trainers like the Tacx Neo that claim to support Descent simulation?

Here is nRF Connect Log from a session with a typical Smart Bike Trainer:

nRF Connect, 2020-12-01
Tacx Flux 46731 (FA:03:E3:1B:FE:4C)
I   19:11:25.482    [Server] Server started
V   19:11:25.507    Device Information (0x180A)
- Firmware Revision String [R] (0x2A26)
- Manufacturer Name String [R] (0x2A29)
- Model Number String [R] (0x2A24)
Unknown Service (669aa605-0c08-969e-e211-86ad5062675f)
- Unknown Characteristic [W] (669aab01-0c08-969e-e211-86ad5062675f)
   Characteristic User Description (0x2901)
- Unknown Characteristic [N] (669aab02-0c08-969e-e211-86ad5062675f)
   Characteristic User Description (0x2901)
   Client Characteristic Configuration (0x2902)
- Unknown Characteristic [W WNR] (669aab21-0c08-969e-e211-86ad5062675f)
   Characteristic User Description (0x2901)
- Unknown Characteristic [N] (669aab22-0c08-969e-e211-86ad5062675f)
   Characteristic User Description (0x2901)
   Client Characteristic Configuration (0x2902)
Unknown Service (669aa501-0c08-969e-e211-86ad5062675f)
- Unknown Characteristic [R W] (669aac01-0c08-969e-e211-86ad5062675f)
   Characteristic Presentation Format (0x2904)
Cycling Power (0x1818)
- Cycling Power Measurement [N] (0x2A63)
   Client Characteristic Configuration (0x2902)
- Cycling Power Feature [R] (0x2A65)
- Sensor Location [R] (0x2A5D)
- Cycling Power Control Point [I W] (0x2A66)
   Client Characteristic Configuration (0x2902)
Fitness Machine (0x1826)
- Indoor Bike Data [N] (0x2AD2)
   Client Characteristic Configuration (0x2902)
- Fitness Machine Feature [R] (0x2ACC)
- Supported Resistance Level Range [R] (0x2AD6)
- Supported Power Range [R] (0x2AD8)
- Fitness Machine Status [N] (0x2ADA)
   Client Characteristic Configuration (0x2902)
- Fitness Machine Control Point [I W] (0x2AD9)
   Client Characteristic Configuration (0x2902)
Unknown Service (6e40fec1-b5a3-f393-e0a9-e50e24dcca9e)
- Unknown Characteristic [N] (6e40fec2-b5a3-f393-e0a9-e50e24dcca9e)
   Client Characteristic Configuration (0x2902)
- Unknown Characteristic [W WNR] (6e40fec3-b5a3-f393-e0a9-e50e24dcca9e)
V   19:11:25.818    Connecting to FA:03:E3:1B:FE:4C...
D   19:11:25.818    gatt = device.connectGatt(autoConnect = false, TRANSPORT_LE, preferred PHY = LE 1M)
D   19:11:26.494    [Server callback] Connection state changed with status: 0 and new state: CONNECTED (2)
I   19:11:26.494    [Server] Device with address FA:03:E3:1B:FE:4C connected
D   19:11:26.547    [Broadcast] Action received: android.bluetooth.device.action.ACL_CONNECTED
D   19:11:26.586    [Callback] Connection state changed with status: 0 and new state: CONNECTED (2)
I   19:11:26.586    Connected to FA:03:E3:1B:FE:4C
V   19:11:26.663    Discovering services...
D   19:11:26.664    gatt.discoverServices()
I   19:11:26.732    Connection parameters updated (interval: 7.5ms, latency: 0, timeout: 5000ms)
D   19:11:27.617    [Callback] Services discovered with status: 0
I   19:11:27.617    Services discovered
V   19:11:27.671    Generic Access (0x1800)
- Device Name [R] (0x2A00)
- Appearance [R] (0x2A01)
- Peripheral Preferred Connection Parameters [R] (0x2A04)
Generic Attribute (0x1801)
- Service Changed [I] (0x2A05)
   Client Characteristic Configuration (0x2902)
Device Information (0x180A)
- Firmware Revision String [R] (0x2A26)
- Manufacturer Name String [R] (0x2A29)
- Model Number String [R] (0x2A24)
Unknown Service (669aa605-0c08-969e-e211-86ad5062675f)
- Unknown Characteristic [W] (669aab01-0c08-969e-e211-86ad5062675f)
   Characteristic User Description (0x2901)
- Unknown Characteristic [N] (669aab02-0c08-969e-e211-86ad5062675f)
   Characteristic User Description (0x2901)
   Client Characteristic Configuration (0x2902)
- Unknown Characteristic [W WNR] (669aab21-0c08-969e-e211-86ad5062675f)
   Characteristic User Description (0x2901)
- Unknown Characteristic [N] (669aab22-0c08-969e-e211-86ad5062675f)
   Characteristic User Description (0x2901)
   Client Characteristic Configuration (0x2902)
Unknown Service (669aa501-0c08-969e-e211-86ad5062675f)
- Unknown Characteristic [R W] (669aac01-0c08-969e-e211-86ad5062675f)
   Characteristic Presentation Format (0x2904)
Cycling Power (0x1818)
- Cycling Power Measurement [N] (0x2A63)
   Client Characteristic Configuration (0x2902)
- Cycling Power Feature [R] (0x2A65)
- Sensor Location [R] (0x2A5D)
- Cycling Power Control Point [I W] (0x2A66)
   Client Characteristic Configuration (0x2902)
Fitness Machine (0x1826)
- Indoor Bike Data [N] (0x2AD2)
   Client Characteristic Configuration (0x2902)
- Fitness Machine Feature [R] (0x2ACC)
- Supported Resistance Level Range [R] (0x2AD6)
- Supported Power Range [R] (0x2AD8)
- Fitness Machine Status [N] (0x2ADA)
   Client Characteristic Configuration (0x2902)
- Fitness Machine Control Point [I W] (0x2AD9)
   Client Characteristic Configuration (0x2902)
Unknown Service (6e40fec1-b5a3-f393-e0a9-e50e24dcca9e)
- Unknown Characteristic [N] (6e40fec2-b5a3-f393-e0a9-e50e24dcca9e)
   Client Characteristic Configuration (0x2902)
- Unknown Characteristic [W WNR] (6e40fec3-b5a3-f393-e0a9-e50e24dcca9e)
D   19:11:27.671    gatt.setCharacteristicNotification(00002a05-0000-1000-8000-00805f9b34fb, true)
D   19:11:27.673    gatt.setCharacteristicNotification(669aab02-0c08-969e-e211-86ad5062675f, true)
D   19:11:27.675    gatt.setCharacteristicNotification(669aab22-0c08-969e-e211-86ad5062675f, true)
D   19:11:27.676    gatt.setCharacteristicNotification(00002a63-0000-1000-8000-00805f9b34fb, true)
D   19:11:27.677    gatt.setCharacteristicNotification(00002a66-0000-1000-8000-00805f9b34fb, true)
D   19:11:27.679    gatt.setCharacteristicNotification(00002ad2-0000-1000-8000-00805f9b34fb, true)
D   19:11:27.679    gatt.setCharacteristicNotification(00002ada-0000-1000-8000-00805f9b34fb, true)
D   19:11:27.680    gatt.setCharacteristicNotification(00002ad9-0000-1000-8000-00805f9b34fb, true)
D   19:11:27.681    gatt.setCharacteristicNotification(6e40fec2-b5a3-f393-e0a9-e50e24dcca9e, true)
I   19:11:27.756    Connection parameters updated (interval: 140.0ms, latency: 0, timeout: 4000ms)
V   19:11:43.635    Reading characteristic 00002acc-0000-1000-8000-00805f9b34fb
D   19:11:43.635    gatt.readCharacteristic(00002acc-0000-1000-8000-00805f9b34fb)
I   19:11:43.860    Read Response received from 00002acc-0000-1000-8000-00805f9b34fb, value: (0x) 82-40-00-00-0C-A0-00-00
A   19:11:43.860    "Fitness Machine Features:
Cadence Supported
Resistance Level Supported
Power Measurement Supported

Target Setting Features:
Resistance Target Setting Supported
Power Target Setting Supported
Indoor Bike Simulation Parameters Supported
Spin Down Control Supported" received
V   19:11:47.599    Reading characteristic 00002ad6-0000-1000-8000-00805f9b34fb
D   19:11:47.599    gatt.readCharacteristic(00002ad6-0000-1000-8000-00805f9b34fb)
I   19:11:47.777    Read Response received from 00002ad6-0000-1000-8000-00805f9b34fb, value: (0x) 00-00-E8-03-01-00
A   19:11:47.777    "Minimum Resistance Level: 0.0
Maximum Resistance Level: 100.0
Minimum Increment: 0.1" received
V   19:11:49.567    Reading characteristic 00002ad8-0000-1000-8000-00805f9b34fb
D   19:11:49.567    gatt.readCharacteristic(00002ad8-0000-1000-8000-00805f9b34fb)
I   19:11:49.735    Read Response received from 00002ad8-0000-1000-8000-00805f9b34fb, value: (0x) 00-00-20-03-01-00
A   19:11:49.735    "Minimum Power: 0 W
Maximum Power: 800 W
Minimum Increment: 1 W" received
V   19:11:53.235    Reading descriptor 00002902-0000-1000-8000-00805f9b34fb
D   19:11:53.235    gatt.readDescriptor(00002902-0000-1000-8000-00805f9b34fb)
I   19:11:53.517    Read Response received from descr. 00002902-0000-1000-8000-00805f9b34fb, value: (0x) 00-00
A   19:11:53.517    "Notifications and indications disabled" received
V   19:11:56.203    Enabling notifications for 00002ada-0000-1000-8000-00805f9b34fb
D   19:11:56.203    gatt.setCharacteristicNotification(00002ada-0000-1000-8000-00805f9b34fb, true)
D   19:11:56.204    gatt.writeDescriptor(00002902-0000-1000-8000-00805f9b34fb, value=0x0100)
I   19:11:56.457    Data written to descr. 00002902-0000-1000-8000-00805f9b34fb, value: (0x) 01-00
A   19:11:56.457    "Notifications enabled" sent
V   19:11:56.466    Notifications enabled for 00002ada-0000-1000-8000-00805f9b34fb
V   19:12:21.266    Reading characteristic 00002a65-0000-1000-8000-00805f9b34fb
D   19:12:21.266    gatt.readCharacteristic(00002a65-0000-1000-8000-00805f9b34fb)
I   19:12:21.516    Read Response received from 00002a65-0000-1000-8000-00805f9b34fb, value: (0x) 0C-00-00-00
A   19:12:21.516    "(0x) 0C-00-00-00" received
V   19:12:24.300    Reading characteristic 00002a5d-0000-1000-8000-00805f9b34fb
D   19:12:24.300    gatt.readCharacteristic(00002a5d-0000-1000-8000-00805f9b34fb)
I   19:12:24.455    Read Response received from 00002a5d-0000-1000-8000-00805f9b34fb, value: (0x) 0C
A   19:12:24.455    "Rear Wheel" received
V   19:12:29.553    Reading descriptor 00002902-0000-1000-8000-00805f9b34fb
D   19:12:29.553    gatt.readDescriptor(00002902-0000-1000-8000-00805f9b34fb)
I   19:12:29.775    Read Response received from descr. 00002902-0000-1000-8000-00805f9b34fb, value: (0x) 00-00
A   19:12:29.775    "Notifications and indications disabled" received
V   19:12:32.623    Enabling indications for 00002a66-0000-1000-8000-00805f9b34fb
D   19:12:32.623    gatt.setCharacteristicNotification(00002a66-0000-1000-8000-00805f9b34fb, true)
D   19:12:32.624    gatt.writeDescriptor(00002902-0000-1000-8000-00805f9b34fb, value=0x0200)
I   19:12:32.856    Data written to descr. 00002902-0000-1000-8000-00805f9b34fb, value: (0x) 02-00
A   19:12:32.856    "Indications enabled" sent
V   19:12:32.866    Indications enabled for 00002a66-0000-1000-8000-00805f9b34fb
V   19:12:40.710    Reading descriptor 00002902-0000-1000-8000-00805f9b34fb
D   19:12:40.710    gatt.readDescriptor(00002902-0000-1000-8000-00805f9b34fb)
I   19:12:40.976    Read Response received from descr. 00002902-0000-1000-8000-00805f9b34fb, value: (0x) 00-00
A   19:12:40.976    "Notifications and indications disabled" received
V   19:12:42.341    Enabling notifications for 00002a63-0000-1000-8000-00805f9b34fb
D   19:12:42.341    gatt.setCharacteristicNotification(00002a63-0000-1000-8000-00805f9b34fb, true)
D   19:12:42.342    gatt.writeDescriptor(00002902-0000-1000-8000-00805f9b34fb, value=0x0100)
I   19:12:42.515    Data written to descr. 00002902-0000-1000-8000-00805f9b34fb, value: (0x) 01-00
A   19:12:42.515    "Notifications enabled" sent
V   19:12:42.520    Notifications enabled for 00002a63-0000-1000-8000-00805f9b34fb
I   19:12:43.079    Notification received from 00002a63-0000-1000-8000-00805f9b34fb, value: (0x) 30-00-00-00-00-00-00-00-00-00-00-00-00-60
A   19:12:43.079    "(0x) 30-00-00-00-00-00-00-00-00-00-00-00-00-60" received
I   19:12:44.059    Notification received from 00002a63-0000-1000-8000-00805f9b34fb, value: (0x) 30-00-00-00-00-00-00-00-00-00-00-00-00-64
A   19:12:44.059    "(0x) 30-00-00-00-00-00-00-00-00-00-00-00-00-64" received
I   19:12:45.038    Notification received from 00002a63-0000-1000-8000-00805f9b34fb, value: (0x) 30-00-00-00-00-00-00-00-00-00-00-00-00-68
A   19:12:45.038    "(0x) 30-00-00-00-00-00-00-00-00-00-00-00-00-68" received
I   19:12:46.019    Notification received from 00002a63-0000-1000-8000-00805f9b34fb, value: (0x) 30-00-00-00-00-00-00-00-00-00-00-00-00-6C
A   19:12:46.019    "(0x) 30-00-00-00-00-00-00-00-00-00-00-00-00-6C" received
I   19:12:47.139    Notification received from 00002a63-0000-1000-8000-00805f9b34fb, value: (0x) 30-00-00-00-00-00-00-00-00-00-00-00-00-70
A   19:12:47.139    "(0x) 30-00-00-00-00-00-00-00-00-00-00-00-00-70" received
I   19:12:48.118    Notification received from 00002a63-0000-1000-8000-00805f9b34fb, value: (0x) 30-00-00-00-00-00-00-00-00-00-00-00-00-74
A   19:12:48.118    "(0x) 30-00-00-00-00-00-00-00-00-00-00-00-00-74" received
I   19:12:49.099    Notification received from 00002a63-0000-1000-8000-00805f9b34fb, value: (0x) 30-00-0A-00-00-00-00-00-00-00-00-00-00-78
A   19:12:49.099    "(0x) 30-00-0A-00-00-00-00-00-00-00-00-00-00-78" received
I   19:12:50.079    Notification received from 00002a63-0000-1000-8000-00805f9b34fb, value: (0x) 30-00-00-00-00-00-00-00-00-00-00-00-00-7C
A   19:12:50.079    "(0x) 30-00-00-00-00-00-00-00-00-00-00-00-00-7C" received
V   19:12:50.310    Disabling notifications for 00002a63-0000-1000-8000-00805f9b34fb
D   19:12:50.310    gatt.setCharacteristicNotification(00002a63-0000-1000-8000-00805f9b34fb, false)
D   19:12:50.311    gatt.writeDescriptor(00002902-0000-1000-8000-00805f9b34fb, value=0x0000)
I   19:12:50.495    Data written to descr. 00002902-0000-1000-8000-00805f9b34fb, value: (0x) 00-00
A   19:12:50.495    "Notifications and indications disabled" sent
V   19:12:50.497    Notifications and indications disabled for 00002a63-0000-1000-8000-00805f9b34fb

Upvotes: 0

Views: 2271

Answers (1)

cyberschlumpf
cyberschlumpf

Reputation: 11

I did an implementation of FTMS for the nRF52382 to interface Zwift. Zwift currently only uses two commands that need to be handled: SET_TARGET_POWER (in ERG mode) and SET_SIMULATION_PARAMETERS. The others I have never seen (SET_INCLINE, SET_RESISTANCE) I presume they are not actually used but only their FE-C counterparts. Also SET_SIMULATION_PARAMETERS only has changing values for grade, windspeed, cww and cr are always fixed (for me). I presume the FE-C emulations get different values. You will need to implement the FE-C formulas described in the ANT+ spec, i.e. calculate rolling resistance, wind resistance and gravitational resistance to derive the "imposed resistance" by the game into your FTMS server. (Read the spec precisely: the encodings are different between FTMS and FE-C!)

Once you have this you can then calculate which setting on your smart trainer best corresponds to the required resistance and set that. I've been working on that for the past two months and it works great so far. Zwift is remote controlling my dumb trainer through the nRF52832 that I interfaced to my hometrainer's PCB

Upvotes: 1

Related Questions