Modification of the BLEClient program of WioTerminal to communicate with an Arduino Nano BLE

Hello,

I have been modifying the BLEClient example to get datas from an Arduino Nano 33 BLE Sense. To be clear:

  • server = Arduino nano 33 BLE Sense
  • client = Wio Terminal.

My code is working if the Serial Monitor of the Server is opend before the Client’s one. I think that I can change the scan duration if I modify the line pBLEScan->start(5, false); in the void setup. But what I would like to do is like a do while loop so that the scan is carried out until the server is detected. I guess I have to put the loop in the void setup but is there another function than the start that I could use? I have tried to put the loop in the class MyAdvertisedDeviceCallbacks, but it didn’t work (and it seems normal to me that it didn’t…)

Here is my Client code for the Wio Terminal :

   /**
 * A BLE client example that is rich in capabilities.
 * There is a lot new capabilities implemented.
 * author unknown
 * updated by chegewara
 */
 
#include "rpcBLEDevice.h"
#include <BLEScan.h>
#include <BLEAdvertisedDevice.h>
 
// The remote service we wish to connect to.
//static BLEUUID serviceUUID(0xFEE0);
static BLEUUID serviceUUID(0x1101);
// The characteristic of the remote service we are interested in.
//static BLEUUID    charUUID(0x2A2B);

static BLEUUID    XcharUUID(0x2101);
static BLEUUID    YcharUUID(0x2102);
static BLEUUID    ZcharUUID(0x2103);
static BLEUUID    TcharUUID(0x2104);
static BLEUUID    McharUUID(0x2105);
 
static boolean doConnect = false;
static boolean connected = false;
static boolean doScan = false;
//static BLERemoteCharacteristic* pRemoteCharacteristic;
static BLERemoteCharacteristic* pTChar;
static BLERemoteCharacteristic* pXChar;
static BLERemoteCharacteristic* pYChar;
static BLERemoteCharacteristic* pZChar;
static BLERemoteCharacteristic* pMChar;
static BLEAdvertisedDevice* myDevice;
uint8_t bd_addr[6] = {0xD3, 0xE3, 0xAE, 0xC0, 0xB9, 0x38};
//uint8_t bd_addr[6] = {0x7d, 0x18, 0x1b, 0xf1, 0xf7, 0x2c}; // MAC address: 2c:f7:f1:1b:18:7d
BLEAddress BattServer(bd_addr);
 
static void temperatureNotifyCallback(
  BLERemoteCharacteristic* pTChar,
  uint8_t* pTData,
  size_t length,
  bool isNotify) {
    Serial.print("Notify callback for temperature characteristic ");
    Serial.print(pTChar->getUUID().toString().c_str());
    Serial.print(" of data length ");
    Serial.println(length);
    Serial.print("data: ");
    Serial.println(*(uint8_t *)pTData);
    Serial.println(*pTData);
    Serial.println(pTData[0]);
    //Serial.println(pData);
}

static void accelerationModuleNotifyCallback(
  BLERemoteCharacteristic* pMChar,
  uint8_t* pMData,
  size_t length,
  bool isNotify) {
    Serial.print("Notify callback for acceleration for module characteristic ");
    Serial.print(pMChar->getUUID().toString().c_str());
    Serial.print(" of data length ");
    Serial.println(length);
    Serial.print("data: ");
    Serial.println(*(uint8_t *)pMData);
    Serial.println(*pMData);
    Serial.println(pMData[0]);
    //Serial.println(pData);
}
 
 
class MyClientCallback : public BLEClientCallbacks {
  void onConnect(BLEClient* pclient) {
  }
 
  void onDisconnect(BLEClient* pclient) {
    connected = false;
    Serial.println("onDisconnect");
  }
};
 
 
bool connectToServer() {
    Serial.print("Forming a connection to ");
    Serial.println(myDevice->getAddress().toString().c_str());
 
    BLEClient*  pClient  = BLEDevice::createClient();
    Serial.println(" - Created client");
 
    pClient->setClientCallbacks(new MyClientCallback());
 
 
    // Connect to the remove BLE Server.
    pClient->connect(myDevice);  // if you pass BLEAdvertisedDevice instead of address, it will be recognized type of peer device address (public or private)
    Serial.println(" - Connected to server");
 
    // Obtain a reference to the service we are after in the remote BLE server.
    BLERemoteService* pRemoteService = pClient->getService(serviceUUID);
    Serial.println(serviceUUID.toString().c_str());
        
    if (pRemoteService == nullptr) {
      Serial.print("Failed to find our service UUID: ");
      Serial.println(serviceUUID.toString().c_str());
      pClient->disconnect();
      return false;
    }
    Serial.println(" - Found our service");
 
 
    // Obtain a reference to the characteristic in the service of the remote BLE server.
    //pRemoteCharacteristic = pRemoteService->getCharacteristic(charUUID);
    pTChar = pRemoteService->getCharacteristic(TcharUUID);
    pXChar = pRemoteService->getCharacteristic(XcharUUID);
    pYChar = pRemoteService->getCharacteristic(YcharUUID);
    pZChar = pRemoteService->getCharacteristic(ZcharUUID);
    pMChar = pRemoteService->getCharacteristic(McharUUID);
    
    if (pTChar == nullptr || pMChar == nullptr) {
      Serial.print("Failed to find our characteristic UUID ");
//     Serial.println(TcharUUID.toString().c_str());
//      Serial.println(XcharUUID.toString().c_str());
//      Serial.println(YcharUUID.toString().c_str());
//      Serial.println(ZcharUUID.toString().c_str());
      pClient->disconnect();
      return false;
    }
    Serial.println(" - Found our characteristic");
 
 
    // Read the temperature characteristic value 
    if(pTChar->canRead()) {
      Serial.println(" -  can  read  start");
      std::string value = pTChar->readValue();
      Serial.print("The characteristic value was: ");
      Serial.println(value.c_str());
    }
 
    if(pTChar->canNotify())
      pTChar->registerForNotify(temperatureNotifyCallback);

/*
      // Read the X characteristic value 
    if(pXChar->canRead()) {
      Serial.println(" -  can  read  start");
      std::string value = pXChar->readValue();
      Serial.print("The characteristic value was: ");
      Serial.println(value.c_str());
    }
 
    if(pXChar->canNotify())
      pXChar->registerForNotify(notifyCallback);

      // Read the Y characteristic value 
    if(pYChar->canRead()) {
      Serial.println(" -  can  read  start");
      std::string value = pYChar->readValue();
      Serial.print("The characteristic value was: ");
      Serial.println(value.c_str());
    }
 
    if(pYChar->canNotify())
      pYChar->registerForNotify(notifyCallback);

      // Read the Z characteristic value 
    if(pZChar->canRead()) {
      Serial.println(" -  can  read  start");
      std::string value = pZChar->readValue();
      Serial.print("The characteristic value was: ");
      Serial.println(value.c_str());
    }
 
    if(pZChar->canNotify())
      pZChar->registerForNotify(notifyCallback);
      */

      // Read the acceleration module characteristic value 
    if(pMChar->canRead()) {
      Serial.println(" -  can  read  start");
      std::string value = pMChar->readValue();
      Serial.print("The acceleration characteristic value was: ");
      Serial.println(value.c_str());
    }
 
    if(pMChar->canNotify())
      pMChar->registerForNotify(accelerationModuleNotifyCallback);
 
    connected = true;
    return true;
}
/**
 * Scan for BLE servers and find the first one that advertises the service we are looking for.
 * Also in BLEscan example but with a shorter onresult
 */
class MyAdvertisedDeviceCallbacks: public BLEAdvertisedDeviceCallbacks { // crée une classe MyAdvertisedDeviceCallbacks qui hérite de la classe BLEAdvertisedDeviceCallbacks
 /**
   * Called for each advertising BLE server.
   */
  void onResult(BLEAdvertisedDevice advertisedDevice) {
   
      Serial.print("BLE Advertised Device found: ");
      Serial.println(advertisedDevice.toString().c_str()); 
 
    // We have found a device, let us now see if it contains the service we are looking for.
    //int memcmp ( const void * ptr1, const void * ptr2, size_t num ); 
    //: Compares the first num bytes of the block of memory pointed by ptr1 to the first num bytes pointed by ptr2, 
    //returning zero if they all match or a value different from zero representing which is greater if they do not.
    if (memcmp(advertisedDevice.getAddress().getNative(),BattServer.getNative(), 6) == 0) {
      Serial.print("BATT Device found: ");
      Serial.println(advertisedDevice.toString().c_str());
      BLEDevice::getScan()->stop();
      Serial.println("new BLEAdvertisedDevice");
      myDevice = new BLEAdvertisedDevice(advertisedDevice);
      Serial.println("new BLEAdvertisedDevice done");
      doConnect = true;
      doScan = true;    
  } // onResult
  }
}; // MyAdvertisedDeviceCallbacks
 
 
void setup() {
  Serial.begin(115200);
  while(!Serial){};
  delay(2000);
  Serial.println("Starting Arduino BLE Client application...");
  BLEDevice::init("");
 
  // Retrieve a Scanner and set the callback we want to use to be informed when we
  // have detected a new device.  Specify that we want active scanning and start the
  // scan to run for 5 seconds.
  BLEScan* pBLEScan = BLEDevice::getScan(); // get scanner from our client device
  pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks()); // behaviour of the scanner each time it find another bluetooth device
  //setAdvertisedDeviceCallbacks, setInterval, setWindow, setActiveScan methods from the librairy BLEscan
  pBLEScan->setInterval(1349); // period between 2 active scans
  pBLEScan->setWindow(449); // active scan time range
  pBLEScan->setActiveScan(true);//beginning of the scan
  pBLEScan->start(5, false);
} // End of setup.
 
 
// This is the Arduino main loop function.
void loop() {
 
  // If the flag "doConnect" is true then we have scanned for and found the desired
  // BLE Server with which we wish to connect.  Now we connect to it.  Once we are 
  // connected we set the connected flag to be true.
  if (doConnect == true) {//static boolean initialized as false
    if (connectToServer()) {
      Serial.println("We are now connected to the BLE Server.");
    } else {
      Serial.println("We have failed to connect to the server; there is nothin more we will do.");
    }
    doConnect = false;
  }
  Serial.println(".");
  delay(1000);
} // End of loop

Here is the code on the Arudino Nano BLE 33 Sense (server):
/*
* 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=1; //number of decimal to keep for the accelerometer
int const d_t=0; //number of decimal to keep for the temperature
int const d_m=2*d_a; //number of decimal to keep for the temperature

//float values read by the sensor
float xSensor=0;
float ySensor=0;
float zSensor=0;
float mSensor=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 mBLE=mSensor*pow(10,d_m);
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");
//BLEService SensorService("FEE0");
BLEUnsignedIntCharacteristic XChar("2101", BLERead | BLENotify);
BLEUnsignedIntCharacteristic YChar("2102", BLERead | BLENotify);
BLEUnsignedIntCharacteristic ZChar("2103", BLERead | BLENotify);
BLEUnsignedIntCharacteristic TChar("2104", BLERead | BLENotify);
BLEUnsignedIntCharacteristic MChar("2105", BLERead | BLENotify);
//BLEUnsignedIntCharacteristic TChar("2A2B", 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(MChar);
SensorService.addCharacteristic(TChar);
BLE.addService(SensorService);

XChar.writeValue(xBLE);
YChar.writeValue(yBLE);
ZChar.writeValue(zBLE);
MChar.writeValue(mBLE);
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);
}
mSensor=xSensor*xSensor+ySensor*ySensor+zSensor*zSensor;
tSensor=HTS.readTemperature();

Serial.print("xSensor ");
Serial.print(xSensor);
Serial.print(" - ySensor ");
Serial.print(ySensor);
Serial.print(" - zSensor ");
Serial.print(zSensor);
Serial.print(" - mSensor ");
Serial.print(mSensor);
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);
mBLE=zSensor*pow(10,d_m);
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(" - mBLE ");
Serial.print(mBLE);
Serial.print(" - tBLE ");
Serial.println(tBLE);
Serial.println("");

XChar.writeValue(xBLE);
YChar.writeValue(yBLE);
ZChar.writeValue(zBLE);
MChar.writeValue(mBLE);
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(" - MChar ");
Serial.print(MChar);
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("");
//}

I would be very grateful for any advise.

Nobody has tried something like what I am looking for?

I have also tried to put the pBLEScan->start in the void loop but i am getting some ‘pBLEscan was not declared in this scope’

/**
 * A BLE client example that is rich in capabilities.
 * There is a lot new capabilities implemented.
 * author unknown
 * updated by chegewara
 */
 
#include "rpcBLEDevice.h"
#include <BLEScan.h>
#include <BLEAdvertisedDevice.h>
#include"TFT_eSPI.h"
TFT_eSPI tft;
 
// The remote service we wish to connect to.
//static BLEUUID serviceUUID(0xFEE0);
static BLEUUID serviceUUID(0x1101);
// The characteristic of the remote service we are interested in.
//static BLEUUID    charUUID(0x2A2B);

static BLEUUID    XcharUUID(0x2101);
static BLEUUID    YcharUUID(0x2102);
static BLEUUID    ZcharUUID(0x2103);
static BLEUUID    TcharUUID(0x2104);
static BLEUUID    McharUUID(0x2105);
 
static boolean doConnect = false;
static boolean connected = false;
static boolean doScan = false;
//static BLERemoteCharacteristic* pRemoteCharacteristic;
static BLERemoteCharacteristic* pTChar;
static BLERemoteCharacteristic* pXChar;
static BLERemoteCharacteristic* pYChar;
static BLERemoteCharacteristic* pZChar;
static BLERemoteCharacteristic* pMChar;
static BLEAdvertisedDevice* myDevice;
uint8_t bd_addr[6] = {0xD3, 0xE3, 0xAE, 0xC0, 0xB9, 0x38};
//uint8_t bd_addr[6] = {0x7d, 0x18, 0x1b, 0xf1, 0xf7, 0x2c}; // MAC address: 2c:f7:f1:1b:18:7d
BLEAddress BattServer(bd_addr);

float tmp_T(0),deltaTmp_T(0);
 
static void temperatureNotifyCallback(
  BLERemoteCharacteristic* pTChar,
  uint8_t* pTData,
  size_t length,
  bool isNotify) {
    Serial.print("Notify callback for temperature characteristic ");
    Serial.print(pTChar->getUUID().toString().c_str());
    Serial.print(" of data length ");
    Serial.println(length);
    Serial.print("data: ");
    Serial.println(*(uint8_t *)pTData);
    Serial.println(*pTData);
    Serial.println(pTData[0]);

    tft.fillRect(0, 40, 100, 30, TFT_WHITE);
    tft.drawString(String(*pTData), 0, 40);

    deltaTmp_T=millis()-tmp_T;
    Serial.print("deltaTmp_T:");
    Serial.print(deltaTmp_T);
    Serial.println("ms");
    tmp_T=millis();
    //Serial.println(pData);
}

static void accelerationModuleNotifyCallback(
  BLERemoteCharacteristic* pMChar,
  uint8_t* pMData,
  size_t length,
  bool isNotify) {
    Serial.print("Notify callback for acceleration for module characteristic ");
    Serial.print(pMChar->getUUID().toString().c_str());
    Serial.print(" of data length ");
    Serial.println(length);
    Serial.print("data: ");
    Serial.println(*(uint8_t *)pMData);
    Serial.println(*pMData);
    Serial.println(pMData[0]);
    //Serial.println(pData);

//fillRect(int32_t x, int32_t y, int32_t w, int32_t h, uint32_t color);
    tft.fillRect(0, 110, 100, 30, TFT_WHITE);
    tft.drawString(String(*pMData), 0, 110);
}
 
 
class MyClientCallback : public BLEClientCallbacks {
  void onConnect(BLEClient* pclient) {
  }
 
  void onDisconnect(BLEClient* pclient) {
    connected = false;
    Serial.println("onDisconnect");
  }
};
 
 
bool connectToServer() {
    Serial.print("Forming a connection to ");
    Serial.println(myDevice->getAddress().toString().c_str());
 
    BLEClient*  pClient  = BLEDevice::createClient();
    Serial.println(" - Created client");
 
    pClient->setClientCallbacks(new MyClientCallback());
 
 
    // Connect to the remove BLE Server.
    pClient->connect(myDevice);  // if you pass BLEAdvertisedDevice instead of address, it will be recognized type of peer device address (public or private)
    Serial.println(" - Connected to server");
 
    // Obtain a reference to the service we are after in the remote BLE server.
    BLERemoteService* pRemoteService = pClient->getService(serviceUUID);
    Serial.println(serviceUUID.toString().c_str());
        
    if (pRemoteService == nullptr) {
      Serial.print("Failed to find our service UUID: ");
      Serial.println(serviceUUID.toString().c_str());
      pClient->disconnect();
      return false;
    }
    Serial.println(" - Found our service");
 
 
    // Obtain a reference to the characteristic in the service of the remote BLE server.
    //pRemoteCharacteristic = pRemoteService->getCharacteristic(charUUID);
    pTChar = pRemoteService->getCharacteristic(TcharUUID);
    pXChar = pRemoteService->getCharacteristic(XcharUUID);
    pYChar = pRemoteService->getCharacteristic(YcharUUID);
    pZChar = pRemoteService->getCharacteristic(ZcharUUID);
    pMChar = pRemoteService->getCharacteristic(McharUUID);
    
    if (pTChar == nullptr || pMChar == nullptr) {
      Serial.print("Failed to find our characteristic UUID ");
//     Serial.println(TcharUUID.toString().c_str());
//      Serial.println(XcharUUID.toString().c_str());
//      Serial.println(YcharUUID.toString().c_str());
//      Serial.println(ZcharUUID.toString().c_str());
      pClient->disconnect();
      return false;
    }
    Serial.println(" - Found our characteristic");
 
 
    // Read the temperature characteristic value 
    if(pTChar->canRead()) {
      Serial.println(" -  can  read  start");
      std::string value = pTChar->readValue();
      Serial.print("The characteristic value was: ");
      Serial.println(value.c_str());
    }
 
    if(pTChar->canNotify())
      pTChar->registerForNotify(temperatureNotifyCallback);

/*
      // Read the X characteristic value 
    if(pXChar->canRead()) {
      Serial.println(" -  can  read  start");
      std::string value = pXChar->readValue();
      Serial.print("The characteristic value was: ");
      Serial.println(value.c_str());
    }
 
    if(pXChar->canNotify())
      pXChar->registerForNotify(notifyCallback);

      // Read the Y characteristic value 
    if(pYChar->canRead()) {
      Serial.println(" -  can  read  start");
      std::string value = pYChar->readValue();
      Serial.print("The characteristic value was: ");
      Serial.println(value.c_str());
    }
 
    if(pYChar->canNotify())
      pYChar->registerForNotify(notifyCallback);

      // Read the Z characteristic value 
    if(pZChar->canRead()) {
      Serial.println(" -  can  read  start");
      std::string value = pZChar->readValue();
      Serial.print("The characteristic value was: ");
      Serial.println(value.c_str());
    }
 
    if(pZChar->canNotify())
      pZChar->registerForNotify(notifyCallback);
      */

      // Read the acceleration module characteristic value 
    if(pMChar->canRead()) {
      Serial.println(" -  can  read  start");
      std::string value = pMChar->readValue();
      Serial.print("The acceleration characteristic value was: ");
      Serial.println(value.c_str());
    }
 
    if(pMChar->canNotify())
      pMChar->registerForNotify(accelerationModuleNotifyCallback);
 
    connected = true;
    return true;
    
}
/**
 * Scan for BLE servers and find the first one that advertises the service we are looking for.
 * Also in BLEscan example but with a shorter onresult
 */
class MyAdvertisedDeviceCallbacks: public BLEAdvertisedDeviceCallbacks { // crée une classe MyAdvertisedDeviceCallbacks qui hérite de la classe BLEAdvertisedDeviceCallbacks
 /**
   * Called for each advertising BLE server.
   */
  void onResult(BLEAdvertisedDevice advertisedDevice) {
    Serial.print("BLE Advertised Device found: ");
    Serial.println(advertisedDevice.toString().c_str());
 
    // We have found a device, let us now see if it contains the service we are looking for.
    //int memcmp ( const void * ptr1, const void * ptr2, size_t num ); 
    //: Compares the first num bytes of the block of memory pointed by ptr1 to the first num bytes pointed by ptr2, 
    //returning zero if they all match or a value different from zero representing which is greater if they do not.
    if (memcmp(advertisedDevice.getAddress().getNative(),BattServer.getNative(), 6) == 0) {
      Serial.print("BATT Device found: ");
      Serial.println(advertisedDevice.toString().c_str());
      BLEDevice::getScan()->stop();
      Serial.println("new BLEAdvertisedDevice");
      myDevice = new BLEAdvertisedDevice(advertisedDevice);
      Serial.println("new BLEAdvertisedDevice done");
      doConnect = true;
      doScan = true;    
  } // onResult
  }
}; // MyAdvertisedDeviceCallbacks
 
 
void setup() {
  //initialisation of the screen
  tft.begin();
  tft.setRotation(3);//
  tft.fillScreen(TFT_WHITE);
  tft.setTextSize(2);                   //sets the size of text
  tft.setTextColor(TFT_BLACK);          //sets the text colour to black
  tft.drawString("Temperature", 0, 10);
  tft.drawString("Acceleration Module", 0, 80);


  //initialisation of the serial connection
  Serial.begin(115200);
  while(!Serial){};
  //delay(2000);
  Serial.println("Starting Arduino BLE Client application...");
  BLEDevice::init("");
 
  // Retrieve a Scanner and set the callback we want to use to be informed when we
  // have detected a new device.  Specify that we want active scanning and start the
  // scan to run for 5 seconds.
  //BLEScan* pBLEScan = BLEDevice::getScan(); // get scanner from our client device
  pBLEScan = BLEDevice::getScan(); //create new scan
  pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks()); // behaviour of the scanner each time it find another bluetooth device
  //setAdvertisedDeviceCallbacks, setInterval, setWindow, setActiveScan methods from the librairy BLEscan
  pBLEScan->setInterval(1349); // period between 2 active scans
  pBLEScan->setWindow(449); // active scan time range
  pBLEScan->setActiveScan(true);//beginning of the scan
  
} // End of setup.
 
 
// This is the Arduino main loop function.
void loop() {

  // If the flag "doConnect" is true then we have scanned for and found the desired
  // BLE Server with which we wish to connect.  Now we connect to it.  Once we are 
  // connected we set the connected flag to be true.
  if (doConnect == true) {//static boolean initialized as false
    if (connectToServer()) {
      Serial.println("We are now connected to the BLE Server.");
    } else {
      Serial.println("We have failed to connect to the server; there is nothin more we will do.");
    }
    doConnect = false;

    //display time information
    

  }   else   {
     BLEScanResults foundDevices = pBLEScan->start(5, false);
     pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks());
    }

    //Serial.println(".");
  //delay(1000);
} // End of loop

In case it could help someone, here are my new programs that are working and it doesn’t need anymore that the Serial Monitor of the Arduino Nano (Server) is first launched.

On the wio Terminal (client):
/**
* A BLE client example that is rich in capabilities.
* There is a lot new capabilities implemented.
* author unknown
* updated by chegewara
*/

#include "rpcBLEDevice.h"
#include <BLEScan.h>
#include <BLEAdvertisedDevice.h>
#include"TFT_eSPI.h"
TFT_eSPI tft;
 
// The remote service we wish to connect to.
//static BLEUUID serviceUUID(0xFEE0);
static BLEUUID serviceUUID(0x1101);
// The characteristic of the remote service we are interested in.
//static BLEUUID    charUUID(0x2A2B);

static BLEUUID    TcharUUID(0x2104);

static boolean doConnect = false;
static boolean connected = false;
static boolean doScan = false;

static BLERemoteCharacteristic* pTChar;
static BLEAdvertisedDevice* myDevice;
uint8_t bd_addr[6] = {0xD9, 0x91, 0xC0, 0x66, 0xAD, 0xF9};
BLEAddress BattServer(bd_addr);

float tmp_T(0),deltaTmp_T(0);
int compteur=0;
int compteur2=0;
int compteur3=0;
 
static void temperatureNotifyCallback(
  BLERemoteCharacteristic* pTChar,
  uint8_t* pTData,
  size_t length,
  bool isNotify) {
Serial.print("Notify callback for temperature characteristic ");
Serial.print(pTChar->getUUID().toString().c_str());
Serial.print(" of data length ");
Serial.println(length);
Serial.print("data: ");
Serial.println(*(uint8_t *)pTData);

compteur3++;
Serial.print("compteur temperatureNotifyCallback \t");
Serial.println(compteur3);
//Serial.println(*pTData);
//Serial.println(pTData[0]);

tft.fillRect(0, 40, 100, 30, TFT_WHITE);
tft.drawString(String(*pTData), 0, 40);
}

class MyClientCallback : public BLEClientCallbacks {
  void onConnect(BLEClient* pclient) {
  }
 
  void onDisconnect(BLEClient* pclient) {
connected = false;
Serial.println("onDisconnect");
  }
};
 
bool connectToServer() {
Serial.println("Inside bool connectToServer ");
Serial.print("Forming a connection to ");
Serial.println(myDevice->getAddress().toString().c_str());
 
BLEClient*  pClient  = BLEDevice::createClient();
Serial.println(" - Created client");
 
pClient->setClientCallbacks(new MyClientCallback());
  
// Connect to the remove BLE Server.
pClient->connect(myDevice);  // if you pass BLEAdvertisedDevice instead of address, it will be recognized type of peer device address (public or private)
Serial.println(" - Connected to server");
 
// Obtain a reference to the service we are after in the remote BLE server.
BLERemoteService* pRemoteService = pClient->getService(serviceUUID);
Serial.println(serviceUUID.toString().c_str());
    
if (pRemoteService == nullptr) {
  Serial.print("Failed to find our service UUID: ");
  Serial.println(serviceUUID.toString().c_str());
  pClient->disconnect();
  return false;
}
Serial.println(" - Found our service");
  
// Obtain a reference to the characteristic in the service of the remote BLE server.
//pRemoteCharacteristic = pRemoteService->getCharacteristic(charUUID);
pTChar = pRemoteService->getCharacteristic(TcharUUID);

//if (pTChar == nullptr || pMChar == nullptr) {
if (pTChar == nullptr) {
  Serial.print("Failed to find our characteristic UUID ");
//     Serial.println(TcharUUID.toString().c_str());
  pClient->disconnect();
  return false;
}
Serial.println(" - Found our characteristic");
  
// Read the temperature characteristic value 
if(pTChar->canRead()) {
  Serial.println(" -  can  read  start");
  std::string value = pTChar->readValue();
  Serial.print("The characteristic value was: ");
  Serial.println(value.c_str());
}
 
if(pTChar->canNotify())
  pTChar->registerForNotify(temperatureNotifyCallback);

compteur2 ++;
Serial.print("compteur connect to server");
Serial.println(compteur2);
connected = true;
return true;
Serial.println("End of bool connectToServer ");

}// bool connectToServer
/**
 * Scan for BLE servers and find the first one that advertises the service we are looking for.
 * Also in BLEscan example but with a shorter onresult
 */
class MyAdvertisedDeviceCallbacks: public BLEAdvertisedDeviceCallbacks { // crée une classe MyAdvertisedDeviceCallbacks qui hérite de la classe BLEAdvertisedDeviceCallbacks
 /**
   * Called for each advertising BLE server.
   */
  void onResult(BLEAdvertisedDevice advertisedDevice) {
Serial.println("Inside onResult ");
Serial.print("BLE Advertised Device found: ");
Serial.println(advertisedDevice.toString().c_str());
 
// We have found a device, let us now see if it contains the service we are looking for.
//int memcmp ( const void * ptr1, const void * ptr2, size_t num ); 
//: Compares the first num bytes of the block of memory pointed by ptr1 to the first num bytes pointed by ptr2, 
//returning zero if they all match or a value different from zero representing which is greater if they do not.
if (memcmp(advertisedDevice.getAddress().getNative(),BattServer.getNative(), 6) == 0) {
  Serial.print("BATT Device found: ");
  Serial.println(advertisedDevice.toString().c_str());
  BLEDevice::getScan()->stop();
  Serial.println("new BLEAdvertisedDevice");
  myDevice = new BLEAdvertisedDevice(advertisedDevice);
  Serial.println("new BLEAdvertisedDevice done");
  doConnect = true;
  doScan = true;    
  } 
 Serial.print("doConnect status");
 Serial.println(doConnect);
  }// onResult
}; // MyAdvertisedDeviceCallbacks
 
 
void setup() {
  //initialisation of the screen
  tft.begin();
  tft.setRotation(3);//
  tft.fillScreen(TFT_WHITE);
  tft.setTextSize(2);                   //sets the size of text
  tft.setTextColor(TFT_BLACK);          //sets the text colour to black
  tft.drawString("Temperature", 0, 10);
  //tft.drawString("Acceleration Module", 0, 80);

  //initialisation of the serial connection
  Serial.begin(115200);
  while(!Serial){};
  //delay(2000);
  Serial.println("Starting Arduino BLE Client application...");
  BLEDevice::init("");
 } // End of setup.
 
 
// This is the Arduino main loop function.
void loop() {
Serial.print("inside the void loop \t");
 compteur++;
Serial.print("compteur void loop \t");
Serial.println(compteur);

Serial.print("doConnect status");
Serial.println(doConnect);

if (doConnect != true) {
// Retrieve a Scanner and set the callback we want to use to be informed when we
  // have detected a new device.  Specify that we want active scanning and start the
  // scan to run for 5 seconds.
  Serial.println("scanning");
  BLEScan* pBLEScan = BLEDevice::getScan(); // get scanner from our client device
  pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks()); // behaviour of the scanner each time it find another bluetooth device
  //setAdvertisedDeviceCallbacks, setInterval, setWindow, setActiveScan methods from the librairy BLEscan
  pBLEScan->setInterval(1349); // period between 2 active scans
  pBLEScan->setWindow(449); // active scan time range
  pBLEScan->setActiveScan(true);//beginning of the scan
  pBLEScan->start(5, false);
}
  
// If the flag "doConnect" is true then we have scanned for and found the desired
  // BLE Server with which we wish to connect.  Now we connect to it.  Once we are 
  // connected we set the connected flag to be true.

  if (doConnect == true) {//static boolean initialized as false
Serial.println("inside the if(doConnect==true) loop");

if (connectToServer()) {
  Serial.println("inside the ConnectToServer loop");
  Serial.println("We are now connected to the BLE Server.");
} else {
  Serial.println("We have failed to connect to the server; there is nothin more we will do.");
}
Serial.println("end of if connectToServer");
//doConnect = false;
//display time information
  }
  
  delay(1000);
  Serial.println("");
} // End of loop

On the Arduino Nano BLE Sense
/*
* 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_t=0; //number of decimal to keep for the temperature

float tSensor=25;

int tBLE=floor(tSensor*pow(10,d_t));

int compteur=0;

BLEService SensorService("1101");

BLEUnsignedIntCharacteristic TChar("2104", BLERead | BLENotify);

void setup() {
  IMU.begin();
  HTS.begin();
  Serial.begin(9600); 
  while (!Serial);
  
  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(TChar);
  BLE.addService(SensorService);
  
  TChar.writeValue(tBLE);
  
  BLE.advertise();
  
  Serial.println("Arduino XYZT peripheral device is now active, waiting for connections...");
}


void loop() {
 
  Serial.print("inside the void loop \t");
  compteur++;
  Serial.print("compteur void loop \t");
  Serial.println(compteur);
  BLEDevice central = BLE.central();  
  BLE.advertise();
  
  if (central) {
    Serial.print("Connected to central: ");
    Serial.print("* Device MAC address: ");
    Serial.println(central.address());
    
    digitalWrite(LED_BUILTIN, HIGH);
    
    if (central.connected()) { // doesn't work if it is a while loop
      
      tSensor=HTS.readTemperature();
      Serial.print(" tSensor /t");
      Serial.println(tSensor);
  
      tBLE=floor(tSensor*pow(10,d_t)+0.5);
      Serial.print(" tBLE ");
      Serial.println(tBLE);
      
      TChar.writeValue(tBLE);
      Serial.print(" TChar ");
      Serial.println(TChar.value());
      }
    }
  Serial.println("");
  digitalWrite(LED_BUILTIN, LOW);
  //Serial.print("Disconnected from central: ");
  //Serial.println(central.address());

  delay(1000);
}

I still have a question, when I run these codes, it looks like the TemperatureNotifyCallback function is repeated without the void loop end. Why is that?

1 Like