Course on "Fast Robots", offered Spring 2022 in the ECE dept at Cornell University
This project is maintained by CEI-lab
The purpose of this lab is to establish communication between your computer and the Artemis board through the bluetooth stack. We will be using Python inside a Jupyter notebook on the computer end and the Arduino programming language on the Artemis side.
Before you begin this lab, please read up on this fantastic summary of Bluetooth Low Energy (BLE).
You will need to install Python 3 and pip. If you already have them installed, please make sure you have the latest releases (Python >= 3.9 and pip >= 21.0).
Some Windows users may need to use `python` instead of `python3`
python3 --version
python3 -m pip --version
Minimum Requirements: Linux kernel 4.15+ and bluez 5.48+
Simply use your package manager to install python3 and pip :).
Minimum Requirements: Windows 10
Recommended OS: macOS 12.0
It may work with (some) older versions. If you have issues with older versions, contact the teaching team. We will try out best to help you.
python3
.A virtual environment is a Python environment such that the Python interpreter, libraries and scripts installed into it are isolated from those installed in other virtual environments, and (by default) any libraries installed in a “system” Python, i.e., one which is installed as part of your operating system.
Run the following commands in a Command Line Interface (CLI):
python3 -m pip install --user virtualenv
Place all your Python scripts and Jupyter notebooks within this directory.
python3 -m venv ece4960_ble
venv will create a virtual Python installation in the newly created ece4960_ble directory.
For any lab using Python scripts (or Jupyter notebooks), you will first need to activate your virtual environment.
This will only work from the project folder (the one containing the ece4960_ble folder).
source ece4960_ble/bin/activate
.\ece4960_ble\Scripts\activate
source ece4960_ble/bin/activate
deactivate
Your CLI prompt should no longer display the prefix.
Your CLI prompt should now have the prefix (ece4960_ble).
pip install numpy pyyaml colorama nest_asyncio bleak jupyterlab.
NOTE: In Windows, you may see an error while installing some of these packages. Follow the download link in the error message to download and install (the unnecessarily huge) C++ build tools.
NOTE: The codebase has been updated on 21 Feb, 2022 to fix a bug (in the Arduino code) related to converting negative float values into a string. Please re-download the codebase or apply (manually or using git) this patch to your old codebase.
MD5SUM checksum: e2b9c785dfa6d7f27749d3ba016e0537
Last Updated: 21 Feb, 2022 (Version: 1.1)
We will be using Jupyter notebooks to write Python code. Before you can open a Jupyter notebook, you need to start the Jupyter server. If the Jupyter server is stopped, you will not be able to run/open/modify any Jupyter notebooks.
The Jupyter server can only access notebooks from the directory it was started in.
jupyter lab
macOS users may have to use
Jupyter lab
(capital J).
If no window opens up, click on the URL displayed in the CLI.
You will be writing most of your Python code using this browser window on Jupyter notebooks. For students proficient in Python, you may choose to write some of your modules in Python script files and import them into your Jupyter notebook.
If you are new to JupyterLab, please go through the Introduction to JupyterLab tutorial (available under the Tutorials page).
Install ArduinoBLE from the library manager (Tools -> Manage Libraries…) in the Arduino IDE.
Make sure you change the serial baud rate to 115200 bps.
The Python and Artemis packages provide you with the base code necessary to establish a communication channel between your computer and the Artemis board through BLE. You will use them to setup an initial communication channel in this lab, and work towards a more comprehensive robot control protocol in your future lab sessions.
Though a characteristic value can be up to 512 bytes long (according to the Bluetooth Core Specification), the ArduinoBLE library limits the maximum size to 255 bytes. We are using a more conservative size limitation of 150 bytes. The provided Python codebase throws an error if you attempt to send data that is larger than the member variable ArtemisBLEController.max_write_length (150 bytes). On the Arduino side, the macro MAX_MSG_SIZE (defined in EString.h) is used to set the character array sizes used in various classes.
The ArduinoBLE library provides different types of constructors for handling different types of data. We recommend using BLEFloatCharacteristic, BLEIntCharacteristic and BLECStringCharacteristic (a new type defined in BLECStringCharacteristic.h); these three types should be sufficient for all the labs.
Refrain from using the C++ish data type “string” in Arduino and its associated BLE constructor BLEStringCharacteristic unless you absolutely know what you are doing. Though it may seem to simplify handling strings, they could pose issues in later labs (Ref).
A string in C (also known as C-string) is an array of characters, followed by a NULL character. The class EString (Estring stands for EnhancedString, defined in EString.h) can be used to easily manipulate character arrays. The header provides getter and setter functions to convert between a character array and a EString object. The append() functions allow to append a float, double, int, character array or string literal to the EString. All the functions defined inside EString are considered to be “unsafe” because they are vulnerable to buffer overruns; modify or use them accordingly.
A robot command is a string of the format "<command_type>:<value_1>|<value_2>|<value_3>..."
. The BLECStringCharacteristic constructor is used to define a writable string GATT characteristic for communicating robot commands. The command type is an integer, and a value may be a float (or double), integer or string literal.
The characters : and | are used as delimiters for the command type and different values. Command messages received on the Artemis that do not strictly match this format may lead to undefined behavior, due to the functions (itoa, atoi, strtok) used to tokenize the robot command string. The command format, command type, value type and delimiters may be changed in RobotCommand.h.
For example, we could use the SEND_TWO_INTS command to send two integers 2 and -3 to the Artemis board (or robot) from the computer. The string data that is essentially sent (or written) would be the string "1:2|-3|"
. The Arduino sketch (in the base code) essentially reads this data and determines the type of the robot command by extracting the integer value in the string data before the character :. It then seeks to extract the two integers from the rest of the string data which are separated by the character |.
The class RobotCommand (defined in RobotCommand.h) is used to extract values of different data types from the robot command string sent to the Artemis board. The functions get_command_type() and get_next_value() internally use strtok() to extract the command type, float, int and string literals from the robot command string.
The sample sketch file ble_arduino.ino defines 2 Read and 1 Write BLE GATT characteristics; one for receiving robot commands, and two for sending a string and a float value. The setup() function sets up the BLE characteristics and provides an example of how to utilize the EString class. The loop() function listens for connections and handles the communication in read_data() and write_data() The handle_command() function together with the enum CommandTypes depicts how a command message may be handled. It also provides some examples of using the get_command_type() and get_next_value() functions.
Run through all the cells before you begin to work on the lab tasks.
artemis_address
in the configuration file (connection.yaml).
A valid MAC address is a 12 digit hexadecimal number, often represented as 6 pairs of hexadecimal digits separated by colons. If the Artemis board displays a MAC address that is lesser than 12 digits, left pad the appropriate pairs with 0s. For example, if the displayed MAC address is
C0:C2:8A:89:98:8
, update the configuration file(connection.yaml) withartemis_address: 'C0:C2:8A:89:98:08'
For example, the computer sends the string value “HiHello” to the Artemis board using the ECHO command, and the computer receives the augmented string “Robot says -> HiHello :)” from a read GATT characteristic.
Perform an analysis on the communication performance.
TIP: Use the notification handler for this. If you find a better way, include your approach in the write-up.
To demonstrate that you’ve successfully completed the lab, please upload a brief lab report (<600 words), with code snippets (not included in the word count), photos, and/or videos documenting that everything works and what you did to make it happen.