Week 13 - Networking

Solo Assignment

For the solo assignment, I chose to network an arduino and a Seeed RP2040 nrF connected to my phone through bluetooth for my final project. I got help from both Seeed Wiki. I plan to have the phone record the user catching the frisbee.

Hardware

I used an arduino and a milled board with a Seeed RP2040 nrF on it that I designed. I also used my phone for bluetooth connection.

I created the board below :

Board Files

Code

The Seeed Wiki was super helpful in providing both the libraries and example code I used for my bluetooth connection

Code 1 - Computer Keyboard to Phone Text

This is the example code from Seeed Wiki that I used.

/*********************************************************************
This is an example for our nRF52 based Bluefruit LE modules

Pick one up today in the adafruit shop!

Adafruit invests time and resources providing this open source code,
please support Adafruit and open-source hardware by purchasing
products from Adafruit!

MIT license, check LICENSE for more information
All text above, and the splash screen below must be included in
any redistribution
*********************************************************************/
#include <bluefruit.h>

BLEDis bledis;
BLEHidAdafruit blehid;

bool hasKeyPressed = false;

void setup() 
{
Serial.begin(115200);
while ( !Serial ) delay(10);   // for nrf52840 with native usb

Serial.println("Bluefruit52 HID Keyboard Example");
Serial.println("--------------------------------\n");

Serial.println();
Serial.println("Go to your phone's Bluetooth settings to pair your device");
Serial.println("then open an application that accepts keyboard input");

Serial.println();
Serial.println("Enter the character(s) to send:");
Serial.println();

Bluefruit.begin();
Bluefruit.setTxPower(4);    // Check bluefruit.h for supported values

// Configure and Start Device Information Service
bledis.setManufacturer("Adafruit Industries");
bledis.setModel("Bluefruit Feather 52");
bledis.begin();

/* Start BLE HID
* Note: Apple requires BLE device must have min connection interval >= 20m
* ( The smaller the connection interval the faster we could send data).
* However for HID and MIDI device, Apple could accept min connection interval 
* up to 11.25 ms. Therefore BLEHidAdafruit::begin() will try to set the min and max
* connection interval to 11.25  ms and 15 ms respectively for best performance.
*/
blehid.begin();

// Set callback for set LED from central
blehid.setKeyboardLedCallback(set_keyboard_led);

/* Set connection interval (min, max) to your perferred value.
* Note: It is already set by BLEHidAdafruit::begin() to 11.25ms - 15ms
* min = 9*1.25=11.25 ms, max = 12*1.25= 15 ms 
*/
/* Bluefruit.Periph.setConnInterval(9, 12); */

// Set up and start advertising
startAdv();
}

void startAdv(void)
{  
// Advertising packet
Bluefruit.Advertising.addFlags(BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE);
Bluefruit.Advertising.addTxPower();
Bluefruit.Advertising.addAppearance(BLE_APPEARANCE_HID_KEYBOARD);

// Include BLE HID service
Bluefruit.Advertising.addService(blehid);

// There is enough room for the dev name in the advertising packet
Bluefruit.Advertising.addName();

/* Start Advertising
* - Enable auto advertising if disconnected
* - Interval:  fast mode = 20 ms, slow mode = 152.5 ms
* - Timeout for fast mode is 30 seconds
* - Start(timeout) with timeout = 0 will advertise forever (until connected)
* 
* For recommended advertising interval
* https://developer.apple.com/library/content/qa/qa1931/_index.html   
*/
Bluefruit.Advertising.restartOnDisconnect(true);
Bluefruit.Advertising.setInterval(32, 244);    // in unit of 0.625 ms
Bluefruit.Advertising.setFastTimeout(30);      // number of seconds in fast mode
Bluefruit.Advertising.start(0);                // 0 = Don't stop advertising after n seconds
}

void loop() 
{
// Only send KeyRelease if previously pressed to avoid sending
// multiple keyRelease reports (that consume memory and bandwidth)
if ( hasKeyPressed )
{
    hasKeyPressed = false;
    blehid.keyRelease();

    // Delay a bit after a report
    delay(5);
}

if (Serial.available())
{
    char ch = (char) Serial.read();

    // echo
    Serial.write(ch);

    blehid.keyPress(ch);
    hasKeyPressed = true;

    // Delay a bit after a report
    delay(5);
}
}

/**
* Callback invoked when received Set LED from central.
* Must be set previously with setKeyboardLedCallback()
*
* The LED bit map is as follows: (also defined by KEYBOARD_LED_* )
*    Kana (4) | Compose (3) | ScrollLock (2) | CapsLock (1) | Numlock (0)
*/
void set_keyboard_led(uint16_t conn_handle, uint8_t led_bitmap)
{
(void) conn_handle;

// light up Red Led if any bits is set
if ( led_bitmap )
{
    ledOn( LED_RED );
}
else
{
    ledOff( LED_RED );
}
}

Code 2 - Recording Code

For this next code, I took the example code from the Adafruit Bluefruit nRF52 Libraries of taking a picture and slightly changed it so it would record a video instead.

/*********************************************************************
This is an example for our nRF52 based Bluefruit LE modules

Pick one up today in the adafruit shop!

Adafruit invests time and resources providing this open source code,
please support Adafruit and open-source hardware by purchasing
products from Adafruit!

MIT license, check LICENSE for more information
All text above, and the splash screen below must be included in
any redistribution
*********************************************************************/

/*
* This sketch uses the HID Consumer Key API to send the Volume Down
* key when pinShutter is grounded. This will cause your mobile device
* to capture a photo when you are in the camera app.
*/
#include <bluefruit.h>

BLEDis bledis;
BLEHidAdafruit blehid;

// Use on-board button if available, else use A0 pin
#ifdef PIN_BUTTON1
uint8_t pinShutter = PIN_BUTTON1;
#else
uint8_t pinShutter = A0;
#endif

// Circuit Play Bluefruit has button active state = high
#ifdef ARDUINO_NRF52840_CIRCUITPLAY
#define BTN_ACTIVE HIGH
#else
#define BTN_ACTIVE LOW
#endif

void setup()
{
pinMode(pinShutter, INPUT_PULLUP);

Serial.begin(115200);

#if CFG_DEBUG
// Blocking wait for connection when debug mode is enabled via IDE
while ( !Serial ) delay(10);   // for nrf52840 with native usb
#endif

Serial.println("Bluefruit52 HID Camera Shutter Example");
Serial.println("--------------------------------------\n");

Serial.println();
Serial.println("Go to your phone's Bluetooth settings to pair your device");
Serial.println("then open the camera application");

Serial.println();
Serial.printf("Set pin %d to GND to capture a photo\n", pinShutter);
Serial.println();

Bluefruit.begin();
Bluefruit.setTxPower(4);    // Check bluefruit.h for supported values

// Configure and start DIS (Device Information Service)
bledis.setManufacturer("Adafruit Industries");
bledis.setModel("Bluefruit Feather 52");
bledis.begin();

/* Start BLE HID
* Note: Apple requires BLE devices to have a min connection interval >= 20m
* (The smaller the connection interval the faster we can send data).
* However, for HID and MIDI device Apple will accept a min connection
* interval as low as 11.25 ms. Therefore BLEHidAdafruit::begin() will try to
* set the min and max connection interval to 11.25 ms and 15 ms respectively
* for the best performance.
*/
blehid.begin();

/* Set connection interval (min, max) to your perferred value.
* Note: It is already set by BLEHidAdafruit::begin() to 11.25ms - 15ms
* min = 9*1.25=11.25 ms, max = 12*1.25= 15 ms
*/
/* Bluefruit.Periph.setConnInterval(9, 12); */

// Set up and start advertising
startAdv();
}

void startAdv(void)
{
// Advertising packet
Bluefruit.Advertising.addFlags(BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE);
Bluefruit.Advertising.addTxPower();
Bluefruit.Advertising.addAppearance(BLE_APPEARANCE_HID_KEYBOARD);

// Include BLE HID service
Bluefruit.Advertising.addService(blehid);

// There is enough room for the dev name in the advertising packet
Bluefruit.Advertising.addName();

/* Start Advertising
* - Enable auto advertising if disconnected
* - Interval:  fast mode = 20 ms, slow mode = 152.5 ms
* - Timeout for fast mode is 30 seconds
* - Start(timeout) with timeout = 0 will advertise forever (until connected)
* 
* For recommended advertising interval
* https://developer.apple.com/library/content/qa/qa1931/_index.html   
*/
Bluefruit.Advertising.restartOnDisconnect(true);
Bluefruit.Advertising.setInterval(32, 244);    // in unit of 0.625 ms
Bluefruit.Advertising.setFastTimeout(30);      // number of seconds in fast mode
Bluefruit.Advertising.start(0);                // 0 = Don't stop advertising after n seconds  
}

void loop()
{
// Skip if shutter pin is not Ground
if ( digitalRead(pinShutter) != BTN_ACTIVE ) return;

// Make sure we are connected and bonded/paired
for (uint16_t conn_hdl=0; conn_hdl < BLE_MAX_CONNECTION; conn_hdl++)
{
    BLEConnection* connection = Bluefruit.Connection(conn_hdl);

    if ( connection && connection->connected() && connection->secured() )
    {
    // Turn on red LED when we start sending data
    digitalWrite(LED_RED, 1);

    // Send the 'volume down' key press to the peer
    // Check tinyusb/src/class/hid/hid.h for a list of valid consumer usage codes
    blehid.consumerKeyPress(conn_hdl, HID_USAGE_CONSUMER_VOLUME_DECREMENT);

    // Delay a bit between reports
    delay(10);

    // Send key release
    blehid.consumerKeyRelease(conn_hdl);

    delay(10000); // RECORDING FOR 10 SECONDS

    blehid.consumerKeyPress(conn_hdl, HID_USAGE_CONSUMER_VOLUME_DECREMENT);

    // Delay a bit between reports
    delay(10);

    // Send key release
    blehid.consumerKeyRelease(conn_hdl);

    // Turn off the red LED
    digitalWrite(LED_RED, 0);
    }
}

// Delay to avoid constant capturing
delay(250);
}

Issues encountered

The main traumatizing issue I faced this week was that my code kept reapetingly activating the volume down button without me activating it. After many many hours of struggling, I figured out that the for loop was constantly repeating despite the return function so I moved the if loop inside the for.

Final Video Result

Below is the video taken by my phone started and ended almost exactly at 10 seconds by my Seeed Xiao RP2040 via bluetooth(BTW my seeed on the board I made had a broken button that made it so I couldn't send code. This is the reason why I am using a non-boarded Xiao). My friend John is the one in the video. lol

Basically, When I hit the LED party button on my computer, proccessing sends the letter "H" through serial to the arduino. Then, the arduino who is constantly reading the Serial receives the letter "H" and proceeds to do the action stated in the Arduino IDE which was flash the NEOpixel.

Group Project

Click here for group page

Reflection

This week taught me how to connect a phone and a micro controller through bluetooth and send information to or from. I later want to delve deeper into getting information from the phone but that is much more complicated and is outside the course of this week.