Lab 1: Artemis & Bluetooth

01.21.2025 - 02.04.2025

Objective

Lab 1 is split into two parts, 1A and 1B. The overall objective of this lab was to set up and familiarize myself with the Arduino IDE and the Artemis board. Lab tasks included programming the board, reading & writing serial messages over USB, using the onboard temperature sensor and microphone, and communicating between my computer (Jupyter notebook) and the Artemis board through Bluetooth.

Lab 1A

I first installed Arduino IDE and made sure that it was updated to the most recent version. I also followed the set up instructions to install the correct board and libraries. After hooking up the Artemis board to my computer and selecting the correct Board and Port, I moved on to the tasks.

Example 2: Serial

I then uploaded and ran the next example, Serial. This code allowed me to type characters in the Serial monitor and then receive the same input characters as outputs, also in the Serial monitor.

Example 3: Analog Read

The third example file was analogRead, which utilized the on board temperature sensor. The temperature measurements were outputted to the serial monitor, and I tested the sensor by holding the board in my hand to warm it up. As seen in the video below, the temperature did increase when I held the board.

Example 4: Microphone Output

The last example had me test the microphone on the Artemis board. The frequency measurements were outputted to the Serial Monitor. I tested whistling, and the frequency increased accordingly.


Lab 1B

I first read through the set up instructions and made sure my Python and pip versions were correct. I also made a virtual environment, installed the necessary packages, and installed the Arduino BLE library. Finally, I downloaded the provided codebase and worked on the tasks using Jupyter lab.

Before beginning the tasks, I followed the instructions to get my MAC address, after which I updated the artemis_address in connections.yaml accordingly. The other set up step was generating a UUID, and updating connections.yaml and ble_arduino.ino.

mac_address uuid

Task 1: ECHO

The first task was to program the board so that I could send a string from my computer to the board using ECHO. The board would then send back to the computer an augmented string."

I added the arduino code below to make the board return the user's string when the ECHO command is used.

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());

Below, you can see the Python end of ECHO, which send the command to the board, and then receives a string back.

echo

Task 2: SEND_THREE_FLOATS

The next command I completed was SEND_THREE_FLOATS, which would allow me to send three floats from my computer to the artemis board. For the Arduino code, I referenced SEND_TWO_INTS, which was already implemented, and changed the implementation accordingly. Below, you can see the Python code to send the floats, and the Serial Monitor.

three_floats_python three_floats_arduino

Task 3: GET_TIME_MILLIS

This task was to get the current time from the Artemis board and return it as a String to the computer.

This Arduino code below uses the millis() method to get the time.

tx_estring_value.clear();
tx_estring_value.append("T: ");
tx_estring_value.append(int(millis()));
tx_characteristic_string.writeValue(tx_estring_value.c_str());

And the Python end is shown below.

get_time_millis

Task 4: Notification Handler

The next few tasks all required the implementation of a notification handler, and Task 4 was to set up a handler which would return the time as a string.

notif_handler_task4

Task 5: Message Speed

For task 5, I wanted to check how fast the board could send messages. To do this, in Arduino, I made a command GET_TIME_LOOP, which repeatedly sent the current time for five seconds:

case GET_TIME_LOOP:
{
    unsigned long startMillis = millis();
    int i = 1;

    while(millis() - startMillis < 5000)  {
        tx_estring_value.clear();
        tx_estring_value.append("T: ");
        tx_estring_value.append(int(millis()));
        tx_characteristic_string.writeValue(tx_estring_value.c_str());
        i++;
    }

    break;
}

I modified the notification handler in Python slightly by changing msg to an array instead of a String. This way, I knew how many messages were sent by the Arduino by just checking the length of msg.

task5_python

Because there were 596 integer messages sent in 5 seconds, I calculated the data transfer rate to be (596 messages * 4 bytes)/5 = 476.8 bytes/second.

Task 6: SEND_TIME_DATA

In task 6, I explored a different way to get time stamps, and its effect on the data transfer rate. Instead of sending every message within the loop, I created an array and filled it with time stamps. I then looped through that array and sent the messages to my computer.

case SEND_TIME_DATA:
{
    unsigned long startMillis = millis();
    int num_msgs = 0;

    // collect time data
    while(millis() - startMillis < 5000)  {
        if (num_msgs < 1000) {
            times[num_msgs] = int(millis());
            num_msgs++;
        }
        delay(50);
    }

    // send time data from the times array to python
    int i = 0;
    while(i <= num_msgs)  {
        tx_estring_value.clear();
        tx_estring_value.append(times[i]);
        tx_characteristic_string.writeValue(tx_estring_value.c_str());
        i++;
    }

    break;
}
                            

I used the same notification handler as in task 5, and got the following data transfer measurements. This came out to be (1001 messages * 4 bytes)/5 second = 800.8 bytes/second.

time_loop_python

Task 7: GET_TEMP_READINGS

Building from task 6, I added another array to keep track of temperature measurements. The logic was the same as in task 6 as well. Shown below is the updated loop for populating the arrays:

while(millis() - startMillis < 5000)  {
    if (num_msgs < 1000) {
        times[num_msgs] = int(millis());
        temps[num_msgs] = float(getTempDegF());
        num_msgs++;
    }
}
temp_readings_python

The computer would then receive the time and temperature measurements, which can be seen above.

Task 8: Data Collection Method Comparison

Method 1 had one loop that sent a message every single iteration. This approach would be beneficial in situations where I need real-time monitoring and action. It has a data transfer rate of 476.8 bytes/second. This is slower than the other method, meaning that although it allowed for quick response and action, it is inefficient for data collection and could use too much bandwidth.

Method 2 used a global array and two loops, one that would populate the array, and another that would iterate through the array and send the stored messages. This method is better for data collection purposes, as it sends larger packets of information and thus reduces the comparative overhead of BLE transmissions. There might be a slight delay due to some time allocated at the beginning to collecting data, as well as more memory used for the data arrays. However, it does have a faster data transfer rate (800.8 bytes/second).

With the knowledge that the Artemis board has 384 kB of RAM, I calculated roughly how much data can be stored. For a single data type (ie just temperature or just time), we can store 384kB / 4B = 96000 messages.