Hello,
I am working on a portable temperature and humidity sensor (ESP32 WROOM + SHT11 temperature and humidity sensor) that sends data over BLE for a few seconds and then deep-sleeps for longer periods. The sensor is on two 3.7 V batteries and my goal is to make it last 10-20 days. The client is also an ESP32 WROOM.
I've tried different coding approach and finally found something that allows for peripheral deep sleeps and connection/disconnection on the client side without crashes and loss of data.
However, I'm now facing the problem that I am not able to read the characteristics sent by the peripheral on the client side. The peripheral prints the temperature and humidity readings and sends them over BLE correctly. The client sees the peripheral, its characteristics and confirms that the characteristics can notify, but I am not able to print the content of the characteristics.
Code for the server:
#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEServer.h>
#include <BLE2902.h>
#include <SPI.h>
#include <Wire.h>
#include <SHT21.h>
//BLE server name
#define bleServerName "BME280_ESP32"
/* Define deep sleep options */
uint64_t uS_TO_S_FACTOR = 1000000; // Conversion factor for micro seconds to seconds
uint64_t TIME_TO_SLEEP = 60;
// Timer variables
unsigned long lastTime = 0;
unsigned long timerDelay = 5000;
bool deviceConnected = false;
SHT21 sht;
float t;
float h;
int timeOut;
float TcorrectionSHT21 = 0;
int BLEtries = 5;
#define SERVICE_UUID "91bad492-b950-4226-aa2b-4ede9fa42f59"
BLECharacteristic temperatureCharacteristic("cba1d466-344c-4be3-ab3f-189f80dd7518", BLECharacteristic::PROPERTY_NOTIFY);
BLEDescriptor temperatureDescriptor(BLEUUID((uint16_t)0x2902));
BLECharacteristic humidityCharacteristic("ca73b3ba-39f6-4ab3-91ae-186dc9577d99", BLECharacteristic::PROPERTY_NOTIFY);
BLEDescriptor humidityDescriptor(BLEUUID((uint16_t)0x2903));
//Setup callbacks onConnect and onDisconnect
class MyServerCallbacks : public BLEServerCallbacks {
void onConnect(BLEServer *pServer) {
deviceConnected = true;
};
void onDisconnect(BLEServer *pServer) {
deviceConnected = false;
}
};
void setup() {
Serial.begin(115200);
/* Enable Timer wake_up */
esp_sleep_enable_timer_wakeup(TIME_TO_SLEEP * uS_TO_S_FACTOR);
/* Initialise sensor */
sht.begin();
/* Initialize Bluetooth communication. */
BLEDevice::init(bleServerName);
// esp_err_t errRc = esp_ble_tx_power_set(ESP_BLE_PWR_TYPE_DEFAULT, ESP_PWR_LVL_P9);
esp_ble_tx_power_set(ESP_BLE_PWR_TYPE_ADV, ESP_PWR_LVL_P9);
esp_ble_tx_power_set(ESP_BLE_PWR_TYPE_SCAN, ESP_PWR_LVL_P3);
// Create the BLE Server
BLEServer *pServer = BLEDevice::createServer();
pServer->setCallbacks(new MyServerCallbacks());
// Create the BLE Service
BLEService *bmeService = pServer->createService(SERVICE_UUID);
/* Add characteristics for temperature and humidity. */
bmeService->addCharacteristic(&temperatureCharacteristic);
temperatureDescriptor.setValue("BME temperature");
temperatureCharacteristic.addDescriptor(&temperatureDescriptor);
bmeService->addCharacteristic(&humidityCharacteristic);
humidityDescriptor.setValue("BME humidity");
humidityCharacteristic.addDescriptor(new BLE2902());
// Start the service
bmeService->start();
// Start advertising
BLEAdvertising *pAdvertising = BLEDevice::getAdvertising();
pAdvertising->addServiceUUID(SERVICE_UUID);
pServer->getAdvertising()->start();
Serial.println("Waiting a client connection to notify...");
delay(500);
readsendTBLE();
Serial.println("DONE! Going to sleep now.");
esp_deep_sleep_start();
}
void loop() {
//Empty
}
void readsendTBLE() {
if ( deviceConnected ) {
Serial.println("Device is connected");
/* Reset counter */
timeOut = 0;
/* Stay if counter is <=5 */
while (timeOut <= BLEtries) {
t = sht.getTemperature();
h = sht.getHumidity();
static char tt[6];
dtostrf(t, 5, 1, tt);
temperatureCharacteristic.setValue(tt);
temperatureCharacteristic.notify();
Serial.print(tt);
Serial.print(", ");
delay(300);
/* Update Bluetooth characteristics with new values. */
static char hh[6];
dtostrf(h, 5, 1, hh);
humidityCharacteristic.setValue(hh);
humidityCharacteristic.notify();
Serial.print(hh);
Serial.println(" ");
timeOut++;
}
BLEDevice::getAdvertising()->stop();
}
}
Code for the client:
#include <BLEDevice.h>
static BLEUUID serviceUUID("91bad492-b950-4226-aa2b-4ede9fa42f59");
static BLEUUID charUUID("cba1d466-344c-4be3-ab3f-189f80dd7518");
uint32_t count = 0;
static boolean doConnect = false;
static boolean doScan = false;
static BLEAdvertisedDevice *myDevice;
char *OUTtemp = 0;
boolean newTemperature = false;
static BLEClient *pClient;
/* Activate notify */
const uint8_t notificationOn[] = { 0x1, 0x0 };
const uint8_t notificationOff[] = { 0x0, 0x0 };
//When the BLE Server sends a new temperature reading with the notify property
static void temperatureNotifyCallback(BLERemoteCharacteristic *pBLERemoteCharacteristic,
uint8_t *pData, size_t length, bool isNotify) {
//store temperature value
OUTtemp = (char *)pData;
newTemperature = true;
}
bool connectToServer() {
if (pClient != nullptr) {
delete pClient;
}
pClient = BLEDevice::createClient();
if (!pClient->connect(myDevice)) {
Serial.print("Failed to find our service UUID: ");
Serial.println(serviceUUID.toString().c_str());
return false;
}
BLERemoteService *pRemoteService = pClient->getService(serviceUUID);
if (pRemoteService == nullptr) {
Serial.print("Failed to find our service UUID: ");
Serial.println(serviceUUID.toString().c_str());
pClient->disconnect();
return false;
}
BLERemoteCharacteristic *pRemoteCharacteristic = pRemoteService->getCharacteristic(charUUID);
if (pRemoteCharacteristic == nullptr) {
Serial.print("Failed to find our characteristic UUID: ");
Serial.println(charUUID.toString().c_str());
pClient->disconnect();
return false;
}
if (pRemoteCharacteristic->canNotify()) {
Serial.print(" characteristic can notify UUID: ");
Serial.println(charUUID.toString().c_str());
pRemoteCharacteristic->getDescriptor(BLEUUID((uint16_t)0x2902))->writeValue((uint8_t *)notificationOn, 2, true);
pRemoteCharacteristic->registerForNotify(temperatureNotifyCallback);
}
pClient->disconnect();
return true;
}
class MyAdvertisedDeviceCallbacks : public BLEAdvertisedDeviceCallbacks {
void onResult(BLEAdvertisedDevice advertisedDevice) {
doScan = true;
if (advertisedDevice.haveServiceUUID() && advertisedDevice.isAdvertisingService(serviceUUID)) {
BLEDevice::getScan()->stop();
if (myDevice != nullptr) {
delete myDevice;
}
myDevice = new BLEAdvertisedDevice(advertisedDevice);
doConnect = true;
doScan = false;
}
}
};
void setup() {
Serial.begin(115200);
Serial.println("Starting Arduino BLE Client application...");
BLEDevice::init("");
BLEScan *pBLEScan = BLEDevice::getScan();
pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks(), true);
//pBLEScan->setInterval(1000);
//pBLEScan->setWindow(1000);
pBLEScan->setActiveScan(true);
pBLEScan->start(10, false);
}
void loop() {
if (doConnect) {
count++;
//Serial.printf("Count: %d\n", count);
//Serial.printf("Free Heap Size: %d\n", esp_get_free_heap_size());
//Serial.printf("System Free Heap Size: %d\n", system_get_free_heap_size());
//Serial.printf("Minimum Free Heap Size: %d\n", esp_get_minimum_free_heap_size());
connectToServer();
Serial.println("Temperature:");
Serial.print(OUTtemp);
Serial.println("C");
doConnect = false;
doScan = true;
} else if (doScan) {
doScan = false;
BLEDevice::getScan()->start(10, false);
}
delay(1000);
}
Anyone can give me some indications to find the problem?
Thanks,
Matteo