ESP32 PS3 Controller: connection event

In this tutorial we will learn how to detect when a PS3 controller connects to the ESP32 using an event handling function. We will be using the Arduino core and this library. The tests from this tutorial were done using a DFRobot’s ESP32 module integrated in a ESP32 development board.

Introduction

In this tutorial we will learn how to detect when a PS3 controller connects to the ESP32 using an event handling function. We will be using the Arduino core and this library.

Note that we have already covered here how to setup the ESP32 to receive a PS3 controller connection and we have checked if the controller was already connected using a polling approach.

Nonetheless polling is, in general, a poor approach that leads to wasting CPU cycles that could be used for other useful computation. Naturally, in the use case we have seen so far, this is not noticeable as our program doesn’t do much, but in more complex applications it could have an impact.

So, moving to an event based approach like the one we will see below typically leads to more efficient programs.

The tests from this tutorial were done using a DFRobot’s ESP32 module integrated in a ESP32 development board.

The code

We will start by importing the Ps3Controller.h library, so we have access to the Ps3 extern variable. This variable exposes to us the controller functionalities.

#include <Ps3Controller.h>

Moving on to the Arduino setup, we will start by opening a serial connection, so we can output the results of the program.

Serial.begin(115200);

Next we will initialize the Bluetooth layer of the ESP32 and make it ready to receive a controller connection simply by calling the begin method on the Ps3 extern variable.

As input, we need to pass the Bluetooth address stored on the PS3 controller. This address can be retrieved by following the procedure illustrated here. Note that the mentioned tutorial covers the connection of a PS4 controller but the procedure and the software to find out the Bluetooth address is exactly the same for a PS3 controller.

Since the begin method returns a Boolean value indicating if the initialization procedure was successful or not, we will do an error check. Naturally, if the initialization fails, we will return as there’s no point in trying to get a connection from a controller.

if (!Ps3.begin("Your Controller address")) {
    Serial.println("Initialization failed.");
    return;
}

In case of success in the initialization, we will then register a callback function that will be executed when a controller connects to the ESP32.

We do this by calling the attachOnConnect on the Ps3 variable, passing as input the event handling function. We will call this function onConnection and check its implementation below.

Ps3.attachOnConnect(onConnection);

The complete setup function can be seen below. We have added an extra print to indicate that the initialization procedure was finished with success.

void setup() {

  Serial.begin(115200);

  if (!Ps3.begin("Your Controller address")) {
    Serial.println("Initialization failed.");
    return;
  }

  Serial.println("Initialization finished.");

  Ps3.attachOnConnect(onConnection);

}

Since we are going to work with an event, we don’t need to poll any object periodically in the Arduino main loop function. So, we can simply delete the corresponding FreeRTOS task with a call to the vTaskDelete function.

void loop() {
  vTaskDelete(NULL);
}

To finalize, we are going to analyze the implementation of the onConnection function. This function needs to follow a defined signature: it must return void and receive no arguments.

void onConnection() {
  // function implementation
}

In the implementation of this function we will simply confirm that a controller is connected by calling the isConnected method on the Ps3 extern variable. If it returns true, we will print a message to the serial port.

Note that checking the isConnected output should be redundant as this callback will be executed when the controller connects.

The full implementation of the function can be seen below.

void onConnection() {
  
  if (Ps3.isConnected()) {
    Serial.println("Controller connected.");
  }
}

The final code can be seen below.

#include <Ps3Controller.h>

void onConnection() {
  
  if (Ps3.isConnected()) {
    Serial.println("Controller connected.");
  }
}

void setup() {

  Serial.begin(115200);

  if (!Ps3.begin("Your Controller address")) {
    Serial.println("Initialization failed.");
    return;
  }

  Serial.println("Initialization finished.");

  Ps3.attachOnConnect(onConnection);

}

void loop() {
  vTaskDelete(NULL);
}

Testing the code

To test the code, simply compile it and upload it to your device using the Arduino IDE. Once the procedure finishes, open the serial monitor.

If everything is correctly initialized, a “Initialization finished” message should be printed to the serial monitor.

After that, turn on the controller by pressing the PS button. The controller should connect to the ESP32, thus triggering the execution of the handling function, which will print the message we defined in the code. The expected result can be seen in figure 1 below.

Output of the program on the Arduino IDE serial monitor.
Figure 1 – Output of the program on the Arduino IDE serial monitor.

Leave a Reply

%d bloggers like this: