I'm new to using the esp32 as a microcontroller. I'm currently working on a so-to-say remote control. Since I want to use the esp32 with an external battery I need to put it in deep-sleep after I pressed some buttons to preserve battery.
All that works fine I've connected a small touchpad to put the esp32 into deep sleep mode using the esp_deep_sleep_start()
function . The controller itself goes to sleep and can be woken up using the following 2 lines:
touchAttachInterrupt(T0, wakeCallback, TOUCH_THRESHOLD);
esp_sleep_enable_touchpad_wakeup();
In order to communicate with my Raspberry Pi 'Base Station' I decided to use BLE.
My server is configured the following way (where bleServer
, bleCharacteristic
and bleService
are global variables):
BLEDevice::init("esp-32-remote");
bleServer = BLEDevice::createServer();
bleServer->setCallbacks(new ServerCallbacks());
bleService = bleServer->createService(SERVICE_UUID);
bleCharacteristic = bleService->createCharacteristic(
CHARACTERISTIC_UUID,
BLECharacteristic::PROPERTY_READ |
BLECharacteristic::PROPERTY_WRITE
);
bleCharacteristic->addDescriptor(new BLE2902());
bleService->start();
BLEAdvertising *pAdvertising = BLEDevice::getAdvertising();
pAdvertising->addServiceUUID(SERVICE_UUID);
pAdvertising->setScanResponse(true);
pAdvertising->setMinPreferred(0x06);
pAdvertising->setMinPreferred(0x12);
BLEDevice::startAdvertising();
Upon regular restart using the buttons everything works fine. I can connect to the device using python and the bluepy library.
If I now wake the controller I can't do anything anymore. The setup()
function gets called and there are no errors, nor does the controller crash due to any code errors (seemingly).
Then the loop function gets called once, and thats it. I can't connect to the device anymore until I press the hardware reset button.
The questions that arise are:
- might there be some error in the way I shutdown the bluetooth module?
- Does the loop function work after being woken up from deep sleep?
Maybe one of you has an idea regarding my issue. If there are more information that I need to provide, don't hesitate to tell me, I'm new to the whole mcu topic and I don't know whats best to provide here.
2 Answers 2
Does the loop function work after being woken up from deep sleep? YES
loop function isn't magical. its just a function that gets called over and over. In other words, if it gets called once, it can be called again except if
- it did something to deactivate itself
- never reached the end
during that first call. Check that you are not activating some sort of state inside the loop or going into a blocking call awaiting a signal that is never sent.
For good measure, make sure to reset all your variables to their expected states - expecting something to be 0 or set via the original definition may be insufficient. This is something that occurs on a power reset so if reset is making it work again, thats a likely culprit. Use a bare minimum of code in the loop for debug so you can figure it out.
-
Thanks for the answer I'll look into that. Do you have any recommendation regarding the BLE issue?hGen– hGen08/27/2020 09:32:46Commented Aug 27, 2020 at 9:32
-
I do not at this time. I did read that a "the TV Begone remote control" intentionally went to a sleep without wake upon sending a power off signal, and tied into the reset button for waking again, so be careful what you copy and from where. gammon.com.au/powerAbel– Abel08/28/2020 07:23:01Commented Aug 28, 2020 at 7:23
There's a good tutorial here on how to connect the BLE server client to the ESP32. And a Good fix here for reconnection issues.
Below is a piece of prototype code I wrote for BLE server client connectivity:
class MyServerCallbacks: public BLEServerCallbacks {
void onConnect(BLEServer* pServer) {
deviceConnected = true;
deviceDisconnected=false;
interface->onBoardLED->led[0] = interface->onBoardLED->LED_GREEN;
interface->onBoardLED->statusLED(100, 1);
BLEDevice::startAdvertising();
};
void onDisconnect(BLEServer* pServer) {
deviceConnected = false;
interface->onBoardLED->led[0] = interface->onBoardLED->LED_BLUE;
interface->onBoardLED->statusLED(100, 1);
interface->onBoardLED->led[0] = interface->onBoardLED->LED_BLUE;
interface->onBoardLED->statusLED(100, 1);
interface->onBoardLED->led[0] = interface->onBoardLED->LED_BLUE;
interface->onBoardLED->statusLED(100, 1);
pServer->getAdvertising()->start();
}
};
class pCharacteristicTX_Callbacks: public BLECharacteristicCallbacks {
void onWrite(BLECharacteristic *pCharacteristic) {
std::string rxValue = pCharacteristic->getValue();
if (rxValue.length() > 0) {
String msg="";
mserial->printStrln("*********");
mserial->printStr("Received Value: ");
for (int i = 0; i < rxValue.length(); i++) {
msg=msg+String(rxValue[i]);
mserial->printStr(String(rxValue[i]));
}
mserial->printStrln("");
mserial->printStrln("*********");
//valueReceived=msg;
}
}
void onRead(BLECharacteristic *pCharacteristic) {
mserial->printStrln("*********");
mserial->printStr("onRead...");
pCharacteristic->setValue("OK");
}
};
class pCharacteristicRX_Callbacks: public BLECharacteristicCallbacks {
void onWrite(BLECharacteristic *pCharacteristic) {
std::string rxValue = pCharacteristic->getValue();
mserial->ble=false;
if (rxValue.length() > 0) {
String msg="";
mserial->printStr("Received Value: ");
for (int i = 0; i < rxValue.length(); i++) {
msg=msg+String(rxValue[i]);
mserial->printStr(String(rxValue[i]));
}
msg.trim();
$BLE_CMD=msg;
mserial->ble=true;
newCMDarrived=true;
}
}
void onRead(BLECharacteristic *pCharacteristic) {
mserial->printStrln("*********");
mserial->printStr("onRead...");
pCharacteristic->setValue("OK");
}
};
//------------------------------------------------------------------
// Create the BLE Device
BLEDevice::init("Smart Concrete Curing"); // Give it a name
// Create the BLE Server
pServer = BLEDevice::createServer();
pServer->setCallbacks(new MyServerCallbacks());
// Create the BLE Service
pService = pServer->createService(SERVICE_UUID);
// Create a BLE Characteristic
pCharacteristicTX = pService->createCharacteristic(
CHARACTERISTIC_UUID_TX,
BLECharacteristic::PROPERTY_NOTIFY
);
pCharacteristicTX->addDescriptor(new BLE2902());
pCharacteristicRX = pService->createCharacteristic(
CHARACTERISTIC_UUID_RX,
BLECharacteristic::PROPERTY_READ |
BLECharacteristic::PROPERTY_WRITE |
BLECharacteristic::PROPERTY_NOTIFY |
BLECharacteristic::PROPERTY_INDICATE
);
pCharacteristicTX->setCallbacks(new pCharacteristicTX_Callbacks());
pCharacteristicRX->setCallbacks(new pCharacteristicRX_Callbacks());
interface->init_BLE(pCharacteristicTX);
// Start the service
pService->start();
on this particular code, I'm using light sleep , so to go to sleep :
btStop();
delay(1000);
WiFi.disconnect(true);
WiFi.mode(WIFI_OFF);
changeMcuFreq(interface, interface->MIN_MCU_FREQUENCY);
and to wake up :
changeMcuFreq(interface, interface->WIFI_FREQUENCY);
btStart();