Sensor Issues with the Nano 33 BLE Sense

Hi, I have been setting up the Nano 33 BLE Sense for a long term experiment over several days. Generally, it is working well but I encountered some issues. I wanted to present some of them here and get a feedback whether any of you has seen similar behavior:

  1. The value of the temperature sensor is about 5°C higher than the actual temperature (controlled with other temperature sensors). It seems like that board is heating up to sensor when in use.

  2. I'm using the board in a container with water. That means the humidity is close to 100%. At the start of the measurement the humidity sensor shows the correct humidity and starts decreasing over time to about 70% relative humidity. Obviously this is a rough environment for sensors anyway.

  3. After a few hours (10-24h) of constant measurement (every 10s) the sensor values jump to a fix number and don't change anymore. These values are always the same: 0 for pressure, 21.06 for temperature and 28.96 for humidity. The board is still functional and talks to my phone via BLE but the sensor values don't change.
    This is how I read the sensors:

void loop(){

    BLE.poll();

    .
    .
    .

    data[2] = HTS.readHumidity() * 100;
    delay(1);
    data[3] = HTS.readTemperature() * 100;
    delay(1);
    data[4] = BARO.readPressure() * 100;
    delay(1);

    int failsafe = 0;       // make sure we don't get stuck in while loop if color sensor breaks
    while (!APDS.colorAvailable() && failsafe < 5) {
      delay(5);
      failsafe++;
    }
    APDS.readColor(r, g, b);
    .
    .
    .
    delay(100); // this brings down the power consumption by ca. 40%
}

Thanks a lot.

1 Like

There's a whole thread on that already. I hope it helps.

https://forum.arduino.cc/index.php?topic=640677.0

Thanks. It seems to be a common problem with these sensors.
This doesn't explain the locking of the sensor values after a certain amount of time, though.

gbar90:
This doesn't explain the locking of the sensor values after a certain amount of time, though.

Could you please post your entire test sketch so I can run it on my board?

Right now you read your sensors about 10x a second and not every 10 seconds, but maybe there is some additional stuff in your sketch.

If you read the sensor too often you can run into issues. Unless you check the source code of the library you do not know whether it is safe to read the sensor at this speed. There are different modes allowed by the device but they need to be configured. You do not know whether the library does that. I doubt it.

Thanks for looking into that.

/*
  This code works with Arduino Nano 33 BLE sense and
  reads data from the following sensors:

  APDS9960
   - color RGB (red, green, blue)

  LPS22HB - Pressure

  HTS221 - temperature and humidity sensor

  BB_PEGS - humidity and spoilage

  BME280 breakout board:
        If using I2C:
        Sensor - Arduino
        Vin    -   3.3V
        GND    -   GND
        SDA    -   SDA (A4 on Arduino Nano)
        SCL    -   SCL (A5 on Arduino Nano)
*/

// Sensors
#include <Arduino_LPS22HB.h>
#include <Arduino_HTS221.h>
#include <Arduino_APDS9960.h>
// BME280
#include <Wire.h>
#include <SPI.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>
Adafruit_BME280 bme;

// BLE
#include <ArduinoBLE.h>

BLEService sensorService("19B10010-E8F2-537E-4F6C-D104768A1214"); // create service

// create characteristics and allow remote device to read and get notification
BLEIntCharacteristic sensorCharacteristic("19B10011-E8F2-537E-4F6C-D104768A1214", BLERead | BLENotify);
BLEIntCharacteristic sensor2Characteristic("19B10012-E8F2-537E-4F6C-D104768A1214", BLERead | BLENotify);
BLEIntCharacteristic humCharacteristic("19B10013-E8F2-537E-4F6C-D104768A1214", BLERead | BLENotify);
BLEIntCharacteristic tempCharacteristic("19B10014-E8F2-537E-4F6C-D104768A1214", BLERead | BLENotify);
BLEIntCharacteristic pressureCharacteristic("19B10015-E8F2-537E-4F6C-D104768A1214", BLERead | BLENotify);
BLEIntCharacteristic lightCharacteristic("19B10016-E8F2-537E-4F6C-D104768A1214", BLERead | BLENotify);
BLEIntCharacteristic hum2Characteristic("19B10017-E8F2-537E-4F6C-D104768A1214", BLERead | BLENotify);
BLEIntCharacteristic temp2Characteristic("19B10018-E8F2-537E-4F6C-D104768A1214", BLERead | BLENotify);
BLEIntCharacteristic pressure2Characteristic("19B10019-E8F2-537E-4F6C-D104768A1214", BLERead | BLENotify);



const int bufferSize = 20; // For Bluetooth 4.0 https://punchthrough.com/maximizing-ble-throughput-part-3-data-length-extension-dle-2/
byte ByteArr[bufferSize];


const int adcPin[] = {A0, A1};
int noMeasure = 100;
int measureInt = 10000;
int r = 0, g = 0, b = 0;
unsigned long lastUpdate = 0;
int data[9] = {0};

void setup() {
  // Start I2C
  Wire.begin();
  // Start Serial
  Serial.begin(9600);
//    while (!Serial) {
//      ; // wait for serial port to connect. Needed for native USB port only
//    }

  digitalWrite(LED_PWR, LOW);
  Serial.println("Serial started.");
  initBLEcom();

  initSensors();


  Serial.println("Sensors connected and bluetooth device active, waiting for connections...");

}

void loop() {

  BLE.poll();



  // Millis() number will overflow (go back to zero), after approximately 50 days.!!!
  if (millis() - lastUpdate > measureInt) {
    lastUpdate = millis();

    data[0] = measurePEGS(0) * 10;
    delay(1);
    data[1] = measurePEGS(1) * 10;
    delay(1);
    data[2] = HTS.readHumidity() * 100;
    delay(1);
    data[3] = HTS.readTemperature() * 100;
    delay(1);
    data[4] = BARO.readPressure() * 100;
    delay(1);

    int failsafe = 0;       // make sure we don't get stuck in while loop if color sensor breaks
    while (!APDS.colorAvailable() && failsafe < 5) {
      delay(5);
      failsafe++;
    }
    APDS.readColor(r, g, b);
    data[5] = r + g + b;
    delay(1);
    data[6] = bme.readHumidity() * 100;
    delay(1);
    data[7] = bme.readTemperature() * 100;
    delay(1);
    data[8] = bme.readPressure();
    delay(1);



    for (int kk = 0; kk < 9; kk++) {
      Serial.print("Data "); Serial.print(kk); Serial.print(": "); Serial.print(data[kk]); Serial.print(" | ");

    }
    Serial.println("");

    sensorCharacteristic.writeValue(data[0]);
    sensor2Characteristic.writeValue(data[1]);
    humCharacteristic.writeValue(data[2]);
    tempCharacteristic.writeValue(data[3]);
    pressureCharacteristic.writeValue(data[4]);
    lightCharacteristic.writeValue(data[5]);
    hum2Characteristic.writeValue(data[6]);
    temp2Characteristic.writeValue(data[7]);
    pressure2Characteristic.writeValue(data[8]);

  }
  delay(100);
}



float measurePEGS(int position) {
  float voltage = 0.0;
  float sum = 0.0;
  for (int jj = 0; jj < noMeasure; jj++) {
    sum = sum + analogRead(adcPin[position]);
    delay(1);
  }
  voltage = sum / noMeasure;
  return voltage;

}

void initBLEcom() {

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

    while (1);
  }

  // set the local name peripheral advertises
  BLE.setLocalName("BearCub-0002");
  // set the UUID for the service this peripheral advertises:
  BLE.setAdvertisedService(sensorService);

  // add the characteristics to the service
  sensorService.addCharacteristic(sensorCharacteristic);
  sensorService.addCharacteristic(sensor2Characteristic);
  sensorService.addCharacteristic(humCharacteristic);
  sensorService.addCharacteristic(tempCharacteristic);
  sensorService.addCharacteristic(pressureCharacteristic);
  sensorService.addCharacteristic(lightCharacteristic);
  sensorService.addCharacteristic(hum2Characteristic);
  sensorService.addCharacteristic(temp2Characteristic);
  sensorService.addCharacteristic(pressure2Characteristic);

  // add the service
  BLE.addService(sensorService);

  sensorCharacteristic.writeValue(0);
  sensor2Characteristic.writeValue(0);
  humCharacteristic.writeValue(0);
  tempCharacteristic.writeValue(0);
  pressureCharacteristic.writeValue(0);
  lightCharacteristic.writeValue(0);
  hum2Characteristic.writeValue(0);
  temp2Characteristic.writeValue(0);
  pressure2Characteristic.writeValue(0);

  // start advertising
  BLE.advertise();

  // assign event handlers for connected, disconnected to peripheral
  BLE.setEventHandler(BLEConnected, blePeripheralConnectHandler);
  BLE.setEventHandler(BLEDisconnected, blePeripheralDisconnectHandler);

}

void initSensors() {
  if (!APDS.begin()) {
    Serial.println("Error initializing APDS9960 sensor.");
    while (true); // Stop forever
  }
  if (!HTS.begin()) {
    Serial.println("Failed to initialize humidity temperature sensor!");
    while (1);
  }
  if (!BARO.begin()) {
    Serial.println("Failed to initialize pressure sensor!");
    while (1);
  }
  if (!IMU.begin()) {
    Serial.println("Failed to initialize IMU!");
    while (1);
  }
  if (!bme.begin()) {
    Serial.println("Could not find a valid BME280 sensor, check wiring!");
    while (1);
  }


  pinMode(adcPin[0], INPUT);
  pinMode(adcPin[1], INPUT);

}

// callback invoked when central connects
void blePeripheralConnectHandler(BLEDevice central) {
  // central connected event handler
  Serial.print("Connected event, central: ");
  Serial.println(central.address());
  BLE.stopAdvertise();
  Serial.println("Advertising stopped");
}

void blePeripheralDisconnectHandler(BLEDevice central) {
  // central disconnected event handler
  Serial.print("Disconnected event, central: ");
  Serial.println(central.address());
//  BLE.advertise();
//  Serial.println("Advertising started");
  
}

I setup a board and will let you know what happens with the sensors.

While we wait, I have a few questions/comments and hints.

  • the barometric pressure reading of the BARO vs BME was different by a factor of 10. I had to add a divide by 10 to the BME to get the same value between them. Maybe my BME sensor is different.

  • I had to remove the IMU begin because the header file was missing, and you did not use the IMU.

  • would it make sense to use standard UUID for the temperature, humidity and pressure to make it easier to debug with BLE apps? Some apps can decode the standard UUIDs.

  • you can use static variables in functions to avoid having all your global variables visible everywhere and it’s easier to copy code from one project to another e.g. you could use the following line inside the loop function

static unsigned long lastUpdate = 0;

  • is there a reason you used delay all over your code? It will make your sketch less responsive. On the Arduino Nano 33 BLE you can make use of delay for sleep mode but it’s probably best to do this in one place, when you are sure you have time.

  • why did you use the array to store all your data? It makes your code harder to read and could introduce errors if you mix up the index. The following code looks clearer and uses less memory.

int humidity = HTS.readHumidity() * 100;
humCharacteristic.writeValue(humidity);

Hi Klaus, wow thanks for all the feedback. I'll try and address your points.

  • the barometric pressure reading of the BARO vs BME was different by a factor of 10. I had to add a divide by 10 to the BME to get the same value between them. Maybe my BME sensor is different.

Yes, I think that's just how the BME gives you the pressure. I take care of all the adjustments in the android app.

  • I had to remove the IMU begin because the header file was missing, and you did not use the IMU.

Sorry for that, I was initially testing the IMU but then removed it.

  • would it make sense to use standard UUID for the temperature, humidity and pressure to make it easier to debug with BLE apps? Some apps can decode the standard UUIDs.

I didn't think of that. I might actually look into that.

  • you can use static variables in functions to avoid having all your global variables visible everywhere and it's easier to copy code from one project to another e.g. you could use the following line inside the loop function

Thanks for the tip.

  • is there a reason you used delay all over your code? It will make your sketch less responsive. On the Arduino Nano 33 BLE you can make use of delay for sleep mode but it's probably best to do this in one place, when you are sure you have time.

I had the impression the sensors would fail less if I used delay after each sensor measurement. I'm also looking into using as little power as possible, sending the board to sleep often, but I guess that's another story.

  • why did you use the array to store all your data? It makes your code harder to read and could introduce errors if you mix up the index. The following code looks clearer and uses less memory.

I used this code in a different way previously. There is no reason for the array anymore.

I had the board running for a little over 40 hours now and the sensor is still working as expected. I had the board powered by a USB power supply and connected to it every now and then reading the values with a BLE app on my smart phone.

So, this is ether an issue with your board, the environment or it can take a lot longer on other boards. 100% humidity is probably out of spec for a board like Arduino. There is no protection against moisture getting into the PCB or some components.

The HTS221 sensor itself does not have a reset logic. You could simply try and reset your Arduino by pressing the button once and see what happens.

  • If that works you could simply add some code that restarts the sensor from time to time. This will cost you a few cycles only, so should not be an issue.
  • If the sensor is still stuck, you could try to power cycle the sensors. There is a pin defined in the pins_arduino.h

#define PIN_ENABLE_SENSORS_3V3 (32u)

So, this should power down the sensors and writing HIGH should power them up again.

digitalWrite( PIN_ENABLE_SENSORS_3V3, LOW );

I doubt that is the case because I could not find an errata sheet on the ST web page. The sensor is a few years old and this issue would have been found by large volume users.

Just FYI, there is an issue with the BLE that when you lose the connection the blePeripheralDisconnectHandler is not triggered and your BLE will stop working. So, when you connect with your phone from too far away or you walk away while connected you will need to reset your Arduino.

Hi Klaus, thanks for the effort.

I was testing the board for a few days in my fridge and the sensors worked fine. It really seems to be the high humidity. When I restart the board, the sensors keep working for a few more hours, even at high humidity though.
So I think I am going for either one of the following solutions:

  • Add some code to check for the sensor values to drop to the static values mentioned above (they are always the same values). If detected restart the board.

  • Go for the Arduino Nano BLE and add a BME280 sensor board. The combination is actually cheaper and I have some experience with the BME sensors. They are reliable.

Just FYI, there is an issue with the BLE that when you lose the connection the blePeripheralDisconnectHandler is not triggered and your BLE will stop working. So, when you connect with your phone from too far away or you walk away while connected you will need to reset your Arduino.

This is actually a bit of an issue. Is there a work around?

gbar90:
This is actually a bit of an issue. Is there a work around?

I do not believe there is a work around for the Arduino Nano 33 BLE. I think this is not an issue on the Arduino Nano 33 IoT. But my IoT board is running another test currently. I could try this again in a day or two.

gbar90:
Hi Klaus, thanks for the effort.

  • Go for the Arduino Nano BLE and add a BME280 sensor board. The combination is actually cheaper and I have some experience with the BME sensors. They are reliable.

I actually wonder how can this be cheaper. At least in Europe, the Nano BLE goes for about 20 euros, plus 15 for the BME280 sensor (if you're lucky). However, the Nano BLE Sense goes for about 30.

filipeteixeira:
I actually wonder how can this be cheaper. At least in Europe, the Nano BLE goes for about 20 euros, plus 15 for the BME280 sensor (if you're lucky). However, the Nano BLE Sense goes for about 30.

I would agree with gbar90. Having two separate boards looks like the better solution.

You can get 3x BME280 on Amazon for (DE) 14.99, (ES) 16.49 (IT) 17.50, (FR) 17.99 Euro.

You can move the sensor away from the Arduino (reducing heating) and expose it to the environment while you keep the Arduino sealed in. I opened a old wireless sensor and it used cheap sensors connected trough ~ 3cm wires.

Klaus_K:
I would agree with gbar90. Having two separate boards looks like the better solution.

You can get 3x BME280 on Amazon for (DE) 14.99, (ES) 16.49 (IT) 17.50, (FR) 17.99 Euro.

You can move the sensor away from the Arduino (reducing heating) and expose it to the environment while you keep the Arduino sealed in. I opened a old wireless sensor and it used cheap sensors connected trough ~ 3cm wires.

Fair but then you lose all the other sensors. I think that in the end if you want all the sensors in the BLE Sense, you need much more than just the BME280.

Also the IOT is BLE 4.2 while the Sense 5.0 and the Sense seems to be faster as well. https://www.arrow.com/en/research-and-events/articles/arduino-every-vs-arduino-33-arduino-boards-comparison.

So in the end I feel that the Sense is the cheapest you can get, unless I'm missing something here.