2

I want to create some buzzers connected via bluetooth for a quiz show. I got several ESP32. One of them is the master (BLE Server), the other ESP32s are the buzzers (BLE Clients) with one big button and some LEDs each. The master sends commands ("turn on", "turn off", "you are number x") to all the buzzers and receives when one of them gets pressed.

The code on both sides works for up to 4 clients, but I can't connect more than 4 BLE clients to the BLE server. I found and changed the CONFIG_BTDM_CONTROLLER_BLE_MAX_CONN and CONFIG_BTDM_CONTROLLER_BLE_MAX_CONN_EFF in sdkconfig.h at C:\Users\MyName\AppData\Local\Arduino15\packages\esp32\hardware\esp32\1.0.4\tools\sdk\include\config.

This seems to be the right place, because both values originally were 3 and then only three clients could connect. The fourth client was rejectet (got a false on pClient->connect(myDevice);). When I updated both numbers to 4, the fourth client could connect and could receive the notifications from the server.

Then I changed these two numbers to 8, because I potentially want to connect even more buzzers. But the 5th buzzer could not connect. It got a true on pClient->connect(myDevice);, but it would not receive any notifications from the server. A few seconds later it starts looking for a server again. The server also does not recognize the 5th client (for client 1 to 4 the server prints Device connected. Now there are x devices connected., but not so for the 5th client)

This is my servers code

#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEServer.h>
#include <BLE2902.h>

#define DEBUG #define VERSION "0.1"

#define BUZZER_SERVICE_UUID "a2066d3e-d566-42bd-9d64-9bf3ae53b504" #define COMMAND_CHAR_UUID "e7adc44d-a04e-46b1-aa4b-ded61bc3b0a8" #define RESPONSE_CHAR_UUID "e7adc44d-a04e-46b1-aa4b-ded61bc3b0a9"

#define PIN_BUTTON_ARM 23 #define PIN_BUTTON_DISARM 22

BLEServer* pServer = NULL; BLECharacteristic* pCommandCharacteristic = NULL; BLECharacteristic* pResponseCharacteristic = NULL; int deviceConnected = 0; bool oldDeviceConnected = false;

bool armPressed = false; bool disarmPressed = false;

class MyServerCallbacks: public BLEServerCallbacks { void onConnect(BLEServer* pServer) { deviceConnected++; BLEDevice::startAdvertising(); #ifdef DEBUG Serial.print("Device connected. Now there are "); Serial.print(deviceConnected); Serial.println(" devices connected."); #endif };

void onDisconnect(BLEServer* pServer) 
{
    deviceConnected--;
    pServer-&gt;startAdvertising(); // restart advertising
    #ifdef DEBUG
    Serial.print(&quot;Device disconnected. Now there are &quot;);
    Serial.print(deviceConnected);
    Serial.println(&quot; devices connected.&quot;);
    #endif
};

};

class MyCharCallbacks: public BLECharacteristicCallbacks { void onWrite(BLECharacteristic *pCharacteristic) { std::string rxValue = pCharacteristic->getValue(); Serial.print(">>> "); Serial.println(rxValue.c_str());

    if (rxValue.length() &gt; 0) 
    {
        //TODO
    }

}

};

void setup() { #ifdef DEBUG Serial.begin(115200); Serial.println("\n\n--------------"); Serial.println("BUZZER HUB"); Serial.println("--------------"); Serial.print("VERSION: "); Serial.println(VERSION); Serial.println("--------------"); #endif

pinMode(PIN_BUTTON_ARM, INPUT_PULLUP);
pinMode(PIN_BUTTON_DISARM, INPUT_PULLUP);

BLEDevice::init(&quot;BuzzerHub&quot;);
pServer = BLEDevice::createServer();
pServer-&gt;setCallbacks(new MyServerCallbacks());

BLEService *pService = pServer-&gt;createService(BUZZER_SERVICE_UUID);

// Create a BLE Characteristic and a BLE Descriptor for sending the commands
pCommandCharacteristic = pService-&gt;createCharacteristic(COMMAND_CHAR_UUID, BLECharacteristic::PROPERTY_NOTIFY);
pCommandCharacteristic-&gt;addDescriptor(new BLE2902());

// Create a BLE Characteristic and a BLE Descriptor for receiving the responses
pResponseCharacteristic = pService-&gt;createCharacteristic(RESPONSE_CHAR_UUID, BLECharacteristic::PROPERTY_WRITE);
pResponseCharacteristic-&gt;addDescriptor(new BLE2902());
pResponseCharacteristic-&gt;setCallbacks(new MyCharCallbacks());

//Start the service
pService-&gt;start();

BLEAdvertising *pAdvertising = BLEDevice::getAdvertising();
pAdvertising-&gt;addServiceUUID(BUZZER_SERVICE_UUID);
pAdvertising-&gt;setScanResponse(true);
pAdvertising-&gt;setMinPreferred(0x06);
BLEDevice::startAdvertising();

#ifdef DEBUG
Serial.println(&quot;BLE is now advertising&quot;);
#endif

}

void loop() { if(digitalRead(PIN_BUTTON_ARM) == LOW) { if(!armPressed) //On pressing the button { armBuzzer(); delay(100); //Debounce } armPressed = true; } else { if(armPressed) //On releasing the button { delay(100); //Debounce } armPressed = false; }

if(digitalRead(PIN_BUTTON_DISARM) == LOW)
{
    if(!disarmPressed) //On pressing the button
    {
        disarmBuzzer();
        delay(100); //Debounce
    }
    disarmPressed = true;
}
else
{
    if(disarmPressed) //On releasing the button
    {
        delay(100); //Debounce
    }
    disarmPressed = false;
}

}

void armBuzzer() { if (deviceConnected) { #ifdef DEBUG Serial.println("<<< ARM"); #endif pCommandCharacteristic->setValue("ARM"); pCommandCharacteristic->notify(); //delay(3); // bluetooth stack will go into congestion, if too many packets are sent, in 6 hours test i was able to go as low as 3ms } }

void disarmBuzzer() { if (deviceConnected) { #ifdef DEBUG Serial.println("<<< DISARM"); #endif pCommandCharacteristic->setValue("DISARM"); pCommandCharacteristic->notify(); //delay(3); // bluetooth stack will go into congestion, if too many packets are sent, in 6 hours test i was able to go as low as 3ms } }

And this is my clients BLE part of the code (there is more, but that got nothing to do with BLE)

// The buzzer service we wish to connect to.
static BLEUUID buzzerServiceUUID("a2066d3e-d566-42bd-9d64-9bf3ae53b504");
// The characteristic of the buzzer service that is there for receiving commands from the hub.
static BLEUUID buzzerCommandCharUUID("e7adc44d-a04e-46b1-aa4b-ded61bc3b0a8");
// The characteristic of the buzzer service that is there for sending commands to the hub.
static BLEUUID buzzerResponseCharUUID("e7adc44d-a04e-46b1-aa4b-ded61bc3b0a9");

static BLERemoteCharacteristic* pCommandCharacteristic; static BLERemoteCharacteristic* pResponseCharacteristic; static BLEAdvertisedDevice* myDevice; String message; bool newMessage;

static boolean doConnect = false; static boolean connected = false;

static void notifyCallback(BLERemoteCharacteristic* pBLERemoteCharacteristic, uint8_t* pData, size_t length, bool isNotify) { #ifdef DEBUG /* Serial.print("Notify callback of data length "); Serial.println(length); Serial.print("data: "); Serial.println((char)pData); / #endif message = ""; for(int i = 0; i < length; i++) { message += (char)pData[i]; } message += '\0'; newMessage = true; }

class MyClientCallback : public BLEClientCallbacks { void onConnect(BLEClient* pclient) { connected = true; setMiddleLed(0,255,0); #ifdef DEBUG Serial.println("onConnect"); #endif }

void onDisconnect(BLEClient* pclient)
{
    connected = false;
    setMiddleLed(255,0,0);
    updatePattern = false;
    #ifdef DEBUG
    Serial.println(&quot;onDisconnect&quot;);
    #endif
}

};

//Scan for BLE servers and find the first one that advertises the service we are looking for. class MyAdvertisedDeviceCallbacks: public BLEAdvertisedDeviceCallbacks { //Called for each advertising BLE server. void onResult(BLEAdvertisedDevice advertisedDevice) { #ifdef DEBUG Serial.print("Advertised Device found: "); Serial.println(advertisedDevice.toString().c_str()); #endif

    // We have found a device, let us now see if it contains the service we are looking for.
    if (advertisedDevice.haveServiceUUID() &amp;&amp; advertisedDevice.isAdvertisingService(buzzerServiceUUID)) // Found our server
    {
        BLEDevice::getScan()-&gt;stop();
        myDevice = new BLEAdvertisedDevice(advertisedDevice);
        doConnect = true;
    }
}

};

bool connectToServer() { #ifdef DEBUG Serial.print("Connecting to "); Serial.println(myDevice->getAddress().toString().c_str()); #endif

//Create Client
BLEClient*  pClient  = BLEDevice::createClient();
pClient-&gt;setClientCallbacks(new MyClientCallback());

// Connect to the remote BLE Server.
bool ok = pClient-&gt;connect(myDevice);  // if you pass BLEAdvertisedDevice instead of address, it will be recognized type of peer device address (public or private)
if (!ok) 
{
    #ifdef DEBUG
    Serial.print(&quot;Failed to connect to address: &quot;);
    Serial.println(myDevice-&gt;getAddress().toString().c_str());
    #endif
    pClient-&gt;disconnect();
    return false;
}

// Obtain a reference to the service we are after in the remote BLE server.
BLERemoteService* pRemoteService = pClient-&gt;getService(buzzerServiceUUID);
if (pRemoteService == nullptr) 
{
    #ifdef DEBUG
    Serial.print(&quot;Failed to find our service UUID: &quot;);
    Serial.println(buzzerServiceUUID.toString().c_str());
    #endif
    pClient-&gt;disconnect();
    return false;
}

// Obtain a reference to the characteristic in the service of the remote BLE server.
pCommandCharacteristic = pRemoteService-&gt;getCharacteristic(buzzerCommandCharUUID);
if (pCommandCharacteristic == nullptr) 
{
    #ifdef DEBUG
    Serial.print(&quot;Failed to find command characteristic UUID: &quot;);
    Serial.println(buzzerCommandCharUUID.toString().c_str());
    #endif
    pClient-&gt;disconnect();
    return false;
}

// Obtain a reference to the characteristic in the service of the remote BLE server.
pResponseCharacteristic = pRemoteService-&gt;getCharacteristic(buzzerResponseCharUUID);
if (pResponseCharacteristic == nullptr) 
{
    #ifdef DEBUG
    Serial.print(&quot;Failed to find response characteristic UUID: &quot;);
    Serial.println(buzzerResponseCharUUID.toString().c_str());
    #endif
    pClient-&gt;disconnect();
    return false;
}

//Register the notification
if(pCommandCharacteristic-&gt;canNotify()) pCommandCharacteristic-&gt;registerForNotify(notifyCallback);

return true;

}

void setupBle() { String name = "Buzzer" + String(dipNumber); BLEDevice::init(name.c_str());

scanForServer();

}

void scanForServer() { #ifdef DEBUG Serial.println("Scanning for Server..."); #endif

setMiddleLed(0,0,255);
updatePattern = false;

// Retrieve a Scanner and set the callback we want to use to be informed when we
// have detected a new device.  Specify that we want active scanning and start the
// scan to run for 5 seconds.
BLEScan* pBLEScan = BLEDevice::getScan();
pBLEScan-&gt;setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks());
pBLEScan-&gt;setInterval(1349);
pBLEScan-&gt;setWindow(449);
pBLEScan-&gt;setActiveScan(true);
pBLEScan-&gt;start(5, false);

}

void loopBle() { // If the flag "doConnect" is true then we have scanned for and found the desired // BLE Server with which we wish to connect. Now we connect to it. if (doConnect == true) { if (connectToServer()) { #ifdef DEBUG Serial.println("Connected to server."); #endif } else { #ifdef DEBUG Serial.println("Failed to connect to server."); #endif } doConnect = false; }

if(!connected)
{
    delay(100);
    setMiddleLed(255,0,0);
    delay(900);
    scanForServer();
}

}

void sendData(String stringToSend) { // Only send when connected if (connected) { //Set the characteristic's value to be the array of bytes that is actually a string. pResponseCharacteristic->writeValue(stringToSend.c_str(), stringToSend.length()); #ifdef DEBUG Serial.print("<<< "); Serial.println(stringToSend); #endif } else { #ifdef DEBUG Serial.println("Can't Send because not connected"); Serial.print("XXX "); Serial.println(stringToSend); #endif } }

How can I connect more clients to my BLE server? What is the maximum number?

Rohit Gupta
  • 618
  • 2
  • 5
  • 18
Tetopia
  • 23
  • 1
  • 3

0 Answers0