← Home
Docs/Software/Wireless & Bluetooth Setup

Wireless Setup & Hardware Control

The ESP32-S3 microcontroller includes built-in wireless hardware (Bluetooth Low Energy and Wi-Fi), which provides a convenient way to monitor live telemetry, adjust motion parameters, and tune controller gains without repeatedly plugging and unplugging USB cables.


1. Hardware Mode Control & Offline Operation

EVDrive includes a dedicated physical SPDT hardware switch (SW4 on GPIO 15) and status indicator LED (D1 on GPIO 16). This gives you direct manual hardware control over wireless connectivity:

  • Interactive Telemetry Mode (Switch ON): The ESP32 boots with Bluetooth/Wi-Fi radios active, allowing browser dashboards and phones to receive real-time encoder readings, battery voltages, and gyro rates.
  • Isolated Offline Mode (Switch OFF): The ESP32 completely skips radio initialization in software, conserving battery power, reducing CPU interrupt overhead, and ensuring 100% standalone autonomous execution.

The Clean Offline Procedure

  1. Interactive Tuning & Telemetry: Turn the hardware wireless switch (SW4 on GPIO 15) ON. Connect from your browser or device, test motion profiles, and log sensor telemetry.
  2. Switching to Standalone Mode: Flip the hardware wireless switch OFF.
  3. Press the Hardware Reset Button (SW6): When firmware checks the switch in setup(), it determines whether to initialize the radio stack on boot. Pressing Reset ensures the radio stack is never allocated in memory, providing a pure offline environment.
  4. Visual Check: Confirm that the Wireless LED (D1, GPIO 16) is completely dark.
  5. Start Run: Trigger the vehicle using the onboard start button (SW5, GPIO 7) to run your autonomous test.

2. Communication Options in Practice

Choose the workflow that best fits your learning goals:

  • USB Serial Cable: The simplest and most direct method. Ideal for viewing Arduino Serial Monitor and Serial Plotter data during desk testing.
  • Web Bluetooth (BLE): Connect directly to modern browsers (Google Chrome, Microsoft Edge) without installing native apps. Great for wireless telemetry in a classroom or open hallway.
  • Onboard Buttons & Display: Wire physical buttons, rotary encoders, or an I2C OLED display to the expansion GPIO header J6 to select target distances directly on the vehicle.

3. Using Bluetooth Low Energy (BLE GATT)

The ESP32 Arduino core includes a built-in BLEDevice library.

Understanding BLE GATT Architecture

BLE organizes communication into GATT (Generic Attribute Profile) structures:

  • Service: A group of capabilities identified by a unique 128-bit UUID (Universally Unique Identifier).
  • Characteristics: Individual data endpoints inside a service:
    • Notify / Read: For streaming telemetry from the vehicle to your device (such as live encoder counts or battery voltage).
    • Write: For sending commands or parameters from your device to the vehicle (such as setting target distances or speed limits).

Example: Setting Up a Simple BLE Server

Here is a minimal snippet showing how to initialize BLE, create a notify characteristic for telemetry, and listen for incoming commands:

cpp
#include <BLEDevice.h>
#include <BLEServer.h>
#include <BLEUtils.h>
#include <BLE2902.h>

// Example UUIDs (you can generate your own standard UUIDs)
#define SERVICE_UUID "19b10000-e8f2-537e-4f6c-d104768a1214"
#define STATUS_UUID  "19b10001-e8f2-537e-4f6c-d104768a1214"
#define CMD_UUID     "19b10002-e8f2-537e-4f6c-d104768a1214"

BLECharacteristic* pStatusChar = nullptr;

// Callback triggered whenever a client writes a command to the vehicle
class CommandCallbacks : public BLECharacteristicCallbacks {
  void onWrite(BLECharacteristic* pCharacteristic) {
    String value = pCharacteristic->getValue();
    if (value.length() > 0) {
      Serial.print("Received Command: ");
      Serial.println(value);
      // Example: parse distance commands like "DIST:5.0"
    }
  }
};

void setupBLE() {
  BLEDevice::init("EVDrive"); // Broadcast name
  BLEServer* pServer = BLEDevice::createServer();
  BLEService* pService = pServer->createService(SERVICE_UUID);

  // Status characteristic (Vehicle -> Client notifications)
  pStatusChar = pService->createCharacteristic(
    STATUS_UUID,
    BLECharacteristic::PROPERTY_NOTIFY
  );
  pStatusChar->addDescriptor(new BLE2902());

  // Command characteristic (Client -> Vehicle writes)
  BLECharacteristic* pCmdChar = pService->createCharacteristic(
    CMD_UUID,
    BLECharacteristic::PROPERTY_WRITE
  );
  pCmdChar->setCallbacks(new CommandCallbacks());

  pService->start();
  BLEDevice::getAdvertising()->addServiceUUID(SERVICE_UUID);
  BLEDevice::startAdvertising();
  Serial.println("BLE advertising started as 'EVDrive'.");
}

Dashboard Note: The open-source browser dashboard at Web Bluetooth & Dashboard connects to these example UUIDs by default.


4. Mode Warning Interlock Check

To prevent launching an autonomous offline run while wireless is still active, you can incorporate a mode interlock check in code:

cpp
const int PIN_START_BTN = 7;
const int PIN_WL_SW     = 15;
const int PIN_WL_LED    = 16;

// If start button is pressed while wireless switch is ON, alert the user
if (digitalRead(PIN_START_BTN) == LOW && digitalRead(PIN_WL_SW) == LOW) {
  // Flash wireless LED as a notification
  for (int i = 0; i < 3; i++) {
    digitalWrite(PIN_WL_LED, LOW);
    delay(100);
    digitalWrite(PIN_WL_LED, HIGH);
    delay(100);
  }
  // Optional: prompt user or proceed in interactive mode
}

Note: If you want a completely offline run, remember to flip the switch OFF and press Reset (SW6).


5. Web Dashboard

If you want to try an example browser-based interface that connects to the car over Web Bluetooth, see Web Bluetooth & Dashboard.