Tuesday 12 November 2019

ESP32 with PS3 Controller - M5StickC

Arduino PS3 Library for the ESP32

Library available originally written for use with Espressif library, but it does have beta support for Arduino at the time of writing.

https://github.com/jvpernis/esp32-ps3

In my experience the device works well in both loop and callback configurations, but I did see issues when attempting to read all the available data from PS3 controller and then write to the screen. It was causing a device reboot that I wasn't able to easily solve.

How to install library:

Tested with Arduino 1.8.10 on Windows 10.

  1. From the command line, navigate to Arduino/libraries/ folder
  2. git clone https://github.com/jvpernis/esp32-ps3.git
  3. git checkout develop
  4. Restart the Arduino IDE and the library should be available in the "examples" section


How to connect to controller:

There are two ways to configure the controller with your device

  1. Retrieve the Bluetooth MAC address of the device the controller is currently connected to
  2. Set the Bluetooth MAC address of the controller
I've opted for option 1 as it allows me to keep the device connected to my PS3 for normal use. To get the PS3 controller Bluetooth MAC address follow the instructions in the readme and retrieve using the SixaxisPairTool.


M5StickC Testing

Example program showing how to retrieve all the available information from the controller and write to the M5StickC screen:

#include <M5StickC.h>
#include <Ps3Controller.h>

// M5StickC screen parameters
#define TEXT_HEIGHT 16                // Height of text to be printed and scrolled
#define TOP_FIXED_AREA 14             // Number of lines in top fixed area (lines counted from top of screen)
#define BOTTOM_FIXED_AREA 0           // Number of lines in bottom fixed area (lines counted from bottom of screen)
#define YMAX 80                       // Bottom of screen area
#define XMAX 160                      // Bottom of screen area

// M5StickC tracking drawing to screen positions
int deviceName = 0;
int controllerInfoX = 20;
int joystickInfoX = 40;
int gyroInfoX = 60;


void setup() {
  // Setup the TFT display
  M5.begin();
  M5.Lcd.setRotation(3);                               // Must be setRotation(0) for this sketch to work correctly
  M5.Lcd.fillScreen(TFT_BLACK);
  M5.Lcd.setTextColor(TFT_WHITE, TFT_BLUE);
  M5.Lcd.fillRect(0, 0, XMAX, TEXT_HEIGHT, TFT_BLUE);
  M5.Lcd.drawCentreString("AliPhoenix Hexapod", XMAX/2, 0, 2);
  M5.Lcd.setTextColor(TFT_WHITE, TFT_BLACK);    // Change colour for scrolling zone text
  
  // Setup the PS3 controller
  Ps3.begin("2c:81:58:a9:8d:76");

  // Setup the serial port for debugging
  Serial.begin(115200);
  Serial.println("Ready.");
}

void loop()
{
  if (Ps3.isConnected()){
    // Clear the area we will be writing to
    M5.Lcd.fillRect(0, controllerInfoX, XMAX, TEXT_HEIGHT, TFT_BLACK);
    
    if( Ps3.data.button.cross ){ 
      M5.Lcd.drawString("Button: CROSS", 0, controllerInfoX, 2);
    }
    if( Ps3.data.button.square ){
      M5.Lcd.drawString("Button: SQUARE", 0, controllerInfoX, 2);
    }
    if( Ps3.data.button.triangle ){
      M5.Lcd.drawString("Button: TRIANGLE", 0, controllerInfoX, 2);
    }
    if( Ps3.data.button.circle ){
      M5.Lcd.drawString("Button: CIRCLE", 0, controllerInfoX, 2);
    }
    if( Ps3.data.button.left ){
      M5.Lcd.drawString("Button: LEFT", 0, controllerInfoX, 2);
    }
    if( Ps3.data.button.right ){
      M5.Lcd.drawString("Button: RIGHT", 0, controllerInfoX, 2);
    }
    if( Ps3.data.button.up ){
      M5.Lcd.drawString("Button: UP", 0, controllerInfoX, 2);
    }
    if( Ps3.data.button.down ){
      M5.Lcd.drawString("Button: DOWN", 0, controllerInfoX, 2);
    }
    if( Ps3.data.button.l1 ){
      M5.Lcd.drawString("Button: L1", 0, controllerInfoX, 2);
    }
    if( Ps3.data.button.l2 ){
      M5.Lcd.drawString("Button: L2", 0, controllerInfoX, 2);
    }
    if( Ps3.data.button.l3 ){
      M5.Lcd.drawString("Button: L3", 0, controllerInfoX, 2);
    }
    if( Ps3.data.button.r1 ){
      M5.Lcd.drawString("Button: R1", 0, controllerInfoX, 2);
    }
    if( Ps3.data.button.r2 ){
      M5.Lcd.drawString("Button: R2", 0, controllerInfoX, 2);
    }
    if( Ps3.data.button.r3 ){
      M5.Lcd.drawString("Button: R3", 0, controllerInfoX, 2);
    }
    if( Ps3.data.button.start ){
      M5.Lcd.drawString("Button: START", 0, controllerInfoX, 2);
    }
    if( Ps3.data.button.select ){
      M5.Lcd.drawString("Button: SELECT", 0, controllerInfoX, 2);
    }
  //-----------------------------------------------------------------------
    // Clear the area we will be writing to
    M5.Lcd.fillRect(0, joystickInfoX, XMAX, TEXT_HEIGHT, TFT_BLACK);
    
    String messageJoystick;
    
    messageJoystick += "lx:";
    messageJoystick += Ps3.data.analog.stick.lx;
    messageJoystick += ", ly:";
    messageJoystick += Ps3.data.analog.stick.ly;
    messageJoystick += ", rx:";
    messageJoystick += Ps3.data.analog.stick.rx;
    messageJoystick += ", ry:";
    messageJoystick += Ps3.data.analog.stick.ry;
    
    // Write the message to the screen
    M5.Lcd.drawString(messageJoystick, 0, joystickInfoX, 2);
  //-----------------------------------------------------------------------
    String message = "PS3: Connected";
  
    // Clear the area we will be writing to
    M5.Lcd.fillRect(0, deviceName, XMAX, TEXT_HEIGHT, TFT_BLACK);
    
    if (Ps3.data.status.battery == ps3_status_battery_charging) message += ", Charging";
    else if (Ps3.data.status.battery == ps3_status_battery_high) message += ", High";
    else if (Ps3.data.status.battery == ps3_status_battery_full) message += ", Full";
    else if (Ps3.data.status.battery == ps3_status_battery_low) message += ", Low";
    else if (Ps3.data.status.battery == ps3_status_battery_dying) message += ", Dying";
    else if (Ps3.data.status.battery == ps3_status_battery_shutdown) message += ", Shutdown";
    else message += ", Undefined";
  
    // Write the message to the screen
    M5.Lcd.drawString(message, 0, deviceName, 2);
  //-----------------------------------------------------------------------
    String messageAccel;
    
    messageAccel += "a.x:";
    messageAccel += Ps3.data.sensor.accelerometer.x;
    messageAccel += " y:";
    messageAccel += Ps3.data.sensor.accelerometer.y;
    messageAccel += " z:";
    messageAccel += Ps3.data.sensor.accelerometer.z;
  
    String messageGyro;
    messageGyro += " g.z:";
    messageGyro += Ps3.data.sensor.gyroscope.z;
  
    M5.Lcd.drawString(messageAccel+messageGyro, 0, gyroInfoX, 2);
  }
  
  delay(100);
}