ESP32 Arduino BLE DeepSleep

Kevin M.

I am working on a project involving 2 ESP32 Wemos D1 Mini boards. I am using the BLE feature to transmit a sensor reading from the "server" to the "client". I use a Characteristic Notify to the client which receives the sensor reading. If I want to implement deep sleep functionality to the server, what would happen to the client? Does the client also have to reset at some point? Also, is it advisable to use Characteristic.Notify in a deep sleep scenario?

Thanks.

Server code:

#include <BLEServer.h>
#include <BLEUtils.h>
#include <BLE2902.h>
#include "DHT.h"

#define DHTPIN 4
#define DHTTYPE DHT22
#define uS_TO_S_FACTOR 1000000  //Conversion factor for micro seconds to seconds
#define TIME_TO_SLEEP  15        //Time ESP32 will go to sleep (in seconds)

RTC_DATA_ATTR int bootCount = 0;
DHT dht(DHTPIN, DHTTYPE);
BLECharacteristic *pCharacteristic;

bool deviceConnected = false;
uint8_t txValue = 50;

#define SERVICE_UUID           "6E400001-B5A3-F393-E0A9-E50E24DCCA9E" // UART service UUID
#define CHARACTERISTIC_UUID_TX "6E400003-B5A3-F393-E0A9-E50E24DCCA9E"

class MyServerCallbacks: public BLEServerCallbacks {
    void onConnect(BLEServer* pServer) {
      deviceConnected = true;
    };

    void onDisconnect(BLEServer* pServer) {
      deviceConnected = false;
    }
};

//Function that prints the reason by which ESP32 has been awaken from sleep
void print_wakeup_reason(){
  esp_sleep_wakeup_cause_t wakeup_reason;
  wakeup_reason = esp_sleep_get_wakeup_cause();
  switch(wakeup_reason)
  {
    case 1  : Serial.println("Wakeup caused by external signal using RTC_IO"); break;
    case 2  : Serial.println("Wakeup caused by external signal using RTC_CNTL"); break;
    case 3  : Serial.println("Wakeup caused by timer"); break;
    case 4  : Serial.println("Wakeup caused by touchpad"); break;
    case 5  : Serial.println("Wakeup caused by ULP program"); break;
    default : Serial.println("Wakeup was not caused by deep sleep"); break;
  }
}

void setup() {
  Serial.begin(115200);

  Serial.println(F("initating DHT22..."));
  dht.begin();

  // Create the BLE Device
  BLEDevice::init("UART"); // Name must not be longer than 5 chars!!!

  // Create the BLE Server
  BLEServer *pServer = BLEDevice::createServer();
  pServer->setCallbacks(new MyServerCallbacks());

  // Create the BLE Service
  BLEService *pService = pServer->createService(SERVICE_UUID);

  // Create a BLE Characteristic
  pCharacteristic = pService->createCharacteristic(
                      CHARACTERISTIC_UUID_TX,
                      BLECharacteristic::PROPERTY_NOTIFY|BLECharacteristic::PROPERTY_READ|BLECharacteristic::PROPERTY_WRITE
                    );

  BLE2902 *desc = new BLE2902();
  desc->setNotifications(true);
  pCharacteristic->addDescriptor(desc);

  // Start the service
  pService->start();
  pServer->getAdvertising()->addServiceUUID(SERVICE_UUID);
  // Start advertising
  pServer->getAdvertising()->start();
  Serial.println(pService->getUUID().toString().c_str());
  Serial.println("Waiting a client connection to notify...");

  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);

    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();

  }
  //delay(60000);
}

void loop() {}

Client code:

#include "BLEDevice.h"
#include <WiFi.h>

// The remote service we wish to connect to.
static BLEUUID serviceUUID("6E400001-B5A3-F393-E0A9-E50E24DCCA9E");
static BLEUUID    charUUID("6E400003-B5A3-F393-E0A9-E50E24DCCA9E");

static BLEAddress *pServerAddress;
static boolean doConnect = false;
static boolean connected = false;
static BLERemoteCharacteristic* pRemoteCharacteristic;

const char* ssid     = "Kings";
const char* password = "GoCanada";
const char* host = "menezes-service.herokuapp.com";
WiFiClient client;

static void notifyCallback(
  BLERemoteCharacteristic* pBLERemoteCharacteristic,
  uint8_t* pData,
  size_t length,
  bool isNotify) {
    Serial.print(pBLERemoteCharacteristic->getUUID().toString().c_str());
    Serial.print(" of data length ");
    Serial.println(length);
    //std::string value = pBLERemoteCharacteristic->readValue();
    byte buffer[42];
    Serial.print("The characteristic value sent was: ");
    //Serial.println(pBLERemoteCharacteristic->readValue().c_str());
    //Serial.println(pBLERemoteCharacteristic->readUInt8());
    std::string farhenheight = pRemoteCharacteristic->readValue();
    Serial.print("Farheinheight: ");
    Serial.println(farhenheight.c_str());
    Serial.println(F("Posting to api!"));
    Serial.println();
    Serial.println("closing connection");
}

class MyClientCallback : public BLEClientCallbacks {
  void onConnect(BLEClient* pclient) {
    Serial.println("connected again ... ");
  }

  void onDisconnect(BLEClient* pclient) {
    connected = false;
    Serial.println("onDisconnect");
  }
};

bool connectToServer(BLEAddress pAddress) {
    Serial.print("Forming a connection to ");
    Serial.println(pAddress.toString().c_str());

    BLEClient*  pClient  = BLEDevice::createClient();
    Serial.println(" - Created client");

    pClient->setClientCallbacks(new MyClientCallback());

    // Connect to the remove BLE Server.
    pClient->connect(pAddress);
    Serial.println(" - Connected to server");

    // Obtain a reference to the service we are after in the remote BLE server.
    BLERemoteService* pRemoteService = pClient->getService(serviceUUID);
    Serial.println(pRemoteService->toString().c_str());
    if (pRemoteService == nullptr) {
      Serial.print("Failed to find our service UUID: ");
      Serial.println(serviceUUID.toString().c_str());
      return false;
    }
    Serial.println(" - Found our service");

    // Obtain a reference to the characteristic in the service of the remote BLE server.
    pRemoteCharacteristic = pRemoteService->getCharacteristic(charUUID);
    if (pRemoteCharacteristic == nullptr) {
      Serial.print("Failed to find our characteristic UUID: ");
      Serial.println(charUUID.toString().c_str());
      return false;
    }
    Serial.println(" - Found our characteristic");

    pRemoteCharacteristic->registerForNotify(notifyCallback);
}

class MyAdvertisedDeviceCallbacks: public BLEAdvertisedDeviceCallbacks {
  void onResult(BLEAdvertisedDevice advertisedDevice) {
    Serial.print("BLE Advertised Device found: ");
    Serial.println(advertisedDevice.toString().c_str());
    //Serial.print(advertisedDevice.haveServiceUUID());

    if(advertisedDevice.haveServiceUUID()){
      Serial.println(advertisedDevice.getServiceUUID().toString().c_str());
    }


    // We have found a device, let us now see if it contains the service we are looking for.
    if (advertisedDevice.haveServiceUUID() && advertisedDevice.getServiceUUID().equals(serviceUUID)) {

      // 
      Serial.print("Found our device!  address: "); 
      advertisedDevice.getScan()->stop();

      pServerAddress = new BLEAddress(advertisedDevice.getAddress());
      doConnect = true;

    } // Found our server

  } // onResult
}; // MyAdvertisedDeviceCallbacks

void setup() {
  Serial.begin(115200);
  Serial.println("Starting Arduino BLE Client application...");
  BLEDevice::init("");
  BLEScan* pBLEScan = BLEDevice::getScan();
  pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks());
  pBLEScan->setActiveScan(true);
  pBLEScan->start(30);

} // End of setup.

// This is the Arduino main loop function.
void loop() {
  if (doConnect == true) {
    if (connectToServer(*pServerAddress)) {
        Serial.println("We are now connected to the BLE Server.");
        connected = true;
    } else {
      Serial.println("We have failed to connect to the server; there is nothin more we will do.");
    }
    //doConnect = false;
  }

  if (connected == false){
    BLEDevice::getScan()->start(0);
  }
  else{
    doConnect = false;
  }

  delay(1000); // Delay a second between loops.
} // End of loop
Youssif Saeed

Please see answers to your questions below:-

If I want to implement deep sleep functionality to the server, what would happen to the client? Does the client also have to reset at some point?

No the client does not have to reset, but you may have to reconnect to the server because in deep sleep the BLE connection is lost. If you want the connection to be established automatically as soon as the server wakes up, then you have to update the client code so that it continuously attempts to reconnect to the server. This way, as soon as the server wakes up, the client would connect to it and continue receiving notifications.

Also, is it advisable to use Characteristic.Notify in a deep sleep scenario?

In deep sleep the CPU will be off, therefore you will not be able to send notifications in this state. In this mode you will only be able to wake up the CPU through a timer or an external peripheral (e.g. touch pins). Please see the link below for more information:-

I hope this helps.

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

Arduino BLE Project (esp32)

How to define the callback for an esp32 arduino ble scan result

ESP32 using BLE and WiFi alternately

Interrupts function not called with ESP32 Arduino

How to send from ESP32 to Arduino?

Different WiFi modes in arduino for esp32

arduino-esp32 do OTA via BLE

how to use esp32 ulp interrupt pulse counter and periodic wake up deepsleep mode

Android ESP32 BLE read after write not working

ESP32 IDF Ble Gatt Server Example

Swift BLE communication between iPhone and ESP32

BLE sent String between ESP32 and Iphone

Arduino ESP32 how to assign BLEUUID object into string

Sending Float Data Type from Arduino to ESP32 (NodeMCU)

How can Firebase acquire data from ESP32/Arduino

Google API for home automation with Raspberry pi/arduino/esp32

Write String to permanent flash memory of Arduino ESP32

ESP32 println gives gibberish output Arduino IDE

arduino esp32 bluetooth recieve a whole string

Arduino, C, Linker error, ESP32 target

How to fix compilation error for ESP32 in Arduino IDE?

BluePy Frequent BLE Disconnects between Raspberry Pi4 and ESP32 - (Bluetooth)

Android BLE, scan started, finds devices but does not connect with filter (ESP32 & Samsung)

Using arduino Nano 32 IOTs BLE to create LED display boards

Arduino and pyserial and ble

ESP32 build in Arduino IDE: undefined reference to `CLASS::function' error

Why is the JSON content missing from my XMLHttpRequest sent to the ESP32 Arduino webserver?

Arduino ESP32 FreeRTOS - How to declare empty byte array in task

How to delete and restart hw timer (for interrupts) on demand for esp32 arduino (stepper motor controller application)