0% found this document useful (0 votes)
93 views4 pages

ESP32 BLE Gamepad Code Example

This document contains an Arduino sketch for a BLE gamepad using an ESP32, defining pin configurations for joysticks and buttons. It includes setup and loop functions to read joystick values, button states, and send reports via Bluetooth. The code also features a debug mode for printing the gamepad status and joystick movements.

Uploaded by

Abdullah Mian
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
93 views4 pages

ESP32 BLE Gamepad Code Example

This document contains an Arduino sketch for a BLE gamepad using an ESP32, defining pin configurations for joysticks and buttons. It includes setup and loop functions to read joystick values, button states, and send reports via Bluetooth. The code also features a debug mode for printing the gamepad status and joystick movements.

Uploaded by

Abdullah Mian
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd

#include <Arduino.

h>
#include <BleGamepad.h>

/* ===================== YOUR ACTUAL PINOUT ===================== */

// RIGHT JOYSTICK
#define RIGHT_VRX_JOYSTICK 12
#define RIGHT_VRY_JOYSTICK 13
#define R3_BUTTON 33

// LEFT JOYSTICK
#define LEFT_VRX_JOYSTICK 14
#define LEFT_VRY_JOYSTICK 27
#define L3_BUTTON 32

// BUTTONS (Pin → Button → GND)


#define SW1_BUTTON 15
#define SW2_BUTTON 17
#define SW3_BUTTON 4
#define SW4_BUTTON 5

#define NUM_BUTTONS 6

int buttonsPins[NUM_BUTTONS] = {
SW1_BUTTON, SW2_BUTTON, SW3_BUTTON,
SW4_BUTTON, R3_BUTTON, L3_BUTTON
};

const char* buttonNames[NUM_BUTTONS] = {


"SW1", "SW2", "SW3", "SW4", "R3", "L3"
};

int PCGamepadButtons[NUM_BUTTONS] = {
1, 2, 3, 4, 11, 12
};

/* ===================== VARIABLES ===================== */

uint16_t lxRaw, lyRaw, rxRaw, ryRaw;


uint16_t lxVal, lyVal, rxVal, ryVal;

uint16_t prevLx = 0, prevLy = 0, prevRx = 0, prevRy = 0;


bool prevButtonStates[NUM_BUTTONS] = {false};
bool prevConnected = false;

const int JOYSTICK_THRESHOLD = 50;

BleGamepad bleGamepad("ESP32_BLE_Gamepad", "ESP32");

/* ===================== HELPERS ===================== */

void printAligned(int value, int width) {


int len = String(value).length();
for (int i = 0; i < width - len; i++) [Link](" ");
[Link](value);
}

void printStatus() {
[Link]();
[Link]("══════════════════════════════════════");
[Link](" ESP32 BLE GAMEPAD STATUS");
[Link]("══════════════════════════════════════");

[Link](" BLE : ");


[Link]([Link]() ? "CONNECTED" : "DISCONNECTED");
[Link]();

[Link](" LEFT JS : X=");


printAligned(lxRaw, 4);
[Link](" (");
printAligned(lxVal, 5);
[Link](") | Y=");
printAligned(lyRaw, 4);
[Link](" (");
printAligned(lyVal, 5);
[Link](")");

[Link](" RIGHT JS : X=");


printAligned(rxRaw, 4);
[Link](" (");
printAligned(rxVal, 5);
[Link](") | Y=");
printAligned(ryRaw, 4);
[Link](" (");
printAligned(ryVal, 5);
[Link](")");

[Link]();
[Link](" BUTTONS :");

for (int i = 0; i < NUM_BUTTONS; i++) {


bool pressed = !digitalRead(buttonsPins[i]);
[Link](" ");
[Link](buttonNames[i]);
[Link](" [");
printAligned(buttonsPins[i], 2);
[Link]("] : ");
[Link](pressed ? "PRESSED" : "RELEASED");
}

[Link]("══════════════════════════════════════");
}

/* ===================== SETUP ===================== */

void setup() {
[Link](115200);
delay(1000);

[Link]("=================================");
[Link](" ESP32 BLE GAMEPAD DEBUG MODE");
[Link](" Press 's' to print full status");
[Link]("=================================\n");

for (int i = 0; i < NUM_BUTTONS; i++) {


pinMode(buttonsPins[i], INPUT_PULLUP);
}
BleGamepadConfiguration cfg;
[Link](false);
[Link](CONTROLLER_TYPE_GAMEPAD);
[Link](16);
[Link](0);

[Link](&cfg);
}

/* ===================== LOOP ===================== */

void loop() {

// Serial command
if ([Link]()) {
char c = [Link]();
if (c == 's' || c == 'S') {
printStatus();
}
}

// Read joysticks
lxRaw = analogRead(LEFT_VRX_JOYSTICK);
lyRaw = analogRead(LEFT_VRY_JOYSTICK);
rxRaw = analogRead(RIGHT_VRX_JOYSTICK);
ryRaw = analogRead(RIGHT_VRY_JOYSTICK);

lxVal = map(lxRaw, 0, 4095, 0, 32767);


lyVal = map(lyRaw, 0, 4095, 0, 32767);
rxVal = map(rxRaw, 0, 4095, 0, 32767);
ryVal = map(ryRaw, 0, 4095, 0, 32767);

// Log joystick changes


if (abs(lxRaw - prevLx) > JOYSTICK_THRESHOLD) {
[Link]("LEFT X : %4d → %4d\n", prevLx, lxRaw);
prevLx = lxRaw;
}
if (abs(lyRaw - prevLy) > JOYSTICK_THRESHOLD) {
[Link]("LEFT Y : %4d → %4d\n", prevLy, lyRaw);
prevLy = lyRaw;
}
if (abs(rxRaw - prevRx) > JOYSTICK_THRESHOLD) {
[Link]("RIGHT X : %4d → %4d\n", prevRx, rxRaw);
prevRx = rxRaw;
}
if (abs(ryRaw - prevRy) > JOYSTICK_THRESHOLD) {
[Link]("RIGHT Y : %4d → %4d\n", prevRy, ryRaw);
prevRy = ryRaw;
}

// Buttons
for (int i = 0; i < NUM_BUTTONS; i++) {
bool pressed = !digitalRead(buttonsPins[i]);
if (pressed != prevButtonStates[i]) {
[Link](buttonNames[i]);
[Link](" : ");
[Link](pressed ? "PRESSED" : "RELEASED");
prevButtonStates[i] = pressed;
}
}

// BLE connection change


bool connected = [Link]();
if (connected != prevConnected) {
[Link](connected ? "\n*** BLE CONNECTED ***\n"
: "\n*** BLE DISCONNECTED ***\n");
prevConnected = connected;
}

// Send BLE report


if ([Link]()) {
for (int i = 0; i < NUM_BUTTONS; i++) {
!digitalRead(buttonsPins[i]) ?
[Link](PCGamepadButtons[i]) :
[Link](PCGamepadButtons[i]);
}

[Link](lxVal);
[Link](lyVal);
[Link](rxVal);
[Link](ryVal);
[Link]();
}

delay(10);
}

Common questions

Powered by AI

The code uses an array `prevButtonStates` to keep track of the last known state of each button. It reads each button’s current state using `digitalRead`, compares it to the stored state, and updates the stored state if a change is detected. If the BLE connection is active, it registers the button press or release using `bleGamepad.press` or `bleGamepad.release`, then sends the report using `bleGamepad.sendReport()`.

The mechanism used to map joystick analog values to a specific range is the 'map' function in Arduino. It converts the values from the range of 0 to 4095 (the raw analogRead values) to 0 to 32767, which likely aligns with a standard gamepad input range.

The 'printAligned' helper function formats and aligns numeric output by calculating the number of leading spaces needed to fit a specific width before printing the value, ensuring that serial output is cleanly formatted and easy to read. This function is used when outputting the joystick and button status on the Serial Monitor.

The code tracks changes in joystick movement by comparing the current raw values (`lxRaw`, `lyRaw`, `rxRaw`, `ryRaw`) against their previous states stored in `prevLx`, `prevLy`, `prevRx`, `prevRy`. If a change exceeds a predefined threshold (`JOYSTICK_THRESHOLD`), it logs the updated values to the Serial Monitor. These raw values are mapped using the `map` function to a range of 0 to 32767, which are then presumably sent over BLE if connected. This ensures transitions are smooth and changes are significant enough to represent meaningful user actions.

Modifying the ESP32 BLE gamepad code to support additional buttons would involve expanding the `buttonsPins` and `buttonNames` arrays to include new pins and names. The `NUM_BUTTONS` variable would need to be updated, and potentially the `PCGamepadButtons` array if the BLE device's button mapping needs adjustment. Additional handling in the loop to manage new button state changes would also be necessary, and consideration of BLE report limits. Resource availability, such as GPIO pins and processing capacity, must be evaluated to maintain performance and reliability.

The ESP32 BLE gamepad code checks the Bluetooth connection status using the `bleGamepad.isConnected()` method. If there's a change in connection status, it prints a message to the Serial Monitor indicating whether the device is connected or disconnected. This change is also stored in the `prevConnected` variable to detect future changes.

Failing to set the correct configuration in the 'BleGamepadConfiguration' object can lead to incorrect operation of the gamepad. This would include setting inappropriate values for automatic reporting and the type of controller, which controls how inputs are interpreted and reported to connected devices. Incorrect configurations might result in improper button mappings or latency issues in input reporting, degrading the user experience. The setup includes specific configurations like disabling auto-report and adjusting button count, essential for correctly aligning with typical gamepad use expectations.

Incorrectly applying a joystick threshold could result in either over-sensitivity or unresponsiveness in joystick reporting. If too low, minor fluctuations or noise would constantly trigger updates, overwhelming the communication channel and reducing performance. If set too high, significant user movements may not be registered, limiting the device's usability and precision. Proper calibration ensures meaningful user inputs are captured and transmitted, balancing responsiveness with stability.

The program listens for serial input, checking for the presence of 's' or 'S' to trigger the `printStatus()` function. This function outputs the status of the BLE connection, joystick readings, and button states to the Serial Monitor, providing valuable diagnostics during development and debugging without additional on-device interfaces. This approach allows real-time insight into device states and inputs, essential for effective troubleshooting.

The pin configuration for the joysticks and buttons appears well-organized, with dedicated pins for each component. Utilizing `INPUT_PULLUP` for button pins suggests a robust design against no-input states. However, the use of discrete digital and analog pins makes the setup flexible but potentially challenging to scale if additional input types or sensors are desired. The selected pins seem appropriate for the ESP32’s capabilities, balancing the use of both GPIO and ADC functionalities effectively.

You might also like