Lost notifications when updating various characteristics

Hello there! I am using an Arduino nano 33 Sense Rev 2 and my project involves sending an image (3072B) from the board to pc. One of the requirements is a high throughput so I chose to send the image using notifications on 13 characteristics. When I do not add any delays between the writing of those characteristics, some of them are not received on the pc. However, if I add a 10ms delay between each characteristic writting, it works fine. I would love to avoid those delays. Any suggestions? Thank you very much :slight_smile:

PS: On the pc side, I am using Simplepyble library.

You might get some acceptable responses if you post an annotated schematic showing how all of this connects together and your code. I believe most of the people on this forum are like me and cannot see what you have.

Got it! Thanks for your response. I'll try to give a good overview of the system:

  • Arduino takes an image as a byte array in a header.
  • I create 13 characteristics to send the image and 1 more to receive a byte back with the predicted class.
  • I connect and subscribe to the characteristics on the central device (PC) where I am using a library called simplepyble.
  • On arduino once the characteristics have been subscribed to, the characterisitics are updated containing the image
  • The central device receives the updated characteristics as notifications and once the image is complete sends on byte back
  • Arduino receives the byte back and stops the time measurement.

My objective is being able to update the characxteristics without delays inbetween. Right now, without them, some notifications get lost. If avoiding the delays is not possible I would love to understand the reason.

Arduino code:

#include <ArduinoBLE.h>
#include "image.h"


const int characteristicSize = 244;
byte value = 0;
int counter = 0;
uint8_t receivedByte;

int start;
int end;
int middle;


//uint8_t yourArray[size];

BLEService customService("19B10000-E8F2-537E-4F6C-D104768A1214"); // Define a custom BLE service

// Create 8 characteristics
BLECharacteristic customCharacteristics[13] = {
  BLECharacteristic("19B10001-E8F2-537E-4F6C-D104768A1214", BLERead | BLEWrite | BLEWriteWithoutResponse | BLENotify | BLEIndicate, characteristicSize),
  BLECharacteristic("19B10002-E8F2-537E-4F6C-D104768A1214", BLERead | BLEWrite | BLEWriteWithoutResponse | BLENotify | BLEIndicate, characteristicSize),
  BLECharacteristic("19B10003-E8F2-537E-4F6C-D104768A1214", BLERead | BLEWrite | BLEWriteWithoutResponse | BLENotify | BLEIndicate, characteristicSize),
  BLECharacteristic("19B10004-E8F2-537E-4F6C-D104768A1214", BLERead | BLEWrite | BLEWriteWithoutResponse | BLENotify | BLEIndicate, characteristicSize),
  BLECharacteristic("19B10005-E8F2-537E-4F6C-D104768A1214", BLERead | BLEWrite | BLEWriteWithoutResponse | BLENotify | BLEIndicate, characteristicSize),
  BLECharacteristic("19B10006-E8F2-537E-4F6C-D104768A1214", BLERead | BLEWrite | BLEWriteWithoutResponse | BLENotify | BLEIndicate, characteristicSize),
  BLECharacteristic("19B10007-E8F2-537E-4F6C-D104768A1214", BLERead | BLEWrite | BLEWriteWithoutResponse | BLENotify | BLEIndicate, characteristicSize),
  BLECharacteristic("19B10008-E8F2-537E-4F6C-D104768A1214", BLERead | BLEWrite | BLEWriteWithoutResponse | BLENotify | BLEIndicate, characteristicSize),
  BLECharacteristic("19B10009-E8F2-537E-4F6C-D104768A1214", BLERead | BLEWrite | BLEWriteWithoutResponse | BLENotify | BLEIndicate, characteristicSize),
  BLECharacteristic("19B10010-E8F2-537E-4F6C-D104768A1214", BLERead | BLEWrite | BLEWriteWithoutResponse | BLENotify | BLEIndicate, characteristicSize),
  BLECharacteristic("19B10011-E8F2-537E-4F6C-D104768A1214", BLERead | BLEWrite | BLEWriteWithoutResponse | BLENotify | BLEIndicate, characteristicSize),
  BLECharacteristic("19B10012-E8F2-537E-4F6C-D104768A1214", BLERead | BLEWrite | BLEWriteWithoutResponse | BLENotify | BLEIndicate, characteristicSize), 
  BLECharacteristic("19B10013-E8F2-537E-4F6C-D104768A1214", BLERead | BLEWrite | BLEWriteWithoutResponse | BLENotify | BLEIndicate, 144),
  //BLECharacteristic("19B10008-E8F2-537E-4F6C-D104768A1214", BLERead | BLEWrite | BLEWriteWithoutResponse | BLENotify, 1)
};
BLEByteCharacteristic classCharacteristic("19B10014-E8F2-537E-4F6C-D104768A1214", BLERead | BLEWrite | BLEWriteWithoutResponse | BLENotify);


// Define the characteristic's event handler 
void switchCharacteristicWritten(BLEDevice central, BLECharacteristic characteristic) {
  
  end = micros();
  Serial.println("time: "+ String(end-start));
  int value = classCharacteristic.value();
  Serial.println("value: "+ String(value));
  BLE.disconnect();
  Serial.println("Disconnected");

}

/*
void onCharacteristicsSubscribed(BLEDevice central, BLECharacteristic characteristic){
  start = micros();
  customCharacteristics[0].writeValue(&test_image_0[0], 244, false);
}
void onCharacteristicsSubscribed2(BLEDevice central, BLECharacteristic characteristic){
  customCharacteristics[1].writeValue(&test_image_0[244], 244, false);
}
void onCharacteristicsSubscribed3(BLEDevice central, BLECharacteristic characteristic){
  customCharacteristics[2].writeValue(&test_image_0[244*2], 244, false);
}
void onCharacteristicsSubscribed4(BLEDevice central, BLECharacteristic characteristic){
  customCharacteristics[3].writeValue(&test_image_0[244*3], 244, false);
}
void onCharacteristicsSubscribed5(BLEDevice central, BLECharacteristic characteristic){
  customCharacteristics[4].writeValue(&test_image_0[244*4], 244, false);
}
void onCharacteristicsSubscribed6(BLEDevice central, BLECharacteristic characteristic){
  customCharacteristics[5].writeValue(&test_image_0[244*5], 244, false);
}
void onCharacteristicsSubscribed7(BLEDevice central, BLECharacteristic characteristic){
  customCharacteristics[6].writeValue(&test_image_0[244*6], 244, false);
}
void onCharacteristicsSubscribed8(BLEDevice central, BLECharacteristic characteristic){
  customCharacteristics[7].writeValue(&test_image_0[244*7], 244, false);
}
void onCharacteristicsSubscribed9(BLEDevice central, BLECharacteristic characteristic){
  customCharacteristics[8].writeValue(&test_image_0[244*8], 244, false);
}
void onCharacteristicsSubscribed10(BLEDevice central, BLECharacteristic characteristic){
  customCharacteristics[9].writeValue(&test_image_0[244*9], 244, false);
}
void onCharacteristicsSubscribed11(BLEDevice central, BLECharacteristic characteristic){
  customCharacteristics[10].writeValue(&test_image_0[244*10], 244, false);
}
void onCharacteristicsSubscribed12(BLEDevice central, BLECharacteristic characteristic){
  customCharacteristics[11].writeValue(&test_image_0[244*11], 244, false);
}
void onCharacteristicsSubscribed13(BLEDevice central, BLECharacteristic characteristic){
  customCharacteristics[12].writeValue(&test_image_0[2928], 144, false);
} 
*/

void setup() {
  Serial.begin(115200);
  while (!Serial){};
  
  // Start BLE
  if (!BLE.begin()) {
    Serial.println("Starting BLE failed!");
    while (1);
  }

  BLE.setConnectionInterval(0x0006, 0x0006);


  // Set the local name for the BLE device
  BLE.setLocalName("Nano33BLE");

  // Add the service and characteristics
  BLE.setAdvertisedService(customService);


  for (int i = 0; i < 13; i++) {
    customService.addCharacteristic(customCharacteristics[i]);
  }
  customService.addCharacteristic(classCharacteristic);


  BLE.addService(customService);

  // Start advertising
  classCharacteristic.setEventHandler(BLEWritten, switchCharacteristicWritten);

  BLE.advertise();

}

void loop() {

  BLEDevice central = BLE.central();

  while (central.connected()) {
   
    if (customCharacteristics[12].subscribed() && counter ==0){ 
      start = micros();
      for (int i = 0; i < 12; i++) {
        customCharacteristics[i].writeValue(&test_image_0[i*244], characteristicSize, false);
        delay(9);
      }   
      customCharacteristics[12].writeValue(&test_image_0[2928], 144, false);
      counter++;
    }      
      
      
  }    
  
}

Python code:

import simplepyble
import numpy as np
import time



    


lista = []   
num = 0


if __name__ == "__main__":
    adapters = simplepyble.Adapter.get_adapters()

    if len(adapters) == 0:
        print("No adapters found")

    # Query the user to pick an adapter
    print("Please select an adapter:")
    for i, adapter in enumerate(adapters):
        print(f"{i}: {adapter.identifier()} [{adapter.address()}]")

    choice = int(input("Enter choice: "))
    adapter = adapters[choice]

    print(f"Selected adapter: {adapter.identifier()} [{adapter.address()}]")

    adapter.set_callback_on_scan_start(lambda: print("Scan started."))
    adapter.set_callback_on_scan_stop(lambda: print("Scan complete."))
    adapter.set_callback_on_scan_found(lambda peripheral: print(f"Found {peripheral.identifier()} [{peripheral.address()}]"))

    # Scan for 5 seconds
    adapter.scan_for(5000)
    peripherals = adapter.scan_get_results()

    # Query the user to pick a peripheral
    print("Please select a peripheral:")
    for i, peripheral in enumerate(peripherals):
        print(f"{i}: {peripheral.identifier()} [{peripheral.address()}]")

    choice = int(input("Enter choice: "))
    peripheral = peripherals[choice]

    service_uuid = '19b10000-e8f2-537e-4f6c-d104768a1214'
    characteristic_uuid= ['19b10001-e8f2-537e-4f6c-d104768a1214',
                          '19b10002-e8f2-537e-4f6c-d104768a1214',
                          '19b10003-e8f2-537e-4f6c-d104768a1214',
                          '19b10004-e8f2-537e-4f6c-d104768a1214',
                          '19b10005-e8f2-537e-4f6c-d104768a1214',
                          '19b10006-e8f2-537e-4f6c-d104768a1214',
                          '19b10007-e8f2-537e-4f6c-d104768a1214',
                          '19b10008-e8f2-537e-4f6c-d104768a1214',
                          '19b10009-e8f2-537e-4f6c-d104768a1214',
                          '19b10010-e8f2-537e-4f6c-d104768a1214',
                          '19b10011-e8f2-537e-4f6c-d104768a1214',
                          '19b10012-e8f2-537e-4f6c-d104768a1214',
                          '19b10013-e8f2-537e-4f6c-d104768a1214',
                          '19b10014-e8f2-537e-4f6c-d104768a1214',]
    

    def callback(data):
        global lista
        #for x in data:
        lista.extend(data)    
        #print(data[0])


    def callback_con():
        for i in range(13):  
            peripheral.notify(service_uuid, characteristic_uuid[i],  callback)
      

    print(f"Connecting to: {peripheral.identifier()} [{peripheral.address()}]")


    peripheral.set_callback_on_connected(callback_con)


    peripheral.connect() 

    while len(lista) != 3072:
        time.sleep(0.001)
    #time.sleep(2)

    message = 5
    peripheral.write_command(service_uuid,characteristic_uuid[-1], message.to_bytes(1,'little')) 
    
    print(lista)
    print(len(lista))  

    
    peripheral.disconnect()
    print("disconnected") 

Thanks again :slight_smile:

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.