How to send an array of 220 bytes via Arduino BLE?

Hi guys,

I am trying to send an array counting from 0 to 219 from the Arduino Nano 33 BLE Sense to my PC. I am able to send the simple data (an array with 1 element only) and it works, I can successfully received the number on the other side, but there is an issue when I want to send a larger amount of data. On the PC side, I can receive this array (0->219) but when I want to decode it and get completely different values. Maybe you can suggest me where I make mistakes. Here is my code:

#include <ArduinoBLE.h>

const char* uuidOftxChar = "2d2F88c4-f244-5a80-21f1-ee0224e80658";
const char* uuidOfService = "180F";
const char* nameofPeripheral = "ImageSender";
const int RX_BUFFER_SIZE = 220;
bool RX_BUFFER_FIXED_LENGTH = false;

unsigned long prevNow = 0;

BLEService imageService(uuidOfService);
BLECharacteristic txChar(uuidOftxChar, BLEIndicate, RX_BUFFER_SIZE, RX_BUFFER_FIXED_LENGTH); 


void setup() {

  Serial.begin(9600);
  while (!Serial);

  if (!BLE.begin()) {
    Serial.println("starting BLE failed!");
    while (1);
  }

  BLE.setLocalName(nameofPeripheral);
  BLE.setAdvertisedService(imageService);
  imageService.addCharacteristic(txChar);
  BLE.addService(imageService);
  BLE.setEventHandler(BLEConnected, blePeripheralConnectHandler);
  BLE.setEventHandler(BLEDisconnected, blePeripheralDisconnectHandler);
  BLE.advertise();
}

void blePeripheralConnectHandler(BLEDevice central) {
  Serial.println("Connected event, central: ");
  Serial.println(central.address());
}

void blePeripheralDisconnectHandler(BLEDevice central) {
  Serial.println("Disconnected event, central: ");
  Serial.println(central.address());
}

void loop() {
  
  BLE.poll();
  long now = millis();
  if (now - prevNow >= 5000) {
    prevNow = now;
    long now = millis();
    if (BLE.connected()) {
      //int rssiValue = BLE.rssi();
      //Serial.println(rssiValue);
      Serial.println("Connected to central");

      int numbers[221];
      for(int k=0; k<221; k++){
        numbers[k] = k;
      }

      Serial.println("First element in the array:");
      Serial.println(numbers[0]);
      Serial.println("Last element in the array:");
      Serial.println(numbers[220]);

      int counter = 0;
      int i=0;

      for(i; i<220; i+=RX_BUFFER_SIZE){
        
        txChar.writeValue(numbers+i, 220);
       
        counter+=1;
      }
    
      Serial.println(counter);
      Serial.println(i);
    }
  }

}

this cycle will be run only once

Yes, as the array contains 220 numbers, and as I know in one BLE packet I can send max 256B (correct me if I am wrong), so here I will just pass immediately 220 bytes and send them. That is the reason why for loop will be executed only once and then again when I enter the loop, I will send the array again. This is how I imagined this test.

If you doing it once - why do you doing that in the for loop?

And just for information - the size of the (int) in the Nano 33 platform is 4 bytes, so your array of 220 int's has size of 880 bytes.

Yes, I completely forgot about that part (size(int)->4B). I redefined this transmission part and now it looks like this:

for(i; i<880; i+=RX_BUFFER_SIZE){
        
        txChar.writeValue(numbers+i, 220);
       
        counter+=1;
      }

Now, the device will go through for loop 4 times until all data from numbers (array) are sent. When I do it like this, I am able to receive 880bytes but still not what I am expecting.

This is the result on the receiver side:

\x00\xdc\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\....

with some weird values such as:

\xa5g\x02\x00!N\x02\x00mM\

already on the second pass you go outside the array boundary in this line:

txChar.writeValue(numbers+i, 220);

because (numbers+i) counting array members, not bytes

In general, you have not quite the right logic for sending cycle. For this task, the FOR cycle is not suitable, it is more correct to use a WHILE.

The sending is process of the two simple stages:

  • send the portion of data - with size of RX_BUFFER_SIZE or less
  • test if the data send completely - if not - return to previous stage

Something like this:

int i = 0;
int counter = 55;
// I have 220 integers (1 int-> 4B), which means that the size of my byte array will be 880bytes
while(i<880){

  txChar.writeValue(numbers+counter, 220); // 220 bytes can cover 55 integers (55*4=220bytes)
  counter+=55;
  i+=220
}

Is there any specific method to check if data is successfully sent?

check the return value of the writeValue() method.
Traditionally, the sending functions should return number of bytes really sent.

Is this way of sending the data better than with the for loop? I also added the additional part in my write function:

txChar.writeValue(numbers+counter, 220, true);

In this way, I think I can get a response that everything is fine, but based on nothing changes really.

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