Problem with receiving data from Arduino Nano BLE using ".RegisterForFloats"/".FloatsReceived"

Hello everyone

I am trying to get an app running that should turn on an LED on Pin 4 of my Arduino 33 Nano BLE and then receive data when the chip got moved (when IMU detects perturbation it turns off the LED and should change a characteristic - customTouchedChar to 1). The final goal is to have a "reaction trainer", where the app will be connected to up to 6 Arduinos and will turn on the next LED as soon as the previous one was turned off.

So far I managed to program a button that will turn the first LED on and it also turns it off as soon as I move the chip. However, even though the characteristic "customTouchedChar" is changing (I tested this by printing it into the Serial port and by double-checking with nRF connect app) my app is not receiving any data (text of Label 1 is not changing at all - not even to sth received). Can anyone explain to me what I am doing wrong?

Here are the blocks I am using:

And the sketch:

// including the BLE and the sensor libraries
#include <ArduinoBLE.h>
#include <Arduino_LSM9DS1.h>

int ledPin = 4; // Pin to whichi the LED is connected
int time_delay = 200; // time delay between checking of touched property - might be changed to get better sensitivity
float x, y, z; // parameters for sensor output
float delta = 4; // senistivity of movement

// define the service and the characteristics
BLEService customService("19b10000-e8f2-537e-4f6c-d104768a1214"); // service
BLEUnsignedIntCharacteristic customTurnONChar("19b10001-e8f2-537e-4f6c-d104768a1214", BLERead | BLENotify| BLEWrite); // Phone input characteristic to turn on the LED
BLEUnsignedIntCharacteristic customTouchedChar("19b10002-e8f2-537e-4f6c-d104768a1214", BLERead | BLENotify); // Touched characteristic that communicates to the phone that the device was touched and turned off


void setup() {
  // initialize IMU
  if (!IMU.begin()){
    Serial.println("Failed to initialize IMU!");
    exit(1);
  }
  
  // initialize serial communication
  Serial.begin(9600); 
  while (!Serial);
  
  // define LED pins as output
  pinMode(LED_BUILTIN, OUTPUT); // will be showing that connection is established
  
  // initialize BLE
  if (!BLE.begin()) {
  Serial.println("BLE failed to Initiate");
  delay(500);
  while (1);
  }

  BLE.setLocalName("Pod_ONE");
  BLE.setAdvertisedService(customService);
  customService.addCharacteristic(customTouchedChar);
  customService.addCharacteristic(customTurnONChar);
  BLE.addService(customService);
  customTouchedChar.writeValue(0);

  BLE.advertise();

  Serial.println("Bluetooth device is now active, waiting for connections...");
  //String myaddress = BLE.address(); // find the address of the Arduino
  //Serial.print("Local address is: ");
  //Serial.println(myaddress); // print the address of the arduino
}

void read_Gyro() {
  if (IMU.gyroscopeAvailable()){
    IMU.readGyroscope(x, y, z);
  }
}

void loop() {
  BLEDevice central = BLE.central();
  if (central) {
    Serial.print("Connected to central: ");
    Serial.println(central.address());
  
    digitalWrite(LED_BUILTIN, HIGH); // turn on internal LED to show that BLE is connected with phone
    while (central.connected()) {
      delay(time_delay);
      if (customTurnONChar.value()==1){
        customTouchedChar.writeValue(0);
        Serial.println("Phone");
        digitalWrite(ledPin, HIGH);
        // here is where we can start the timer
        while(customTurnONChar.value()==1){
          read_Gyro();
          if(y < -delta || y > delta){
            Serial.println("touched");
            digitalWrite(ledPin, LOW);
            customTouchedChar.writeValue(1);
            Serial.println(customTouchedChar);
            customTurnONChar.setValue(0);
            // here is where we would stop the timer and send the value to phone
           }
           delay(time_delay);
        }
      }
    }
  Serial.print("Disconnected");
  digitalWrite(LED_BUILTIN, LOW);
  }

}

I didn't have time to go through your all your code but I could see that you have the same UUID for all your characteristics and service. You may want to change that and assign different UUIDs.

Hi! Thanks for your reply. The UUIDs are actually already different at the end of the first part: 19b10000-.., 19b10001-.., and 19b10002-... I think that should be fine, no?

Sorry, I didn't see that.
I'm no expert in BLE so I don't know if the UUID numbers separated by dashes have to be correlated somehow so I use this web page to generate UUID https://www.guidgenerator.com/online-guid-generator.aspx

I notice you have two BLE components.

You register for floats on both, but you only have a when floats received event for the first.

Also, that test for is 1 in list of incoming floats looks restrictive for that data type.
Floats rarely get exact matches.
It would be informative to show the incoming floats in a label, regardless of value, for debugging.

Thank you both for replying!

@GuilleR I am also not an expert in this, so just to check I tried with your UUID generator to check if that would make a difference, but even with three completely different UUIDs it did not solve the problem. When you solved your problem did you have to change the definition of your characteristic in your sketch?

@ABG you saw that correctly, I am just not done with everything yet. So the final goal would be that the app switches on the LED on the second BLE component as soon as the first one is touched and the app receives the customTouchedChar is equal to 1. Then again when the second component has been touched the LED on the first one should be switched on again. I really like your idea of printing the value, however, my problem is that the .FloatsReceived Block is not even triggered, so apparently the app is not receiving anything. But if I go to check in the nRF app I can see that the Characteristic has changed after touching and therefore the app should have received something? Do you know which data type would be best/easiest to try to receive? And how much does it depend on the type of characteristic I am defining in the line below?

BLEUnsignedIntCharacteristic customTouchedChar("19b10002-e8f2-537e-4f6c-d104768a1214", BLERead | BLENotify); // Touched characteristic that communicates to the phone that the device was touched and turned off

I'm no BLE expert, but that UnsignedInt in the characteristic definition looks like it would result in Unsigned Integers arriving at AI2.

Char 1 is a non-printing character. It is also not a float. You must match up the units between Sketch and App.

Hi falcon10,
You are planning to have 6 Arduino's, but why are you not concentrating on getting just ONE working. It will save you so much time now and later. Also, when you can, use strings instead of numbers. AI is really good at handling Strings as numbers, but not so good at handling incoming numbers from BLE devices.
It would be a good idea also to have a label that shows the connection status of your Arduino's.
Cheers.

1 Like

@ABG
Yeah, I tried with the .RegisterForIntegers and .IntegersReceived first which didn't work and then I found another post where they switched to floats, so thats what I tried too. I have to admit that I am more of a MATLAB person, and all Arduino projects that I worked on so far where controlled by MATLAB so I am really new to AI2.

@ChrisWard

Can you explain to me which characteristic you mean with Char 1 and why you see that it is a non-printing character?

@Ghica

Oh I see, good idea, I guess I could define a string characteristic and then just write numbers in there. I will try that tomorrow and let you know if it worked :smile:

I second @ChrisWard and @ABG, you have to align the types/sizes on both sides. Your characteristic in the sketch is specified as an unsigned integer (4 bytes) and you're attempting to read a float (IEEE 754, also 4 bytes, but a different format). All the app sees is a sequence of individual bytes and it needs to know how to interpret them. If you tell the BLE extension to interpret the bytes as a floating point value when it is encoded as an (unsigned) integer then it will likely get a Not-a-number value and not report anything.

1 Like

Hello Falcon

This is I think your best move. Follow a simple example Project and get that working with your kit. You can then build-up from there.

I have a number of links on my website and many of them will prove useful. Take a look at link 21, written by my colleague Juan Antonio.

https://www.professorcad.co.uk/appinventortips#TipsArduino

1 Like

Thank you all for replying and the explanations! I guess you were all right, there was definitely a mismatch between the definitions of the data types in the sketch and the app. While I still don't know what I needed to do in order to receive the Integer (because the app was also not working when I was trying to work with .RegisterForIntegers and .IntegersReceived - Does anyone have an idea why that didn't work? - just curious) I got it working now with strings.

In case another newbie has the same problem in the future, here is what I changed:

In the sketch, I adjusted the characteristic type:
BLECharacteristic customTouchedChar("19b10002-e8f2-537e-4f6c-d104768a1214", BLERead | BLENotify, 1);

The way I am registering for updates:


and the receiving data block:

Again thank you all for your help, now I am looking forward to trying to plot the reaction times in the app and expand the project to more Arduinos in the end! Wish you all a great weekend!

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