Problem reading Strings with app from Arduino BLE

Hello everyone,

I'm having troubles when I try to read string data received from my Arduino.
It connects perfectly via BLE but I only get Chinese characters on my phone screen and the App crashes.
So far I haven't read correctly any String value, even when I try to receive only one string data I keep receiving the chinese letters.


I would really appreciate your help.

Kind regards.

Arduino Code

#include <Arduino_LSM9DS1.h>
#include <ArduinoBLE.h>

BLEService gyroService("0000480f-0000-1000-8000-00805f9b34fb");
BLEStringCharacteristic LevelChar("00002a11-0000-1000-8000-00805f9b34fb", BLERead | BLENotify,100);
unsigned int igUpdateTime;

void setup() {
Serial.begin(9600);
igUpdateTime = millis();

if (!IMU.begin()) { //LSM9DS1 begin
Serial.println("LSM9DS1 error!");
while (1);
}
if (!BLE.begin()) {
Serial.println("BLE error!");
while (1);
}
// set advertised local name and service UUID:
BLE.setAdvertisedService(gyroService); // add the service UUID
gyroService.addCharacteristic(LevelChar);
BLE.addService(gyroService);
// start advertising
BLE.setLocalName("gyro");
// start advertising
BLE.advertise();
}

float ac_x, ac_y, ac_z;
float gy_x, gy_y, gy_z;
float ma_x, ma_y, ma_z;
String Level_String;

void updategyroLevel() {
if (IMU.accelerationAvailable()) {
IMU.readAcceleration(ac_x, ac_y, ac_z);
}
if (IMU.gyroscopeAvailable()) {
IMU.readGyroscope(gy_x, gy_y, gy_z);
}
if (IMU.magneticFieldAvailable()) {
IMU.readMagneticField(ma_x, ma_y, ma_z);
}
Level_String=String(ac_x,3)+","+String(ac_y,3)+","+String(ac_z,3)+","+String(gy_x,3)+","+String(gy_y,3)+","+String(gy_z,3)+","+String(ma_x,3)+","+String(ma_y,3)+","+String(ma_z,3);
// Level_String+=","+String(gy_x,3)+","+String(gy_y,3)+","+String(gy_z,3);
// Level_String+=","+String(ma_x,3)+","+String(ma_y,3)+","+String(ma_z,3);
LevelChar.writeValue(Level_String);
// Serial.println(Level_String);
}

void loop() {
// listen for BLE peripherals to connect:
BLEDevice central = BLE.central();
// updategyroLevel();
// delay(50);
// if a central is connected to peripheral:
if (central) {
while (central.connected()) {
if(millis() - igUpdateTime > 1000){
igUpdateTime = millis();
updategyroLevel();
}

// delay(2000);
}
}
}


IMU.aia (184.7 KB)

BLE works by default with 20-byte packets.

Try a simple String:

Level_String= "123,456";

This is your problem.

It is better to create a byte array for your data. Just remember at a float value requires 4 bytes.

BLECharacteristic(const char* uuid, uint8_t properties, int valueSize, bool fixedLength = false);

So in your Arduino code, if you used:
BLECharacteristic LevelChar("00002a11-0000-1000-8000-00805f9b34fb", BLERead | BLENotify,100, true);

This would send 100 bytes of data (a bit too much, but just here as an example) and this is an array of fixed size (i.e. data array cannot be less).

Hello, thank you for your answers @Juan_Antonio and @Gerriko_io

I've solved the problem with the corrupted data (chinese symbols) using the "register for string" block instead of "read strings".

But I have a new problem, I only can see 3 values on my app, I think the problem is with the list length.

First I got this message: "Attempt to get item number 5 of a list of length 4"

I tried to solve this problem by verifying the length of the list as you can see in the image (Blocks and app screen):


The Arduino code is the same I have already posted.

@Gerriko_io I tried redefining as you suggested but I don't really know what I'm doing wrong, I get this message in the IDE. Is it maybe the way I'm defining the byte array?

#include <Arduino_LSM9DS1.h>
#include <ArduinoBLE.h>

BLEService gyroService("0000480f-0000-1000-8000-00805f9b34fb");
BLECharacteristic LevelChar("00002a11-0000-1000-8000-00805f9b34fb", BLERead | BLENotify, 100, true);
unsigned int igUpdateTime;

void setup() {
Serial.begin(9600);
igUpdateTime = millis();

if (!IMU.begin()) { //LSM9DS1 begin
Serial.println("LSM9DS1 error!");
while (1);
}
if (!BLE.begin()) {
Serial.println("BLE error!");
while (1);
}
// set advertised local name and service UUID:
BLE.setAdvertisedService(gyroService); // add the service UUID
gyroService.addCharacteristic(LevelChar);
BLE.addService(gyroService);
// start advertising
BLE.setLocalName("gyro");
// start advertising
BLE.advertise();
}

float ac_x, ac_y, ac_z;
float gy_x, gy_y, gy_z;
float ma_x, ma_y, ma_z;
String Level_String;

void updategyroLevel() {
if (IMU.accelerationAvailable()) {
IMU.readAcceleration(ac_x, ac_y, ac_z);
}
if (IMU.gyroscopeAvailable()) {
IMU.readGyroscope(gy_x, gy_y, gy_z);
}
if (IMU.magneticFieldAvailable()) {
IMU.readMagneticField(ma_x, ma_y, ma_z);
}
// Level_String=String(ac_x,3);
Level_String=String(ac_x,3)+"|"+String(ac_y,3)+"|"+String(ac_z,3)+"|"+String(gy_x,3)+"|"+String(gy_y,3)+"|"+String(gy_z,3)+"|"+String(ma_x,3)+"|"+String(ma_y,3)+"|"+String(ma_z,3);
// Level_String+=","+String(gy_x,3)+","+String(gy_y,3)+","+String(gy_z,3);
// Level_String+=","+String(ma_x,3)+","+String(ma_y,3)+","+String(ma_z,3);
LevelChar.writeValue(Level_String);
// Serial.println(Level_String);
}

void loop() {
// listen for BLE peripherals to connect:
BLEDevice central = BLE.central();
// updategyroLevel();
// delay(50);
// if a central is connected to peripheral:
if (central) {
while (central.connected()) {
if(millis() - igUpdateTime > 4000){
igUpdateTime = millis();
updategyroLevel();
}

// delay(2000);
}
}
}

I would really appreciate your help.
Thank you so much

Kind regards.

BLE works by default with 20-byte packets. (MTU)

Try with block RequestMTU

Here a tutorial of BLE HM-10, it is another module and another code very different from yours, but maybe you can get some ideas.