# Using ps4 controller to control arduino car

#### Killerbee65

Joined May 15, 2017
121
Hello Everyone!

I am a novice and inspiring engineer today I have come across a problem with the Arduino serial monitor/ my code. The problem I am encountering is: when moving the analog stick the serial monitor is supposed to print the movement and make the attached motors spin in that specified direction (ex: analog stick goes up the motors go forward) and it does neither of those things. When I open the serial monitor it displays "ps4 Bluetooth library open" or something along those lines (I don't currently have the IDE open).

I use an Arduino Mega 2560
- usb host shield:
https://www.amazon.com/LM-YN-Arduino-Support-Android/dp/B0777DR3T6/ref=sr_1_2?crid=2D6K6RMZEQZ54&keywords=usb+host+shield&qid=1585080411&s=electronics&sprefix=usb+host+sh,electronics,244&sr=1-2

here is the link to the project I am trying to replicate:
https://maker.pro/arduino/projects/how-to-control-an-arduino-robot-with-a-ps4-bluetooth-controller

A screenshot of what my screen looks like for further context:

I made sure I was using the right port selected that I was using a MEGA. If any more information is needed just let me know and Thank you!

#### djsfantasi

Joined Apr 11, 2010
6,196
I didn’t look in detail, but the serial monitor and the USB interface are both serial interfaces.

The error appears to indicate that both functions are using the same port. I suspect that when you initialize the USB device, you need to specify a different port if you’re also using the serial monitor.

Somewhere, the USB library must be initialized on a different port.

#### Killerbee65

Joined May 15, 2017
121
I didn’t look in detail, but the serial monitor and the USB interface are both serial interfaces.

The error appears to indicate that both functions are using the same port. I suspect that when you initialize the USB device, you need to specify a different port if you’re also using the serial monitor.

Somewhere, the USB library must be initialized on a different port.
It is possible to code a different port for the USB?

#### Killerbee65

Joined May 15, 2017
121
I didn’t look in detail, but the serial monitor and the USB interface are both serial interfaces.

The error appears to indicate that both functions are using the same port. I suspect that when you initialize the USB device, you need to specify a different port if you’re also using the serial monitor.

Somewhere, the USB library must be initialized on a different port.
Oh wait I read it wrong, so how would one go on about doing this? Any ideas?

Joined Jan 15, 2015
5,140
I have to give you credit for persistence.

I doubt your problem is the serial monitor. Your PS4 is using a USB Port dongle to communicate with your Arduino. Let's say I write some software to communicate with an Arduino Uno (or similar). In my software I call out SerialPort1.PortName = "com5" because Com5 is where my Arduino is. If I open my Arduino Serial Monitor and it is reading Com5 and then I tell my software to connect using SerialPort1.Open() my software will throw an error to the effect of the port is in use. The error will look like this:
Message="Access to the port 'com5' is denied."
Source="System"

There will be a bunch more in a stack but you get the idea. That is my guess. While I have never tried it using a dongle and PS4 I have seen it when the port is in use and I try to access it. Your PS4 is trying to write to the Arduino and the serial monitor is open. In your case both are using Com3.

I didn’t look in detail, but the serial monitor and the USB interface are both serial interfaces.

The error appears to indicate that both functions are using the same port.

Try this. Open your Arduino IDE, run your program. Do not open the serial monitor at this point. Now connect your dongle to a USB port and do whatever setup you need to do. With everything setup do the motors run? Keep in mind do not open the serial monitor. No, there is no way to change the port because your PS4 is constantly writing to that port to control your motors. Most code I have seen like this normally doesn't have Serial.print reference used.

Your sketch aside for a moment you may want to make a test and run the following code sample which does use the Serial.print while monitoring a PS4 and if this code with the associated libraries works then we will know more than we do now.

Code:
/*
Example sketch for the PS4 USB library - developed by Kristian Lauszus
For more information visit my blog: http://blog.tkjelectronics.dk/ or
send me an e-mail:  kristianl@tkjelectronics.com
*/

#include <PS4USB.h>

// Satisfy the IDE, which needs to see the include statment in the ino too.
#ifdef dobogusinclude
#include <spi4teensy3.h>
#endif
#include <SPI.h>

USB Usb;
PS4USB PS4(&Usb);

bool printAngle, printTouch;
uint8_t oldL2Value, oldR2Value;

void setup() {
Serial.begin(115200);
#if !defined(__MIPSEL__)
while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection
#endif
if (Usb.Init() == -1) {
Serial.print(F("\r\nOSC did not start"));
while (1); // Halt
}
Serial.print(F("\r\nPS4 USB Library Started"));
}

void loop() {

if (PS4.connected()) {
if (PS4.getAnalogHat(LeftHatX) > 137 || PS4.getAnalogHat(LeftHatX) < 117 || PS4.getAnalogHat(LeftHatY) > 137 || PS4.getAnalogHat(LeftHatY) < 117 || PS4.getAnalogHat(RightHatX) > 137 || PS4.getAnalogHat(RightHatX) < 117 || PS4.getAnalogHat(RightHatY) > 137 || PS4.getAnalogHat(RightHatY) < 117) {
Serial.print(F("\r\nLeftHatX: "));
Serial.print(PS4.getAnalogHat(LeftHatX));
Serial.print(F("\tLeftHatY: "));
Serial.print(PS4.getAnalogHat(LeftHatY));
Serial.print(F("\tRightHatX: "));
Serial.print(PS4.getAnalogHat(RightHatX));
Serial.print(F("\tRightHatY: "));
Serial.print(PS4.getAnalogHat(RightHatY));
}

if (PS4.getAnalogButton(L2) || PS4.getAnalogButton(R2)) { // These are the only analog buttons on the PS4 controller
Serial.print(F("\r\nL2: "));
Serial.print(PS4.getAnalogButton(L2));
Serial.print(F("\tR2: "));
Serial.print(PS4.getAnalogButton(R2));
}
if (PS4.getAnalogButton(L2) != oldL2Value || PS4.getAnalogButton(R2) != oldR2Value) // Only write value if it's different
PS4.setRumbleOn(PS4.getAnalogButton(L2), PS4.getAnalogButton(R2));
oldL2Value = PS4.getAnalogButton(L2);
oldR2Value = PS4.getAnalogButton(R2);

if (PS4.getButtonClick(PS))
Serial.print(F("\r\nPS"));
if (PS4.getButtonClick(TRIANGLE)) {
Serial.print(F("\r\nTriangle"));
PS4.setRumbleOn(RumbleLow);
}
if (PS4.getButtonClick(CIRCLE)) {
Serial.print(F("\r\nCircle"));
PS4.setRumbleOn(RumbleHigh);
}
if (PS4.getButtonClick(CROSS)) {
Serial.print(F("\r\nCross"));
PS4.setLedFlash(10, 10); // Set it to blink rapidly
}
if (PS4.getButtonClick(SQUARE)) {
Serial.print(F("\r\nSquare"));
PS4.setLedFlash(0, 0); // Turn off blinking
}

if (PS4.getButtonClick(UP)) {
Serial.print(F("\r\nUp"));
PS4.setLed(Red);
} if (PS4.getButtonClick(RIGHT)) {
Serial.print(F("\r\nRight"));
PS4.setLed(Blue);
} if (PS4.getButtonClick(DOWN)) {
Serial.print(F("\r\nDown"));
PS4.setLed(Yellow);
} if (PS4.getButtonClick(LEFT)) {
Serial.print(F("\r\nLeft"));
PS4.setLed(Green);
}

if (PS4.getButtonClick(L1))
Serial.print(F("\r\nL1"));
if (PS4.getButtonClick(L3))
Serial.print(F("\r\nL3"));
if (PS4.getButtonClick(R1))
Serial.print(F("\r\nR1"));
if (PS4.getButtonClick(R3))
Serial.print(F("\r\nR3"));

if (PS4.getButtonClick(SHARE))
Serial.print(F("\r\nShare"));
if (PS4.getButtonClick(OPTIONS)) {
Serial.print(F("\r\nOptions"));
printAngle = !printAngle;
}
printTouch = !printTouch;
}

if (printAngle) { // Print angle calculated using the accelerometer only
Serial.print(F("\r\nPitch: "));
Serial.print(PS4.getAngle(Pitch));
Serial.print(F("\tRoll: "));
Serial.print(PS4.getAngle(Roll));
}

if (printTouch) { // Print the x, y coordinates of the touchpad
if (PS4.isTouching(0) || PS4.isTouching(1)) // Print newline and carriage return if any of the fingers are touching the touchpad
Serial.print(F("\r\n"));
for (uint8_t i = 0; i < 2; i++) { // The touchpad track two fingers
if (PS4.isTouching(i)) { // Print the position of the finger if it is touching the touchpad
Serial.print(F("X")); Serial.print(i + 1); Serial.print(F(": "));
Serial.print(PS4.getX(i));
Serial.print(F("\tY")); Serial.print(i + 1); Serial.print(F(": "));
Serial.print(PS4.getY(i));
Serial.print(F("\t"));
}
}
}
}
}
The above code was taken from here.

Ron

#### Killerbee65

Joined May 15, 2017
121
I have to give you credit for persistence.

I doubt your problem is the serial monitor. Your PS4 is using a USB Port dongle to communicate with your Arduino. Let's say I write some software to communicate with an Arduino Uno (or similar). In my software I call out SerialPort1.PortName = "com5" because Com5 is where my Arduino is. If I open my Arduino Serial Monitor and it is reading Com5 and then I tell my software to connect using SerialPort1.Open() my software will throw an error to the effect of the port is in use. The error will look like this:
Message="Access to the port 'com5' is denied."
Source="System"

There will be a bunch more in a stack but you get the idea. That is my guess. While I have never tried it using a dongle and PS4 I have seen it when the port is in use and I try to access it. Your PS4 is trying to write to the Arduino and the serial monitor is open. In your case both are using Com3.

Try this. Open your Arduino IDE, run your program. Do not open the serial monitor at this point. Now connect your dongle to a USB port and do whatever setup you need to do. With everything setup do the motors run? Keep in mind do not open the serial monitor. No, there is no way to change the port because your PS4 is constantly writing to that port to control your motors. Most code I have seen like this normally doesn't have Serial.print reference used.

Your sketch aside for a moment you may want to make a test and run the following code sample which does use the Serial.print while monitoring a PS4 and if this code with the associated libraries works then we will know more than we do now.

Code:
/*
Example sketch for the PS4 USB library - developed by Kristian Lauszus
For more information visit my blog: http://blog.tkjelectronics.dk/ or
send me an e-mail:  kristianl@tkjelectronics.com
*/

#include <PS4USB.h>

// Satisfy the IDE, which needs to see the include statment in the ino too.
#ifdef dobogusinclude
#include <spi4teensy3.h>
#endif
#include <SPI.h>

USB Usb;
PS4USB PS4(&Usb);

bool printAngle, printTouch;
uint8_t oldL2Value, oldR2Value;

void setup() {
Serial.begin(115200);
#if !defined(__MIPSEL__)
while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection
#endif
if (Usb.Init() == -1) {
Serial.print(F("\r\nOSC did not start"));
while (1); // Halt
}
Serial.print(F("\r\nPS4 USB Library Started"));
}

void loop() {

if (PS4.connected()) {
if (PS4.getAnalogHat(LeftHatX) > 137 || PS4.getAnalogHat(LeftHatX) < 117 || PS4.getAnalogHat(LeftHatY) > 137 || PS4.getAnalogHat(LeftHatY) < 117 || PS4.getAnalogHat(RightHatX) > 137 || PS4.getAnalogHat(RightHatX) < 117 || PS4.getAnalogHat(RightHatY) > 137 || PS4.getAnalogHat(RightHatY) < 117) {
Serial.print(F("\r\nLeftHatX: "));
Serial.print(PS4.getAnalogHat(LeftHatX));
Serial.print(F("\tLeftHatY: "));
Serial.print(PS4.getAnalogHat(LeftHatY));
Serial.print(F("\tRightHatX: "));
Serial.print(PS4.getAnalogHat(RightHatX));
Serial.print(F("\tRightHatY: "));
Serial.print(PS4.getAnalogHat(RightHatY));
}

if (PS4.getAnalogButton(L2) || PS4.getAnalogButton(R2)) { // These are the only analog buttons on the PS4 controller
Serial.print(F("\r\nL2: "));
Serial.print(PS4.getAnalogButton(L2));
Serial.print(F("\tR2: "));
Serial.print(PS4.getAnalogButton(R2));
}
if (PS4.getAnalogButton(L2) != oldL2Value || PS4.getAnalogButton(R2) != oldR2Value) // Only write value if it's different
PS4.setRumbleOn(PS4.getAnalogButton(L2), PS4.getAnalogButton(R2));
oldL2Value = PS4.getAnalogButton(L2);
oldR2Value = PS4.getAnalogButton(R2);

if (PS4.getButtonClick(PS))
Serial.print(F("\r\nPS"));
if (PS4.getButtonClick(TRIANGLE)) {
Serial.print(F("\r\nTriangle"));
PS4.setRumbleOn(RumbleLow);
}
if (PS4.getButtonClick(CIRCLE)) {
Serial.print(F("\r\nCircle"));
PS4.setRumbleOn(RumbleHigh);
}
if (PS4.getButtonClick(CROSS)) {
Serial.print(F("\r\nCross"));
PS4.setLedFlash(10, 10); // Set it to blink rapidly
}
if (PS4.getButtonClick(SQUARE)) {
Serial.print(F("\r\nSquare"));
PS4.setLedFlash(0, 0); // Turn off blinking
}

if (PS4.getButtonClick(UP)) {
Serial.print(F("\r\nUp"));
PS4.setLed(Red);
} if (PS4.getButtonClick(RIGHT)) {
Serial.print(F("\r\nRight"));
PS4.setLed(Blue);
} if (PS4.getButtonClick(DOWN)) {
Serial.print(F("\r\nDown"));
PS4.setLed(Yellow);
} if (PS4.getButtonClick(LEFT)) {
Serial.print(F("\r\nLeft"));
PS4.setLed(Green);
}

if (PS4.getButtonClick(L1))
Serial.print(F("\r\nL1"));
if (PS4.getButtonClick(L3))
Serial.print(F("\r\nL3"));
if (PS4.getButtonClick(R1))
Serial.print(F("\r\nR1"));
if (PS4.getButtonClick(R3))
Serial.print(F("\r\nR3"));

if (PS4.getButtonClick(SHARE))
Serial.print(F("\r\nShare"));
if (PS4.getButtonClick(OPTIONS)) {
Serial.print(F("\r\nOptions"));
printAngle = !printAngle;
}
printTouch = !printTouch;
}

if (printAngle) { // Print angle calculated using the accelerometer only
Serial.print(F("\r\nPitch: "));
Serial.print(PS4.getAngle(Pitch));
Serial.print(F("\tRoll: "));
Serial.print(PS4.getAngle(Roll));
}

if (printTouch) { // Print the x, y coordinates of the touchpad
if (PS4.isTouching(0) || PS4.isTouching(1)) // Print newline and carriage return if any of the fingers are touching the touchpad
Serial.print(F("\r\n"));
for (uint8_t i = 0; i < 2; i++) { // The touchpad track two fingers
if (PS4.isTouching(i)) { // Print the position of the finger if it is touching the touchpad
Serial.print(F("X")); Serial.print(i + 1); Serial.print(F(": "));
Serial.print(PS4.getX(i));
Serial.print(F("\tY")); Serial.print(i + 1); Serial.print(F(": "));
Serial.print(PS4.getY(i));
Serial.print(F("\t"));
}
}
}
}
}
The above code was taken from here.

Ron
Ok Thank you!

Joined Jan 15, 2015
5,140
Ok Thank you!
While I have written to an Arduino over a USB port I have never done it using a dongle and PS4. I have done it with the Arduino Uno and Mega driving the L298 H Bridge module. I know I have had problems when the serial monitor is open and I try to write to that port. If you have or can get the libraries for the code I posted it should tell you if the setup works.

Ron

#### Killerbee65

Joined May 15, 2017
121
While I have written to an Arduino over a USB port I have never done it using a dongle and PS4. I have done it with the Arduino Uno and Mega driving the L298 H Bridge module. I know I have had problems when the serial monitor is open and I try to write to that port. If you have or can get the libraries for the code I posted it should tell you if the setup works.

Ron
so same situation: code runs without errors, serial monitor displays "ps4 library started" (missing "USB" between and "ps4") usb dongle connects without a problem and the ps4 remote pairs with the dongle. I followed what you said above with the troubleshooting but If I connect the usb dongle to the computer instead of the arduino it pairs with the computer.

Joined Jan 15, 2015
5,140
The dongle can't pair with the Arduino, it has to pair with the PC. The dongle needs a USB Host System which is inclusive of a USB Stack which the computer has and Arduino doesn't have. This is why the dongle connects to the computer and the computer to the Arduino. If you want to connect the dongle directly to an Arduino Uno or Mega I ampretty sure you need a USB Host Shield between Arduino and dongle. The only Arduino I know of which has a USB Host built in is the Arduino Due which runs on the USB Host library. Simply put the Arduino needs the PC or a host shield. That is why it won't pair with the dongle directly.

Ron

#### Killerbee65

Joined May 15, 2017
121
The dongle can't pair with the Arduino, it has to pair with the PC. The dongle needs a USB Host System which is inclusive of a USB Stack which the computer has and Arduino doesn't have. This is why the dongle connects to the computer and the computer to the Arduino. If you want to connect the dongle directly to an Arduino Uno or Mega I ampretty sure you need a USB Host Shield between Arduino and dongle. The only Arduino I know of which has a USB Host built in is the Arduino Due which runs on the USB Host library. Simply put the Arduino needs the PC or a host shield. That is why it won't pair with the dongle directly.

Ron

But I do have a USB shield, I think I left a link of the actual product in my first post.

#### djsfantasi

Joined Apr 11, 2010
6,196
Depending on the application, you don’t need additional hardware for a USB Host shield. In certain configurations, the Arduino has all the necessary hardware and only needs the appropriate software.

From your description, it’s my understanding that the dongle is in conflict with other serial functions. And I think that the only other serial connection is used for the serial monitor.

With the serial library, you can move the serial monitor to other pins.

Then, the built-in USB stack can be used by the dongle. And you can connect in the manner that you want.

It does require an understanding of the Arduino USB stack, the software serial library, having the proper serial cable to connect between the PC and Arduino and PC software to make a serial connection.

#### Killerbee65

Joined May 15, 2017
121
Depending on the application, you don’t need additional hardware for a USB Host shield. In certain configurations, the Arduino has all the necessary hardware and only needs the appropriate software.

From your description, it’s my understanding that the dongle is in conflict with other serial functions. And I think that the only other serial connection is used for the serial monitor.

With the serial library, you can move the serial monitor to other pins.

Then, the built-in USB stack can be used by the dongle. And you can connect in the manner that you want.

It does require an understanding of the Arduino USB stack, the software serial library, having the proper serial cable to connect between the PC and Arduino and PC software to make a serial connection.
so which way do you think the guy in the video did it? it looks like he just plugged in the usb dongle into the usb host shield and it just worked. I tried to message the guy but haven't heard from him since.

#### Killerbee65

Joined May 15, 2017
121
Depending on the application, you don’t need additional hardware for a USB Host shield. In certain configurations, the Arduino has all the necessary hardware and only needs the appropriate software.

From your description, it’s my understanding that the dongle is in conflict with other serial functions. And I think that the only other serial connection is used for the serial monitor.

With the serial library, you can move the serial monitor to other pins.

Then, the built-in USB stack can be used by the dongle. And you can connect in the manner that you want.

It does require an understanding of the Arduino USB stack, the software serial library, having the proper serial cable to connect between the PC and Arduino and PC software to make a serial connection.
So I did some research and I kinda get what you mean. I learned the mega has 4 serial pins in total (or tx0 rx0, tx1 rx1, tx2 rx2, etc). The default serial port used is 0 because it is what the shield connects to. So if I am right in my thinking, you are saying to implement a code that changes which port the main serial monitor is located? so instead of the main serial monitor communicating and conflicting with tx0 and rx0 I would use, let's say, Serial3.begin to "move" it? that way the dongle sends and receives data on the main serial port (tx0 rx0) with no interference from the main serial monitor because it would be "located" in a different port?

#### djsfantasi

Joined Apr 11, 2010
6,196
So I did some research and I kinda get what you mean. I learned the mega has 4 serial pins in total (or tx0 rx0, tx1 rx1, tx2 rx2, etc). The default serial port used is 0 because it is what the shield connects to. So if I am right in my thinking, you are saying to implement a code that changes which port the main serial monitor is located? so instead of the main serial monitor communicating and conflicting with tx0 and rx0 I would use, let's say, Serial3.begin to "move" it? that way the dongle sends and receives data on the main serial port (tx0 rx0) with no interference from the main serial monitor because it would be "located" in a different port?
You’re heading in the right direction. To send a message to the first alternate serial port, you’d use the command
Serial1.print()​
And similar syntax for Serial1.println() and the serial read commands.

Just note that you don’t need an Arduino for additional serial ports. The library SoftwareSerial can be loaded on other Arduinos to add additional serial ports.

Note that when using alternate serial ports in this manner, a hardware cable and/or dongle may be necessary to connect to the other device.

#### Killerbee65

Joined May 15, 2017
121
You’re heading in the right direction. To send a message to the first alternate serial port, you’d use the command
Serial1.print()​
And similar syntax for Serial1.println() and the serial read commands.

Just note that you don’t need an Arduino for additional serial ports. The library SoftwareSerial can be loaded on other Arduinos to add additional serial ports.

For that last part do you mean to the USB blue tooth single or the USB host shield?

Note that when using alternate serial ports in this manner, a hardware cable and/or dongle may be necessary to connect to the other device.

#### djsfantasi

Joined Apr 11, 2010
6,196
Can’t understand your response.

#### Killerbee65

Joined May 15, 2017
121
Can’t understand your response.

I don't know why it didn't send but I wanted to know if you mean connect the hardware cable to the USB host shield or the USB blue tooth dongle?

#### djsfantasi

Joined Apr 11, 2010
6,196
If the dongle does not require the USB Host Shield, connect it to the USB jack on the Arduino. An adapter may be required (I.e., USB-A to mini-USB extension cable)

The additional serial ports on the Mega or SoftwareSerial ports ore TTL-compatible serial ports. You will likely need what I called a “hardware cable” to convert TTL Serial to USB on the PC to use it as a console. I have an FTDI based adapter cable.

You don’t need anything like a hardware cable, to connect the USB Shield to the Arduino. That’s the definition of a shield. It’s an add-on that connects to the Arduino by piggybacking the boards and allowing the pins to connect the two together.

#### Killerbee65

Joined May 15, 2017
121
If the dongle does not require the USB Host Shield, connect it to the USB jack on the Arduino. An adapter may be required (I.e., USB-A to mini-USB extension cable)

The additional serial ports on the Mega or SoftwareSerial ports ore TTL-compatible serial ports. You will likely need what I called a “hardware cable” to convert TTL Serial to USB on the PC to use it as a console. I have an FTDI based adapter cable.

You don’t need anything like a hardware cable, to connect the USB Shield to the Arduino. That’s the definition of a shield. It’s an add-on that connects to the Arduino by piggybacking the boards and allowing the pins to connect the two together.
So seeing how I do have a USB host shield what is the point of the shield if you have to use two different serial ports? Correct me if I'm wrong here but as far as I know no matter what I connect to the USB host shield it will still interfere with the main serial port

#### djsfantasi

Joined Apr 11, 2010
6,196
So seeing how I do have a USB host shield what is the point of the shield if you have to use two different serial ports? Correct me if I'm wrong here but as far as I know no matter what I connect to the USB host shield it will still interfere with the main serial port
You cannot run the dongle and the serial monitor on one serial port.

So, let’s say you run the dongle on the USB Host Shield. Where are you going to connect the serial monitor?

Im guessing that you’re planning on using the Arduino USB programming for the latter. And the USB Dongle will connect to the USB Host Shield.

I’d read the documentation of the USB Host Shield in detail. Somewhere, there must be a description of a function to initialize the USB Host Shield. That function likely assigns a serial port to the USB connection.

You need to find that documentation.