top of page

Empowering Tetraplegic Individuals with iCycle: A BLE-Enabled Virtual Cycling Experience

  • Photo du rédacteur: dov azogui
    dov azogui
  • 5 sept. 2024
  • 2 min de lecture


ree

As part of the iCycle project at University College London (UCL), I had the opportunity to enhance the virtual cycling experience for tetraplegic users. My contribution focused on developing a custom Bluetooth Low Energy (BLE) sensor using an ESP32 module, designed specifically to simulate wheel rotations and integrate seamlessly with virtual cycling platforms like Zwift.

Technical Highlights:

Advanced BLE Sensor Integration: I engineered a BLE sensor that accurately captures and transmits real-time cycling data. This technology is crucial for translating minimal physical interactions into dynamic movements within the virtual environment, thereby enhancing user engagement and simulation realism.

Seamless Virtual Environment Interaction: The sensor’s integration with virtual platforms allows for real-time feedback and adjustment based on the user’s input, ensuring a fluid and realistic cycling experience. This synchronization is vital for immersing users in a virtual world that mirrors the physical dynamics of cycling.

Code Explanation and Implementation: The setup involves configuring the ESP32 as a BLE server with specific UUIDs for cycling speed and cadence. The implementation handles real-time data such as wheel and crank revolutions, which are essential for realistic virtual cycling dynamics.

Here’s an overview of the code structure:


#include <Arduino.h>
#include <BLEDevice.h>
#include <BLEServer.h>
#include <BLEUtils.h>
#include <BLE2902.h>
// Define the UUIDs for BLE service and characteristics
#define SERVICE_UUID "00001816-0000-1000-8000-00805f9b34fb" // Cycling Speed and Cadence Service
#define CHARACTERISTIC_UUID "00002a5b-0000-1000-8000-00805f9b34fb" // CSC Measurement Characteristic
BLECharacteristic *pCharacteristic;
bool deviceConnected = false;
uint32_t lastSentTime = 0;
uint16_t wheelRevolutions = 0;
uint16_t crankRevolutions = 0;
uint16_t lastWheelEventTime = 0;
uint16_t lastCrankEventTime = 0;
class MyServerCallbacks : public BLEServerCallbacks {
    void onConnect(BLEServer* pServer) {
      deviceConnected = true;
      Serial.println("Device connected");
    };
    void onDisconnect(BLEServer* pServer) {
      deviceConnected = false;
      Serial.println("Device disconnected");
    }
};
void setup() {
  Serial.begin(115200); // Start serial communication
  BLEDevice::init("ESP32 CSC"); // Initialize BLE device
  BLEServer *pServer = BLEDevice::createServer(); // Create BLE server
  pServer->setCallbacks(new MyServerCallbacks());
  BLEService *pService = pServer->createService(SERVICE_UUID);
  pCharacteristic = pService->createCharacteristic(
                      CHARACTERISTIC_UUID,
                      BLECharacteristic::PROPERTY_NOTIFY
                    );
  pCharacteristic->addDescriptor(new BLE2902());
  pService->start(); // Start the service
  pServer->getAdvertising()->start(); // Start advertising
  Serial.println("Waiting for a client connection to notify...");
}
void loop() {
  if (deviceConnected) {
    if (millis() - lastSentTime > 1000) {
      uint8_t value[9] = {0x03, lowByte(wheelRevolutions), highByte(wheelRevolutions),
                          lowByte(lastWheelEventTime), highByte(lastWheelEventTime),
                          lowByte(crankRevolutions), highByte(crankRevolutions),
                          lowByte(lastCrankEventTime), highByte(lastCrankEventTime)};
      pCharacteristic->setValue(value, sizeof(value));
      pCharacteristic->notify();
      lastSentTime = millis();
      Serial.println("Notification sent");
      wheelRevolutions++;
      crankRevolutions++;
      lastWheelEventTime += 1024;
      lastCrankEventTime += 512;
    }
  }
  if (Serial.available() > 0) {
    int newSpeed = Serial.readStringUntil('\n').toInt();
    wheelRevolutions = newSpeed;
    Serial.print("New speed set to: ");
    Serial.println(newSpeed);
  }
  delay(100);
}

 
 
bottom of page