Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issues and Feature requests #259

Open
DrSimgear opened this issue Jan 22, 2025 · 9 comments
Open

Issues and Feature requests #259

DrSimgear opened this issue Jan 22, 2025 · 9 comments

Comments

@DrSimgear
Copy link
Contributor

DrSimgear commented Jan 22, 2025

There is this #include <driver/adc.h> in

#include <driver/adc.h>

picture
I'm not sure why its there but I was getting this warning so I removed it and warning went away.

Second Issue;
Throttle axis is int16 but it should be uint16. When I set 65535 and 0 as max min, it doesn't really work the way I intend since the max is 32767. I also use the Joystick_ESP32S2 library in combination with it for usb gamepad so I switch between usb and ble on the fly. On that using 65535 and 0 works perfectly well but if I connect through ble then the numbers go into negative because anything above 32767 loops around to -32767. Throttle shouldn't need to go into negative, there is no games that need negative throttle values afaik

Third;
I would like to be able to disconnect clients and start/stop advertising ble. There is functions in nimble arduino library to do this but I couldn't figure it out how to add them to my arduino program because I couldn't get the syntax right. First I tried to turn off ble all together but when I turned it back on I would get overflow because there is a procedure you have to follow to turn off ble properly, someone posted how for esp idf but I couldn't get the syntax right for it in arduino ide. Basically I would like for esp32 ble connection to cut out when I plug in the usb into a computer at which point the usb gamepad takes over or vice versa, since they look like the same device with the same vid and pid, etc. games start getting inputs from the usb without having to rebind etc.

@LeeNX
Copy link
Contributor

LeeNX commented Jan 22, 2025

Thanks @DrSimgear for the report. Some suggestions to make tracking and offering assistants easier, would be break your issue up into small, clear issues, each of there own. You could link them in the description or comments if they are related. Just makes things little easier for everybody. Also providing a link to your code or snippets showing the problem would take a lot of guess work out for people wanting to help.

First issue:
might be worth removing. I don't see where any ADC stuff is happening directly in the library. Why don't you make a PR, then we can test. This will get you GitHub street cred. Somebody else might do it, if you don't know how, but maybe you would like to try and we can help you along.

Second issue:
I have not used axis other than in the test sketchers, so can't give you a clear answer, but hopefully I can offer some suggestions. I think the HID description is for two byte value. Setting the minimum value to zero, might help?
As outline in FlightControllerTest.ino

// 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.setAxesMax(0x7FFF); // 32767 --> int16_t - 16 bit signed integer - Can be in decimal or hexadecimal
// Shows how simulation control min/max axes can be set independently of the other axes
bleGamepadConfig.setSimulationMin(-255); // -255 --> int16_t - 16 bit signed integer - Can be in decimal or hexadecimal
bleGamepadConfig.setSimulationMax(255); // 255 --> int16_t - 16 bit signed integer - Can be in decimal or hexadecimal

Third:
I am guessing you looking at turn off bluetooth in your sketch vs disconnecting the currently connected client. This is where splitting this up into multiple issues would be better, because now discussing this item does not really relate to the other items.
I have a ToDo item to ban a client from connecting or just disconnecting, something like

void disconnectClient() {
    NimBLEServer* server = NimBLEDevice::getServer();
    if (server) {
        // Iterate through connected peer devices
        for (uint16_t connHandle : server->getPeerDevices()) {
            server->disconnect(connHandle); // Disconnect the client
            Serial.printf("Disconnected client with connHandle: %d\n", connHandle);
        }
    } else {
        Serial.println("No server instance available.");
    }
}

void loop() {
    // For demonstration: disconnect the client when a button is pressed
    if (bleGamepad.isConnected()) {
        Serial.println("BLE Client connected");
        
        // Add your gamepad logic here
        
        // Simulate a disconnect action
        if (digitalRead(0) == LOW) { // Assuming a button is wired to pin 0
            disconnectClient();
        }
    }

    delay(100); // Adjust as needed
}

This just compiles, I have not tested further.

Let us know how it does.

@DrSimgear
Copy link
Contributor Author

Hi, Thanks for the reply @LeeNX . I made a pr, let me know if it's good to go. Sorry I shouldn't have combined multiple issues, I didn't want to add spam too much. For the third issue, I will give the code a try on the weekend. I think I will need to add the advertising part to it too because I want windows to reconnect back when I unplug usb.

Second issue: https://github.com/DrSimgear/OH58-Kiowa-Collective
I created a repository for my code to make things easier. Basically throttle in BLE Gamepad is a signed 16bit value. Which goes from -32767 to +32767. Even if I set it to 0 and 65535 which is a unsigned 16bit value, if my throttle goes above +32767 then it will loop back to -32767 in windows.

@lemmingDev
Copy link
Owner

Setting axes should now be fixed in https://github.com/lemmingDev/ESP32-BLE-Gamepad/releases/tag/v0.6.6

@DrSimgear
Copy link
Contributor Author

@lemmingDev I updated to newest version and flashed same firmware but axis output from ble is stuck at 0. It is sending button states though and I can see axis position change in serial monitor.

@lemmingDev
Copy link
Owner

ooh - should've tested myself - I see no axes are working now after the recent release

I've just tested myself, and there didn't seem to be any issues in the first place in all of the built-in examples for my library before I updated it trying to fix an issue (that perhaps doesn't exist?)

I'll release a new version reverting back to the way it was and then might check your controller code for issues

Thanks

@lemmingDev
Copy link
Owner

Here is an updated driving controller test sketch where you can set the axes min to either a zero or negative value, and it works perfectly across the entire range

I cannot find any issue whatsoever

Please test and confirm the same with updated v0.6.8 release

/*
 * Driving controller test
 */

#include <Arduino.h>
#include <BleGamepad.h>

#define numOfButtons 10
#define numOfHatSwitches 0
#define enableX false
#define enableY false
#define enableZ false
#define enableRX false
#define enableRY false
#define enableRZ false
#define enableSlider1 false
#define enableSlider2 false
#define enableRudder false
#define enableThrottle false
#define enableAccelerator true
#define enableBrake true
#define enableSteering true

//int16_t simMin = 0x8000;      // -32767 --> Some non-Windows operating systems and web based gamepad testers don't like min axis set below 0, so 0 is set by default
//int16_t axesCenter = 0x00;      
int16_t simMin = 0x00;        // Set simulation minimum axes to zero.
int16_t axesCenter = 0x3FFF;
int16_t simMax = 0x7FFF;        // 32767 --> int16_t - 16 bit signed integer - Can be in decimal or hexadecimal
int16_t stepAmount = 0xFF;
uint16_t delayAmount = 25;

BleGamepad bleGamepad("BLE Driving Controller", "lemmingDev", 100);

void setup()
{
    Serial.begin(115200);
    Serial.println("Starting BLE work!");

    // Setup controller with 10 buttons, accelerator, brake and steering
    BleGamepadConfiguration bleGamepadConfig;
    bleGamepadConfig.setAutoReport(false);
    bleGamepadConfig.setControllerType(CONTROLLER_TYPE_GAMEPAD); // CONTROLLER_TYPE_JOYSTICK, CONTROLLER_TYPE_GAMEPAD (DEFAULT), CONTROLLER_TYPE_MULTI_AXIS
    bleGamepadConfig.setButtonCount(numOfButtons);
    bleGamepadConfig.setWhichAxes(enableX, enableY, enableZ, enableRX, enableRY, enableRZ, enableSlider1, enableSlider2);      // Can also be done per-axis individually. All are true by default
    bleGamepadConfig.setWhichSimulationControls(enableRudder, enableThrottle, enableAccelerator, enableBrake, enableSteering); // Can also be done per-control individually. All are false by default
    bleGamepadConfig.setHatSwitchCount(numOfHatSwitches);                                                                      // 1 by default
    bleGamepadConfig.setSimulationMin(simMin);
    bleGamepadConfig.setSimulationMax(simMax);
    
    bleGamepad.begin(&bleGamepadConfig);
    // changing bleGamepadConfig after the begin function has no effect, unless you call the begin function again

    // Set steering to center
    bleGamepad.setSteering(axesCenter);

    // Set brake and accelerator to min
    bleGamepad.setBrake(simMin);
    bleGamepad.setAccelerator(simMax);

    bleGamepad.sendReport();
}

void loop()
{
    if (bleGamepad.isConnected())
    {
        Serial.println("Press all buttons one by one");
        for (int i = 1; i <= numOfButtons; i += 1)
        {
            bleGamepad.press(i);
            bleGamepad.sendReport();
            delay(100);
            bleGamepad.release(i);
            bleGamepad.sendReport();
            delay(25);
        }

        Serial.println("Move steering from center to min");
        for (int i = axesCenter; i > simMin; i -= stepAmount)
        {
            bleGamepad.setSteering(i);
            bleGamepad.sendReport();
            delay(delayAmount);
        }

        Serial.println("Move steering from min to max");
        for (int i = simMin; i < simMax; i += stepAmount)
        {
            bleGamepad.setSteering(i);
            bleGamepad.sendReport();
            delay(delayAmount);
        }

        Serial.println("Move steering from max to center");
        for (int i = simMax; i > axesCenter; i -= stepAmount)
        {
            bleGamepad.setSteering(i);
            bleGamepad.sendReport();
            delay(delayAmount);
        }
        bleGamepad.setSteering(axesCenter);
        bleGamepad.sendReport();

        Serial.println("Move accelerator from min to max");
        // Axis is reversed, so swap min <--> max
        for (int i = simMax; i > simMin; i -= stepAmount)
        {
            bleGamepad.setAccelerator(i);
            bleGamepad.sendReport();
            delay(delayAmount);
        }

        Serial.println("Move accelerator from max to min");
        // Axis is reversed, so swap min <--> max
        for (int i = simMin; i < simMax; i += stepAmount)
        {
            bleGamepad.setAccelerator(i);
            bleGamepad.sendReport();
            delay(delayAmount);
        }
        bleGamepad.setAccelerator(simMax);
        bleGamepad.sendReport();

        Serial.println("Move brake from min to max");
        for (int i = simMin; i < simMax; i += stepAmount)
        {
            bleGamepad.setBrake(i);
            bleGamepad.sendReport();
            delay(delayAmount);
        }
        
        Serial.println("Move brake from max to min");
        for (int i = simMax; i > simMin; i -= stepAmount)
        {
            bleGamepad.setBrake(i);
            bleGamepad.sendReport();
            delay(delayAmount);
        }
        bleGamepad.setBrake(simMin);
        bleGamepad.sendReport();
    }
}

@lemmingDev
Copy link
Owner

Oh, and don't use anything over 0x7FFF / 32767 in the axes max, as over that goes into negatives values when you assign them to the USB HID descriptor

It's standard int16_t behaviour

Eg,

  Serial.println((int16_t)0x7FFE);
  Serial.println((int16_t)0x7FFF);
  Serial.println((int16_t)0x8000);
  Serial.println((int16_t)0x8001);
  Serial.println((int16_t)0xFFFE);
  Serial.println((int16_t)0xFFFF);

gives you

32766
32767
-32768
-32767
-2
-1

@lemmingDev
Copy link
Owner

lemmingDev commented Jan 25, 2025

Your 65535 is actually 0xFFFF which is -1

Serial.println((int16_t)65535);

gives you

-1

@lemmingDev
Copy link
Owner

lemmingDev commented Jan 25, 2025

I just checked that Joystick_ESP32S2 library you referenced

You should be able to set the 2 lines in Joystick_ESP32S2.cpp from

#define JOYSTICK_AXIS_MAXIMUM 65535
#define JOYSTICK_SIMULATOR_MAXIMUM 65535

to

#define JOYSTICK_AXIS_MAXIMUM 32767
#define JOYSTICK_SIMULATOR_MAXIMUM 32767

and then use 32767 as the max and 0 as the min when setting up my library, and then both libraries should be able to coexist fine in your sketch

I don't think there's a need to modify this library to accept max axis values larger than the max int16_t value of 32767 as even that is overkill for any kind of game controller IMO

0 to 32767 gives 15 bits and -32768 to 32767 gives 16 bits of resolution. I'm not aware of any consumer grade input device that could accurately give that resolution

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants