SOLVED I2C USB Host PS4 Bluetooth Controller with Arduino UNO?

I recently bought a USB Host Controller Board with pre-loaded PS4 Dualshock controller software, together with the recommended Bluetooth dongle.

The intention was to use it in conjunction with an I2C PWM servo controller board to control a bunch of micro servos - replacing the analogue thumb joysticks I’m currently using for the same purpose. The boards have different default I2C addresses so I thought it would be a simple matter of chaining them up in parallel and implementing the relevent libraries.

Unfortunately I’m getting absolutely no joy communicating with the board and have struggled to find a decent library or tutorial to help out. Most of the sample libraries I’ve seen seem to relate to SPI host controller boards rather than I2C.

I have the board connected as follows:

  • 5V to 5V power supply
  • Ground to power supply GND (common with Arduino GND)
  • SDA to Arduino pin A4 (SDA)
  • SCL to Arduino pin A5 (SCL)

I’m assuming that’s all that’s needed to get this up and running with I2C?

The board powers up OK and I can successfully pair it with a PS4 Dualshock controller using the instructions provided by the supplier. But that’s about as far as I can get. The attached test harness just hangs on the get_ps4() function and I never get a response.

The I2C PWM servo board (disconnected for this test) works fine so I don’t think there’s a problem with the Arduino.

I’m sure I’m doing something incredibly dumb here :frowning: but would be very grateful for any tips or examples of working wiring and code.

ps4_test.ino (1.13 KB)

I’ve done a bit more diagnostics on this. I’ve run a quick I2C scan sketch and the USB host is being correctly detected on channel 0x29 (decimal 41) as expected.

The reason I never get a response appears to be twofold:

Firstly, the example program doesn’t invoke a Wire.begin() command at the start.

Secondly, the get_ps4() function in the example ps4_i2c.h file is checking for a ‘ps4_battery’ value between 3 and 15, whereas the value captured always appears to be 0 (the controller is fully charged).

When I add the Wire.begin() command and force the ps4_battery value to be 8, I do now see a steady stream of data. Unfortunately, only the first value appears to be meaningful - ‘l_joystick_x’ does correctly sweep between 0 and 255 when I move the left joystick on the Dualshock. All the following values in the struct appear to be random.

Could this be an I2C read length issue? Is it possible the structure of the data from the Dualshock has changed since the example program was written?

ps4_test serial output.png

ps4_test_DEBUG.ino (1.04 KB)

ps4_i2c.h (3.79 KB)

For those interested, I managed to sort out the problem with some assistance from the supplier Hobbytronics. :o

  • You have to turn off Serial mode on the USB host controller board before you can use it in I2C mode.
  • There are a couple of tweaks you need to make to the example program provided by the supplier, including adding a Wire.Begin() command in the setup.

I’ve attached a sample program which includes instructions on how to turn off Serial mode (reproduced below - apparently I’m the only one in the world who didn’t know how to do this!). It also includes the necessary minor tweak to the ps4_i2c.h header file.

NB: in order for the USB host controller to work in I2C mode, it is necessary to turn off SERIAL mode on the USB host controller board. This needs to be done via a direct UART (Rx/Tx) connection to the host controller board, bypassing the UART chip on the Arduino, which can be set up as follows:

Temporary connections to turn off Serial mode on USB host controller:

  • 5V on host controller → 5V on Arduino
  • 0V on host controller → GND on Arduino
  • TX on host controller → TX-> on Arduino
  • RX on host controller → ->RX on Arduino
  • RESET pin on Arduino → GND on Arduino (this is to bypass the Arduino’s internal UART chip so we’re talking directly to the USB host controller)

Instructions to turn off Serial mode on the USB host controller board:

  • Remove the bluetooth dongle from the host controller
  • Open up the Serial Monitor in the Arduino IDE and set the line mode to “Carriage return” and the baud rate to whatever rate the Arduino was using (recommend 115200).
  • Enter the command HELP in the command line and click Send.
  • You should see a report of the current settings of the host controller board (if HELP doesn’t work, try ? instead) - by default, Serial mode is ON.
  • Enter the command SERIAL OFF and click Send.
  • Then type HELP or ? again and you should see that the SERIAL mode is now OFF.
  • Now turn everything off and disconnect it, reinsert the bluetooth dongle into the host controller, change the Serial Monitor line mode back to “No line ending” and reconnect as per the normal connections shown below.

Normal I2C Connections:

  • 5V on host controller → 5V on Arduino
  • 0V on host controller → GND on Arduino
  • SDA on host controller → pin A4 (SDA) on Arduino
  • SCL on host controller → pin A5 (SCL) on Arduino
  • non-latching SPST push switch between 0V and SS pin on host controller to enable bluetooth pairing mode (blue LED flashes faster)

Everything seems to be working fine now. The PS4 Dualshock controller offers a wide variety of control surfaces, all of which are now accessible to Arduino or Teensy programs. This makes remote controlling robotic projects a dream :slight_smile:

ps4_test.zip (6.11 KB)

Thanks for looking into this semucon.

Like yourself, I wasn’t aware of how to connect directly to the USB host with the Arduino and was having problems using the I2C interface on the board.

All sorted now! :slight_smile: