Get continuously the value of a BLE service, communication between 2 arduino Nano 33 BLE Sense

Hello,

I have been working on Arduino Nano 33 BLE Sense for a while to find solutions to read the sensors values via BLE. Currently I am working on using a second Arduino Nano 33 BLE Sense to read the values of the integrated sensors. I am interested with temperature and accelerometer for now. I think my Peripheral code is okay, I managed to detect the peripheral with the phone. However, I couldn't find that much codes online for using the board as a central to read values of BLE services.

Peripheral code:

/*
 * Device: Arduino Nano 33 BLE Sense
 * Peripheral
 * The values of the integrated temperature sensor and 
 * accelerometer are sent using BLE.
 */

#include <ArduinoBLE.h>
#include <Arduino_LSM9DS1.h> //accelerometer sensor
#include <Arduino_HTS221.h> // temperature sensor

float T=37;
float X=0;
float Y=0;
float Z=0;

BLEService SensorService("1101");
BLEUnsignedIntCharacteristic XChar("2101", BLERead | BLEWrite);
BLEUnsignedIntCharacteristic YChar("2102", BLERead | BLEWrite);
BLEUnsignedIntCharacteristic ZChar("2103", BLERead | BLEWrite);
BLEUnsignedIntCharacteristic TChar("2104", BLERead | BLEWrite);

void setup() {
IMU.begin();
HTS.begin();
Serial.begin(9600); 
while (!Serial);

//  if (!HTS.begin()){
//    Serial.println("Failed to start the HTS221 sensor.");
//    while(1);
//
//  if (!IMU.begin()) {
//    Serial.println("Failed to start the LSM9DS sensor.");
//    while (1);

pinMode(LED_BUILTIN, OUTPUT);

if (!BLE.begin()) {
Serial.println("BLE failed to Initiate");
delay(500);
while (1);
}

BLE.setLocalName("Arduino XTZT (peripheral)");
BLE.setAdvertisedService(SensorService);
SensorService.addCharacteristic(XChar);
SensorService.addCharacteristic(YChar);
SensorService.addCharacteristic(ZChar);
SensorService.addCharacteristic(TChar);
BLE.addService(SensorService);
XChar.writeValue(X);
YChar.writeValue(Y);
ZChar.writeValue(Z);
TChar.writeValue(T);

BLE.advertise();

Serial.println("Bluetooth device is now active, waiting for connections...");
}


void loop() {

BLEDevice central = BLE.central();
if (central) {
Serial.print("Connected to central: ");
Serial.print("* Device MAC address: ");
Serial.println(central.address());
Serial.println(" ");

digitalWrite(LED_BUILTIN, HIGH);

while (central.connected()) {
//delay(200);
if (IMU.accelerationAvailable()) {
    IMU.readAcceleration(X, Y, Z);
}
T=HTS.readTemperature();

XChar.writeValue(X);
YChar.writeValue(Y);
ZChar.writeValue(Z);
TChar.writeValue(T);

Serial.println("At Main Function");
Serial.print("X ");
Serial.print(X);
Serial.print(" - Y ");
Serial.print(Y);
Serial.print(" - Z ");
Serial.print(Z);
Serial.print(" - T ");
Serial.println(T);
Serial.println("");
Serial.println("");
}
 //Serial.println("* Disconnected to central device!");

}
digitalWrite(LED_BUILTIN, LOW);
Serial.print("Disconnected from central: ");
delay(1000);
Serial.println(central.address());
}

Here is the central code (not working)

/*
  BLE_Central_Device.ino

 /*
 * Device: Arduino Nano 33 BLE Sense
 * Central
 * The values of the integrated temperature sensor and 
 * accelerometer of another Nano 33 BLE are received using BLE.
 */

#include <ArduinoBLE.h>

void setup() {
  Serial.begin(9600);
  while (!Serial);

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

  BLE.setLocalName("Arduino XYZT (Central)"); 
  BLE.advertise();

  Serial.println("Arduino XYZT (Central)");
  Serial.println(" ");
}

void loop() {
 BLEDevice peripheral = BLE.available();

 Serial.println("- Discovering peripheral device...");

  do
  {
    BLE.scanForUuid("1101");
    peripheral = BLE.available();
  } while (!peripheral);

  if (peripheral) {

    Serial.println("* Peripheral device found!");
    Serial.print("* Device MAC address: ");
    Serial.println(peripheral.address());
    Serial.print("* Device name: ");
    Serial.println(peripheral.localName());
    Serial.print("* Advertised service UUID: ");
    Serial.println(peripheral.advertisedServiceUuid());
    Serial.println(" ");
    BLE.stopScan();
  }

   if (peripheral.connect()) {

    Serial.println("* Connected to peripheral device!");
    Serial.println(" ");

    BLECharacteristic TChar = peripheral.characteristic( "2104" );
    if ( TChar )
    {
    int temperature;
    TChar.readValue( temperature );
    Serial.print( "Temperature: " );
    Serial.print( temperature );
    Serial.println( "°C" );
    }

    
    } else {
    Serial.println("* Connection to peripheral device failed!");
    Serial.println(" ");
    return;

  }

}

I get the error:

no matching function for call to 'readValue(int&)'

I would be very grateful if someone could give me a hint on which function I should use to read the service value (I have studied the ArduinoBLE librairy and the exemples, but possible I missed some point).

Thank you for reading

//int temperature;
uint32_t temperature;

The use of "int" seems to be ambiguous to the compiler.
You are sending an unsigned long, so read it as such.
With this change the code compiles.

1 Like

Thanks a lot cattledog !

Even if I don't have anymore the error, I still have a problem on getting the values of the peripheral's sensor on the central's serial monitor. For now I am focussing on the temperature and I only get 0°C values.

I have changed a bit my central code since my initial post (there was a loop problem and I have replaced the "if (peripheral.connect())" loop into a while loop as in the peripheral program).

/*
  BLE_Central_Device.ino

 /*
 * Device: Arduino Nano 33 BLE Sense
 * Central
 * The values of the integrated temperature sensor and 
 * accelerometer of another Nano 33 BLE are received using BLE.
 */

#include <ArduinoBLE.h>

void setup() {
  Serial.begin(9600);
  while (!Serial);

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

  BLE.setLocalName("Arduino XYZT (Central)"); 
  BLE.advertise();

  Serial.println("Arduino XYZT (Central)");
  Serial.println(" ");
}

void loop() {
 BLEDevice peripheral = BLE.available();

 Serial.println("- Discovering peripheral device...");

  do
  {
    BLE.scanForUuid("1101");
    peripheral = BLE.available();
  } while (!peripheral);

  if (peripheral) {

    Serial.println("* Peripheral device found!");
    Serial.print("* Device MAC address: ");
    Serial.println(peripheral.address());
    Serial.print("* Device name: ");
    Serial.println(peripheral.localName());
    Serial.print("* Advertised service UUID: ");
    Serial.println(peripheral.advertisedServiceUuid());
    Serial.println(" ");
    //BLE.stopScan();
  
    while (peripheral.connect()) {

    //Serial.println("* Connected to peripheral device!");
    //Serial.println(" ");

    BLECharacteristic TChar = peripheral.characteristic( "2104" );
    //if ( TChar )
    //{
    int32_t temperature;
    TChar.readValue( temperature );
    Serial.print( "Temperature: " );
    Serial.print( temperature );
    Serial.println( "°C" );
    delay(1000);
    }
    
//    } else {
//    Serial.println("* Connection to peripheral device failed!");
//    Serial.println(" ");
//    return;
    }
    Serial.print("Disconnected from peripheral: ");

}

I get this on the monitor :

Arduino XYZT (Central)
 
- Discovering peripheral device...
* Peripheral device found!
* Device MAC address: 38:b9:c0:ae:e3:d3
* Device name: Arduino XTZT (peripheral)
* Advertised service UUID: 1101
 
Temperature: 0°C
Temperature: 0°C
Temperature: 0°C
Temperature: 0°C
...

I also think there is a loop problem in the peripheral program, because the sensor values are printed only twice (so once for the void setup and only once for the void loop)

Another thing I have noticed is that the communication seems to stop if the 2 boards are disconnected even if there are put again closed from each other. So I understand the void loop is not running continuously. How could I fix that?

I apologised having so much question but I am new on Arduino, managed to learn quite a lot on my own during the last month but some points remains pretty blurred to me. I would be grateful if anyone has some answers or advise.

Thanks

Hello,

I have been keeping working on this today and I am updating in case.

I have changed the peripheral program so that it prints both the value read from the sensor and the one writen on the services. It appears that the writen values are all equal to one. I have realised that I write Unsigned interger value into float, so maybe it is one of the problems? However if the value is equal to one in the peripheral, why is it equal to zero in the central?

Then I have tried to use the exemple Peripheral explorer program instead of my central. The connection success but the attribute discovery fails. I have no idea so far...

Thanks for reading

I also have been trying to get a Central example working, and also had issues at that same area. Like you, I can use nrfConnect on an Android phone to see your peripheral.

Part of my difficulties is that I only have one Nano 33 Ble to work with. I did manage to write a peripheral(server) program for an ESP 32 which I could read with Peripheral Explorer on the Nano 33. Both sets of code are not really close to your two programs.

I am trying to understand what works and why and simplify both sides, but it is slow going.

I do believe that it is possible to configure the Nano 33 BLE as a central. I would work with the the the library example Peripheral Explorer and focus on getting a peripheral written that can be seen and read by it.

I'll keep poking around, but without a second Nano its not clear if I can come up with something that will work for you. :frowning_face:

Thanks for your answer and help cattledog !

I will keep on working on this and update. I am just a bit frustrated I thought it was something basic to do since I found some tutorials on gesture sensor even if I didn't manage to make it work.

What were your issues with the tutorial?

Are you using the latest version of ArduinoBLE.h? Should be version 1.2.1. There were some issues reported on GitHub about Central on an earlier version.

As I said, the peripheral explorer example works with the correct server, so I would focus on your Server program and getting it to run with the example.

Here is a stripped down Central version, which reads a four byte unsigned long integer (like a float temperature *100) and reports the received value like the original with 2 dp. There are issues with this code and reconnections. It does not deal with errors. I just wanted to see if some minimal central program could be made to work.

The server is a simple ESP 32 ble program to sent a 4 byte value which can be read.

#include <ArduinoBLE.h>

void setup() {
  Serial.begin(9600);
  while (!Serial);

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

  Serial.println("BLE Central for Temperature Server");
  //custom sensor service 1101
  BLE.scanForUuid("1101"); 
}

void loop() {
  // check if a peripheral has been discovered
  BLEDevice peripheral = BLE.available();
 
  if (peripheral) {
    // discovered a peripheral, print out address, local name, and advertised service
    Serial.print("Found ");
    Serial.print(peripheral.address());
    Serial.print(" '");
    Serial.print(peripheral.localName());
    Serial.print("' ");
    Serial.print(peripheral.advertisedServiceUuid());
    Serial.println();
    BLE.stopScan();
  }
  peripheral.connect();
  while (peripheral)
  {
    peripheral.discoverAttributes();
    BLEService service = peripheral.service("1101");
    Serial.print("Service ");
    Serial.print(service.uuid());
    BLECharacteristic characteristic = service.characteristic("2104");
    readCharacteristicValue(characteristic);
    delay(2000);
  }
}

void readCharacteristicValue(BLECharacteristic characteristic) {
  // print the UUID and properties of the characteristic
  Serial.print("\tCharacteristic ");
  Serial.print(characteristic.uuid());
  // check if the characteristic is readable
  if (characteristic.canRead()) {
    // read the characteristic value
    characteristic.read();

    if (characteristic.valueLength() > 0) {
      Serial.print(", value = ");
      //characteristic.value() returns byte array
      unsigned long bitShiftData = 0;
      bitShiftData = (uint32_t)characteristic.value()[3] << 24 | (uint32_t)characteristic.value()[2] << 16 | (uint32_t)characteristic.value()[1] << 8 | characteristic.value()[0];
      Serial.println(bitShiftData, DEC);
      Serial.print(bitShiftData / 100);
      Serial.print('.');
      if (bitShiftData % 100 < 10)
        Serial.print('0');
      Serial.println(bitShiftData % 100);
    }
  }
}

I checked and yes !

Okay, i will try to focus on that. Thanks a lot for sharing your code!

An update about that : I was getting zero value because I was printing directly the service instead of service.value()

To help you with your toolset, here is a version of the Central program PeripheralExplorer modified to run continuously. You should be able to see the details of your peripheral and its service.

/*
  Peripheral Explorer

  This example scans for BLE peripherals until one with a particular name ("LED")
  is found. Then connects, and discovers + prints all the peripheral's attributes.

  The circuit:
  - Arduino MKR WiFi 1010, Arduino Uno WiFi Rev2 board, Arduino Nano 33 IoT,
    Arduino Nano 33 BLE, or Arduino Nano 33 BLE Sense board.

  You can use it with another board that is compatible with this library and the
  Peripherals -> LED example.

  This example code is in the public domain.
*/

#include <ArduinoBLE.h>

void setup() {
  Serial.begin(9600);
  while (!Serial);

  // begin initialization
  if (!BLE.begin()) {
    Serial.println("starting BLE failed!");

    while (1);
  }

  Serial.println("BLE Central - Peripheral Explorer");

  // start scanning for peripherals
  BLE.scan();
}

void loop() {
  // check if a peripheral has been discovered
  BLEDevice peripheral = BLE.available();

  if (peripheral) {
    // discovered a peripheral, print out address, local name, and advertised service
    Serial.print("Found ");
    Serial.print(peripheral.address());
    Serial.print(" '");
    Serial.print(peripheral.localName());
    Serial.print("' ");
    Serial.print(peripheral.advertisedServiceUuid());
    Serial.println();

    // see if peripheral is a LED
    if (peripheral.localName() == "ESP32") {  //Local Name hoes here
      // stop scanning
      BLE.stopScan();

      explorerPeripheral(peripheral);

      // peripheral disconnected, we are done
      // while (1) {
      // do nothing
      // }
    }
  }
}

void explorerPeripheral(BLEDevice peripheral) {
  // connect to the peripheral
  Serial.println("Connecting ...");

  if (peripheral.connect()) {
    Serial.println("Connected");
  } else {
    Serial.println("Failed to connect!");
    return;
  }

  while (peripheral) {
    // discover peripheral attributes
    Serial.println("Discovering attributes ...");
    if (peripheral.discoverAttributes()) {
      Serial.println("Attributes discovered");
    } else {
      Serial.println("Attribute discovery failed!");
      peripheral.disconnect();
      return;
    }

    // read and print device name of peripheral
    Serial.println();
    Serial.print("Device name: ");
    Serial.println(peripheral.deviceName());
    Serial.print("Appearance: 0x");
    Serial.println(peripheral.appearance(), HEX);
    Serial.println();

    // loop the services of the peripheral and explore each
    for (int i = 0; i < peripheral.serviceCount(); i++) {
      BLEService service = peripheral.service(i);

      exploreService(service);
    }

    Serial.println();
    delay(1000);
  }

  // we are done exploring, disconnect
  //Serial.println("Disconnecting ...");
  //peripheral.disconnect();
  //Serial.println("Disconnected");
  //}
}

void exploreService(BLEService service) {
  // print the UUID of the service
  Serial.print("Service ");
  Serial.println(service.uuid());

  // loop the characteristics of the service and explore each
  for (int i = 0; i < service.characteristicCount(); i++) {
    BLECharacteristic characteristic = service.characteristic(i);

    exploreCharacteristic(characteristic);
  }
}

void exploreCharacteristic(BLECharacteristic characteristic) {
  // print the UUID and properties of the characteristic
  Serial.print("\tCharacteristic ");
  Serial.print(characteristic.uuid());
  Serial.print(", properties 0x");
  Serial.print(characteristic.properties(), HEX);

  // check if the characteristic is readable
  if (characteristic.canRead()) {
    // read the characteristic value
    characteristic.read();

    if (characteristic.valueLength() > 0) {
      // print out the value of the characteristic
      Serial.print(", value 0x");
      printData(characteristic.value(), characteristic.valueLength());
    }
  }
  Serial.println();

  // loop the descriptors of the characteristic and explore each
  for (int i = 0; i < characteristic.descriptorCount(); i++) {
    BLEDescriptor descriptor = characteristic.descriptor(i);

    exploreDescriptor(descriptor);
  }
}

void exploreDescriptor(BLEDescriptor descriptor) {
  // print the UUID of the descriptor
  Serial.print("\t\tDescriptor ");
  Serial.print(descriptor.uuid());

  // read the descriptor value
  descriptor.read();

  // print out the value of the descriptor
  Serial.print(", value 0x");
  printData(descriptor.value(), descriptor.valueLength());

  Serial.println();
}

void printData(const unsigned char data[], int length) {
  for (int i = 0; i < length; i++) {
    unsigned char b = data[i];

    if (b < 16) {
      Serial.print("0");
    }

    Serial.print(b, HEX);
  }
}

Here's the output I see when I send a single 4 byte value with characteristic 2104. I can see the value changing as I send changing values of the characteristic with a temperature simulation.

Discovering attributes ...
Attributes discovered

Device name: ESP32
Appearance: 0x0

Service 1801
	Characteristic 2a05, properties 0x20
		Descriptor 2902, value 0x0000
Service 1800
	Characteristic 2a00, properties 0x2, value 0x4553503332
		Descriptor 2803, value 0x021800012A
		Descriptor 2a01, value 0x0000
	Characteristic 2a01, properties 0x2, value 0x0000
		Descriptor 2803, value 0x021A00A62A
		Descriptor 2aa6, value 0x00
	Characteristic 2aa6, properties 0x2, value 0x00
Service 1101
	Characteristic 2104, properties 0x2, value 0xE5190000
		Descriptor 2902, value 0x0000

Can you please post your latest server and central code versions. Thanks.

1 Like

Hello,

Thank you for your answer.
Here are my versions from friday. I managed to transfer the temperature value thanks to your readCharacteristicValue.

Peripheral

/*
 * Device: Arduino Nano 33 BLE Sense
 * Peripheral
 * The values of the integrated temperature sensor and 
 * accelerometer are sent using BLE.
 */

#include <ArduinoBLE.h>
#include <Arduino_LSM9DS1.h> //accelerometer sensor
#include <Arduino_HTS221.h> // temperature sensor

int d=0; //number of decimal to keep

//float values read by the sensor
float t_f=37;
float x_f=0;
float y_f=0;
float z_f=0;

//integer variables to write yhr 
//int t_i=t_f*pow(10,d);
//int x_i=x_f*pow(10,d);
//int y_i=y_f*pow(10,d);
//int z_i=z_f*pow(10,d);
int t_i=t_f*100;
int x_i=x_f*100;
int y_i=y_f*100;
int z_i=z_f*100;



BLEService SensorService("1101");
BLEUnsignedIntCharacteristic XChar("2101", BLERead | BLENotify);
BLEUnsignedIntCharacteristic YChar("2102", BLERead | BLENotify);
BLEUnsignedIntCharacteristic ZChar("2103", BLERead | BLENotify);
BLEUnsignedIntCharacteristic TChar("2104", BLERead | BLENotify);

void setup() {
IMU.begin();
HTS.begin();
Serial.begin(9600); 
while (!Serial);

//  if (!HTS.begin()){
//    Serial.println("Failed to start the HTS221 sensor.");
//    while(1);
//
//  if (!IMU.begin()) {
//    Serial.println("Failed to start the LSM9DS sensor.");
//    while (1);

pinMode(LED_BUILTIN, OUTPUT);

if (!BLE.begin()) {
Serial.println("BLE failed to Initiate");
delay(500);
while (1);
}

BLE.setLocalName("Arduino XTZT (peripheral)");
BLE.setAdvertisedService(SensorService);
SensorService.addCharacteristic(XChar);
SensorService.addCharacteristic(YChar);
SensorService.addCharacteristic(ZChar);
SensorService.addCharacteristic(TChar);
BLE.addService(SensorService);
XChar.writeValue(x_i);
YChar.writeValue(y_i);
ZChar.writeValue(z_i);
TChar.writeValue(t_i);

BLE.advertise();

Serial.println("Bluetooth device is now active, waiting for connections...");
}


void loop() {

BLEDevice central = BLE.central();
if (central) {
Serial.print("Connected to central: ");
Serial.print("* Device MAC address: ");
Serial.println(central.address());
Serial.println(" ");

digitalWrite(LED_BUILTIN, HIGH);

while (central.connected()) {
delay(200);
//read_sensor();
if (IMU.accelerationAvailable()) {
IMU.readAcceleration(x_f, y_f, z_f);
}
t_f=HTS.readTemperature();

Serial.print("x_f ");
Serial.print(x_f);
Serial.print(" - y_f ");
Serial.print(y_f);
Serial.print(" - z_f ");
Serial.print(z_f);
Serial.print(" - t_f ");
Serial.println(t_f);
Serial.println("");
//x_i=x_f*pow(10,d);
//y_i=y_f*pow(10,d);
//z_i=z_f*pow(10,d);
//t_i=t_f*pow(10,d);

int t_i=t_f*100;
int x_i=x_f*100;
int y_i=y_f*100;
int z_i=z_f*100;

Serial.print("x_i ");
Serial.print(x_i);
Serial.print(" - y_i ");
Serial.print(y_i);
Serial.print(" - z_i ");
Serial.print(z_i);
Serial.print(" - t_i ");
Serial.println(t_i);
Serial.println("");

XChar.writeValue(x_i);
YChar.writeValue(y_i);
ZChar.writeValue(z_i);
TChar.writeValue(t_i);

//Serial.println("At Main Function");
Serial.print("XChar ");
Serial.print(XChar.value());
Serial.print(" - YChar ");
Serial.print(YChar.value());
Serial.print(" - ZChar ");
Serial.print(ZChar);
Serial.print(" - TChar ");
Serial.println(TChar.value());
Serial.println("");
Serial.println("");
//Serial.println("");
//Serial.println("");

delay(1000);

}
}
digitalWrite(LED_BUILTIN, LOW);
Serial.print("Disconnected from central: ");
Serial.println(central.address());
BLE.advertise();



}

//void read_sensor(){
//if (IMU.accelerationAvailable()) {
//IMU.readAcceleration(x_f, y_f, z_f);
//}
//t_f=HTS.readTemperature();
//
//Serial.print("x_f ");
//Serial.print(x_f);
//Serial.print(" - y_f ");
//Serial.print(y_f);
//Serial.print(" - z_f ");
//Serial.print(z_f);
//Serial.print(" - t_f ");
//Serial.println(t_f);
//Serial.println("");
////x_i=x_f*pow(10,d);
////y_i=y_f*pow(10,d);
////z_i=z_f*pow(10,d);
////t_i=t_f*pow(10,d);
//
//int t_i=t_f;
//int x_i=x_f;
//int y_i=y_f;
//int z_i=z_f;
//
//Serial.print("x_i ");
//Serial.print(x_i);
//Serial.print(" - y_i ");
//Serial.print(y_i);
//Serial.print(" - z_i ");
//Serial.print(z_i);
//Serial.print(" - t_i ");
//Serial.println(t_i);
//Serial.println("");

Central

/*
  BLE_Central_Device.ino

 /*
 * Device: Arduino Nano 33 BLE Sense
 * Central
 * The values of the integrated temperature sensor and 
 * accelerometer of another Nano 33 BLE are received using BLE.
 */

#include <ArduinoBLE.h>

void setup() {
  Serial.begin(9600);
  while (!Serial);

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

  BLE.setLocalName("Arduino XYZT (Central)"); 
  Serial.println("Arduino XYZT (Central)");
  Serial.println(" ");

  //BLE.advertise();
  BLE.scan();
}

void loop() {
 BLEDevice peripheral = BLE.available();

 //Serial.println("- Discovering peripheral device...");

//  do
//  {
//    BLE.scanForUuid("1101");
//    peripheral = BLE.available();
//  } while (!peripheral);

  if (peripheral) {
    Serial.print("Found ");
    Serial.print(peripheral.address());
    Serial.print(" '");
    Serial.print(peripheral.localName());
    Serial.print("' ");
    Serial.print(peripheral.advertisedServiceUuid());
    Serial.println();
    
//    Serial.println("* Peripheral device found!");
//    Serial.print("* Device MAC address: ");
//    Serial.println(peripheral.address());
//    Serial.print("* Device name: ");
//    Serial.println(peripheral.localName());
//    Serial.print("* Advertised service UUID: ");
//    Serial.println(peripheral.advertisedServiceUuid());
//    Serial.println(" ");
    //BLE.stopScan();

    if (peripheral.localName() == "Arduino XTZT (peripheral)") {
      // stop scanning
      BLE.stopScan();
      
      if (peripheral.connect()) {
       Serial.println("Connected");
       } else {
       Serial.println("Failed to connect!");
       return;
      }
      
     // discover peripheral attributes
      Serial.println("Discovering attributes ...");
      if (peripheral.discoverAttributes()) {
      Serial.println("Attributes discovered");
      } else {
      Serial.println("Attribute discovery failed!");
      peripheral.disconnect();
      return;
      }
      
     // read and print device name of peripheral
     Serial.println();
     Serial.print("Device name: ");
     Serial.println(peripheral.deviceName());
     Serial.print("Appearance: 0x");
     Serial.println(peripheral.appearance(), HEX);
     Serial.println();
     }

  while (peripheral.connect()) {
  
    //BLECharacteristic TChar = peripheral.characteristic( "2104" );
      BLEService service = peripheral.service("1101");
    Serial.print("Service ");
    Serial.print(service.uuid());
    BLECharacteristic characteristic = service.characteristic("2104");
    readCharacteristicValue(characteristic);

    
    delay(1000);
    }


    
//    } else {
//    Serial.println("* Connection to peripheral device failed!");
//    Serial.println(" ");
//    return;
    }
    //Serial.println("Disconnected from peripheral: ");
}

void readCharacteristicValue(BLECharacteristic characteristic) {
  // print the UUID and properties of the characteristic
  Serial.print("\tCharacteristic ");
  Serial.print(characteristic.uuid());
  // check if the characteristic is readable
  if (characteristic.canRead()) {
    // read the characteristic value
    characteristic.read();

    if (characteristic.valueLength() > 0) {
      Serial.print(", value = ");
      //characteristic.value() returns byte array
      unsigned long bitShiftData = 0;
      bitShiftData = (uint32_t)characteristic.value()[3] << 24 | (uint32_t)characteristic.value()[2] << 16 | (uint32_t)characteristic.value()[1] << 8 | characteristic.value()[0];
      Serial.println(bitShiftData, DEC);
      Serial.print(bitShiftData / 100);
      Serial.print('.');
      if (bitShiftData % 100 < 10)
        Serial.print('0');
      Serial.println(bitShiftData % 100);
    }
  }
}

Still have to work on it to understand what is happening (especially the line `

I still haven't worked on your last message, but I should tomorrow. Then have to include also the sending of the accelerometer. I am very very grateful for your help !!!!

You have been making good progress :grinning:

I have been learning some BLE coding skills along with you and I have some recommendations to make on the temperature characteristic.

I'm not clear what the values of the temperature are, but they are between +/- 327 degrees they can be sent as a signed integer (int16_t), as the multiplication of the float value by 100 will fall within the range -32768 to +32767.

There are more simple ways to combine the bytes of the received characteristic value back into the sent value than the bitshifting recombination I used.

There are .readValue() functions in the library which can directly handle the recombination of variables.
The readCharacteristic() function can look like this when using the signed integer (int16_t).

void readCharacteristicValue(BLECharacteristic characteristic) {
  // print the UUID and properties of the characteristic
  Serial.print("\tCharacteristic ");
  Serial.print(characteristic.uuid());
  // check if the characteristic is readable
  if (characteristic.canRead()) {
    //read the characteristic value
    int16_t temperature = 0;
    characteristic.readValue(&temperature,2);
    Serial.print(", temperature = ");
    Serial.println((float)temperature/100.0);
  }
}

I will start to take a look at the acceleration data, and they may want to be sent as floats. I doubt that the unsigned long is correct as it won't deal with negative numbers. Perhaps int32_t if you want to avoid floats and multiply.

There is an example here which uses a similar reading of the characteristic value as a float if it is sent as a 4 byte float.

float floatValue;
 floatValueCharacteristic.readValue( &floatValue, 4 );
 Serial.println( floatValue );
1 Like

Hello,

I am not done with working on this topic but here are my last codes that work for temperature and accelerometer. From now, I will start to work on the communication of a NanoBLE 33 sense with a Wio terminal to display the datas.

Peripheral

/*
 * Device: Arduino Nano 33 BLE Sense
 * Peripheral
 * The values of the integrated temperature sensor and 
 * accelerometer are sent using BLE.
 */

#include <ArduinoBLE.h>
#include <Arduino_LSM9DS1.h> //accelerometer sensor
#include <Arduino_HTS221.h> // temperature sensor

int const d_a=2; //number of decimal to keep for the accelerometer
int const d_t=2; //number of decimal to keep for the temperature

//float values read by the sensor
float xSensor=0;
float ySensor=0;
float zSensor=0;
float tSensor=37;

//integer variables to send via BLE
int xBLE=xSensor*pow(10,d_a);
int yBLE=ySensor*pow(10,d_a);
int zBLE=zSensor*pow(10,d_a);
int tBLE=tSensor*pow(10,d_t);
//int t_i=t_f*100;
//int x_i=x_f*100;
//int y_i=y_f*100;
//int z_i=z_f*100;

BLEService SensorService("1101");
BLEUnsignedIntCharacteristic XChar("2101", BLERead | BLENotify);
BLEUnsignedIntCharacteristic YChar("2102", BLERead | BLENotify);
BLEUnsignedIntCharacteristic ZChar("2103", BLERead | BLENotify);
BLEUnsignedIntCharacteristic TChar("2104", BLERead | BLENotify);

void setup() {
IMU.begin();
HTS.begin();
Serial.begin(9600); 
while (!Serial);

//  if (!HTS.begin()){
//    Serial.println("Failed to start the HTS221 sensor.");
//    while(1);
//
//  if (!IMU.begin()) {
//    Serial.println("Failed to start the LSM9DS sensor.");
//    while (1);

pinMode(LED_BUILTIN, OUTPUT);

if (!BLE.begin()) {
Serial.println("BLE failed to Initiate");
delay(500);
while (1);
}

BLE.setLocalName("Arduino XYZT (peripheral)");
BLE.setAdvertisedService(SensorService);
SensorService.addCharacteristic(XChar);
SensorService.addCharacteristic(YChar);
SensorService.addCharacteristic(ZChar);
SensorService.addCharacteristic(TChar);
BLE.addService(SensorService);

XChar.writeValue(xBLE);
YChar.writeValue(yBLE);
ZChar.writeValue(zBLE);
TChar.writeValue(tBLE);

BLE.advertise();

Serial.println("Arduino XYZT peripheral device is now active, waiting for connections...");
}


void loop() {

BLEDevice central = BLE.central();
if (central) {
Serial.print("Connected to central: ");
Serial.print("* Device MAC address: ");
Serial.println(central.address());
Serial.println(" ");

digitalWrite(LED_BUILTIN, HIGH);

while (central.connected()) {
//delay(200);
//read_sensor();
if (IMU.accelerationAvailable()) {
IMU.readAcceleration(xSensor, ySensor, zSensor);
}
tSensor=HTS.readTemperature();

Serial.print("xSensor ");
Serial.print(xSensor);
Serial.print(" - ySensor ");
Serial.print(ySensor);
Serial.print(" - zSensor ");
Serial.print(zSensor);
Serial.print(" - tSensor ");
Serial.println(tSensor);
Serial.println("");
xBLE=xSensor*pow(10,d_a);
yBLE=ySensor*pow(10,d_a);
zBLE=zSensor*pow(10,d_a);
tBLE=tSensor*pow(10,d_t);

//int t_i=t_f*100;
//int x_i=x_f*100;
//int y_i=y_f*100;
//int z_i=z_f*100;

//writeCharacteristicValue (Tchar, Xchar, Ychar, Zchar);

Serial.print("xBLE ");
Serial.print(xBLE);
Serial.print(" - yBLE ");
Serial.print(yBLE);
Serial.print(" - zBLE ");
Serial.print(zBLE);
Serial.print(" - tBLE ");
Serial.println(tBLE);
Serial.println("");

XChar.writeValue(xBLE);
YChar.writeValue(yBLE);
ZChar.writeValue(zBLE);
TChar.writeValue(tBLE);
//Serial.println("At Main Function");
Serial.print("XChar ");
Serial.print(XChar.value());
Serial.print(" - YChar ");
Serial.print(YChar.value());
Serial.print(" - ZChar ");
Serial.print(ZChar);
Serial.print(" - TChar ");
Serial.println(TChar.value());
Serial.println("");
Serial.println("");
//Serial.println("");
//Serial.println("");

delay(1000);

}
}
else {
delay(1000);
}
digitalWrite(LED_BUILTIN, LOW);
Serial.print("Disconnected from central: ");
Serial.println(central.address());
BLE.advertise();
}

//void read_sensor(){
//if (IMU.accelerationAvailable()) {
//IMU.readAcceleration(x_f, y_f, z_f);
//}
//t_f=HTS.readTemperature();
//
//Serial.print("x_f ");
//Serial.print(x_f);
//Serial.print(" - y_f ");
//Serial.print(y_f);
//Serial.print(" - z_f ");
//Serial.print(z_f);
//Serial.print(" - t_f ");
//Serial.println(t_f);
//Serial.println("");
////x_i=x_f*pow(10,d);
////y_i=y_f*pow(10,d);
////z_i=z_f*pow(10,d);
////t_i=t_f*pow(10,d);
//
//int t_i=t_f;
//int x_i=x_f;
//int y_i=y_f;
//int z_i=z_f;
//
//Serial.print("x_i ");
//Serial.print(x_i);
//Serial.print(" - y_i ");
//Serial.print(y_i);
//Serial.print(" - z_i ");
//Serial.print(z_i);
//Serial.print(" - t_i ");
//Serial.println(t_i);
//Serial.println("");
//}

Central

/*
  BLE_Central_Device.ino

 /*
 * Device: Arduino Nano 33 BLE Sense
 * Central
 * The values of the integrated temperature sensor and 
 * accelerometer of another Nano 33 BLE are received using BLE.
 */

#include <ArduinoBLE.h>

void setup() {
  Serial.begin(9600);
  while (!Serial);

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

  BLE.setLocalName("Arduino XYZT (Central)"); 
  Serial.println("Arduino XYZT (Central)");
  Serial.println(" ");

  //BLE.advertise();
  
}

void loop() {
  BLE.scan();
 BLEDevice peripheral = BLE.available();

 //Serial.println("- Discovering peripheral device...");

//  do
//  {
//    BLE.scanForUuid("1101");
//    peripheral = BLE.available();
//  } while (!peripheral);

  if (peripheral) {
    Serial.print("Found ");
    Serial.print(peripheral.address());
    Serial.print(" '");
    Serial.print(peripheral.localName());
    Serial.print("' ");
    Serial.print(peripheral.advertisedServiceUuid());
    Serial.println();
    
//    Serial.println("* Peripheral device found!");
//    Serial.print("* Device MAC address: ");
//    Serial.println(peripheral.address());
//    Serial.print("* Device name: ");
//    Serial.println(peripheral.localName());
//    Serial.print("* Advertised service UUID: ");
//    Serial.println(peripheral.advertisedServiceUuid());
//    Serial.println(" ");
    //BLE.stopScan();

    if (peripheral.localName() == "Arduino XYZT (peripheral)") {
      // stop scanning
      BLE.stopScan();
      
      if (peripheral.connect()) {
       Serial.println("Connected");
       } else {
       Serial.println("Failed to connect!");
       return;
      }
      
     // discover peripheral attributes
      Serial.println("Discovering attributes ...");
      if (peripheral.discoverAttributes()) {
      Serial.println("Attributes discovered");
      } else {
      Serial.println("Attribute discovery failed!");
      peripheral.disconnect();
      return;
      }
      
     // read and print device name of peripheral
     Serial.println();
     Serial.print("Device name: ");
     Serial.println(peripheral.deviceName());
     Serial.print("Appearance: 0x");
     Serial.println(peripheral.appearance(), HEX);
     Serial.println();
     }

  while (peripheral.connect()) {
  
    //BLECharacteristic TChar = peripheral.characteristic( "2104" );
      BLEService service = peripheral.service("1101");
    Serial.print("Service ");
    Serial.print(service.uuid());
    
    //BLECharacteristic characteristic = service.characteristic("2104");
    //readCharacteristicValue(characteristic);
    BLECharacteristic Tchar = service.characteristic("2104");
    //readCharacteristicValue(characteristic);
    Serial.print("\tTemperature characteristic ");
    Serial.print(Tchar.uuid());
    // check if the characteristic is readable
    if (Tchar.canRead()) {
      //read the characteristic value
      int16_t temperature = 0;
      Tchar.readValue(&temperature,2);
      Serial.print(", temperature = ");
      Serial.println((float)temperature/100.0);
    }

    
    BLECharacteristic Xchar = service.characteristic("2101");
    //readCharacteristicValue(characteristic);
    Serial.print("\tX characteristic ");
    Serial.print(Xchar.uuid());
    // check if the characteristic is readable
    if (Xchar.canRead()) {
      //read the characteristic value
      int32_t x = 0;
      Xchar.readValue(&x,4);
      Serial.print(", x = ");
      Serial.println((float)x/100.0);
    }

    BLECharacteristic Ychar = service.characteristic("2102");
    //readCharacteristicValue(characteristic);
    Serial.print("\tY characteristic ");
    Serial.print(Ychar.uuid());
    // check if the characteristic is readable
    if (Ychar.canRead()) {
      //read the characteristic value
      int32_t y = 0;
      Ychar.readValue(&y,4);
      Serial.print(", y = ");
      Serial.println((float)y/100.0);
    }

    BLECharacteristic Zchar = service.characteristic("2103");
    //readCharacteristicValue(characteristic);
    Serial.print("\tZ characteristic ");
    Serial.print(Zchar.uuid());
    // check if the characteristic is readable
    if (Zchar.canRead()) {
      //read the characteristic value
      int32_t z = 0;
      Zchar.readValue(&z,4);
      Serial.print(", z = ");
      Serial.println((float)z/100.0);
    }

    
    delay(1000);
    }


    
//    } else {
//    Serial.println("* Connection to peripheral device failed!");
//    Serial.println(" ");
//    return;
    }
    //Serial.println("Disconnected from peripheral: ");
}

void readCharacteristicValue(BLECharacteristic characteristic) {
  // print the UUID and properties of the characteristic
  Serial.print("\tCharacteristic ");
  Serial.print(characteristic.uuid());
  // check if the characteristic is readable
  if (characteristic.canRead()) {
    // read the characteristic value
    characteristic.read();

    if (characteristic.valueLength() > 0) {
      Serial.print(", value = ");
      //characteristic.value() returns byte array
      unsigned long bitShiftData = 0;
      bitShiftData = (uint32_t)characteristic.value()[3] << 24 | (uint32_t)characteristic.value()[2] << 16 | (uint32_t)characteristic.value()[1] << 8 | characteristic.value()[0];
      Serial.println(bitShiftData, DEC);
      Serial.print(bitShiftData / 100);
      Serial.print('.');
      if (bitShiftData % 100 < 10)
        Serial.print('0');
      Serial.println(bitShiftData % 100);
    }
  }
}

The peripheral code could be cleaner if I had managed to write a proper writeCharacteristicValue function.

Sometimes the reconnection works and sometimes it doesn't. Also sometimes the Attributes discovery fails, and the program stop so I still have to work to make it run until it works. I haven't tried to send the acceleration datas using floats yet.

I have 2 major issues so far:

Another thing is that I get weird values with this part of the peripheral code, so I am not sure how the value function works.

Serial.print("XChar ");
Serial.print(XChar.value());
Serial.print(" - YChar ");
Serial.print(YChar.value());
Serial.print(" - ZChar ");
Serial.print(ZChar);
Serial.print(" - TChar ");
Serial.println(TChar.value());
Serial.println("");

Thanks again @cattledog, still have a lot to do but you have helped me a lot with this first step !

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