I have an ESP32 which should receive data over BLE and then send the data over WiFi to a webserver. If I code both tasks separately in Arduino, then everything works but as soon as I merge both tasks, sending over WiFi breaks down.
From what I understand, BLE and WiFi are sharing the same radio on the ESP32, thus the tasks need to be done alternately to avoid interferences. I've tried to implement this by adding delays between the two tasks but was unsuccessful.
This is the code I have so far:
#include <HTTPClient.h>
#include <BLEDevice.h>
#include <BLEScan.h>
const char* ssid = "xx";
const char* password = "xx";
int scanTime = 2; //In seconds
BLEScan* pBLEScan;
class MyAdvertisedDeviceCallbacks: public BLEAdvertisedDeviceCallbacks {
void onResult(BLEAdvertisedDevice advertisedDevice) {
Serial.printf("Advertised Device: %s \n", advertisedDevice.toString().c_str());
}
};
void setup()
{
Serial.begin(115200);
Serial.setDebugOutput(1);
Serial.setDebugOutput(0); //turn off debut output
WiFi.begin(ssid, password);
int retrycon = 50;
while (WiFi.status() != WL_CONNECTED)
{
delay(500);
if (--retrycon == 0)
{
Serial.println("RESTART");
ESP.restart();
}
Serial.print(".");
}
Serial.print("WiFi connected with IP: ");
Serial.println(WiFi.localIP());
BLEDevice::init("");
pBLEScan = BLEDevice::getScan();
pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks());
pBLEScan->setActiveScan(true);
pBLEScan->setInterval(100);
pBLEScan->setWindow(99);
}
void loop()
{
BLEScanResults foundDevices = pBLEScan->start(scanTime, false);
Serial.print("Devices found: ");
Serial.println(foundDevices.getCount());
pBLEScan->clearResults();
delay(3000);
int tryconnect = 20;
while (--tryconnect != 0) {
if (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.println("...");
} else {
break;
}
}
if (WiFi.status() != WL_CONNECTED) {
WiFi.reconnect();
Serial.println("reconnect");
}
else {
Serial.println("connected to WiFi");
HTTPClient http;
http.begin("http://httpbin.org/ip");
int httpCode = http.GET();
if (httpCode > 0) {
Serial.print("HTTP code ");
Serial.println(httpCode);
} else {
Serial.println("Error on HTTP request");
}
http.end();
delay(10000);
}
}
Can anybody tell me how to implement the two tasks (receiving over BLE, sending over WiFi) to avoid interferences?
I use commands like this to turn off BLE and WiFi:
WiFi.disconnect(true);
WiFi.mode(WIFI_OFF);
btStop();
adc_power_off();
//esp_wifi_stop(); // Doesn't work for me!
esp_bt_controller_disable();
In my code I BLE advertize/scan, then do the stuff above, then connect to WiFi. No problem. Oh and remember to BLEDevice::deinit
when you finished with BLE, otherwise you can't get it to fit in a 4Mb ESP32. I do BLE, WiFi, HTTPS/SSL, OTA and use the SPIFFS to store data, all on a standard 4Mb ESP32 (ESP-WROOM-32) without PSRAM.
All above is in a function to lower the power usage, so I call it all every time I change 'mode'. In deep sleep I only use 5uA.
Also:
pBLEScan->setInterval(100);
pBLEScan->setWindow(99);
... don't work for me, so I commented them out, and scan for 3 sec.
UPDATE:
Added the partition table:
# ESP-IDF Partition Table
# Name, Type, SubType, Offset, Size, Flags
#nvs,data,nvs,0x9000,20K,
#otadata,data,ota,0xe000,8K,
#app0,app,ota_0,0x10000,1920K,
#app1,app,ota_1,0x1f0000,1920K,
#spiffs,data,spiffs,0x3d0000,192K,
# ESP-IDF Partition Table
# Name, Type, SubType, Offset, Size, Flags
nvs, data, nvs, 0x009000, 0x005000,
otadata,data, ota, 0x00e000, 0x002000,
app0, app, ota_0, 0x010000, 0x130000,
spiffs, data, spiffs, 0x140000, 0x2C0000,