Low power BLE data logging

Hi everyone,
i recently got an Arduino nano 33 IoT and I wanted to experiment on Bluetooth Low Energy.
My expertiment consisted on hooking up to the arduino some temperature and pressure sensors and logging data every minute using BLE connectivity offered by the board.

I modified the BatteryLevel.ino example in order to retrive temperature and pressure from a BMP280 and transmit them via BLE.

The point was that if I try to put into sleep the board after it transmits data I am not able to hold the connection from the peripheral device.

My goal is to battery power that device, when connected to a 3.7 V battery it draws ~ 50 mA.

Code is following,
Thank you in advance for the advices!



#include <ArduinoBLE.h>
#include <Wire.h>
#include <SPI.h>
#include <Adafruit_BMP280.h>


#define SERVICE_UUID "517c08ac-f21c-4f78-b7f4-4d34f151f6ac"
#define T_UUID "8dbff573-85e7-4d42-97a1-f778e10f988a"
#define P_UUID "0b7a7690-c3e5-4952-816d-680fcc46e3ce"
#define DELAY 2000;

/*
 * Ble services setup
 */

BLEService WeatherLogs(SERVICE_UUID);
BLEFloatCharacteristic Pressure(P_UUID, BLERead | BLENotify);
BLEFloatCharacteristic Temperature(T_UUID, BLERead | BLENotify);

/**
 * Barometric pressure and temperature sensor setup
 */

Adafruit_BMP280 bmp; // use I2C interface
Adafruit_Sensor *bmp_temp = bmp.getTemperatureSensor();
Adafruit_Sensor *bmp_pressure = bmp.getPressureSensor();

float T = 0;
float P = 0;

long prevMillis = 0;
long currMillis{0};
long interval = 2000;

void blink_bl(unsigned int d){
  delay(d);
  digitalWrite(LED_BUILTIN, LOW);
  delay(d);
  digitalWrite(LED_BUILTIN, HIGH);
  
}

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

  pinMode(LED_BUILTIN, OUTPUT);  

  if (!BLE.begin()) {
    digitalWrite(LED_BUILTIN, HIGH);
    //Serial.println("starting BLE failed!");
    while (1);
  }

  unsigned status;
  status = bmp.begin(BMP280_ADDRESS_ALT, BMP280_CHIPID);

  if(!status){
    blink_bl(200);
  }

  bmp.setSampling(Adafruit_BMP280::MODE_NORMAL,     /* Operating Mode. */
                Adafruit_BMP280::SAMPLING_X2,     /* Temp. oversampling */
                Adafruit_BMP280::SAMPLING_X16,    /* Pressure oversampling */
                Adafruit_BMP280::FILTER_X16,      /* Filtering. */
                Adafruit_BMP280::STANDBY_MS_500); /* Standby time. */

  BLE.setLocalName("Pressure_Temp_Sensor");
  BLE.setAdvertisedService(WeatherLogs);
  WeatherLogs.addCharacteristic(Pressure);
  WeatherLogs.addCharacteristic(Temperature);
  BLE.addService(WeatherLogs);

  BLE.advertise();
  //Serial.println("Waiting for connection");
  digitalWrite(LED_BUILTIN, LOW);


}

void loop() {
  BLEDevice central = BLE.central();
  if(central){
    //Serial.print("Connected to central, MAC : ");
    //Serial.println(central.address());
    //digitalWrite(LED_BUILTIN, HIGH);
    BLE.stopAdvertise();
    while(central.connected()){
      
      //updateReadings();
      
      currMillis = millis();
      long delta = currMillis - prevMillis;
      if(delta >= interval){
        prevMillis = currMillis;
        updateReadings();
      }

      /*
       * if I change the previous code to 
       * updateReadings();
       * delay(60000); // or other sleep functions 
       * 
       * it stops working
       */
      
    }
    BLE.advertise();
  digitalWrite(LED_BUILTIN, LOW);

  }
  
}

void readFromSensors(){

  sensors_event_t temp_event, pressure_event;
  bmp_temp->getEvent(&temp_event);
  bmp_pressure->getEvent(&pressure_event);
  T = temp_event.temperature - 1.0f;
  P = pressure_event.pressure;

}

void updateReadings(){
  readFromSensors();
  Pressure.writeValue(P);
  Temperature.writeValue(T);  
}

Welcome to the forum.

Here are a few tips for your project

  • I recommend avoiding floating point for characteristics and for public interfaces in general. There are multiple floating point formats so your code will be less portable. The BLE SiG has shown how to do this better by using integer with a known exponent. Here is an example I posted a while ago that shows how and a few other useful things.

https://forum.arduino.cc/t/bluetooth-communications/902610/2

  • The Arduino Nano 33 IoT is not designed for low power BLE apps. The NINA module also supports WiFi and therefore is more power hungry than pure BLE solutions can be. The Arduino Nano 33 BLE with the nRF52840 is likely a better choice. There have been discussions about low power in the past. Have a look trough the Nano 33 sub forums. Google works nicely with site:arduino.cc filtering everything else.

  • The power circuit of the Arduino is not optimal for low power. On the Arduino Nano 33 BLE it can be disabled. Then you can use a 3V battery directly. Your 3.7V battery will not work because the voltage is too high.

BLE does not transmit data at the application level. When you update a characteristic in a peripheral/server device you just update internal data and that is it. The central/client decides when it wants to read data. Your sketch needs to talk to the BLE module on a regular basis to ensure it reacts to communication outside. So, if you sleep then only for very short amounts of time.

  • You must not use delay to control the flow of your application. Delay should only be used once in your code to make use of sleep when you are certain that you can do it. Otherwise avoid delay, while or waiting for things. Make sure your loop runs as often as possible. Handle timing by using millis() and status variables. This will ensure your communication stack can be called as often as necessary.

A BLE peripheral won't really be "always-on" most of the time, but rather in a deep sleep mode. In this state, only the most essential parts of the peripheral are active (it'll depend on the needs of the application, but it will usually be some low power timers or something like that). While on dsm, the peripheral will draw an order of magnitude less current (uA, not mA).

moderator edit: spam removed

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