Building and testing the firmware
- Xander (Hien Van) To
- Jul 17, 2022
- 4 min read
Updated: Aug 4, 2022
In order to control the ESP32 microcontroller via BLE, the firmware must enable BLE connectivity on the chip and configure a proper BLE Generic Attribute Profile (GATT) to allow data transfer from smartphones [7]. The firmware must also generate a PWM signal from the microcontroller’s timers to feed the level shifter to control the servo motor. Serial monitor is used for debugging the firmware and can be turned off via a toggle variable in the header. A flowchart of the firmware is shown below.

After the bootup process, the microcontroller enters the setup function where the serial monitor, input/output pin, and the BLE GATT configuration are configured and initialized. The BLE GATT has 1 service. The service has 1 characteristic. The characteristic has 2 properties: write and notify. The write property allows data transfer between the smartphone and ESP32 while the notify property will allow the ESP32 to notify the smartphone when the tension adjustment request has been processed. The microcontroller will be a BLE server and continuously advertises its existence after the setup function.
The smartphone will use the LightBlue app to scan for and connect to the ESP32. During the pairing process, the two devices will negotiate the Maximum Transmission Unit (MTU), Min/Max Interval between MTU packet, latency, and timeout. After entering the correct service and characteristic on the smartphone app (the ESP32 BLE has only 1 service and 1 characteristic), we then can start sending new tension levels to the microcontroller under string format by writing to the Write characteristic. The smartphone needs to listen to the notification from the microcontroller.
When the data packet reaches the ESP32, the onWrite callback handler, which is an external interrupt, is activated. New data will be read into an int-type value and go through a series of checks:
If the received value is out of adjustment range, returns an “Out of range tension level” message
If the generator voltage is below the threshold voltage, the servo motor can’t be controlled properly so a “Generator voltage is too low” message is returned.
If the new value is different from the previous value, the new value is saved, the motor is driven to a new position by output PWM signal with corresponding pulse width and a message is returned to confirm the change, otherwise, a return message indicates this level has been set before.
The range of tension: 1 to 10 for manual adjustment from tension level 1 to tension level 10, 11 is automatic Comfort Mode, 12 is automatic Sport Mode, 13 is automatic Ludicrous Mode, 14 is automatic Adaptive Mode, 15 is Random Mode.
Then the microcontroller notifies the smartphone about the return message. The app will show the message once the notification is sent.
Inside the main loop, the microcontroller constantly monitors the generator voltage. If the generator voltage is low than a threshold, the tension will be reduced before the generator voltage is too low to drive the motor back to the default position. This is to avoid the bike stuck at high tension setting, which causes inconvenience for users to start pedaling the bike to enough speed for driving the motor. If the bike is in automatic mode, the tension will increase as generator voltage is above a threshold, which is varied based on which automatic mode is chosen. For example, Comfort Mode increases tension at high pedaling speed for a light exercise, Sport Mode increases tension at medium pedaling speed for a moderate workout session, and Ludicrous Mode increases tension at low pedaling speed for a more challenging workout session. Adaptive Mode is a special mode that it will calculate the rate of change of generator voltage, which is proportional to the pedaling acceleration to determine what generator voltage threshold to increase tension and duration between tension level are. The more aggressive pedal acceleration, the earlier and faster the tension level is incremented.
The firmware was flashed to the microcontroller in Arduino IDE for convenience. Serial Monitor was used for debugging or troubleshooting purposes.
We will use the LightBlue app to communicate with the microcontroller via BLE. This app is available on both Android and iOS smartphones.
Using the app, we can search for the microcontroller BLE named "Tensioning System". We connect to the device, select the write channel, choose the characteristic format to be UTF-8 String, and start sending data to the ESP32 microcontroller.
There are 10 tensioning levels for the bike. By default, the tension level is 1. To change to another level, simply send the new number level to the microcontroller via the LightBlue app and the microcontroller will generate a PWM signal to drive the servo motor, adjusting the magnet array position to vary the tension, while also returning a confirmation message to the smartphone new tension has been applied. If the new level is the same as the previous level, the microcontroller will keep the current setting and also return a message to the smartphone indicating that this level has already been selected.
Below is the output from the Serial Monitor:

Below is a download link for the firmware code used in our project:
Kommentare