esp32 BLE deep sleep + notifyCallback not being hit

pipe2path
Posts: 3
Joined: Sun May 17, 2020 9:22 pm

esp32 BLE deep sleep + notifyCallback not being hit

Postby pipe2path » Sun May 17, 2020 9:40 pm

Hi,
I have 2 ESP32s, a server and a client in the Arduino platform. The notifyCallback works fine when a sensor message is sent from the server code in the loop(). However, I plan to use the server (sensor) ESP32 in a battery operated scenario. I'd like to send the sensor value, then put the ESP32 into deep sleep mode. When I moved the code out of the loop(), to be in the setup() with deep sleep functionality, I don't get a notification back from the client. Following is my code:

Server Code:
  1. #include <BLEDevice.h>
  2. #include <BLEServer.h>
  3. #include <BLEUtils.h>
  4. #include <BLE2902.h>
  5. #include "DHT.h"
  6.  
  7. #define DHTPIN 4
  8. #define DHTTYPE DHT22
  9. #define uS_TO_S_FACTOR 1000000  //Conversion factor for micro seconds to seconds
  10. #define TIME_TO_SLEEP  15        //Time ESP32 will go to sleep (in seconds)
  11.  
  12. RTC_DATA_ATTR int bootCount = 0;
  13. DHT dht(DHTPIN, DHTTYPE);
  14. BLECharacteristic *pCharacteristic;
  15.  
  16. bool deviceConnected = false;
  17. uint8_t txValue = 50;
  18.  
  19. #define SERVICE_UUID           "4fafc201-1fb5-459e-8fcc-c5c9c331914b" // UART service UUID
  20. #define CHARACTERISTIC_UUID_TX "beb5483e-36e1-4688-b7f5-ea07361b26a8"
  21.  
  22. class MyServerCallbacks: public BLEServerCallbacks {
  23.     void onConnect(BLEServer* pServer) {
  24.       deviceConnected = true;
  25.     };
  26.  
  27.     void onDisconnect(BLEServer* pServer) {
  28.       deviceConnected = false;
  29.     }
  30. };
  31.  
  32. //Function that prints the reason by which ESP32 has been awaken from sleep
  33. void print_wakeup_reason(){
  34.   esp_sleep_wakeup_cause_t wakeup_reason;
  35.   wakeup_reason = esp_sleep_get_wakeup_cause();
  36.   switch(wakeup_reason)
  37.   {
  38.     case 1  : Serial.println("Wakeup caused by external signal using RTC_IO"); break;
  39.     case 2  : Serial.println("Wakeup caused by external signal using RTC_CNTL"); break;
  40.     case 3  : Serial.println("Wakeup caused by timer"); break;
  41.     case 4  : Serial.println("Wakeup caused by touchpad"); break;
  42.     case 5  : Serial.println("Wakeup caused by ULP program"); break;
  43.     default : Serial.println("Wakeup was not caused by deep sleep"); break;
  44.   }
  45. }
  46.  
  47. void setup() {
  48.   Serial.begin(115200);
  49.  
  50.   Serial.println(F("initating DHT22..."));
  51.   dht.begin();
  52.  
  53.   // Create the BLE Device
  54.   BLEDevice::init("UART"); // Name must not be longer than 5 chars!!!
  55.  
  56.   // Create the BLE Server
  57.   BLEServer *pServer = BLEDevice::createServer();
  58.   pServer->setCallbacks(new MyServerCallbacks());
  59.  
  60.   // Create the BLE Service
  61.   BLEService *pService = pServer->createService(SERVICE_UUID);
  62.  
  63.   // Create a BLE Characteristic
  64.   pCharacteristic = pService->createCharacteristic(
  65.                       CHARACTERISTIC_UUID_TX,
  66.                       BLECharacteristic::PROPERTY_NOTIFY|BLECharacteristic::PROPERTY_READ|BLECharacteristic::PROPERTY_WRITE
  67.                     );
  68.  
  69.   BLE2902 *desc = new BLE2902();
  70.   desc->setNotifications(true);
  71.   pCharacteristic->addDescriptor(desc);
  72.  
  73.   // Start the service
  74.   pService->start();
  75.   pServer->getAdvertising()->addServiceUUID(SERVICE_UUID);
  76.   // Start advertising
  77.   pServer->getAdvertising()->start();
  78.   Serial.println(pService->getUUID().toString().c_str());
  79.   Serial.println("Waiting for a client connection to notify...");
  80.  
  81.   if (deviceConnected) {
  82.  
  83.     float f = dht.readTemperature(true);
  84.     char fStr[10];
  85.     sprintf(fStr, "%4.4f", f);
  86.    
  87.     Serial.print("Temperature reading: ");
  88.     Serial.println(fStr);
  89.  
  90.     Serial.printf("*** Sent Value: %d ***\n", fStr);
  91.     pCharacteristic->setValue(fStr);
  92.  
  93.     delay(3000);
  94.  
  95.     pCharacteristic->setValue(fStr);
  96.    
  97.     pCharacteristic->notify();
  98.  
  99.     //Set timer to 5 seconds
  100.     esp_sleep_enable_timer_wakeup(TIME_TO_SLEEP * uS_TO_S_FACTOR);
  101.     Serial.println("Setup ESP32 to sleep for every " + String(TIME_TO_SLEEP) +
  102.     " Seconds");
  103.  
  104.     //Go to sleep now
  105.     esp_deep_sleep_start();
  106.    
  107.   }
  108.   //delay(60000);
  109. }
  110.  
  111. void loop() {}
Here is my serial output:
rst:0x1 (POWERON_RESET),boot:0x17 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:1
load:0x3fff0018,len:4
load:0x3fff001c,len:1216
ho 0 tail 12 room 4
load:0x40078000,len:9720
ho 0 tail 12 room 4
load:0x40080400,len:6352
entry 0x400806b8
initating DHT22...
4fafc201-1fb5-459e-8fcc-c5c9c331914b
Waiting a client connection to notify...



Client code:
  1. #include "BLEDevice.h"
  2.  
  3. // The remote service we wish to connect to.
  4. static BLEUUID serviceUUID("4fafc201-1fb5-459e-8fcc-c5c9c331914b");
  5. static BLEUUID    charUUID("beb5483e-36e1-4688-b7f5-ea07361b26a8");
  6.  
  7. static BLEAddress *pServerAddress;
  8. static boolean doConnect = false;
  9. static boolean connected = false;
  10. static BLERemoteCharacteristic* pRemoteCharacteristic;
  11.  
  12. static void notifyCallback(
  13.   BLERemoteCharacteristic* pBLERemoteCharacteristic,
  14.   uint8_t* pData,
  15.   size_t length,
  16.   bool isNotify) {
  17.     Serial.print(pBLERemoteCharacteristic->getUUID().toString().c_str());
  18.     Serial.print(" of data length ");
  19.     Serial.println(length);
  20.     byte buffer[42];
  21.     Serial.print("The characteristic value sent was: ");
  22.     std::string farhenheight = pRemoteCharacteristic->readValue();
  23.     Serial.print("Farheinheight: ");
  24.     Serial.println(farhenheight.c_str());
  25. }
  26.  
  27. class MyClientCallback : public BLEClientCallbacks {
  28.   void onConnect(BLEClient* pclient) {
  29.     Serial.println("connected again ... ");
  30.   }
  31.  
  32.   void onDisconnect(BLEClient* pclient) {
  33.     connected = false;
  34.     Serial.println("onDisconnect");
  35.   }
  36. };
  37.  
  38. bool connectToServer(BLEAddress pAddress) {
  39.     Serial.print("Forming a connection to ");
  40.     Serial.println(pAddress.toString().c_str());
  41.    
  42.     BLEClient*  pClient  = BLEDevice::createClient();
  43.     Serial.println(" - Created client");
  44.  
  45.     pClient->setClientCallbacks(new MyClientCallback());
  46.    
  47.     // Connect to the remove BLE Server.
  48.     pClient->connect(pAddress);
  49.     Serial.println(" - Connected to server");
  50.  
  51.     // Obtain a reference to the service we are after in the remote BLE server.
  52.     BLERemoteService* pRemoteService = pClient->getService(serviceUUID);
  53.     Serial.println(pRemoteService->toString().c_str());
  54.     if (pRemoteService == nullptr) {
  55.       Serial.print("Failed to find our service UUID: ");
  56.       Serial.println(serviceUUID.toString().c_str());
  57.       return false;
  58.     }
  59.     Serial.println(" - Found our service");
  60.  
  61.     // Obtain a reference to the characteristic in the service of the remote BLE server.
  62.     pRemoteCharacteristic = pRemoteService->getCharacteristic(charUUID);
  63.     if (pRemoteCharacteristic == nullptr) {
  64.       Serial.print("Failed to find our characteristic UUID: ");
  65.       Serial.println(charUUID.toString().c_str());
  66.       return false;
  67.     }
  68.     Serial.println(" - Found our characteristic");
  69. //
  70. //    Serial.print("The characteristic value sent was: ");
  71. //    std::string farhenheight = pRemoteCharacteristic->readValue();
  72. //    Serial.print("Farheinheight: ");
  73. //    Serial.println(farhenheight.c_str());
  74.  
  75.    
  76.     pRemoteCharacteristic->registerForNotify(notifyCallback);
  77. }
  78.  
  79. class MyAdvertisedDeviceCallbacks: public BLEAdvertisedDeviceCallbacks {
  80.   void onResult(BLEAdvertisedDevice advertisedDevice) {
  81.     Serial.print("BLE Advertised Device found: ");
  82.     Serial.println(advertisedDevice.toString().c_str());
  83.     //Serial.print(advertisedDevice.haveServiceUUID());
  84.  
  85.     if(advertisedDevice.haveServiceUUID()){
  86.       Serial.println(advertisedDevice.getServiceUUID().toString().c_str());
  87.     }
  88.        
  89.     // We have found a device, let us now see if it contains the service we are looking for.
  90.     if (advertisedDevice.haveServiceUUID() && advertisedDevice.getServiceUUID().equals(serviceUUID)) {
  91.  
  92.       //
  93.       Serial.print("Found our device!  address: ");
  94.       advertisedDevice.getScan()->stop();
  95.  
  96.       pServerAddress = new BLEAddress(advertisedDevice.getAddress());
  97.       doConnect = true;
  98.  
  99.     } // Found our server
  100.    
  101.   } // onResult
  102. }; // MyAdvertisedDeviceCallbacks
  103.  
  104. void setup() {
  105.   Serial.begin(115200);
  106.   Serial.println("Starting Arduino BLE Client application...");
  107.   BLEDevice::init("");
  108.   BLEScan* pBLEScan = BLEDevice::getScan();
  109.   pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks());
  110.   pBLEScan->setActiveScan(true);
  111.   pBLEScan->start(30);
  112. } // End of setup.
  113.  
  114. // This is the Arduino main loop function.
  115. void loop() {
  116.   if (doConnect == true) {
  117.     if (connectToServer(*pServerAddress)) {
  118.         Serial.println("We are now connected to the BLE Server.");
  119.         connected = true;
  120.     } else {
  121.       Serial.println("We have failed to connect to the server; there is nothin more we will do.");
  122.     }
  123.     //doConnect = false;
  124.   }
  125.  
  126.   if (connected == false){
  127.     BLEDevice::getScan()->start(0);
  128.   }
  129.   else{
  130.     doConnect = false;
  131.   }
  132.  
  133.   delay(1000); // Delay a second between loops.
  134. } // End of loop
Client Serial output:
rst:0x1 (POWERON_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:1
load:0x3fff0018,len:4
load:0x3fff001c,len:1216
ho 0 tail 12 room 4
load:0x40078000,len:9720
ho 0 tail 12 room 4
load:0x40080400,len:6352
entry 0x400806b8
Starting Arduino BLE Client application...
BLE Advertised Device found: Name: , Address: 19:e7:99:d9:32:64, manufacturer data: 060001092002e206e435e8b3b0de4daa475d8a7609aad95f554fc87cd5
BLE Advertised Device found: Name: , Address: 78:bd:bc:41:75:fc, manufacturer data: 7500420401808078bdbc4175fc7abdbc819fc201000000000000
BLE Advertised Device found: Name: , Address: 79:1a:60:1b:5a:40, manufacturer data: 4c001005481c78327b, txPower: 12
BLE Advertised Device found: Name: , Address: 74:3e:c8:ef:1b:57, manufacturer data: 4c001005051c4e8858, txPower: 12
BLE Advertised Device found: Name: , Address: 55:cd:00:9a:4d:f7, manufacturer data: 4c001006131a07f82cda, txPower: 12
BLE Advertised Device found: Name: UART, Address: 80:7d:3a:c5:06:e6, serviceUUID: 4fafc201-1fb5-459e-8fcc-c5c9c331914b, txPower: 3
4fafc201-1fb5-459e-8fcc-c5c9c331914b
Found our device! address: Forming a connection to 80:7d:3a:c5:06:e6
- Created client
connected again ...
- Connected to server
Service: uuid: 4fafc201-1fb5-459e-8fcc-c5c9c331914b, start_handle: 40 0x0028, end_handle: 65535 0xffff
- Found our service
- Found our characteristic
We are now connected to the BLE Server.


As you can see, the code in the client never reaches the notifyCallback handler method. I have looked for answers on this forum, tried quite a few things, but no luck. Any idea what I am doing wrong?

Thx in advance for any suggestions.

chegewara
Posts: 2362
Joined: Wed Jun 14, 2017 9:00 pm

Re: esp32 BLE deep sleep + notifyCallback not being hit

Postby chegewara » Tue May 19, 2020 2:53 am

This code is never running and your code ends up in loop (there is just no option that connection will be established that point of code):

Code: Select all

if (deviceConnected) {
 
    float f = dht.readTemperature(true);
    char fStr[10];
    sprintf(fStr, "%4.4f", f);
   
    Serial.print("Temperature reading: ");
    Serial.println(fStr);
 
    Serial.printf("*** Sent Value: %d ***\n", fStr);
    pCharacteristic->setValue(fStr);
 
    delay(3000);
 
    pCharacteristic->setValue(fStr);
   
    pCharacteristic->notify();
 
    //Set timer to 5 seconds
    esp_sleep_enable_timer_wakeup(TIME_TO_SLEEP * uS_TO_S_FACTOR);
    Serial.println("Setup ESP32 to sleep for every " + String(TIME_TO_SLEEP) +
    " Seconds");
 
    //Go to sleep now
    esp_deep_sleep_start();
   
  }

pipe2path
Posts: 3
Joined: Sun May 17, 2020 9:22 pm

Re: esp32 BLE deep sleep + notifyCallback not being hit

Postby pipe2path » Tue May 19, 2020 3:15 am

Are you saying I shouldn't the advertising and notify in the Setup() portion of the Arduino sketch? If that's the case, how can I put the ESP32 to sleep?

chegewara
Posts: 2362
Joined: Wed Jun 14, 2017 9:00 pm

Re: esp32 BLE deep sleep + notifyCallback not being hit

Postby chegewara » Tue May 19, 2020 4:12 am

You can and probably you should start advertising from setup, but remember that setup is running only 1 time and then control is take over by loop. All jobs that will be updated over time usually are running in loop and notify is such task.

You can put esp32 into sleep mode whenever you want, just remember radio is going to be turn off and wifi or bluetooth wont run (im saying about deep sleep, in light sleep wifi may still be running, not sure if its enabled in arduino ).

Who is online

Users browsing this forum: No registered users and 63 guests