Lab 2: Bluetooth Communication

In this lab, we’re going to establish communication between our computer and the Artemis board through the bluetooth stack. We’ll be using Python inside a Jupyter notebook on the computer end, and the Arduinno programming language on the Artemis side.

Setup

BLE

Arduino has a library (ArduinoBLE) that supports all the Arduino boards that have the hardware enabled for Bluetooth Low Energy (BLE) and Bluetooth 4.0 and above. BLE is optimized for low power use at low data rates.

Computer Setup

This is a brief summary of the computer set-up required for this lab.

Install Python

$ python3 --version
$ python3 -m pip --version

Virtual Environment

$ python3 -m pip install --user virtualenv
$ python3 -m venv ece4960_ble
$ source ece4960_ble/bin/activate

Python Packages

$ pip install numpy pyyaml colorama nest_asyncio bleak jupyterlab

Artemis Board Setup

We installed ArduinoBLE from the library manager in the Arduino IDE and loaded the ble_arduino.ino example sketch into the Artemis board. The Artemis board printed it’s MAC address as shown below.

Code Overview

Python Package

The demo.ipynb notebook is a demo file that helps us set up the bluetooth connection between the computer and the board.

Lab Tasks

Echo

For this task, I had to update the Arduino sketch to handle the appropriate cases as instructed. In the case of the ECHO command type, the Artemis would need to echo the message that it had received back to the computer, where the computer would print it out. As instructed in the lab handout, I sent back the message to the computer but modifying it such that the computer receives "Robot says -> <msg> :)".

The embedded code below shows the message printed in Jupyter Notebook and the screenshot of the Arduino serial output shows the print statement that shows when the Artemis sends the message to the computer.

Send Three Floats

For this task, I also had to update the Arduino sketch. I referred to the SEND_TWO_INTS command and replicated it, changing the relevant parts of the code such that it took a float instead of an int, and took three sets of data instead of two. I then printed it to the serial output as shown in the screenshot below.

Receive Float

In the demo, we had learned how to receive a float. In this task, we were still receiving a float. The difference is that, instead of having one instance of receiving a value, we would make a global variable that would constantly be updated using the notification feature that uses the start_notify() and stop_notify() functions. Whenever this global variable was printed, it would print the most updated value that is received. No Arduino code was needed to be added/modified, but there was some Python code that we needed to add.

The first step was to create the global variable that is to be updated. This was assigned a random value. The function start_notify() takes in two arguments: the uuid and a callback function. So the next step was to create the callback function. The callback function takes in two arguments: the uuid, which is purely for debugging purposes, i.e., to print in the callback function, and the bytearray to be converted into a float. This bytearray to be converted to a float (using the bytearray_to_float function) is then assigned to the global variable. Now that the callback function is complete, all we need to do is pass this function as the second argument in start_notify(), and the uuid (in our case, 'RX_FLOAT') as the first argument. After running this, I made a few cells that would print out the value of this global function. Without having to call receive_float(), this variable is constantly updated.