Who is in control?
- When a training app (like Zwift on your laptop) has connected to your trainer using the FTMS protocol: is it possible to connect multiple devices via FTMS? As FTMS enables control of a physical device there can only be one “controller” to avoid safety issues. This means that you will not be able to connect multiple devices directly to the indoor bike trainer or treadmill using FTMS. If the trainer does not appear in an app’s (e.g. Zwift's) device list (on the Zwift pairing screen) it generally means the trainer is (still) connected to another controlling app or device. It is virtually impossible to connect the trainer to Zwift using FTMS, have a nice indoor ride and at the same time to connect for example the Simcline to the trainer or Zwift for simulating road incline... This means that other active cycling App's (installed on your telephone and/or tablet) are in competition with your Zwift App on the laptop to connect with the trainer! Be carefull with devices with active cycling Apps near your setup during the connection phase! Notice that modern smartphones have very powerful BLE/WIFI chips that have an indoor BLE reach of 6-10 meters. If in doubt: turn Flight Mode On!
What about ANT+ (FE-C) and FTMS at the same time?
- When a training app (like Zwift) has connected to your trainer using the ANT+ protocol: is it possible to connect other devices via FTMS?
Since this ANT+ connection enables control of the physical device (trainer) there can NOT be connected another “controller” at the same time over FTMS to avoid safety issues. Only one (1) controlling app is allowed to connect and drive the Trainer at any time. You know, 2 captains on one ship is a recipe for disaster! If this case, unfortunately and undesirebly, happens with your equipment setup, the controlling Client-side code will not connect or disconnect with an error message! So keep these worlds separated! If you intend to use devices with BLE and FTMS: mechanically disconnect the ANT+ dongle to avoid your controller App (like Zwift) to (auto)connect over ANT+.
What about Zwift Hub and Jetblack users?
- There is an excellent review available DCRainmaker Zwift Hub review, that describes o.a. a special goodie that comes with the Zwift Hub and Jetblack:
– Protocol Compatibility: ANT+ FE-C, ANT+ Power, Bluetooth Smart Trainer Control, Bluetooth Smart Power (everything you need)
– Unique Party Trick: Can rebroadcast your heart rate sensor within a single channel, ideal for Apple TV Zwift users (who are Bluetooth channel limited)
– App Compatibility: Every app out there basically (Zwift, TrainerRoad, Rouvy, RGT, The Sufferfest, Kinomap, etc…)
Simcline-V2 fully supports this proprietary Zwift function for your heart rate sensor connection. The code supports the same features as you would have had with only Zwift App connected to Zwift Hub or JetBlack trainer! Use your heart rate band the way you are used too before the Simcline-V2 came in between your Zwift Hub/Jetblack trainer and the Zwift App! It should be fully transparent with respect to this feature! Please test yourself!
How to cleanup Zwift devices from the past?
- Zwift can sometimes hang onto the wrong info, such as trainers or sensors that were paired to the game in the past. Zwift uses Mac Addresses from previous connections to identify devices. So when device names change Zwift hangs on to the unique Mac Addresses rather than the names that you see in the pairing screens! This can be rather confusing and lead to misunderstandings when you connect devices having only their original names shown and not the actual names....
Check out the steps below.
For PC/Mac to reset all the Zwift stored devices on a PC or Mac, complete these steps:
- Close Zwift
- On your desktop, open Documents
- Double-click Zwift
- Delete or Edit <knowndevices.xml>
Next time you go for a Zwift ride:
- Launch Zwift
- Pair your devices
How does Simcline-V2 utilize the Dual Processor capacities of the ESP32?
- One of the advantages of the ESP32 platform is the fact that the ESP32 WROOM processor has two cores. This makes it possible to precisely balance the load of a program over 2 processor cores. With the mechatronic Simcline setup this is particular usefull for the motor control of the actuator and the BLE MITM traffic, heavily leaning on the NimBLE-Arduino library.
During operation Zwift sends (about every 800 ms) new settings, and one of these is the grade value (road inclination in degrees). Simcline-V2 translates the grade to a level that should be reached by the actuator to simulate exactly the road grade that was received from Zwift. However, the actuator can only be switched to move up, move down or stop. After having set the actuator to move (up or down), the program has to check continuously if the actuator has reached the desired level by reading its position with the help of the Time-Of-Flight sensor and act accordingly. To avoid conflicts during variable updates (i.c. TargetPosition) a Binary Semaphore scheme is applied to protect task shared variables during an update and presentation.
Meanwhile the trainer sends all your cycling data (CPS, CSC, FTMS and optional HRM) 4-5 times per second over BLE MITM channels. The Zwift app has to confirm the receipt of several of these data. Vice versa, the (virtual ride) data sent by Zwift have to be tranferred to the trainer and also the trainer has to confirm the receipt of several of these data. Simcline-V2, being a BLE MITM, handles a huge amount of BLE traffic per second and it does not allow for mistakes!
The load of Simcline-V2 is balanced over 2 processor cores of the ESP32 processor:
On Core 0: exclusively all the BLE handling (NimBLE-Arduino)
On Core 1: the critical control of the actuator, presentation (display) and other small tasks.
Why is my trainer variably successful in connecting with the SIMCLINE?
- In most cases this behavior can be attributed to NOT follow the critical sequence for starting and connecting of Trainer, SIMCLINE and Zwift.
- The Start or Initial situation of ALL parties involved is: Laptop/Zwift, Simcline and Trainer are Powered OFF!
- Trainer Power-ON --> Trainer needs some time (4 seconds?) to settle and start advertising!
- Power-ON or Reset Simcline (ESP32 board) --> Simcline needs some time to start, test motor functions and start scanning for Trainer!
- Wait for Simcline and Trainer to connect! 9 Out of 10 times this is immediately successful. If this is NOT the case then Reset Simcline first and wait again for a Simcline-Trainer connection! If this is NOT successful: Read FAQ #1, take appropriate measures and than go back to "Start" after ALL components have been Powered OFF first.
- Laptop/Zwift Power-ON --> ONLY when Simcline and Trainer have been connected successfully!
- Wait and wait for the Zwift pairing window to pop-up
- Click orange POWER SOURCE button and select in the list with devices: ESP32#### (Simcline) --> Close
- Click orange RESISTANCE button and select in the list with devices: ESP32#### (Simcline) --> Close
- Click orange CADENCE button and select in the list with devices: ESP32#### (Simcline) --> Close
- Click orange OK! button, when all the selected devices are conforming your choices and are indicated as CONNECTED!
Will Simcline-V2 work out-of-the-box with my ESP32S3 development board?
- Yes, in most cases, when we assume your ESP32S3 has enough Flash and PSRAM memory on board. Particularly when you restrict (!) your attention initially to the Smart-MITM application, to check out if the concept is working with your hardware.
If you want finally a full blown working SIMCLINE setup, you have to complement the concrete ESP32board class in the file:/documents/arduino/libraries/Simcline-V2/src/board/YOUR_ESP32_Board.h. It needs minimally definitions for the PIN assignments: TOF-sensor (I2C), DRV8871 Motor Driver board (Actuator) and optionally for 2 Buttons. Possibly you have to insert code for specific board initialization (not shown).
#define PIN_ACTUATOR_1 -1 // PIN to be connected to pin IN2 of the Adafruit DRV8871 Motor Driver board
#define PIN_ACTUATOR_2 -1 // PIN to be connected to pin IN1 of the Adafruit DRV8871 Motor Driver board
// Optional Button 1 and 2 PIN connections
//#define PIN_BUTTON_1 -1 // PIN to be connected to Internal/External button
//#define PIN_BUTTON_2 -1 // PIN to be connected to Internal/External button
#define PIN_I2C_SCL SCL // Default in Arduino IDE -> Check for your board!
#define PIN_I2C_SDA SDA // Default in Arduino IDE -> Check for your board!For how Arduino IDE 2.x handles the specific board pin assignments, search for your board in: this reference
How are Zwift, Trainer and Simcline handling (changes in) road grade during your ride!
- The trainer calculates the resistance, among others using road grade information. That's why Zwift sends modified road grades to the trainer to set resistance. Simple as that! However, resistance (i.e. road grade) is also dependent of Zwift's famous difficulty setting. With the default difficulty setting of 50%, Zwift sends only half the value of the road grade to the trainer. Only when the Zwift App difficulty setting is 100%, Zwift will send unmodified road grades to the trainer (WYSIWYG). As a consequence the Simcline will lift accordingly and show the road grade values on the display! If you observe deviations when riding long and steady climbs, like Alpe-de-Huez or Mt-Ventoux, check the Zwift App "difficulty setting" that is most likely the cause! Most Zwifters have set the Zwift difficulty at 100%, because they want a "road-realistic" experience when training and racing indoors with Zwift.
- Trainers do NOT react momentarily, but delayed on changes in road grade, they need to process incoming info and the (direct) drive mechanism has to be settled accordingly before you will feel it as a change in resistance. The delay between the initial command (by Zwift) and the feel on the bike is 1 to 1.5 seconds. To accommodate for this delay, the Zwift app sends commands 1 to 1.5 second earlier (!) than what you observe on your screen (slope of the road you see and the displayed road grade value on the Zwift window). This explains temporarily deviating values on the Simcline display in comparison what you see on the Zwift window, after all Simcline is a MITM and is the first to receive changes in road grade, to react (moving the lift mechanism) and to show the new value on the display. When riding rolling hills in rapid succession, like Zwift's Titans Grove, this is most visible! Notice that the Simcline's responsiveness is benefiting of the feature!
- Zwift handles downhill roads differently! When the road grade values become negative, during a downhill section of the road, Zwift will consequently send only half of the road grade value to the trainer (i.e Simcline). Modern trainers with direct drive are capable to accelerate proportionally with negative road grades. So when the Zwift window shows a -8.0 grade value it has sent only -4.0 road grade to the trainer. The rationale behind this is to minimize effortless riding, after all you get on an indoor bike to do some work! Simcline will act accordingly and display only 50% of the Zwift road grade value on downhill sections!
- After Zwift has paired with your trainer it sends a first road grade value (randomly between 2.0 and 5.0) to the trainer, to wake-up/activate the resistance mechanism. You will feel the resistance while you were expecting a flat road for a start. Simcline, being a MITM, will lift your front wheel accordingly! This road grade value remains constant, until you have actually started with the ride of your choice!
- The Simcline code has its own setting that influences how it will react on and display the road grade value sent by Zwift. The Grade-Change-Factor functionality was originally designed and implemented to allow a Simcline user to attenuate the actuator movements in case of a noisy and/or slow actuator. Notice that the original (unmodified) Zwift grade value is passed on to the trainer, so the trainer's resistance is NOT affected by the Grade-Change-Factor setting! Default code setting for the Grade-Change-Factor is 100% and it can be modified dynamically using the Simcline app.
In conclusion when you see different road grade values in the Zwift window compared with the Simcline display, this can have different reasons! If you consider this a problem: check first Zwift difficulty setting and Grade-Change-Factor of the Simcline, these can be modified to what you prefer! Like it or not, the other causes are Zwift features and part of the design! Cycling Apps like Rouvy and MyWhoosh handle road grades more or less comparably.
How to (later) manage (changed) Device MAC Addresses?
When you run Smart-MITM, it is instructed to detect and store in ESP32 NVS (Non-Volatile-Storage) the MAC addresses for Trainer and Laptop. These stored MAC addresses are used by Smart-Simcline to unmistakenly connect to the right client and server! If you want to check or eventually change the MAC addresses in NVS (because of changing devices) you will find in Simcline-V2/examples a tool Test_Board_plus_NVS that will help with the task! Notice that MAC addresses have to be a) correct and b) in right format to be resolved at connection-time!
The second option with permanent result, is to insert defines for Laptop and Trainer addresses in the configNimBLE.h.
- Open file, edit and save(!):
/documents/arduino/libraries/Simcline-V2/src/config/configNimBLE.h
Look for the following section:
// ----------------------------------------------------------------------------------------
// Your FIXED hardware Laptop/Trainer/Smartphone BLE MAC- or DEVICE-Addresses
// Enter address string here like the printed format like [00:01:02:03:04:05 0]
// LAPTOP Fixed Device Address --------Public Type (0) --------- Random Type (1)-----------
#define LAPTOPADDRESS "00:01:02:03:04:05 0" // Example Mac string of Public Type
// TRAINER Fixed Device Address --------Public Type (0) --------- Random Type (1)----------
#define TRAINERADDRESS "00:01:02:03:04:05 1" // Example Mac string of Random Type- Uncommented
#define LAPTOPADDRESSand#define TRAINERADDRESSare overruling whatever values are stored within NVS !