The PS2 joystick module is one of the most satisfying components to add to any Arduino project. That familiar thumbstick feel — borrowed directly from PlayStation 2 controllers — translates beautifully into robot control, RC cars, game interfaces, and pan-tilt camera rigs. In this guide you will learn everything from wiring and calibration to writing clean, readable Arduino code and building real projects around this humble but versatile module.
What Is a PS2 Joystick Module?
A PS2 joystick module combines two potentiometers (one for X-axis, one for Y-axis) and a momentary push-button switch mounted inside a standard thumbstick housing. When you move the stick, the two potentiometers change resistance, producing analog voltages that your Arduino reads through its ADC channels. Pressing the stick straight down activates the built-in switch, giving you a digital input as well.
The module exposes five pins: VCC (3.3 V or 5 V power), GND, VRX (X-axis analog output), VRY (Y-axis analog output), and SW (switch, active LOW). It is compact — typically around 26 × 26 mm — and draws less than 10 mA, making it ideal for battery-powered robots and handheld remotes.
The resting (centre) position produces roughly half the supply voltage on both VRX and VRY, which maps to approximately 512 on the Arduino’s 10-bit ADC (range 0–1023). Full deflection in either direction approaches 0 or 1023. This predictable behaviour makes calibration straightforward.
PS2 Joystick Pinout and Wiring to Arduino
Wiring is quick because the module is a pure analog device — no I2C address, no SPI clock, no library dependencies needed for basic use.
Standard connections to Arduino Uno/Nano:
- VCC → Arduino 5 V pin
- GND → Arduino GND
- VRX → Arduino A0
- VRY → Arduino A1
- SW → Arduino D2 (enable internal pull-up)
Note that some modules label the X and Y axes opposite to what you might expect because the physical orientation of the potentiometers varies between manufacturers. Always verify axis direction in software before mounting the joystick in your project enclosure.
If you are using a 3.3 V board such as the Arduino Nano 33 IoT, connect VCC to 3.3 V instead of 5 V. The potentiometers will still swing their full range and the ADC will read 0–1023 correctly.
Reading the Joystick: Arduino Code
The following sketch reads both axes and the button, applies a dead-zone to prevent drift, and prints the results to the Serial Monitor.
const int VRX_PIN = A0;
const int VRY_PIN = A1;
const int SW_PIN = 2;
const int DEADZONE = 50; // ignore noise near centre
void setup() {
Serial.begin(9600);
pinMode(SW_PIN, INPUT_PULLUP); // SW pulls LOW when pressed
}
void loop() {
int xRaw = analogRead(VRX_PIN); // 0-1023
int yRaw = analogRead(VRY_PIN); // 0-1023
bool pressed = (digitalRead(SW_PIN) == LOW);
// Map to -512 … +512 centred on zero
int xVal = xRaw - 512;
int yVal = yRaw - 512;
// Apply dead-zone
if (abs(xVal) < DEADZONE) xVal = 0;
if (abs(yVal) < DEADZONE) yVal = 0;
Serial.print("X:"); Serial.print(xVal);
Serial.print(" Y:"); Serial.print(yVal);
Serial.print(" BTN:"); Serial.println(pressed ? "PRESSED" : "open");
delay(100);
}
The dead-zone is critical. Cheap potentiometers rarely settle exactly at 512 when released; they drift 10–40 counts. Without a dead-zone, a robot will slowly creep even when you are not touching the stick. A value of 50 works well in practice; adjust it up if you see residual drift on your particular module.
Mapping to motor speed is a one-liner using the Arduino map() function:
int motorSpeed = map(xVal, -512, 512, -255, 255);
Negative values mean reverse; positive means forward. Pass the absolute value to a PWM pin and the sign bit to the motor direction pin of your H-bridge driver.
Differential Drive Robot Control
The most common use of a PS2 joystick module is controlling a two-wheeled differential drive robot. The algorithm mixes the X and Y axes to produce independent left and right motor speeds — a technique called arcade drive:
int leftSpeed = constrain(yVal + xVal, -512, 512);
int rightSpeed = constrain(yVal - xVal, -512, 512);
// Scale to PWM range 0-255
int leftPWM = map(abs(leftSpeed), 0, 512, 0, 255);
int rightPWM = map(abs(rightSpeed), 0, 512, 0, 255);
Push the stick straight forward: both motors run at equal speed. Push it right: left motor speeds up, right slows down — the robot turns right. Pull back and left: reverse arc to the left. This intuitive control scheme is exactly what PlayStation 2 games used and it works just as naturally for physical robots.
For wireless robot control you can pair the joystick with an NRF24L01 radio module on the controller side and a matching receiver on the robot. The joystick readings are packaged into a 4-byte struct and transmitted at 50 Hz, giving fluid, low-latency control across a range of 50–100 metres.
Building a Dual-Joystick Game Controller
Two PS2 joystick modules mounted in a 3D-printed or project-box enclosure produce a fully functional game controller. The left stick controls movement; the right stick controls camera angle or aims a weapon. You can add up to four axis readings on a standard Arduino Uno (A0 through A3) and still have A4/A5 free for I2C peripherals.
For PC game control, the Arduino Leonardo or Micro is the classic choice because it can enumerate as a USB HID joystick device using the Joystick.h library. The host PC sees it as a native gamepad — no custom drivers required. Here is the minimal sketch:
#include <Joystick.h>
Joystick_ Joystick;
void setup() { Joystick.begin(); }
void loop() {
Joystick.setXAxis(analogRead(A0));
Joystick.setYAxis(analogRead(A1));
Joystick.setRxAxis(analogRead(A2));
Joystick.setRyAxis(analogRead(A3));
delay(10);
}
Add tactile buttons on the Leonardo’s digital pins and map them with Joystick.setButton(index, state) to create a full-featured controller with shoulder buttons, face buttons, and thumbstick clicks.
Pan-Tilt Camera Rig Control
A pan-tilt servo gimbal is another excellent application. The X-axis controls the pan servo (left/right) and the Y-axis controls the tilt servo (up/down). Because servo positions are absolute rather than velocity-based, you map the joystick to an angle and store it in a variable that updates continuously:
#include <Servo.h>
Servo panServo, tiltServo;
int panAngle = 90;
int tiltAngle = 90;
void loop() {
int xVal = analogRead(A0) - 512;
int yVal = analogRead(A1) - 512;
if (abs(xVal) > 50) panAngle += (xVal > 0) ? 1 : -1;
if (abs(yVal) > 50) tiltAngle += (yVal > 0) ? 1 : -1;
panAngle = constrain(panAngle, 0, 180);
tiltAngle = constrain(tiltAngle, 30, 150);
panServo.write(panAngle);
tiltServo.write(tiltAngle);
delay(15);
}
The increment-per-loop approach means slow stick movement = slow pan, fast deflection = fast pan. This is much smoother than directly mapping joystick position to servo angle, which causes the camera to snap instantly to the full-deflection position.
Troubleshooting Common Problems
Axis reads maximum value (1023) permanently: VCC is not connected or the potentiometer wiper is open-circuit. Check the VCC and VRX/VRY connections.
Button never registers: Ensure you have INPUT_PULLUP on the SW pin and that your code checks for LOW (not HIGH) to detect a press. The switch connects SW to GND when pressed.
Robot drifts without touching stick: Increase the dead-zone constant. Values between 50 and 100 handle most cheap modules. If drift persists, the potentiometer centre-tap has drifted with wear — replace the module.
Noisy readings jumping ±20 counts: Add a 100 nF ceramic capacitor between VRX and GND (and another between VRY and GND) right at the module pins. This filters ADC noise caused by long wire runs or motor interference.
Only one axis works: Check that both A0 and A1 are configured as inputs (they are by default, but calling pinMode(A0, OUTPUT) by mistake will break analog reading).
Frequently Asked Questions
Can I use a PS2 joystick module with a 3.3 V Arduino?
Yes. Connect VCC to the 3.3 V pin instead of 5 V. The potentiometers are resistive voltage dividers and work correctly across a wide supply range. The ADC will still produce 0–1023 readings spanning the full joystick travel. Most modern Arduino boards (Nano 33, MKR series, RP2040) operate at 3.3 V logic and this is the recommended connection.
How many joystick modules can I connect to one Arduino Uno?
The Uno has six analog inputs (A0–A5). Each joystick uses two analog pins, so you can connect three joysticks simultaneously. The button pins use digital I/O, which is plentiful. For more than three joysticks, switch to an Arduino Mega (16 analog inputs) or use an I2C ADC expander such as the ADS1115.
What is the difference between a PS2 joystick module and a thumbstick breakout?
They are functionally identical — both use the same thumbstick mechanical assembly. “PS2 joystick module” typically implies a PCB with voltage regulation and pin headers pre-soldered, making breadboard prototyping easier. A bare thumbstick breakout may require you to add your own pull-up resistor and solder directly to the potentiometer legs.
How do I add a dead-zone to prevent my robot from moving on its own?
After reading the raw ADC value (0–1023), subtract 512 to centre it at zero. Then check if the absolute value is less than your dead-zone threshold (typically 30–80). If it is, treat the reading as zero. Only send motor commands when the joystick is genuinely deflected beyond this threshold. See the code example in the Reading the Joystick section above.
Can I use the PS2 joystick module wirelessly?
Absolutely. Pair it with an NRF24L01 or HC-12 radio module on the transmitter side and a matching receiver on the robot. The joystick itself remains wired to the transmitter Arduino, but the data travels wirelessly. For Bluetooth, use an HC-05 module on the joystick Arduino and the Arduino Serial Bluetooth library to send joystick values as a comma-separated string over BLE.
Ready to Build Your Robot Controller?
The PS2 joystick module is one of the most cost-effective ways to add intuitive human control to any Arduino project. Whether you are building a competition robot, a handheld gaming console, or a remote camera rig, this small module delivers reliable two-axis analog control with a satisfying mechanical feel.
Browse the full range of Arduino boards, shields, and modules at zbotic.in — Arduino & Microcontrollers. We stock genuine Arduino boards alongside compatible modules, sensors, and motor drivers to complete your build in one order.
Add comment