Project tutorial
Arduino 101 BLE Rover Remote Control

Arduino 101 BLE Rover Remote Control © LGPL

I couldn't find an existing BLE Remote Control for an Arduino 101 Rover - this is my novel solution!

  • 4,996 views
  • 4 comments
  • 12 respects

Components and supplies

About this project

I bought an Arduino 101 for the Arduino compatibility combined with extra features like built-in Bluetooth Low Energy and the 6-axis accelerometer/gyroscope. I wanted to build an Arduino-based remote control rover with my Arduino 101 but struggled to find the sample code. I found numerous examples of RC rovers utilizing Bluetooth, but none for Bluetooth LE.

Breaking down the communications problem into small chunks, I needed to:

  • Figure out how to transmit a byte from my smartphone or tablet to the Arduino 101
  • Determine how to create a workable remote control to send these bytes to the rover's state machine.

I did solve both problems. I quickly discovered that I could modify the LED and CallbackLED samples that are included with the CurieBLE library to transmit a byte to the Arduino 101, but struggled to find a reliable, easy to use remote control. After a lot of internet searching and bit of work, I found a novel solution that is presented here.

Step 1: Sending bytes to the Arduino 101 over BLE

I found an answer to this basic communications challenge on the Arduino forum at: Arduino Forum> Products> Arduino 101. Here is the explanation.

In the Arduino 101 CurieBLE example called CallbackLED - an eventHandler is defined to be called when the switch characteristic is written. The code in setup() function looks like this:

// assign event handlers for characteristic  
switchChar.setEventHandler(BLEWritten, switchCharacteristicWritten);

In the switchCharacteristicWritten event handler function, the code checks whether the value that was written is a zero (0x00) or something else. If non-zero, it turns the LED 'on' and if zero, it turns the LED 'off'. The code looks like this:

if (switchChar.value()) {
    Serial.println("LED on");    digitalWrite(ledPin, HIGH);
else {
    Serial.println("LED off");    digitalWrite(ledPin, LOW);   }

To capture the byte that was written, it is only necessary to save it to a variable and then print it out on the serial monitor, the code would look like this:

if (switchChar.value()) { 
    Serial.println("LED on"); 
    digitalWrite(ledPin, HIGH); 
    char state =     switchChar.value(); 
    Serial.print("new value written: "); 
    Serial.println(state);  }
else {
    Serial.println("LED off"); 
    digitalWrite(ledPin, LOW);   }

I verified this worked by writing the character via the nRF Connect application from Nordic Semiconductor, which is available in both the Play Store and the App Store.

Here are the detailed steps after installing the application:

1. Run the nRF Connect application

2. Run the scanner by pressing 'Scan' in the upper right corner - it usually runs automatically

3. Select your named service (in the sample it is named "LEDCB").

4. Press 'Connect' on the right.

5. Select the Unknown Service (last on the list for your service).

6. Press the up arrow on the right. This brings up a write value dialog box.

7. Press 'New value', enter a byte value in hex like 61 - which is an "a" in ASCII text.

8. Press 'Send' in the lower right and your byte is sent.

Following these steps, we are successfully writing bytes over Bluetooth LE to the Arduino 101.

Step 2: Creating the Bluetooth LE Remote Control

I like the nRF Connect application, but there was no way that I could find to make a workable remote. Entering bytes manually via the nRF Connect application was not going to allow me to control the rover efficiently. To try out other Arduino 101 samples, I had downloaded another nRF application called the nRF Toolbox. In the toolbox, the last application was titled "UART". The UART app has nine user definable buttons that can be configured to send a command on a button press. Pressing 'Edit' in the upper right corner makes all the buttons orange. Touching a button brings up a dialog box to associate an icon to the button and define the command to send when pressed.

I have an Android phone and the available icons match my remote control perfectly. On an IOS device, the icons are not quite as ideal for this usage, but pick ones that you can remember. My rover's motion control is based on a simple one byte code that uses the following configuration (I used the control sequence that was used in Deba168's tutorial for a "Smartphone Controlled Arduino Rover". Here is the list of commands and corresponding characters:

a - forward

b - left

c - stop

d - right

e - reverse

1 - 25% of motor power

2 - 50% of motor power

3 - 75% of motor power

4 - 100% of motor power

When I created the remote control the first time I entered the ASCII value of the character - this did not work. The correct command is the letter/number itself, not its ASCII value. When I entered all nine icons and commands, I pressed 'Done". My finished remote looked like the picture.

Simple, right? Well not so fast. When I tried to connect my Arduino 101 BLE service with the CallbackLED switch characteristic to the UART app, it complained that "The device does not have the required services". I did an internet search on Nordic and UART. I found that the UART application expects to see very specific service UUIDs and characteristics. Using the information at: https://www.nordicsemi.com/eng/Products/Nordic-mob.... I integrated the correct service name, UUID, and the Tx and Rx characteristics into my Arduino sketch, then I made a couple of adjustments to account for the fact that the service can transmit more than one character and therefore provides a pointer to the first element of an array and it works.

Step 3: Testing the Remote Control

The Sketch will send the transmitted byte to the Serial Monitor to verify that each button on the UART application sends the desired byte.

In order to use the remote, follow these steps:

1. Open the nRF Toolbox

2. Select the UART application

3. press the 'Connect' button and then select the name of your BLE service - "BLE_ROV".

The button should now read 'Disconnect'. You are now connected and each button press will transmit the command for that button.

NOTE: In testing this sketch with older IOS phones, I found that my advertised local name of "BLE_ROV" did not show up in the list to connect to. Instead I saw something like, 'Arduino 101-xxxx' where xxxx is the last 4 hex digits of the Mac address for the BLE chip - shown on a small sticker on the back of the Arduino 101 board. Simply select this name to connect to and everything should work.

This was the simplest solution I could find. The Arduino sketch is included for download as well as an image of the serial monitor when you press each key on the remote and then disconnect.

I hope this is useful. I will provide the full instructions for the rover I built at a later date.

Code

RoverRemoteC/C++
Arduino Sketch that sets up the Nordic Semiconductor UART BLE service as a RC rover remote control
/*
  This Sketch creates a simple Remote Control for an Arduino 101
  based Rover. It can be easily modified for other purposes.
  Author: Dave Shade

  It is intended to be paired with the UART sample in the 
  nRF Toolbox available for the Android and IOS platforms
  
  The Nordic Semiconductor UART profile for Bluetooth Low Energy
  is implemented in the CallbackLED sample for the Arduino 101 
  which is: 
  
  Copyright (c) 2015 Intel Corporation. All rights reserved. 

  Both that sample and this sketch are covered under the 
  license below.

  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2.1 of the License, or (at your option) any later version.

  This library is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  Lesser General Public License for more details.

  You should have received a copy of the GNU Lesser General Public
  License along with this library; if not, write to the Free Software
  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-
  1301 USA
*/


#include <CurieBLE.h>

const int ledPin = 13; // set ledPin to use on-board LED

char state;   // variable to hold a transmitted byte

BLEPeripheral blePeripheral;  // BLE Peripheral Device (the board you're programming)

// ====  create Nordic Semiconductor UART service =========
BLEService uartService = BLEService("6E400001B5A3F393E0A9E50E24DCCA9E");
// create characteristics
BLECharacteristic rxCharacteristic = BLECharacteristic("6E400002B5A3F393E0A9E50E24DCCA9E", BLEWriteWithoutResponse, 20);  // == TX on central (android app)
BLECharacteristic txCharacteristic = BLECharacteristic("6E400003B5A3F393E0A9E50E24DCCA9E", BLENotify , 20); // == RX on central (android app)

void setup() {
  Serial.begin(9600);
  pinMode(ledPin, OUTPUT); // use the LED on pin 13 as an output

  // set advertised local name and service UUID:
  blePeripheral.setLocalName("BLE_ROV");
  blePeripheral.setAdvertisedServiceUuid(uartService.uuid());

  // add service, rx and tx characteristics:
  blePeripheral.addAttribute(uartService);
  blePeripheral.addAttribute(rxCharacteristic);
  blePeripheral.addAttribute(txCharacteristic);

  // assign event handlers for connected, disconnected to peripheral
  blePeripheral.setEventHandler(BLEConnected, blePeripheralConnectHandler);
  blePeripheral.setEventHandler(BLEDisconnected, blePeripheralDisconnectHandler);

  // assign event handler for characteristic
  rxCharacteristic.setEventHandler(BLEWritten, rxCharacteristicWritten);

  // advertise the service
  blePeripheral.begin();
}

void loop() {
  // poll ble peripheral
  blePeripheral.poll();  
}

void blePeripheralConnectHandler(BLECentral& central) {
  // central connected event handler
  Serial.print("Connected event, central: ");
  Serial.println(central.address());
  //Serial.println("LED on");
  digitalWrite(ledPin, HIGH);
}

void blePeripheralDisconnectHandler(BLECentral& central) {
  // central disconnected event handler
  Serial.print("Disconnected event, central: ");
  Serial.println(central.address());
  //Serial.println("LED off");
  digitalWrite(ledPin, LOW);
}

void rxCharacteristicWritten(BLECentral& central, BLECharacteristic& characteristic) {
  // central wrote new value to characteristic, update LED
  Serial.print("Characteristic event, written: ");
  
  if (characteristic.value()) {       //null pointer check
    state = *characteristic.value();  //set state to be the value written from the phone/tablet to the Arduino 101
    Serial.println(char(state));      //print out the character to the serial monitor
  } 
}

Schematics

Arduino 101 Schematic
Arduino 101 Schematic

Comments

Author

Shadeydave
shadeydave
  • 3 projects
  • 13 followers

Additional contributors

  • Stable, well documented ble mobile application by Nordic Semiconductor

Published on

July 28, 2016

Members who respect this project

GovknJlmyraAsv2VisoftAjkpwur11949297 10153302854393692 2740910040574473093 n11061776 809631785758759 7366756882373923995 nPowerbot

and 4 others

See similar projects
you might like

Similar projects you might like

Arduino 101 BLE Rover

Project tutorial by shadeydave

  • 3,463 views
  • 0 comments
  • 13 respects

Servo Control with TV Remote Control

Project showcase by eldo85

  • 5,596 views
  • 5 comments
  • 17 respects

Control RGB LED by Dragging – Arduino 101 & App Inventor

Project tutorial by DFRobot and CAVEDU Education

  • 4,437 views
  • 0 comments
  • 12 respects

Arduino101 BLE Autonomous Rover

Project tutorial by 4 developers

  • 13,718 views
  • 2 comments
  • 31 respects

Arduino 101 BLE App

Project in progress by Alexis Santiago Allende

  • 10,794 views
  • 26 comments
  • 51 respects

Control Your Computer With A Remote Control

Project tutorial by Arduino_Scuola

  • 5,942 views
  • 1 comment
  • 8 respects
Add projectSign up / Login