NimBLE-Arduino icon indicating copy to clipboard operation
NimBLE-Arduino copied to clipboard

BLE 5 ESP32 C3

Open lucasromeiro opened this issue 2 years ago • 5 comments

Hello how are you? I'm making a software to read temperature sensors. These sensors send an advertisement every 5 to 30 seconds. I can set this up. The longer the time the better for me as the battery will last longer.

I'm having trouble reading these advertising packages. I need to read at least 1 packet per minute, worst case scenario. But I find that sometimes I can't read any advertising for more than 3 minutes. I don `t understand why. I don't know if it's better for me to put a higher or lower scan time...

I don't understand why you don't capture the advertising packets every time.

I'm using ESP32-C3.

I used the example for bluetooth 5

I also put it to read only the MAC of my sensor.

Can anyone help me understand this?

`#include <WiFi.h> #include <WiFiMulti.h> #include <NimBLEDevice.h> #if !CONFIG_BT_NIMBLE_EXT_ADV

error Must enable extended advertising, see nimconfig.h file.

#endif WiFiClient espClient; WiFiMulti wifiMulti;

void scanEndedCB(NimBLEScanResults results);

#define SERVICE_UUID "ABCD" #define CHARACTERISTIC_UUID "1234"

static NimBLEAdvertisedDevice* advDevice; static bool doConnect = false; static uint32_t scanTime = 40; /* 0 = scan forever */

NimBLEScan *pBLEScan;

/* Define the PHY's to use when connecting to peer devices, can be 1, 2, or all 3 (default)./ static uint8_t connectPhys = BLE_GAP_LE_PHY_CODED_MASK | BLE_GAP_LE_PHY_1M_MASK /| BLE_GAP_LE_PHY_2M_MASK */ ;

/* Define a class to handle the callbacks for client connection events / class ClientCallbacks : public NimBLEClientCallbacks { void onConnect(NimBLEClient pClient) { Serial.printf("Connected\n"); };

void onDisconnect(NimBLEClient* pClient) {
    Serial.printf("%s Disconnected - Starting scan\n", pClient->getPeerAddress().toString().c_str());
    NimBLEDevice::getScan()->start(scanTime, scanEndedCB);
};

};

/* Define a class to handle the callbacks when advertisements are received */ class AdvertisedDeviceCallbacks: public NimBLEAdvertisedDeviceCallbacks {

void onResult(NimBLEAdvertisedDevice* advertisedDevice) {
    Serial.printf("Advertised Device found: %s\n", advertisedDevice->toString().c_str());
    if(advertisedDevice->isAdvertisingService(NimBLEUUID("ABCD")))
    {
        Serial.printf("Found Our Service\n");
        /* Ready to connect now */
        doConnect = true;
        /* Save the device reference in a global for the client to use*/
        advDevice = advertisedDevice;
        /* stop scan before connecting */
        NimBLEDevice::getScan()->stop();
    }
};

};

/* Callback to process the results of the last scan or restart it / void scanEndedCB(NimBLEScanResults results){ Serial.printf("Scan Ended\n"); if (!doConnect) { / Don't start the scan while connecting */ NimBLEDevice::getScan()->start(scanTime, scanEndedCB); } }

/* Handles the provisioning of clients and connects / interfaces with the server / bool connectToServer() { NimBLEClient pClient = nullptr;

pClient = NimBLEDevice::createClient();
pClient->setClientCallbacks(new ClientCallbacks, false);

/* Set the PHY's to use for this connection. This is a bitmask that represents the PHY's:
 * * 0x01 BLE_GAP_LE_PHY_1M_MASK
 * * 0x02 BLE_GAP_LE_PHY_2M_MASK
 * * 0x04 BLE_GAP_LE_PHY_CODED_MASK
 * Combine these with OR ("|"), eg BLE_GAP_LE_PHY_1M_MASK | BLE_GAP_LE_PHY_2M_MASK | BLE_GAP_LE_PHY_CODED_MASK;
 */
pClient->setConnectPhy(connectPhys);

/** Set how long we are willing to wait for the connection to complete (seconds), default is 30. */
pClient->setConnectTimeout(10);

if (!pClient->connect(advDevice)) {
    /* Created a client but failed to connect, don't need to keep it as it has no data */
    NimBLEDevice::deleteClient(pClient);
    Serial.printf("Failed to connect, deleted client\n");
    return false;
}

Serial.printf("Connected to: %s RSSI: %d\n",
       pClient->getPeerAddress().toString().c_str(),
       pClient->getRssi());

/* Now we can read/write/subscribe the charateristics of the services we are interested in */
NimBLERemoteService* pSvc = nullptr;
NimBLERemoteCharacteristic* pChr = nullptr;

pSvc = pClient->getService(SERVICE_UUID);

if (pSvc) {
    pChr = pSvc->getCharacteristic(CHARACTERISTIC_UUID);

    if (pChr) {
        // Read the value of the characteristic.
        if (pChr->canRead()) {
            std::string value = pChr->readValue();
            Serial.printf("Characteristic value: %s\n", value.c_str());
        }
    }

} else {
    Serial.printf("ABCD service not found.\n");
}

NimBLEDevice::deleteClient(pClient);
Serial.printf("Done with this device!\n");
return true;

}

void setup () { Serial.begin(115200); Serial.printf("Starting NimBLE Client\n"); WiFi.mode(WIFI_STA); wifiMulti.addAP("xxx", "xxxx"); wifiMulti.addAP("ssid_from_AP_2", "your_password_for_AP_2"); wifiMulti.addAP("ssid_from_AP_3", "your_password_for_AP_3"); if(wifiMulti.run() == WL_CONNECTED) { Serial.println(""); Serial.println("WiFi connected"); Serial.println("IP address: "); Serial.println(WiFi.localIP()); } /* Initialize NimBLE, no device name specified as we are not advertising */ NimBLEAddress a("00:3C:84:1D:CA:8D"); //NimBLEAddress b("00:3C:84:1B:42:33");

NimBLEDevice::init("");
NimBLEDevice::whiteListAdd(a);
//NimBLEDevice::whiteListAdd(b);

pBLEScan = NimBLEDevice::getScan();

/* create a callback that gets called when advertisers are found */
pBLEScan->setAdvertisedDeviceCallbacks(new AdvertisedDeviceCallbacks());
pBLEScan->setFilterPolicy(BLE_HCI_SCAN_FILT_USE_WL);
pBLEScan->setMaxResults(0);

/* Set scan interval (how often) and window (how long) in milliseconds */
pBLEScan->setInterval(97);
pBLEScan->setWindow(67);

/*  Active scan will gather scan response data from advertisers
 *  but will use more energy from both devices
 */
pBLEScan->setActiveScan(true);

/*  Start scanning for advertisers for the scan time specified (in seconds) 0 = forever
 *  Optional callback for when scanning stops.
 */
pBLEScan->start(scanTime, scanEndedCB);

}

void loop () { /* Loop here until we find a device we want to connect to / if (doConnect) { / Found a device we want to connect to, do it now */ if (connectToServer()) { Serial.printf("Success!, scanning for more!\n"); } else { Serial.printf("Failed to connect, starting scan\n"); }

    doConnect = false;
    NimBLEDevice::getScan()->start(scanTime, scanEndedCB);
}

delay(1000);
Serial.printf(".");
wifiMulti.run();

}`

lucasromeiro avatar Dec 12 '22 19:12 lucasromeiro

How long do these devices advertise for? It could be that the scan has ended while the device is advertising.

h2zero avatar Dec 17 '22 20:12 h2zero

How long do these devices advertise for? It could be that the scan has ended while the device is advertising.

Hi @h2zero .

The sensor sends an advertisement every 4 seconds without interruption.

lucasromeiro avatar Dec 17 '22 21:12 lucasromeiro

Hello, anyone can help with this?

lucasromeiro avatar Jan 02 '23 14:01 lucasromeiro

How long do these devices advertise for? It could be that the scan has ended while the device is advertising.

hi, can u help?

lucasromeiro avatar Feb 22 '23 21:02 lucasromeiro

I know this is quite old but I have had some challenges with getting BLE5 working and here are some of my findings.

Enabling BLE5 gives you access to Extended Advertising that allows you to send up to 252 characters in the advertisement. However this requires that the client is running in active scanning mode. I also found out that most of the BLE scanners for Windows and IOS does not detect these extended packages but an ESP32 will so you should implement both the server and client. So the compatibility from what I have seen is not that good.

If you don't need this much then stick with compatible and use for instance the iBeacon format or the other standards that exist.

I also found out that once the advertisement has been scanned by the client the server will stop advertising to you will need to activate that again in the code if you want it permanent. This can be done in the advertisement callback.

mp-se avatar Dec 17 '23 12:12 mp-se

Closing as I believe @mp-se has answered this.

h2zero avatar Jun 04 '24 22:06 h2zero