Nano BLE Sense with Nano IOT - can't read characteristics

So, I’m trying to read the temperature value of my Nano BLE Sense from my Nano IOT board by using BLE. I already tried all the example sketches, mixing up some code, but for some reason I just cannot read characteristics from my Nano BLE Sense…
With the nrF app however the characteristics are visible.
So I guess it has to be a trivial thing I’m just not seeing.

BLE Sense Code:

#include <ArduinoBLE.h>
#include <Arduino_HTS221.h>

BLEService environmentalService("0000181A-0000-1000-8000-00805F9B34FB");
BLEFloatCharacteristic temperatureChar("00002A6E-0000-1000-8000-00805F9B34FB", BLERead | BLENotify);

void setup() {
  Serial.begin(9600);
  while (!Serial) {
    ; // wait for serial port to connect.
  }
  if (!HTS.begin()) {
    Serial.println("Failed to initialize humidity temperature sensor!");
    while (1);
  }
  if (!BLE.begin()) {
    Serial.println("starting BLE failed!");
    while (1);
  }
  
  BLE.setLocalName("BLETest");
  BLE.setAdvertisedService(environmentalService);
  environmentalService.addCharacteristic(temperatureChar);
  BLE.addService(environmentalService);
  //temperatureChar.writeValue(0.0);
  BLE.advertise();
  Serial.println("Bluetooth device active, waiting for connections...");
}

void loop() {
  BLEDevice central = BLE.central();
  if (central)  {
      Serial.print("Connected to central: ");
      Serial.println(central.address());
      while (central.connected()) {
          float temperature = HTS.readTemperature();
          temperatureChar.writeValue(temperature);
          delay(2500);
      }
   }
}

Nano IOT code:

#include <ArduinoBLE.h>

void setup() {
  Serial.begin(9600);
  while (!Serial) {
    ; // wait for serial port to connect.
  }
  if (!BLE.begin()) {
    Serial.println("starting BLE failed!");
    while (1);
  }
  BLE.scan(true);
  //BLE.scanForUuid("0000181A-0000-1000-8000-00805F9B34FB");
}

void loop() {
  Serial.println("Looping");
  BLEDevice peripheral = BLE.available();
  if (peripheral) {
    if (peripheral.localName() = "BLETest") {
      BLE.stopScan();
      explorerPeripheral(peripheral);
      BLE.scan(true);
      //BLE.scanForUuid("0000181A-0000-1000-8000-00805F9B34FB"); 
    }
  }
  delay(5000);
}

void explorerPeripheral(BLEDevice peripheral) {
  // connect to the peripheral
  Serial.println("Connecting ...");
  if (peripheral.connect()) {
    Serial.println("Connected");
  } else {
    Serial.println("Failed to connect!");
    return;
  }

  // read and print device name of peripheral
  Serial.print("Local name: ");
  Serial.println(peripheral.localName());

  // loop the services and characteristics
  if (peripheral.hasAdvertisedServiceUuid()) {
      Serial.print("Service UUID: ");
      Serial.println(peripheral.advertisedServiceUuid());
      BLECharacteristic temperatureChar = peripheral.characteristic("00002a6e-0000-1000-8000-00805f9b34fb");
      if (!temperatureChar) {
        Serial.println("no temperature characteristic found!");
        peripheral.disconnect();
        Serial.println("Disconnected");
        return;
      } else if (!temperatureChar.canSubscribe()) {
        Serial.println("temperature characteristic is not subscribable!");
        peripheral.disconnect();
        Serial.println("Disconnected");
        return;
      } else if (!temperatureChar.subscribe()) {
        Serial.println("subscription failed!");
        peripheral.disconnect();
        Serial.println("Disconnected");
        return;
      } else {
      Serial.println("Subscribed"); //?
      }
  }

  peripheral.disconnect();
  Serial.println("Disconnected");
}

Output(I can find the service but not its characteristics):

Output nRF app:

I know it’s a lot of code ut I’m getting desperate here :D.
Any input is much appreciated.
Thank you!

One of the issues is the use of delay in the BLE Sense sketch. When I connect with the BLE Scanner app it takes a long time until the services are shown after connecting.

I have modified a sketch I have written for another post to implement an Environmental Sensing Service with Temperature and Humidity as specified by the Bluetooth org. The update rate is limited by the use of millis instead of delay. Have a look at the Files → Examples → 02. Digital → BlinkWithoutDelay for a generic example of this.

Please note that the two characteristics have been defined by Bluetooth org as different types (see notes in code) while library provides float values.

I have tested the code with the ERF Connect app on iPhone which decodes some known services. It also shows negative temperature correctly.

/*
  This example creates a BLE peripheral with a Environmental Sensing Service (ESS)
  that contains a temperature and a humidity characteristic.
  The yellow LED shows the BLE module is initialized.
  The green LED shows RSSI of zero. The more it blinks the worse the connection.

  The circuit:
  - Arduino Nano 33 BLE Sense board.

  You can use a generic BLE central app, like LightBlue (iOS and Android) or
  nRF Connect (Android), to interact with the services and characteristics
  created in this sketch.

  This example code is in the public domain.
*/

#include <ArduinoBLE.h>
#include <Arduino_HTS221.h>

//----------------------------------------------------------------------------------------------------------------------
// BLE UUIDs
//----------------------------------------------------------------------------------------------------------------------

// https://www.bluetooth.com/specifications/assigned-numbers/environmental-sensing-service-characteristics/

#define BLE_UUID_ENVIRONMENTAL_SENSING_SERVICE    "181A"
#define BLE_UUID_TEMPERATURE                      "2A6E"
#define BLE_UUID_HUMIDITY                         "2A6F"

//----------------------------------------------------------------------------------------------------------------------
// BLE
//----------------------------------------------------------------------------------------------------------------------

BLEService environmentalSensingService( BLE_UUID_ENVIRONMENTAL_SENSING_SERVICE );
BLEShortCharacteristic temperatureCharacteristic( BLE_UUID_TEMPERATURE, BLERead | BLENotify );
BLEUnsignedShortCharacteristic humidityCharacteristic( BLE_UUID_HUMIDITY, BLERead | BLENotify );

const int BLE_LED_PIN = LED_BUILTIN;
const int RSSI_LED_PIN = LED_PWR;


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

  pinMode( BLE_LED_PIN, OUTPUT );
  pinMode( RSSI_LED_PIN, OUTPUT );

  // Without Serial when using USB power bank HTS sensor seems to needs some time for setup
  delay( 10 );
  
  if ( !HTS.begin() )
  {
    Serial.println( "Failed to initialize Humidity Temperature Sensor!" );
    while ( 1 )
    {
      digitalWrite( BLE_LED_PIN, HIGH );
      delay(100);
      digitalWrite( BLE_LED_PIN, LOW );
      delay(1000);
    }
  }

  if( setupBleMode() )
  {
    digitalWrite( BLE_LED_PIN, HIGH );
  }
} // setup


void loop()
{
  static long previousMillis = 0;

  // listen for BLE peripherals to connect:
  BLEDevice central = BLE.central();

  if ( central )
  {
    Serial.print( "Connected to central: " );
    Serial.println( central.address() );

    while ( central.connected() )
    {
      long interval = 1000;
      unsigned long currentMillis = millis();
      if( currentMillis - previousMillis > interval )
      {
        previousMillis = currentMillis;

        Serial.print( "Central RSSI: " );
        Serial.println( central.rssi() );

        if( central.rssi() != 0 )
        {
          digitalWrite( RSSI_LED_PIN, LOW );

          // BLE defines Temperature UUID 2A6E Type sint16
          // Unit is in degrees Celsius with a resolution of 0.01 degrees Celsius
          int16_t temperature = round( HTS.readTemperature() * 100.0 );
          temperatureCharacteristic.writeValue( temperature );

          // BLE defines Humidity UUID 2A6F Type uint16
          // Unit is in percent with a resolution of 0.01 percent
          uint16_t humidity = round( HTS.readHumidity() * 100.0 );
          humidityCharacteristic.writeValue( humidity );
        }
        else
        {
          digitalWrite( RSSI_LED_PIN, HIGH );
        }
      } // intervall
    } // while connected

    Serial.print( F( "Disconnected from central: " ) );
    Serial.println( central.address() );
  } // if central
} // loop



bool setupBleMode()
{
  if ( !BLE.begin() )
  {
    return false;
  }

  // set advertised local name and service UUID:
  BLE.setDeviceName( "Arduino Nano 33 BLE" );
  BLE.setLocalName( "Arduino Nano 33 BLE" );
  BLE.setAdvertisedService( environmentalSensingService );

  // BLE add characteristics
  environmentalSensingService.addCharacteristic( temperatureCharacteristic );
  environmentalSensingService.addCharacteristic( humidityCharacteristic );

  // add service
  BLE.addService( environmentalSensingService );

  // set the initial value for the characeristic:
  temperatureCharacteristic.writeValue( 0 );
  humidityCharacteristic.writeValue( 0 );

  // start advertising
  BLE.advertise();

  return true;
}

Great fix!!! I didn't even pay attention to the values and the time to connect but you're completely right.
Thank you very much Klaus_K, I'm getting correct sensor values now :).

I have two questions on your code:

  • The LED_PWR variable isn't recognized. I can find it however on the PIN OUT diagram documentation, so this issue is probably related to not updating a library or the editor?
  • Strangely, when I unplug my Nano IOT board when it is connected to the BLE sense board, the while ( central.connected() ) loop isn't stopped. central.connected() returns true without the Nano IOT device even being powered => infinite loop :o . Very strange. When the BLE connection is stopped before unplugging the power, there is no issue.

I'm still working on my Nano IOT code, since the temperature characteristic still won't read (I also applied the milli's method there but no luck so far). So any suggestions are very welcome :). I will post when I find a solution.

EDIT: peripheral.serviceCount() returns 0, I'm getting closer to the problem.

rocc0:

  • Strangely, when I unplug my Nano IOT board when it is connected to the BLE sense board, the while ( central.connected() ) loop isn't stopped. central.connected() returns true without the Nano IOT device even being powered => infinite loop :o . Very strange. When the BLE connection is stopped before unplugging the power, there is no issue.

This is a know issue, which affects the Nano 33 BLE but not the Nano 33 IoT. Have a look at the following post.

rocc0:
I have two questions on your code:

  • The LED_PWR variable isn't recognized. I can find it however on the PIN OUT diagram documentation, so this issue is probably related to not updating a library or the editor?

This is defined in the pins_arduino.h file for the Arduino Nano 33 BLE.

C:\Users\UserName\AppData\Local\Arduino15\packages\arduino\hardware\mbed\1.1.4\variants\ARDUINO_NANO33BLE

It is not available for the Arduino Nano 33 IoT. The corresponding file is variant.h in

C:\Users\UserName\AppData\Local\Arduino15\packages\arduino\hardware\samd\1.8.6\variants\nano_33_iot

The example should work with the standard installation and setting the board to the Nano 33 BLE.

Here is a central example sketch that works together with my sketch from reply #1. It works with the Arduino Nano 33 BLE and Nano 33 IoT. I have chosen a longer interval for the update just to show that they can be different.

You can connect a smartphone app to the peripheral because the sketch disconnects in between. But while the smartphone app is connected there will be no output. You can only have one connection to a peripheral. When you disconnect the app the Arduino output will continue.

Right now the sketch does not use notifications. For this you would need to stay connected. For an environmental display this is not really necessary.

/*
  This example creates a BLE central that scans for a peripheral with a Environmental Sensing Service (ESS).
  If that contains temperature and humidity characteristics the values are displayed.

  The circuit:
  - Arduino Nano 33 BLE or Arduino Nano 33 IoT board.

  This example code is in the public domain.
*/

#include <ArduinoBLE.h>

//----------------------------------------------------------------------------------------------------------------------
// BLE UUIDs
//----------------------------------------------------------------------------------------------------------------------

// https://www.bluetooth.com/specifications/assigned-numbers/environmental-sensing-service-characteristics/

#define BLE_UUID_ENVIRONMENTAL_SENSING_SERVICE    "181A"
#define BLE_UUID_TEMPERATURE                      "2A6E"
#define BLE_UUID_HUMIDITY                         "2A6F"

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

  BLE.begin();

  BLE.scanForUuid( BLE_UUID_ENVIRONMENTAL_SENSING_SERVICE );
} // setup


void loop()
{
  static long previousMillis = 0;

  long interval = 5000;
  unsigned long currentMillis = millis();
  if ( currentMillis - previousMillis > interval )
  {
    previousMillis = currentMillis;

    BLEDevice peripheral = BLE.available();

    if ( peripheral )
    {
      if ( peripheral.localName() != "Arduino Nano 33 BLE" )
      {
        return;
      }

      BLE.stopScan();

      explorePeripheral( peripheral );

      BLE.scanForUuid( BLE_UUID_ENVIRONMENTAL_SENSING_SERVICE );
    }
  }
} // loop


bool explorePeripheral( BLEDevice peripheral )
{
  if ( !peripheral.connect() )
  {
    return false;
  }

  if ( !peripheral.discoverAttributes() )
  {
    peripheral.disconnect();
    return false;
  }

  BLECharacteristic temperatureCharacterisic = peripheral.characteristic( BLE_UUID_TEMPERATURE );
  if ( temperatureCharacterisic )
  {
    int16_t temperature;
    temperatureCharacterisic.readValue( temperature );
    Serial.print( "Temperature: " );
    Serial.print( temperature / 100.0 );
    Serial.println( "°C" );
  }

  BLECharacteristic humidityCharacterisic = peripheral.characteristic( BLE_UUID_HUMIDITY );
  if ( humidityCharacterisic )
  {
    uint16_t humidity;
    humidityCharacterisic.readValue( humidity );
    Serial.print( "Humidity: " );
    Serial.print( humidity / 100.0 );
    Serial.println( "%" );
  }

  peripheral.disconnect();
  return true;
} // explorePeripheral

Klaus_K:
Here is a central example sketch that works together with my sketch from reply #1. It works with the Arduino Nano 33 BLE and Nano 33 IoT. I have chosen a longer interval for the update just to show that they can be different.

Thanks a lot for following up!
I used this code, your WIFI / BLE changeover code on my Nano 33 IoT and the workaround for resetting the Arduino Nano 33 BLE by using a watchdog in the links your provided.
And... it's working :).
I just got my first temperature values in the cloud.
Thank you for making my first Arduino project an enjoyable one.