Objective
The purpose of lab 2 was to establish a working bluetooth connection between the computer and Artemis board. Other goals include downloading the various tools required to establish said bluetooth connection, as well as to gain familiarity with the Bluetooth Low Energy (BLE) Arduino library which can be learnt about in more detail here.
Prelab Setup
For the current and all future labs, the latest version of Python, version 3.10, was installed from the official website. A virtual environment was set up using the command line actions:
python3 -m pip install --user virtualenv
python3 -m venv FastRobots_ble
.\FastRobots_ble\Scripts\activate
Within the virtual environment, various packages were installed using the following command line action:
pip install numpy pyyaml colorama nest_asyncio bleak jupyterlab
The coding for this lab will be done via Jupyter notebook as a Python IDE, as well as a course-provided code base. The Jupyter notebook was opened using the command line action:
jupyter lab
Setup
The course-provided .ino Arduino file was burned onto the Artemis board, which outputs its MAC address into the serial monitor via the following code:
Serial.println(BLE.address());
Unique bluetooth UUIDs were generated by the command line commands:
from uuid import uuid4
uuid4()
The unique uuid4's are used in the connection.yaml file of the Jupyter notebook, as well as the string and float characteristics of the Arduino code to ensure the computer can communicate with the Artemis board via unique addresses. It is vital for the Artemis board to have a unique address to differentiate it from other students' devices, and unique RX and TX characteritc UUIDs are similarly important so the laptop and Artemis board can communicate data accurately. The computer can connect to the Artemis board using the Python method ble.connect():
# Get ArtemisBLEController object
ble = get_ble_controller()
# Connect to the Artemis Device
ble.connect()
The computer will search for nearby bluetooth devices with the same UUID as defined in the connection.yaml file. This same UUID is used to identify the Artemis board. When both devices, the laptop and the Artemis board, have bluetooth enabled they will search for other devices with matching UUIDs until they pair.
Task 1: ECHO
The first task involved creating a new command type ECHO, which passes a string to the Artemis board's rx_characteristic_string. This string can then be receive back from the Artemis board.
On the Arduino side, the code involves receiving the character array that is passed by the computer, appending it to an Estring value, and writing the new Estring value to the Artemis board's tx_characteristic_string. Some portions of the code are shown below:
#Paraphrased code snippets
case ECHO:
char char_arr[MAX_MSG_SIZE];
tx_estring_value.clear();
tx_estring_value.append(char_arr);
tx_characteristic_string.writeValue(tx_estring_value.c_str());
break;
Task 2: GET_TIME_MILLIS
The next task is similar to the first in that we'd like to write a value to the string character. Instead of passing the string value from the computer, the millis() Arduino function was used to get the current time in milliseconds.
#Paraphrased code snippets
int time = millis();
tx_estring_value.append(time);
tx_characteristic_string.writeValue(tx_estring_value.c_str());
Task 3: Notification Handler
For task 3, a Python notification handler was built. When the notification handler is started, any changes to the bluetooth characteristic of interest will be notified of to the computer. A notification handler is started with the method ble.start_notify(ble.uuid['RX_STRING'], callback), where RX_STRING is the characteristic we want to be notified of changes to, and where callback is the the callback function.
Task 4: GET_TEMP_5s
The command GET_TEMP_5s uses the same logic as tasks 1 and 2 to get the internal die temperature of the Artemis board temperature sensor. The library functions getTempDegF() and getTempDegC() correspond to the temperature in fahrenheit and celsius respectively. Temperature data was updated once per second over the course of 5 seconds. The below image shows the results of the command after enabling the notification handler.
#Paraphrased code snippets
for (int i = 0; i < 5; i++){
float temp_f = getTempDegF();
float temp_c = getTempDegC();
tx_estring_value.append(temp_f);
tx_estring_value.append(temp_c);
tx_characteristic_string.writeValue(tx_estring_value.c_str());
delay(1000);
}
Task 5:
Task 5 is identical to task 4 but involves updating the temperature more times over the same time frame. To accomplish this, a shorter delay and larger loop were used.
#Paraphrased code snippets
for (int i = 0; i < 50; i++){
float temp_f = getTempDegF();
float temp_c = getTempDegC();
tx_estring_value.append(temp_f);
tx_estring_value.append(temp_c);
tx_characteristic_string.writeValue(tx_estring_value.c_str());
delay(100);
}
Task 6:
The Artemis board has 384 kB of RAM. Because of this physical memory limitation, much of the processing must be done on the board itself before communication with the computer. Assuming 16-bit values are taken at 150 Hz, approximately 2400 bits or 300 bytes are written in one second. The board can collect data at this rate for 1280 seconds before running out of memory space.