Lab 2
Net ID: pp386
Objective:
This lab’s main objective is to familiarize
Parts required:
1) 1 x SparkFun RedBoard Artemis Nano
2) 1 x USB C-to-C or A-to-C cable
Software Required
1) Arduino IDE
2) Jupyter Lab
Setup
This lab required the installations of the ArduinoBLE library in Arduino IDE and also the installation of Jupyter Lab and Python in a Virtual Environment. Since the laptop has an inbuilt Bluetooth, the external Bluetooth was not utilized. After connecting the Artemis to the PC, the sketch given in the lab files was uploaded onto the Artemis. The Demo Jupyter Notebook was run and the Bluetooth was tested using simple commands. The MAC address of the Artemis was also updated in the connections.yaml file.
Task 1
Send an ECHO command with a string value from the computer to the Artemis board, and receive an augmented string on the computer.
This section implements an ECHO command in Artemis through BLE. The Artemis is first connected via Bluetooth to the PC and then the ECHO command is sent via the Jupyter Lab terminal to expect a response from the Artemis back. The code updated in the Arduino sketch is:
case ECHO:
char char_arr[MAX_MSG_SIZE];
// Extract the next value from the command string as a character array
success = robot_cmd.get_next_value(char_arr);
if (!success)
return;
tx_estring_value.clear();
tx_estring_value.append("Robot says -> ");
tx_estring_value.append(char_arr);
tx_estring_value.append(" :)");
tx_characteristic_string.writeValue(tx_estring_value.c_str());
Serial.print("Sent back: ");
Serial.println(tx_estring_value.c_str());
break;
The code above clears the estring value first, then appends the first part of the response, then appends the word or string to be echoed and then appends the smile at the end. Then the value is written back to get an output in Jupyter Lab as shown below and the output is also displayed on the Serial Monitor of the Arduino IDE.
Task 2
Send three floats to the Artemis board using the SEND_THREE_FLOATS command and extract the three float values in the Arduino sketch.
In this section, the sketch is modified by looking at the case for SEND_TWO_INTS and developing a corresponding code for SEND_THREE_FLOATS. Float values are separated by pipes. The code updated in the Arduino sketch is:
case SEND_THREE_FLOATS:
float float_a, float_b, float_c;
// Extract the next value from the command string as an integer
success = robot_cmd.get_next_value(float_a);
if (!success)
return;
// Extract the next value from the command string as an integer
success = robot_cmd.get_next_value(float_b);
if (!success)
return;
success = robot_cmd.get_next_value(float_c);
if (!success)
return;
Serial.print("Three Floats: ");
Serial.print(float_a);
Serial.print(", ");
Serial.println(float_b);
Serial.print(", ");
Serial.println(float_c);
break;
Then the below cell is run in Jupyter Lab and the output is seen on the Serial Monitor of the Arduino IDE.
As we can see in the image below, the Serial Monitor prints the value of the 3 floats.
Task 3
Setup a notification handler in Python to receive the float value (the BLEFloatCharactersitic in Arduino) from the Artemis board.
In this section, I have tried to write a notification handler function which essentially notifies us whenever there is a change in a FLOAT value received from the Artemis. This is done by using a callback function method and the function definition of the notification handler is shown below.
y=0.0
def notification_handler(uuid, byte_array):
x=ble.bytearray_to_float(byte_array)
global y
y=x
print(y)
The notification handler function takes a uuid characteristic and a byte array which is streamed from the Artemis. Then the bytearray is converted to FLOAT with the bytearray_to_float function. Then a global variable y is updated everytime there is a change in x and hence we can see the change in y without having to explicitly write the receive_float command. start_notify and stop_notify are functions from the BLE library and they are used to start and stop the notification of the values in the Jupyter Lab environment.
Task 4
Briefly explain the difference between the two approaches:
1) Receive a float value in Python using receive_float() on a characteristic that is defined as BLEFloatCharactersitic in the Arduino side
2) Receive a float value in Python using receive_string() (and subsequently converting it to a float type in Python) on a characteristic that is defined as a BLECStringCharactersitic in the Arduino side
In the first option we are able to receive only a FLOAT value meanwhile in the second option we can get a mixture of int, float and characters from which we can get FLOAT values as required. The first option is less memory expensive and in the second option, we need to be careful to not exceed the 512 byte limit.
Additional tasks for ECE5960
Additional Task 1
Effective Data Rate
In this section, I have used a modified notification handler function called notification_handler_string which times the function as well. Using the byte_to_string method and using the function for ECHO is how I have proceeded. I am using the time library from Python and using the time.time() function to get the current time. The start time is noted before sending command to Artemis for ECHO and the notification handler string function notes down the end time; i.e. when the ECHO was received back from the Artemis.
import time
from sys import getsizeof
end = 0
def notification_handler_string(uuid, byte_array):
s = ble.bytearray_to_string(byte_array)
global end
end = time.time()
print(end)
ble.start_notify(ble.uuid['RX_STRING'], notification_handler_string)
start = time.time()
print(start)
ble.send_command(CMD.ECHO, "Hi Priyam")
Then we subtract start from end to get the time elapsed.
time_elapsed = end - start
print(time_elapsed)
Finally, we will calculate the data rate by using the getsizeof function to get the total size of the messages sent back and forth and then dividing the total size by the elapsed time. This gives us the data rate.
total_size = getsizeof("Hi Priyam") + getsizeof("Robot says -> Hi Priyam :)")
print(total_size)
data_rate = total_size/time_elapsed
print(data_rate)
The below image shows the plot of the different message sizes and different bit rates I have plot using Matplotlib.
As we can see from the graph, the data rate increases because for a smaller message size, there is a larger comparative overhead but once the message becomes longer, the bit rate becomes faster as a general trend.
Additional Task 2
Reliability
To check the reliability of the bluetooth data transfer, I have used strings of varying lengths to see whether the communication fails or misses some bits due to a very long string size. I tried entering a very large string and got the Exception: Cannot write string larger than 150 bytes.
But for all other sizes lesser than the Max size, I got reliable output as in I didn’t see the BLE transfer missing any bits. I think there is no data loss for all varying sizes of the message.
Conclusion
In this lab, I worked with the BLE (Bluetooth Low Energy) module on the Artemis and using BLE, I learned how to communicate with the computer. This would be very useful in gaining the sensor readings from the robot in the future and hence, it can be a vital tool for the robot. I also learned how to stress test the BLE from the additional tasks given for MEng students.