Objective

Run Bluetooth between the artemis board and the computer



Materials Used



Procedure

To start with I downloaded the source code found on the course website here, which had all the relevant python and c code.
I also plugged in the usb to bluetooth adapter we were given in our kits, and reran the commands to install bleak.
Next, I uploaded the code to the Artemis board from the Arduino IDE, confirming that the blue LED blinked and the serial monitor printed the requisite information
Next, I ensured I could use USB devices in the VM by enabling them in VirtualBox manager
After first running main.py in the VM, I got bleak errors. Then, I got bluetooth adapter not found issues. After some headscratching and good-ole ECE turning it off and turning it back on again, I found that I had to reconnect the bluetooth module after the VM was already running, else it would not be found. It finally found my device! I added the robot's address to settings.py as well to speed up the process in the future.

Ping Robot

Now I moved on to the Ping Robot stage. I simply edited the myRobotTasks() code to run await theRobot.ping()
The pinging worked right off the bat, and I was able to collect data on the round trip time, shown below in these two histograms
ping rate

Oddly enough, the ping rate went down after a short period of time, shown below
ping rate

However, the average ping rate was around 161ms with a standard deviation of 41ms

The packet size is defined in __bleak_ping, which length to PING.Value (1 byte) + 98 zeros; a total of 99 bytes.
Given an average of .161 seconds per message, this results in around 614 bytes/sec (or 4919 bits/sec). This is round trip time, however, so one side will send at around 10kb/sec. This is about an order of magnitude slower than our baud rate for serial of 115200 symbols/sec, which adds up for wireless communication.

Request Float

Next, I went through the process of requesting a float from the device, which I decided to make pi to 5 digits.
I first started by trying to just write to res_cmd->data directly, but when that errored out on me, I took a look at case START_BYTESTREAM_TX , which showed that there was a tricky type-conversion format that I was unfamiliar with. Copying that, I added ((float *)(res_cmd->data))[0] = 3.14159f;, and changed TODO_VAL to 1. When I tried that, I got the error that it needed 4 bytes, so I changed the number to 4, but that still didn't work.
ping rate
Then, I learned I needed 1 byte for the length and one for the type, and tried that (6). Still, nothing worked. So I tried the suggestion on campuswire to print the raw value of what I was sending, and realized I forgot to add the command_type.
ping rate
I went to simpleHandler in main.py and found Commands.GIVE_FLOAT.value. Finally, I added that, et voila. The number was not exactly correct beyond the numbers I gave it, so any comparison I did would have to be constrained to the accuracy of the digits provided.
ping rate
        case REQ_FLOAT:
            Serial.println("Going to send a float");

            res_cmd->command_type = GIVE_FLOAT;
            res_cmd->length = 8; 
            ((float *)(res_cmd->data))[0] = 3.14159f;
            
            amdtpsSendData((uint8_t *)res_cmd, 6);
            
            break;

      

Testing the Data Rate

Last but *certainly* not least was testing the data rate
At first, I tried just setting bytestream_active = true; in case START_BYTESTREAM_TX: and adding a 32 bit value to the amdtpsSendData function, setting the length to 6, and setting command_type to BYTESTREAM_TX. I was getting errors about the having bad chars.
Next, I tried adding bytestream_active = false; after it had sent once, and actually looking at the raw output again.
I ended up adding await theRobot.sendCommand(Commands.REQ_FLOAT) instead of using await theRobot.testByteStream(25) , because I wasn't entirely sure what was going on there, and using the memcpy() function suggested on campuswire. Finally, I was not getting any errors.
Next, I added the unpacking function to that case. I looked at the GIVE_FLOAT example for reference, which used the unpack() function and left-carrot f, which was unfamiliar to me. Googling it led me to this documenation for structs, showing me how to properly unpack the structs for different sizes.
Once I did that, and used the right sizes, I was able to send a 32 bit integer via this function!
32bit num

I tested it with both a 32bit and 64 bit integer with these results.
14byte

The average round trip time was 10.69 ms, and a loss of around 34% based on how many packets were sent and how many were recieved.
  if (bytestream_active)
    {

        res_cmd->command_type = BYTESTREAM_TX;
        res_cmd->length = 64;
        //TODO: Put an example of a 32-bit integer and a 64-bit integer
        //for the stream. Be sure to add a corresponding case in the
        //python program.

        uint32_t numToSendShort = 15960;
        uint64_t numToSendLong  = 100000007;

        memcpy(res_cmd->data, &numToSendShort, 4);
        memcpy(res_cmd->data+4, &numToSendLong, 8);

        
        //Serial.printf("Stream %d \n", bytestream_active);
        amdtpsSendData((uint8_t *)res_cmd, 14);

        unsigned long timePassed = micros();
        
        Serial.printf("Cycle %d took %d us\n", numByteStreams, timePassed); 
        numByteStreams += 1;
        
    }

      

I also tried with a larger packet size and got the following results
14byte

The average round trip time was 10.66 ms, and a loss of around 84% based on how many packets were sent and how many were recieved. This is a much higher loss than I expected. It is odd that the time was lower, but maybe I would need more data points and a bigger difference in packet size to properly assess the relationship. For both I used around 2000 samples.