Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 29 additions & 26 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,51 +2,54 @@

![A picture of a cat](/assets/_MG_6227.JPG)

VescBLEBridge is a project that lets you add Bluetooth connectivity to your Vesc Controller for only 3€. It utilizes the ESP32 C3 microcontroller as a cost-effective BLE (Bluetooth Low Energy) module. It allows seamless communication between your Vesc controllers and the Vesc Tool App.
VescBLEBridge is a project that lets you add Bluetooth connectivity to your Vesc Controller for only 3€. It utilizes cheap, readily available microcontrollers like the ESP32-C3 and ESP32-C6 as cost-effective BLE (Bluetooth Low Energy) modules. It allows seamless communication between your VESC controllers and the official Vesc Tool App.

## Features

- **Compact Design:** The ESP32 C3's small form factor makes it an ideal choice for applications where space is a constraint.

- **Cost-Effective:** Utilizing the ESP32 C3 as a BLE module provides a budget-friendly alternative to an NRF module for integrating Bluetooth connectivity into Vesc controllers.

- **User-Friendly:** VescBLEBridge is designed to be easy to use, with straightforward setup and configuration. Prebuild versions with flashed firmware and soldered connectors are also planned.
- **Compact Design:** The small form factor of ESP32 dev boards makes them an ideal choice for applications where space is a constraint (skateboards, e-bikes, e-SUPs).
- **Cost-Effective:** Utilizing an ESP32 as a BLE module provides a budget-friendly alternative to an NRF module for integrating Bluetooth connectivity.
- **Multi-Board Support:** Fully supports both the generic ESP32-C3 and the ultra-compact Seeed Studio XIAO ESP32-C6 out of the box.
- **User-Friendly:** Designed to be easy to use with straightforward setup and configuration via PlatformIO.

## Getting Started

### Hardware Setup:
### Hardware Setup
**What you need:**
- [ESP32 C3 Dev Board](https://de.aliexpress.com/item/1005005967641936.html)
- Some Wires
- Fitting connector for your Vesc Uart port (Most likely JST-PH2.0)
- USB C Cable
- An ESP32 Dev Board (e.g., [ESP32-C3](https://de.aliexpress.com/item/1005005967641936.html) or Seeed XIAO ESP32-C6)
- Some wires
- Fitting connector for your VESC UART port (Most likely JST-PH2.0)
- USB-C Cable

Connect the ESP32 C3 to your Vesc controller following the table below.
Connect the ESP32 to your VESC controller following the table below based on which board you are using. *(Remember: TX goes to RX, and RX goes to TX!)*

| ESP32 C3 || VESC |
| ----------- |-| -------------|
| 5V |->| 5V |
| GND |->| GND |
| 20 |->| RX |
| 21 |->| TX |
| VESC | ESP32-C3 (Generic) | ESP32-C6 (Seeed XIAO) |
| :--- | :--- | :--- |
| **5V** | 5V | 5V |
| **GND** | GND | GND |
| **RX** | TX (Pin 21) | TX (Pin D9) |
| **TX** | RX (Pin 20) | RX (Pin D10) |

If it doesnt work you can try swapping rx and tx pins cause they are swapped on some vesc controllers.
*Note: If it doesn't work, try swapping the RX and TX pins, as the labeling convention can vary on some VESC controllers.*

### Flashing Firmware:
To flash the firmware to the esp you need the following prerequisites:
### Flashing Firmware
To flash the firmware to the ESP, you need the following prerequisites:
- [Visual Studio Code](https://code.visualstudio.com/)
- [PlattformIO IDE](https://marketplace.visualstudio.com/items?itemName=platformio.platformio-ide) extension for VSCode
- [PlatformIO IDE](https://marketplace.visualstudio.com/items?itemName=platformio.platformio-ide) extension for VSCode

Once you have VSCode and its PlattformIO extension installed, you need to open this git repo in VSCode. Then connect the esp32 to your computer and hit upload.
Once you have VSCode and its PlatformIO extension installed:
1. Open this git repo folder in VSCode.
2. Connect the ESP32 to your computer via USB.
3. PlatformIO is configured with multiple environments. Select your target board (`esp32-c3-devkitm-1` or `seeed_xiao_esp32c6`) from the project tasks menu.
4. Hit **Upload**.

If you have trouble you can read the official [PlattformIO docs](https://docs.platformio.org/en/latest/integration/ide/vscode.html#ide-vscode)
If you have trouble, you can read the official [PlatformIO docs](https://docs.platformio.org/en/latest/integration/ide/vscode.html#ide-vscode).

## Contributing

We welcome contributions from the community! If you have ideas for improvements, feature requests, or bug reports, please open an issue or submit a pull request.

## Support

For any questions or issues, feel free open an issue.
For any questions or issues, feel free to open an issue.

Happy riding!
Happy riding!
18 changes: 15 additions & 3 deletions platformio.ini
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,24 @@
; Please visit documentation for the other options and examples
; https://docs.platformio.org/page/projectconf.html

; Original C3 Environment (Upgraded to NimBLE v2)
[env:esp32-c3-devkitm-1]
platform = espressif32
board = esp32-c3-devkitm-1
framework = arduino
build_flags =
-DARDUINO_USB_MODE=1
-DARDUINO_USB_CDC_ON_BOOT=1
-DARDUINO_USB_MODE=1
-DARDUINO_USB_CDC_ON_BOOT=1
monitor_speed = 115200
lib_deps = h2zero/NimBLE-Arduino@^1.4.1
lib_deps = h2zero/NimBLE-Arduino@^2.0.0

; seeed_xiao_esp32c6 Environment (Upgraded to NimBLE v2)
[env:seeed_xiao_esp32c6]
platform = https://github.com/pioarduino/platform-espressif32/releases/download/stable/platform-espressif32.zip
board = seeed_xiao_esp32c6
framework = arduino
build_flags =
-DARDUINO_USB_MODE=1
-DARDUINO_USB_CDC_ON_BOOT=1
monitor_speed = 115200
lib_deps = h2zero/NimBLE-Arduino@^2.0.0
57 changes: 29 additions & 28 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,28 +20,37 @@ uint8_t txValue = 0;
#define VESC_CHARACTERISTIC_UUID_RX "6E400002-B5A3-F393-E0A9-E50E24DCCA9E"
#define VESC_CHARACTERISTIC_UUID_TX "6E400003-B5A3-F393-E0A9-E50E24DCCA9E"

#define LOG_TAG_BLESERVER "BleServer"


// Detect if the board is the Seeed XIAO C6
#if defined(ARDUINO_SEEED_XIAO_ESP32C6)
#define VESC_RX_PIN D10
#define VESC_TX_PIN D9
// Otherwise, default to the original C3 pins
#else
#define VESC_RX_PIN 20
#define VESC_TX_PIN 21
#endif

/** None of these are required as they will be handled by the library with defaults. **
** Remove as you see fit for your needs */
class MyServerCallbacks : public BLEServerCallbacks
{
void onConnect(NimBLEServer *pServer, ble_gap_conn_desc *desc)
{
ESP_LOGI(LOG_TAG_BLESERVER, "Client connected: %s", NimBLEAddress(desc->peer_ota_addr).toString().c_str());
class MyServerCallbacks : public NimBLEServerCallbacks {
void onConnect(NimBLEServer *pServer, NimBLEConnInfo& connInfo) override {
ESP_LOGI(LOG_TAG_BLESERVER, "Client connected: %s", connInfo.getAddress().toString().c_str());
ESP_LOGI(LOG_TAG_BLESERVER, "Multi-connect support: start advertising");
deviceConnected = true;
NimBLEDevice::startAdvertising();
}

void onDisconnect(NimBLEServer *pServer)
{
void onDisconnect(NimBLEServer *pServer, NimBLEConnInfo& connInfo, int reason) override {
ESP_LOGI(LOG_TAG_BLESERVER, "Client disconnected - start advertising");
deviceConnected = false;
NimBLEDevice::startAdvertising();
}

void onMTUChange(uint16_t MTU, ble_gap_conn_desc *desc)
{
ESP_LOGI(LOG_TAG_BLESERVER, "MTU changed - new size %d, peer %s", MTU, NimBLEAddress(desc->peer_ota_addr).toString().c_str());
void onMTUChange(uint16_t MTU, NimBLEConnInfo& connInfo) override {
ESP_LOGI(LOG_TAG_BLESERVER, "MTU changed - new size %d, peer %s", MTU, connInfo.getAddress().toString().c_str());
MTU_SIZE = MTU;
PACKET_SIZE = MTU_SIZE - 3;
}
Expand All @@ -63,19 +72,14 @@ void dumpBuffer(std::string header, std::string buffer)
ESP_LOGD(LOG_TAG_BLESERVER, "%s", tmpbuf);
}

class MyCallbacks : public BLECharacteristicCallbacks
{
void onWrite(BLECharacteristic *pCharacteristic)
{
class MyCallbacks : public NimBLECharacteristicCallbacks {
void onWrite(NimBLECharacteristic *pCharacteristic, NimBLEConnInfo& connInfo) override {
ESP_LOGD(LOG_TAG_BLESERVER, "onWrite to characteristics: %s", pCharacteristic->getUUID().toString().c_str());
std::string rxValue = pCharacteristic->getValue();
if (rxValue.length() > 0)
{
if (pCharacteristic->getUUID().equals(pCharacteristicVescRx->getUUID()))
{
if (rxValue.length() > 0) {
if (pCharacteristic->getUUID().equals(pCharacteristicVescRx->getUUID())) {
dumpBuffer("BLE/UART => VESC: ", rxValue);
for (int i = 0; i < rxValue.length(); i++)
{
for (int i = 0; i < rxValue.length(); i++) {
Serial1.write(rxValue[i]);
}
}
Expand All @@ -86,7 +90,7 @@ class MyCallbacks : public BLECharacteristicCallbacks
void setup()
{
Serial.begin(115200);
Serial1.begin(115200, SERIAL_8N1, 20, 21); // RX=20, TX=21
Serial1.begin(115200, SERIAL_8N1, VESC_RX_PIN, VESC_TX_PIN);

// Create the BLE Device
NimBLEDevice::init("VescBLEBridge");
Expand All @@ -95,8 +99,10 @@ void setup()
// Create the BLE Server
pServer = NimBLEDevice::createServer();
pServer->setCallbacks(new MyServerCallbacks());
auto pSecurity = new NimBLESecurity();
pSecurity->setAuthenticationMode(ESP_LE_AUTH_BOND);
//auto pSecurity = new NimBLESecurity();
//pSecurity->setAuthenticationMode(ESP_LE_AUTH_BOND);

NimBLEDevice::setSecurityAuth(true, false, false); // Enable bonding

// Create the BLE Service
BLEService *pService = pServer->createService(VESC_SERVICE_UUID);
Expand All @@ -115,15 +121,10 @@ void setup()

pCharacteristicVescRx->setCallbacks(new MyCallbacks());

// Start the VESC service
pService->start();

// Start advertising
NimBLEAdvertising *pAdvertising = NimBLEDevice::getAdvertising();
pAdvertising->addServiceUUID(VESC_SERVICE_UUID);
// pAdvertising->setAppearance(0x00);
// pAdvertising->setScanResponse(true);
// pAdvertising->setMinPreferred(0x0); // set value to 0x00 to not advertise this parameter

pAdvertising->start();
ESP_LOGI(LOG_TAG_BLESERVER, "waiting a client connection to notify...");
Expand Down