Control Zumo rover using Bluetooth low energy serial communication with Arduino Uno, ESP32 and WatchX

IMG_5717

The Challenge
I recently ordered this cool Arduino compatible watch from watchX and been trying to hook it up with my Zumo rover for our weekly challenge we have with the guys at the office. I dig the fact that this gadget ships bare bones and when put together, you get a fully functional smartwatch which you can code with Arduino and C++. My goal is to able to send commands to the rover by utilizing watchX’s bluetooth low energy capabilities and hence navigate the rover forward, back, left and right.. basic stuff.

So what is watchX ?
WatchX is an Arduino compatible watch designed and developed by guys from Turkey. Visit their site here, they also run a community site here. It’s built on MCU Atmega 32U4 chip and has a flash program memory of 32KB and supports Bluetooth Low Energy. Besides this, it also does come loaded with a bunch if sensors too.

Accelerometer & Gyroscope.
Temperature sensor & Barometric Pressure Sensor.
3 Axis Magnetometer.


For a full list of features, check this this link
For this project, I already have a fully assembled rover that’s also compatible with Arduino

Why Bluetooth and not RC

Bluetooth is a wireless technology standard for exchanging data between fixed and mobile devices over short distances using short-wavelength UHF radio waves. So given my operational requirements of less than 30 meters, Bluetooth ended up the cheapest and best option. I also happen to have an ESP32 dev board with BLE capabilities I bought earlier on for my bee hive connect project laying around and I guess it’s cheap and readily available for use.

When talking about Bluetooth Low Energy vs. Bluetooth, the key difference is in Bluetooth 4.0’s (BLE) low power consumption. Although that may sound negative, it’s extremely positive when talking about applications that run on a small battery life for years.

Bluetooth is not a good choice for long distance range communication signals and it will never replace RC receiver. Bluetooth usually range within 30-100m and RC receiver can easy go for 1000m.

Components needed for this project

ESP32 Dev Module – used this for intercepting BLE commands to the onboard Arduino Uno via UART (Universal Asynchronous serial communication)
WatchX – used as a peripheral device to advertise rover commands
Zumo robot fully assembled
Arduino UNO – Runs code to navigate the rover

Ok so let’s get started

Step 1 Configuring ESP32 Dev Board

Hardware

Small Breadboard
4 male to female jumpers
ESP32 Dev Board
– We will connect RX and TX pins if the ESP32 board to the Arduino Uno TX and RX pins using the two jumpers swapped (RX->TX and TX->RX). The other two jumpers are for power and ESP32 dev board strictly requires 3.5v, So we mount 3.5v of the Dev board to 3.5v and GND to ground of the Arduino UNO.

Software Libraries


ESP32_BLE_Arduino – This library provides an implementation bluetooth low energy support for the ESP32 using the Arduino platform

Our Esp32 dev board will communicate with our watchX using serial UART service advertised by our watchX. These services uses GATT which stands for Generic ATTribute Profile, governs data organization and data exchanges between connected devices.  One device (the peripheral) acts as a GATT Server, which stores data in Attribute records, and the second device in the connection (the central) acts as a GATT Client, requesting data from the server whenever necessary. Our Esp32 device will act as out GATT client constantly getting notified of the changes by our GATT Server watchX.

We will be subscribing to the UART service we advertised on watchX for two important characteristics for reading and transmitting data.

//Include ESP32 BLE support library
include "BLEDevice.h" 

//We define ESP32 RX and TX pins to read and write from
#define RXD2 16 
#define TXD2 17

// We define the remote UART service we wish to connect to.
 static BLEUUID serviceUUID("6e400001-b5a3-f393-e0a9-e50e24dcca9e");

// The RX characteristic of the remote service we are interested in.
 static BLEUUID    charUUID_RX("6e400003-b5a3-f393-e0a9-e50e24dcca9e");

// The TX characteristic of the remote service we are interested in.
 static BLEUUID    charUUID_TX("6e400002-b5a3-f393-e0a9-e50e24dcca9e");

 static BLERemoteCharacteristic* pRemoteCharacteristic_TX;
 static BLERemoteCharacteristic* pRemoteCharacteristic_RX;
 static BLEAdvertisedDevice* myDevice;

//We will get notified whenever the value on the BLE device characteristic changes and transmit that data to the host Arduino UNO RX and TX pins
static void notifyCallback  (
   BLERemoteCharacteristic* pBLERemoteCharacteristic,
   uint8_t* pData,
   size_t length,
   bool isNotify) {
     //transmit commands to the host Arduino UNO via UART  
      Serial2.println((char)pData);
 }

I’ve shared full source code for the ESP32 here

Step 2 – Configure watch X firmware

Github Download link: https://github.com/mtulu-argeX/Basic_Watch 113

Forked from https://github.com/kghunt/Basic_Watch 19
Developer’s original blog: https://www.reddit.com/r/watchX/comments/8vmotl/basic_watch_fairly_big_update/ 33

Installation instructions:

  • Download the firmware from the Github download link
  • Download the missing library: https://github.com/adafruit/Adafruit_SleepyDog 38 You can also import this library as follows: Sketch -> Include Library -> Manage Libraries then search Adafruit_SleepyDog and install.

I refactored the bluetooth header file to enable us to send direction commands to interested GATT clients using UART service. “AT+BLEUARTTX=” command will transmit the specified text message out via the UART Service while you are running in Command Mode.

Adafruit_BluefruitLE_SPI ble(BLUEFRUIT_SPI_CS, BLUEFRUIT_SPI_IRQ, BLUEFRUIT_SPI_RST);     

void bluetoothinit()  {
      ble.begin(VERBOSE_MODE);
      ble.factoryReset();
      //name of our bluetooth device
      ble.sendCommandCheckOK(F( "AT+GAPDEVNAME=LEXX" ));
      //set our bluetooth device to data mode
      ble.setMode(BLUEFRUIT_MODE_DATA);
      ble.sendCommandCheckOK(F("AT+GATTCLEAR"));
      ble.reset();
}
//move rover right
 void moveRoverRight() {
     ble.sendCommandCheckOK(F("AT+BLEUARTTX=R"));
 }
 //move rover left
 void moveRoverLeft() { 
   ble.sendCommandCheckOK(F("AT+BLEUARTTX=L"));
 }
 //move rover forward
 void moveRoverForward() {
   ble.sendCommandCheckOK(F("AT+BLEUARTTX=F"));
 }
 // move rover back
 void moveRoverBack(){
    ble.sendCommandCheckOK(F("AT+BLEUARTTX=B"));
 }
 //stop rover
 void stopRover(){
    ble.sendCommandCheckOK(F("AT+BLEUARTTX=S"));
 }

Download the rest of the project source here

About the Author

Father, backyard bee keeper, avid gardener, Founder and Medicine man at Blue Bean Software.