Open sosssego opened 3 months ago
I don't believe that ESP32-BLE-Gamepad supports two gamepads over one connect.
The Strings pasted to to bleGamepad.begin
is to name the device to the host OS, not to setup different gamepads, as can be seen - https://github.com/lemmingDev/ESP32-BLE-Gamepad/blob/11ee6e927df7c8bef37b2cdc36eb798e5173c15f/examples/CharacteristicsConfiguration/CharacteristicsConfiguration.ino#L10
I think ESP32-BLE-CompositeHID is more modular and has compositeHID.addDevice(&gamepad);
which you might be able to call twice, but not something I have tried.
Hope that helps.
Thanks for the answer. Maybe my explanation was not clear. I am not trying to connect twice, not twice in the same ESP32. I have 2 esp32, and I trying to connect both devices to a PC. but it fails to connect the second one.
Interesting ... Apologies for the miss read. Never tried to bind two of the same devices at the same time, but should not be a problem.
I wonder if using the BLE serial numbers for each devices been different. Thou should have different Mac address and seen as two different devices, but I could be wrong here.
Possible make each device with a unique SerialNumber
. Please let us know if it works. Might be worth adding a test case.
Another possible corner case, did you possible change any BLE characteristics and not delete the BLE device from Windows and reconnect? Been bitten more than once while testing new BLE setups.
Tried different names, serial, and other bleGamepadConfig settings (VID, PID, GUID) with no success. And unfortunately, I accidentally remove the USB of one of my boards. I will buy another one to test. Or try the ESP32 c3 super mini if I can apply the solution to the sleep problem(link)
Oh no, broken a few interfaces myself.
I need to put some time into testing multiple gamepads on the same host and see if I get the same problem. Things I would do, to try and eliminate possible causes. First would be trying another host, possible a different OS, like maybe your phone.
Another would be using a BLE scanner/analyser like LightBlue or nRF Connect on Android and see if two different devices are been listed. Also nice to see the BLE attributes, characteristics, services and descriptors.
I hope some of that helps. Please let us know how it goes.
I tried connecting both(now one esp32 wroom and 1 esp32 c3) to Android. Android is not seens to recognize It as a BLE device, it says, I need an APP to use it. I do not play games on Android so don't know any that would accept a BLE gamepad, even harder to accept 2. Installing nRF Connect changed things a little, I was able to connect both to Android, but no idea if they are really working. Any information from the nRF Connect that may be helpful?
Hi, I have the same problem. I can't connect to Bluetooth with 2 devices. This is my second board. I used the same code as my first board and just config VID/PID and serialnumber I try forget the first board and this board can be connected but I have to switch every time. How can I fix this?
I don't have Windows, at least not at the moment setup. I have received a few ESP32-C3, which I did some tests a few weeks back on.
I will try and tested today with OSX and Android as the host and even possible another ESP32-C3 running BluePad32. Maybe with Linux too, but let's see.
Is this because NimBLE-Arduino is using the same IRK? A possible way On Win11 and Mac, I can't connect 2 ESP32 Bluetooth too, the syslog on Windows says: The device (????) is trying to distribute an Identity Resolving Key that is already used by a paired device. The pairing was rejected, if the intent was to pair with this device, you may need to first delete the existing pairing information. Has anyone solved this issue?
This works for me using two ESP32-C3 and a very basic sketch that just ramps the battery level up and down.
Only thing I changed between the two two devices in the sketch was different serial numbers
Device A
bleGamepadConfig.setSerialNumber("987654321A");
Device B
bleGamepadConfig.setSerialNumber("987654321B");
I can share the full sketch if anybody would like to try the same thing?
First tests was on a Mac
Second test on my Android 13 device.
Just for completeness
#include <Arduino.h>
#include <BleGamepad.h>
BleGamepad bleGamepad("Custom Contoller Name", "lemmingDev", 100); // Set custom device name, manufacturer and initial battery level
BleGamepadConfiguration bleGamepadConfig; // Create a BleGamepadConfiguration object to store all of the options
int batteryLevel = 100;
// Use the procedure below to set a custom Bluetooth MAC address
// Compiler adds 0x02 to the last value of board's base MAC address to get the BT MAC address, so take 0x02 away from the value you actually want when setting
// I've noticed the first number is a little picky and if set incorrectly don't work and will default to the board's embedded address
// 0xAA definately works, so use that, or experiment
uint8_t newMACAddress[] = {0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF - 0x02};
uint16_t loopCheckDelay = 1500;
uint64_t loopCheckMillis;
int rampSpeed = 20; // Adjust the speed of ramping
int direction = 1; // 1 for increasing, -1 for decreasing
void setup()
{
Serial.begin(115200);
Serial.println("Starting BLE work!");
bleGamepadConfig.setAutoReport(false);
bleGamepadConfig.setControllerType(CONTROLLER_TYPE_GAMEPAD); // CONTROLLER_TYPE_JOYSTICK, CONTROLLER_TYPE_GAMEPAD (DEFAULT), CONTROLLER_TYPE_MULTI_AXIS
bleGamepadConfig.setVid(0xe502);
bleGamepadConfig.setPid(0xabcd);
bleGamepadConfig.setModelNumber("1.0");
bleGamepadConfig.setSoftwareRevision("Software Rev 1");
bleGamepadConfig.setSerialNumber("987654321B");
bleGamepadConfig.setFirmwareRevision("2.0");
bleGamepadConfig.setHardwareRevision("1.7");
// Some non-Windows operating systems and web based gamepad testers don't like min axis set below 0, so 0 is set by default
//bleGamepadConfig.setAxesMin(0x8001); // -32767 --> int16_t - 16 bit signed integer - Can be in decimal or hexadecimal
bleGamepadConfig.setAxesMin(0x0000); // 0 --> int16_t - 16 bit signed integer - Can be in decimal or hexadecimal
bleGamepadConfig.setAxesMax(0x7FFF); // 32767 --> int16_t - 16 bit signed integer - Can be in decimal or hexadecimal
bleGamepad.begin(&bleGamepadConfig); // Begin gamepad with configuration options
//esp_base_mac_addr_set(&newMACAddress[0]); // Set new MAC address
//randomSeed(analogRead(A0)); // Seed the random number generator with noise from an unconnected analog pin
}
void loop()
{
if (bleGamepad.isConnected())
{
if (millis() - loopCheckMillis > loopCheckDelay )
{
/*
if(batteryLevel > 0)
{
batteryLevel -= 1;
}
*/
// Update battery level with randomness
batteryLevel += direction * (random(1, 5)); // Ramp up or down by a random value between 1 and 4
// Change direction randomly
if (random(0, 100) < 5) { // 5% chance to change direction
direction *= -1;
}
// Keep battery level within the range of 5 to 95
if (batteryLevel > 95) {
batteryLevel = 95;
direction = -1; // Change direction to decrease
} else if (batteryLevel < 5) {
batteryLevel = 5;
direction = 1; // Change direction to increase
}
Serial.print("Battery Level Set To: ");
Serial.print(batteryLevel);
Serial.println("%");
bleGamepad.setBatteryLevel(batteryLevel);
// delay(30000);
// Delay to control ramp speed
//delay(rampSpeed);
//restart this TIMER
loopCheckMillis = millis();
}
}
}
My start up logs for one of the devices, looks like
11:03:45.486 -> D NimBLEAdvertising: << Advertising start
11:03:45.486 -> D NimBLECharacteristic: >> setValue: length=1, data=64, characteristic UUID=0x2a19
11:03:45.519 -> D NimBLECharacteristic: << setValue
11:03:45.519 -> [ 2745][D][BleGamepad.cpp:1437] taskServer(): [BLEGamepad] Advertising started!
11:05:59.178 -> D NimBLEServer: >> handleGapEvent:
11:05:59.178 -> D NimBLEServerCallbacks: onConnect(): Default
11:05:59.178 -> Battery Level Set To: 95%
11:05:59.178 -> D NimBLECharacteristic: >> setValue: length=1, data=5f, characteristic UUID=0x2a19
11:05:59.178 -> D NimBLECharacteristic: << setValue
11:05:59.211 -> D NimBLECharacteristic: >> notify: length: 1
11:05:59.211 -> D NimBLECharacteristic: << notify: No clients subscribed.
11:05:59.360 -> D NimBLEServer: >> handleGapEvent:
11:05:59.360 -> D NimBLEServerCallbacks: onAuthenticationComplete: default
11:05:59.360 -> D NimBLEServer: >> handleGapEvent:
11:05:59.360 -> I NimBLEServer: subscribe event; attr_handle=35, subscribed: true
11:05:59.360 -> I NimBLECharacteristic: New subscribe value for conn: 1 val: 1
11:05:59.360 -> D NimBLECharacteristicCallbacks: onSubscribe: default
11:05:59.360 -> D NimBLEServer: >> handleGapEvent:
11:05:59.360 -> I NimBLEServer: subscribe event; attr_handle=8, subscribed: false
11:05:59.360 -> D NimBLEServer: >> handleGapEvent:
11:05:59.360 -> I NimBLEServer: subscribe event; attr_handle=40, subscribed: true
11:05:59.396 -> I NimBLECharacteristic: New subscribe value for conn: 1 val: 1
11:05:59.396 -> D NimBLECharacteristicCallbacks: onSubscribe: default
11:05:59.396 -> D NimBLEServer: >> handleGapEvent:
11:05:59.396 -> I NimBLEServer: mtu update event; conn_handle=1 mtu=104
11:05:59.396 -> D NimBLEServerCallbacks: onMTUChange(): Default
11:05:59.431 -> D NimBLEServer: >> handleGapEvent:
11:05:59.431 -> D NimBLEServer: Connection parameters updated.
11:05:59.431 -> D NimBLECharacteristic: Characteristic 0x2a19 Read event
11:05:59.431 -> D NimBLECharacteristicCallbacks: onRead: default
11:05:59.431 -> D NimBLECharacteristicCallbacks: onRead: default
11:05:59.713 -> Battery Level Set To: 93%
11:05:59.713 -> D NimBLECharacteristic: >> setValue: length=1, data=5d, characteristic UUID=0x2a19
11:05:59.713 -> D NimBLECharacteristic: << setValue
11:05:59.713 -> D NimBLECharacteristic: >> notify: length: 1
11:05:59.713 -> D NimBLECharacteristicCallbacks: onNotify: default
11:05:59.713 -> D NimBLEServer: >> handleGapEvent:
11:05:59.713 -> D NimBLECharacteristicCallbacks: onStatus: default
11:05:59.713 -> D NimBLECharacteristic: << notify
11:06:00.218 -> Battery Level Set To: 90%
Last post for today on this item ... ;-).
I have set my Core Debug Level
to verbose and get the following logs on start up
1:03:44.916 -> [ 157][V][esp32-hal-periman.c:235] perimanSetBusDeinit(): Dein=========== Before Setup Start ===========
11:03:44.916 -> Chip Info:
11:03:44.916 -> ------------------------------------------
11:03:44.916 -> Model : ESP32-C3
11:03:44.916 -> Package : 0
11:03:44.916 -> Revision : 4
11:03:44.916 -> Cores : 1
11:03:44.916 -> CPU Frequency : 160 MHz
11:03:44.916 -> XTAL Frequency : 40 MHz
11:03:44.916 -> Features Bitfield : 0x00000012
11:03:44.916 -> Embedded Flash : No
11:03:44.916 -> Embedded PSRAM : No
11:03:44.916 -> 2.4GHz WiFi : Yes
11:03:44.916 -> Classic BT : No
11:03:44.916 -> BT Low Energy : Yes
11:03:44.916 -> IEEE 802.15.4 : No
11:03:44.916 -> ------------------------------------------
11:03:44.916 -> INTERNAL Memory Info:
11:03:44.916 -> ------------------------------------------
11:03:44.916 -> Total Size : 303944 B ( 296.8 KB)
11:03:44.916 -> Free Bytes : 276128 B ( 269.7 KB)
11:03:44.916 -> Allocated Bytes : 23928 B ( 23.4 KB)
11:03:44.916 -> Minimum Free Bytes: 271060 B ( 264.7 KB)
11:03:44.916 -> Largest Free Block: 131060 B ( 128.0 KB)
11:03:44.916 -> ------------------------------------------
11:03:44.916 -> Flash Info:
11:03:44.916 -> ------------------------------------------
11:03:44.916 -> Chip Size : 4194304 B (4 MB)
11:03:44.916 -> Block Size : 65536 B ( 64.0 KB)
11:03:44.916 -> Sector Size : 4096 B ( 4.0 KB)
11:03:44.916 -> Page Size : 256 B ( 0.2 KB)
11:03:44.916 -> Bus Speed : 80 MHz
11:03:44.954 -> Bus Mode : QIO
11:03:44.954 -> ------------------------------------------
11:03:44.954 -> Partitions Info:
11:03:44.954 -> ------------------------------------------
11:03:44.954 -> nvs : addr: 0x00009000, size: 20.0 KB, type: DATA, subtype: NVS
11:03:44.954 -> otadata : addr: 0x0000E000, size: 8.0 KB, type: DATA, subtype: OTA
11:03:44.954 -> app0 : addr: 0x00010000, size: 1280.0 KB, type: APP, subtype: OTA_0
11:03:44.954 -> app1 : addr: 0x00150000, size: 1280.0 KB, type: APP, subtype: OTA_1
11:03:44.954 -> spiffs : addr: 0x00290000, size: 1408.0 KB, type: DATA, subtype: SPIFFS
11:03:44.954 -> coredump : addr: 0x003F0000, size: 64.0 KB, type: DATA, subtype: COREDUMP
11:03:44.954 -> ------------------------------------------
11:03:44.954 -> Software Info:
11:03:44.954 -> ------------------------------------------
11:03:44.954 -> Compile Date/Time : Sep 14 2024 10:44:33
11:03:44.954 -> Compile Host OS : macosx
11:03:44.954 -> ESP-IDF Version : v5.1.4-586-gb6b4727c58-dirty
11:03:44.954 -> Arduino Version : 3.0.4
11:03:44.954 -> ------------------------------------------
11:03:44.954 -> Board Info:
11:03:44.954 -> ------------------------------------------
11:03:44.954 -> Arduino Board : ESP32C3_DEV
11:03:44.954 -> Arduino Variant : dfrobot_beetle_esp32c3
11:03:44.954 -> Arduino FQBN : esp32:esp32:dfrobot_beetle_esp32c3:CDCOnBoot=cdc,PartitionScheme=default,CPUFreq=160,FlashMode=qio,FlashFreq=80,FlashSize=4M,UploadSpeed=115200,DebugLevel=verbose,EraseFlash=none
11:03:44.954 -> ============ Before Setup End ============
11:03:45.026 -> [ 2279][I][esp32-hal-periman.c:141] perimanSetPinBus(): Pin 18 already has type USB_DM (38) with bus 0x3fc94c2c
11:03:45.026 -> [ 2279][I][esp32-hal-periman.c:141] perimanSetPinBus(): Pin 19 already has type USB_DP (39) with bus 0x3fc94c2c
11:03:45.026 -> Starting BLE work!
11:03:45.026 -> =========== After Setup Start ============
11:03:45.026 -> INTERNAL Memory Info:
11:03:45.026 -> ------------------------------------------
11:03:45.026 -> Total Size : 303944 B ( 296.8 KB)
11:03:45.026 -> Free Bytes : 228660 B ( 223.3 KB)
11:03:45.026 -> Allocated Bytes : 70820 B ( 69.2 KB)
11:03:45.026 -> Minimum Free Bytes: 228660 B ( 223.3 KB)
11:03:45.063 -> Largest Free Block: 114676 B ( 112.0 KB)
11:03:45.063 -> ------------------------------------------
11:03:45.063 -> GPIO Info:
11:03:45.063 -> ------------------------------------------
11:03:45.063 -> GPIO : BUS_TYPE[bus/unit][chan]
11:03:45.063 -> --------------------------------------
11:03:45.063 -> 18 : USB_DM
11:03:45.063 -> 19 : USB_DP
11:03:45.063 -> 20 : UART_RX[0]
11:03:45.063 -> 21 : UART_TX[0]
11:03:45.063 -> ============ After Setup End =============
Been thinking more about this issue. Some ideas that we could test. If the same firmware is upload to both devices, which has the same serial number, this could cause this problem I guess. I could see how that could happen pretty easy.
I will see if I can reproduce tomorrow. I can also upload my two firmwares images that I made.
Android can just be used for testing gamepad, like Game Controller Tester ... I am sure there are others.
Another test, try the ESP32 Keyboard or Mouse at the same time as the ESP32 BLE Game.
Looking to rule out two of the same frimwares, default mac address uploaded to both devices. Different ESP-IDF Version ( v5.1.4-586-gb6b4727c58-dirty) and/or Arduino Core Version (3.0.4) and/or Bluetooth stack and lastly, software or hardware fault.
Doing keyboard and mice tests will rule out Host OS hardware, software and possible drivers.
Another idea would be to try two totally different firmware tools, like RealRobots Gamepad Configurator.
I think my PoC proves select using test case of multiple guest devices that can connect to a host, if under the correct conditions. If we can found out the conditions that don't work and document them, other people will not fall into these same problems. Also hopeful make it easier for somebody to pick up a failed task and see what progress they can make.
Can't wait ti poke at some setup ideas and see what we find. Hoping a boomtasic and fun journey tomorrow.
This is a very exciting. I used ArduinoIDE to write the original code in one esp32 and realrobots in another, the two can be connected to one Win PC at the same time.
This also indirectly proves that the previous problem may be caused by the firmware.
It’s just that realrobots is not powerful enough at present. For example, I use a joystick, and the way it identifies the direction is actually to use the four buttons of up, down, left and right. In the code, I can use bleGamepad.setAxes
to convert the coordinates, but this cannot be achieved in realrobots.
So currently I can only use four buttons to replace Axes.
I did another experiment. After uploading the RealRobots Gamepad firmware to esp32, I did not use the connect function of RealRobots, but directly used ArduinoIDE to write the original code. This also did not work.
Been thinking more about this issue. Some ideas that we could test. If the same firmware is upload to both devices, which has the same serial number, this could cause this problem I guess. I could see how that could happen pretty easy.
I will see if I can reproduce tomorrow. I can also upload my two firmwares images that I made.
Android can just be used for testing gamepad, like Game Controller Tester ... I am sure there are others.
Another test, try the ESP32 Keyboard or Mouse at the same time as the ESP32 BLE Game.
Looking to rule out two of the same frimwares, default mac address uploaded to both devices. Different ESP-IDF Version ( v5.1.4-586-gb6b4727c58-dirty) and/or Arduino Core Version (3.0.4) and/or Bluetooth stack and lastly, software or hardware fault.
Doing keyboard and mice tests will rule out Host OS hardware, software and possible drivers.
Another idea would be to try two totally different firmware tools, like RealRobots Gamepad Configurator.
I think my PoC proves select using test case of multiple guest devices that can connect to a host, if under the correct conditions. If we can found out the conditions that don't work and document them, other people will not fall into these same problems. Also hopeful make it easier for somebody to pick up a failed task and see what progress they can make.
Can't wait ti poke at some setup ideas and see what we find. Hoping a boomtasic and fun journey tomorrow.
Could you confirm if you were using NimBLE version 1.4.1 or 1.4.2 for these tests? @sosssego would you be able to confirm the same? I'm trying to track down this problem myself and I'm curious if it relates to issue #229. I'm attempting a fix in #230.
The version of NimBLE used is 1.4.2. One of my esp32 seems to be broken, so I can't test with 1.4.1 again.
@leonhoo i think i can confirm it.I have a problem with 1.4.2 i can't use multiple devices and when i tried 1.4.1 it have no problem with it everything worked well
@leonhoo @OatKungKTZ I managed to get it working over in #230. Try pulling that fix and if that doesn't work, upgrade your NimBLE-Arduino to the 1.5 branch as well.
@Mystfit i tried once (your method) with 1.4.2 but it's doesn't work ok will try again with 1.5
@OatKungKTZ My fix probably isn't the solution but it could be related to upstream issue in the esp-nimble repo which enforces new IRK keys on a fresh boot. This fix is available in esp-nimble 1.5.0 which was merged into Nimble-Arduino at the end of June. Nimble-Arduino 1.5 is not officially released yet so you'll have to clone it instead of using the Arduino library manager.
Thank you @leonhoo for pointing me in the right direction regarding IRK.
Borrowed another esp32 to test again, and the 1.4.1 version still didn't solve the problem. Yes, both esp32s could connect to the computer, but after a short while, one of them would automatically disconnect and reconnect, repeating this action over and over again.
Borrowed another esp32 to test again, and the 1.4.1 version still didn't solve the problem. Yes, both esp32s could connect to the computer, but after a short while, one of them would automatically disconnect and reconnect, repeating this action over and over again.
Give the Nimble-Arduino 1.5 branch a go.
https://github.com/user-attachments/assets/1ddaa2cf-ece9-40fe-b049-23eaef991a41 #mac https://github.com/user-attachments/assets/b61a8cd3-d5e0-4cdc-8d44-abeeae386fbe #win11
Nimble-Arduino 1.5, the issue remains.
/************************** Gamepad1 *************************/
char *GAMEPAD_NAME = "EGP1";
char *MODEL_NUMBER = "1.0.1";
char *SERIAL_NUMBER = "11111111";
int VID = 0x1101;
int PID = 0x1102;
/************************** Gamepad2 *************************/
// char *GAMEPAD_NAME = "EGP2";
// char *MODEL_NUMBER = "1.0.2";
// char *SERIAL_NUMBER = "22222222";
// int VID = 0x2201;
// int PID = 0x2202;
/************************** END *************************/
Any update?
Even though I have two different vid pid esp cards, I can't connect the second card while one is paired (even when it's not connected). I have to unpair the first one first.
I have been playing with PlatformIO, as I ran into problems with funky library versions issues in other problems(at least I did think I was, but it was GPIO differences with different ESP32 boards). I was wondering if anybody would like to test the firmware builds that work for me, not just the source code or PlatformIO project. Try and rule out local library problems.
Also wondering, how many people facing this problem is local to Widows host OS? I have tried on multiple OSX versions and platforms (x86_64/aarch64) and multiple Android devices without running into this problem. I really should test some more on Linux, I have enough of the devices near by, just none with a desktop.
Last idea for request for feedback, any suggestions on what to add into the debugging sketch that might help with insight to where or what might be the problem. Please add reason why or how the addition with be helpful in the debugging sketch.
I tried to use the BLE gamepad example from Arduino to make 2 gamepads and play cooperative games. The only difference in code is the name of the gamepad
BleGamepad bleGamepad("Gamepad1");
BleGamepad bleGamepad("Gamepad2");
When trying to connect the second gamepad windows Failed and asked to try again. Trying again resulted in the same issue.I used 2 generic ESP32 devkit V1.
Connecting the controllers alone works ok.
Is there anything else I need to change in the code between the 2 gamepads?
example code: