BLE Latency Testing



 /*********************************************************************


>>> A sketch to TEST BLE TRANSMIT/RECEIVE LATENCY <<<
    This sketch transmits live atmospheric (vario) data from a DPS310
    in a $PTVSOAR sentence (fully readable by TV).
    The other data (pitot, battery, etc) is unchanging dummy data.

May 2023 - BLE print functionality is now broken out to a separate Function.
           Ie: Build Sentence part-1 -> BLE Print ->
            back to Build Sentence part-2 -> BLE Print (again) -> Loop
 
22 April 2023 - Working with XIAO nRF (ie: not XIAO mBed device).

INFO:
  MCU Hardware - Seeed XIAO nRF52840 (not "Sense" model)
  Using Arduino IDE 1.8.19
  Using Arduino 'Board' -> "Seeed nRF52 Boards" -> "Seeed XIAO nRF52840"
Text copied from Arduino IDE 2.1.0 (better colours)

*********************************************************************/

//========================================

// ----------LIBRARIES--------------

#include <bluefruit.h>
#include <Adafruit_LittleFS.h>
#include <InternalFileSystem.h>
#include <Wire.h>
#include <avr/dtostrf.h> // for dtostrf
#include <Adafruit_DPS310.h> // Adafruit DPS310 library


// ---------CONSTANTS---------------

// Function Timing
const int IntervalBLE = 99; // number of mS before BLE function repeats
const int IntervalDPS = 113;   // number of mS before DPS function repeats and collects Atmospheric Pressure

// -----------CLASSES---------------

// BLE Services
BLEDfu  bledfu;  // OTA DFU service
BLEDis  bledis;  // device information
BLEUart bleuart; // uart over ble

// Absolute Pressure Sensor
Adafruit_DPS310 dps;

//------------VARIABLES-------------

// Function Timing
unsigned long currentMillis = 0;     // stores the value of millis() in each iteration of loop()
unsigned long previousBLEMillis = 0; // will store last time
unsigned long previousDPSMillis = 0; // will store last time

// Infinion Atmospheric Pressure Variable
float absPres = 966.0;  // Variable for the Atmospheric absolute pressure

//===================SETUP========================

void setup()
{
  Serial.begin(115200);
  Wire.begin();

#if CFG_DEBUG
  // Blocking wait for connection when debug mode is enabled via IDE
  while ( !Serial ) yield();
#endif

  // Config the peripheral connection with maximum bandwidth
  // more SRAM required by SoftDevice
  // Note: All config***() function must be called before begin()
  Bluefruit.configPrphBandwidth(BANDWIDTH_MAX);

  Bluefruit.begin();
  Bluefruit.setTxPower(-12); // Set max power. Accepted values are: -40, -30, -20, -16, -12, -8, -4, 0, 4
  //Bluefruit.setName(getMcuUniqueID()); // useful testing with multiple central connections or (eg):  Bluefruit.setName("Name");
  Bluefruit.setName("ProbeS4");
  Bluefruit.Periph.setConnectCallback(connect_callback);
  Bluefruit.Periph.setDisconnectCallback(disconnect_callback);

  // To be consistent OTA DFU should be added first if it exists
  bledfu.begin();

  // Configure and Start Device Information Service
  bledis.setManufacturer("Seeed");
  bledis.setModel("XIAOnRF");
  bledis.begin();

  // Configure and Start BLE Uart Service
  bleuart.begin();

  // Set up and start advertising
  startAdv();

  // Initialise I2C
  Wire.begin();

  // Initialise Infinion DPS sensor
  if (! dps.begin_I2C()) {             // Can pass in I2C address here
    while (1) yield();
  }
  dps.configurePressure(DPS310_16HZ, DPS310_32SAMPLES); // See DPS310 datasheet for combinations
  dps.configureTemperature(DPS310_2HZ, DPS310_2SAMPLES);

}

void startAdv(void)
{
  // Advertising packet
  Bluefruit.Advertising.addFlags(BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE);
  Bluefruit.Advertising.addTxPower();
  // Include bleuart 128-bit uuid
  Bluefruit.Advertising.addService(bleuart);
  // Secondary Scan Response packet (optional)
  // Since there is no room for 'Name' in Advertising packet
  Bluefruit.ScanResponse.addName();
  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
}

//===================LOOP========================

void loop()
{
  currentMillis = millis(); // Capture the latest value of millis()
  readDPS();                // This function reads DPS function reads Atmospheric Pressure and sends to variable
  buildMSG();               // This function builds the XCTOD sentence and sends via BLE
}

//================FUNCTIONS=====================

// Callback invoked when central connects
void connect_callback(uint16_t conn_handle)
{
  // Get the reference to current connection
  BLEConnection* connection = Bluefruit.Connection(conn_handle);

  char central_name[32] = { 0 };
  connection->getPeerName(central_name, sizeof(central_name));
  Serial.print("Connected to ");
  Serial.println(central_name);
}

void disconnect_callback(uint16_t conn_handle, uint8_t reason)
{
  (void) conn_handle;
  (void) reason;
  Serial.print("Disconnected, reason = 0x"); Serial.println(reason, HEX);
}

// READ DPS FUNCTION --------------------------------------------------------

// readDPS+++++++++++
void readDPS()  // Function to read Atmospheric Pressure from DPS sensor
{
  if (currentMillis >= previousDPSMillis + IntervalDPS)  // run 'readDPS' function only once time is up
  {
    previousDPSMillis = currentMillis;  // save the time when change was made
    sensors_event_t temp_event, pressure_event;
    while (!dps.temperatureAvailable() || !dps.pressureAvailable()) {
      return; // wait until there's something to read
    }
    dps.getEvents(&temp_event, &pressure_event);
    absPres = pressure_event.pressure;

    previousDPSMillis += IntervalDPS; // save the time when change was made
  }
}

// END OF READ DPS ---------------------------------------------------------


// BUILD MSG FUNCTION --------------------------------------------------------

// buildMSG+++++++++++
void buildMSG() // Function to build sentence
{
  if (currentMillis - previousBLEMillis >= IntervalBLE) // run 'build' function only once time is up
  {
    char strDPS[8];
    float dps = absPres; // Atmospheric Pressure from DPS sensor
    dtostrf(dps, 6, 2, strDPS); // format float value to string
   
    String msg = "$PTVSOAR,MNA,FlyingSilicon,MMO,ProbeS4,MSN,2023Q2001,"; // FIRST Half of $PTVSOAR Sentence
    printMSG(msg); // Call the printMSG function to transmit to BLE then come back here ...

    String msg1a = "PIT,100.00,OAT,22.0,OAH,88.8,PCT,88.8,PRS,"; // SECOND Half of $PTVSOAR Sentence
    String msg1b = msg1a + strDPS;
    msg1b.concat(" \n"); // End of sentence notifier for TV
    msg = msg1b;
    printMSG(msg); // Call the printMSG function to transmit to BLE then come back here ...

    previousBLEMillis += IntervalBLE; // save the time when change was made
  }
}

// END OF BUILD MSG ---------------------------------------------------------


// BLE UART WRITE MSG FUNCTION --------------------------------------------------------

// printMSG+++++++++++
void printMSG(String msg) // Function to transmit to BLE
{
  uint8_t buf[64];          // create a variable 'buf1' of size 64
  msg.getBytes(buf, msg.length() + 1);   // move msg1 characters into 'buf', for length of msg
  bleuart.write( buf, msg.length() + 0 ); // write 'buf2' characters to BLE, for length of msg
}

// END OF BLE UART WRITE MSG FUNCTION ---------------------------------------------------------

/*********************************************************************

>>> A sketch to TEST BLE TRANSMIT/RECEIVE LATENCY <<<

    21 May 23 - LOGGED TIMESTAMPED RESULTS

10:24:05.914 Connecting to ProbeS4 ...
10:24:07.263 Connected
10:24:07.470 $PTVSOAR,MNA,FlyingSilicon,MMO,ProbeS4,MSN,2023Q2001,PIT,100.00,OAT,22.0,OAH,88.8,PCT,88.8,PRS,1001.72
10:24:07.526 $PTVSOAR,MNA,FlyingSilicon,MMO,ProbeS4,MSN,2023Q2001,$PTVSOAR,MNA,FlyingSilicon,MMO,ProbeS4,MSN,2023Q2001,PIT,100.00,OAT,22.0,OAH,88.8,PCT,88.8,PRS,1001.72
10:24:07.615 $PTVSOAR,MNA,FlyingSilicon,MMO,ProbeS4,MSN,2023Q2001,PIT,100.00,OAT,22.0,OAH,88.8,PCT,88.8,PRS,1001.72
10:24:07.712 $PTVSOAR,MNA,FlyingSilicon,MMO,ProbeS4,MSN,2023Q2001,PIT,100.00,OAT,22.0,OAH,88.8,PCT,88.8,PRS,1001.72
10:24:07.809 $PTVSOAR,MNA,FlyingSilicon,MMO,ProbeS4,MSN,2023Q2001,PIT,100.00,OAT,22.0,OAH,88.8,PCT,88.8,PRS,1001.72
10:24:07.907 $PTVSOAR,MNA,FlyingSilicon,MMO,ProbeS4,MSN,2023Q2001,PIT,100.00,OAT,22.0,OAH,88.8,PCT,88.8,PRS,1001.72
10:24:08.006 $PTVSOAR,MNA,FlyingSilicon,MMO,ProbeS4,MSN,2023Q2001,PIT,100.00,OAT,22.0,OAH,88.8,PCT,88.8,PRS,1001.72
10:24:08.102 $PTVSOAR,MNA,FlyingSilicon,MMO,ProbeS4,MSN,2023Q2001,PIT,100.00,OAT,22.0,OAH,88.8,PCT,88.8,PRS,1001.72
10:24:08.199 $PTVSOAR,MNA,FlyingSilicon,MMO,ProbeS4,MSN,2023Q2001,PIT,100.00,OAT,22.0,OAH,88.8,PCT,88.8,PRS,1001.72
10:24:08.297 $PTVSOAR,MNA,FlyingSilicon,MMO,ProbeS4,MSN,2023Q2001,PIT,100.00,OAT,22.0,OAH,88.8,PCT,88.8,PRS,1001.72
10:24:08.394 $PTVSOAR,MNA,FlyingSilicon,MMO,ProbeS4,MSN,2023Q2001,PIT,100.00,OAT,22.0,OAH,88.8,PCT,88.8,PRS,1001.72
10:24:08.491 $PTVSOAR,MNA,FlyingSilicon,MMO,ProbeS4,MSN,2023Q2001,PIT,100.00,OAT,22.0,OAH,88.8,PCT,88.8,PRS,1001.72
10:24:08.593 $PTVSOAR,MNA,FlyingSilicon,MMO,ProbeS4,MSN,2023Q2001,PIT,100.00,OAT,22.0,OAH,88.8,PCT,88.8,PRS,1001.72
10:24:08.686 $PTVSOAR,MNA,FlyingSilicon,MMO,ProbeS4,MSN,2023Q2001,PIT,100.00,OAT,22.0,OAH,88.8,PCT,88.8,PRS,1001.72
10:24:08.785 $PTVSOAR,MNA,FlyingSilicon,MMO,ProbeS4,MSN,2023Q2001,PIT,100.00,OAT,22.0,OAH,88.8,PCT,88.8,PRS,1001.72
10:24:08.882 $PTVSOAR,MNA,FlyingSilicon,MMO,ProbeS4,MSN,2023Q2001,PIT,100.00,OAT,22.0,OAH,88.8,PCT,88.8,PRS,1001.72
10:24:08.979 $PTVSOAR,MNA,FlyingSilicon,MMO,ProbeS4,MSN,2023Q2001,PIT,100.00,OAT,22.0,OAH,88.8,PCT,88.8,PRS,1001.72
10:24:09.125 $PTVSOAR,MNA,FlyingSilicon,MMO,ProbeS4,MSN,2023Q2001,PIT,100.00,OAT,22.0,OAH,88.8,PCT,88.8,PRS,1001.72
10:24:09.224 $PTVSOAR,MNA,FlyingSilicon,MMO,ProbeS4,MSN,2023Q2001,PIT,100.00,OAT,22.0,OAH,88.8,PCT,88.8,PRS,1001.72
10:24:09.368 $PTVSOAR,MNA,FlyingSilicon,MMO,ProbeS4,MSN,2023Q2001,PIT,100.00,OAT,22.0,OAH,88.8,PCT,88.8,PRS,1001.73
10:24:09.418 $PTVSOAR,MNA,FlyingSilicon,MMO,ProbeS4,MSN,2023Q2001,PIT,100.00,OAT,22.0,OAH,88.8,PCT,88.8,PRS,1001.73
10:24:09.516 $PTVSOAR,MNA,FlyingSilicon,MMO,ProbeS4,MSN,2023Q2001,PIT,100.00,OAT,22.0,OAH,88.8,PCT,88.8,PRS,1001.73
10:24:09.613 $PTVSOAR,MNA,FlyingSilicon,MMO,ProbeS4,MSN,2023Q2001,PIT,100.00,OAT,22.0,OAH,88.8,PCT,88.8,PRS,1001.73
10:24:09.711 $PTVSOAR,MNA,FlyingSilicon,MMO,ProbeS4,MSN,2023Q2001,PIT,100.00,OAT,22.0,OAH,88.8,PCT,88.8,PRS,1001.72
10:24:09.808 $PTVSOAR,MNA,FlyingSilicon,MMO,ProbeS4,MSN,2023Q2001,PIT,100.00,OAT,22.0,OAH,88.8,PCT,88.8,PRS,1001.72
10:24:09.906 $PTVSOAR,MNA,FlyingSilicon,MMO,ProbeS4,MSN,2023Q2001,PIT,100.00,OAT,22.0,OAH,88.8,PCT,88.8,PRS,1001.72
10:24:10.004 $PTVSOAR,MNA,FlyingSilicon,MMO,ProbeS4,MSN,2023Q2001,PIT,100.00,OAT,22.0,OAH,88.8,PCT,88.8,PRS,1001.72
10:24:10.102 $PTVSOAR,MNA,FlyingSilicon,MMO,ProbeS4,MSN,2023Q2001,PIT,100.00,OAT,22.0,OAH,88.8,PCT,88.8,PRS,1001.72
10:24:10.197 $PTVSOAR,MNA,FlyingSilicon,MMO,ProbeS4,MSN,2023Q2001,PIT,100.00,OAT,22.0,OAH,88.8,PCT,88.8,PRS,1001.72
10:24:10.295 $PTVSOAR,MNA,FlyingSilicon,MMO,ProbeS4,MSN,2023Q2001,PIT,100.00,OAT,22.0,OAH,88.8,PCT,88.8,PRS,1001.73
10:24:10.394 $PTVSOAR,MNA,FlyingSilicon,MMO,ProbeS4,MSN,2023Q2001,PIT,100.00,OAT,22.0,OAH,88.8,PCT,88.8,PRS,1001.73
10:24:10.493 $PTVSOAR,MNA,FlyingSilicon,MMO,ProbeS4,MSN,2023Q2001,PIT,100.00,OAT,22.0,OAH,88.8,PCT,88.8,PRS,1001.73
10:24:10.589 $PTVSOAR,MNA,FlyingSilicon,MMO,ProbeS4,MSN,2023Q2001,PIT,100.00,OAT,22.0,OAH,88.8,PCT,88.8,PRS,1001.73
10:24:10.687 $PTVSOAR,MNA,FlyingSilicon,MMO,ProbeS4,MSN,2023Q2001,PIT,100.00,OAT,22.0,OAH,88.8,PCT,88.8,PRS,1001.73
10:24:10.789 $PTVSOAR,MNA,FlyingSilicon,MMO,ProbeS4,MSN,2023Q2001,PIT,100.00,OAT,22.0,OAH,88.8,PCT,88.8,PRS,1001.73
10:24:10.881 $PTVSOAR,MNA,FlyingSilicon,MMO,ProbeS4,MSN,2023Q2001,PIT,100.00,OAT,22.0,OAH,88.8,PCT,88.8,PRS,1001.73
10:24:10.979 $PTVSOAR,MNA,FlyingSilicon,MMO,ProbeS4,MSN,2023Q2001,PIT,100.00,OAT,22.0,OAH,88.8,PCT,88.8,PRS,1001.73
10:24:11.076 $PTVSOAR,MNA,FlyingSilicon,MMO,ProbeS4,MSN,2023Q2001,PIT,100.00,OAT,22.0,OAH,88.8,PCT,88.8,PRS,1001.73
10:24:11.174 $PTVSOAR,MNA,FlyingSilicon,MMO,ProbeS4,MSN,2023Q2001,PIT,100.00,OAT,22.0,OAH,88.8,PCT,88.8,PRS,1001.73
10:24:11.273 $PTVSOAR,MNA,FlyingSilicon,MMO,ProbeS4,MSN,2023Q2001,PIT,100.00,OAT,22.0,OAH,88.8,PCT,88.8,PRS,1001.73
10:24:11.368 $PTVSOAR,MNA,FlyingSilicon,MMO,ProbeS4,MSN,2023Q2001,PIT,100.00,OAT,22.0,OAH,88.8,PCT,88.8,PRS,1001.73
10:24:11.465 $PTVSOAR,MNA,FlyingSilicon,MMO,ProbeS4,MSN,2023Q2001,PIT,100.00,OAT,22.0,OAH,88.8,PCT,88.8,PRS,1001.73
10:24:11.562 $PTVSOAR,MNA,FlyingSilicon,MMO,ProbeS4,MSN,2023Q2001,PIT,100.00,OAT,22.0,OAH,88.8,PCT,88.8,PRS,1001.73
10:24:11.601 Disconnected

*********************************************************************/