Raspberry Pi - Joystick

This tutorial instructs you how to use joystick with Raspberry Pi. We will delve into:

Raspberry Pi joystick

Hardware Preparation

1×Raspberry Pi 4 Model B
1×ADS1115 ADC Module
1×Joystick
1×Jumper Wires
1×(Optional) Screw Terminal Block Shield for Raspberry Pi
1×(Optional) USB-C Power Cable with On/Off Switch for Raspberry Pi 4B
1×(Optional) Plastic Case and Cooling Fan for Raspberry Pi 4B
1×(Optional) HDMI Touch Screen Monitor for Raspberry Pi

Or you can buy the following sensor kits:

1×DIYables Sensor Kit (30 sensors/displays)
1×DIYables Sensor Kit (18 sensors/displays)
Disclosure: Some of the links provided in this section are Amazon affiliate links. We may receive a commission for any purchases made through these links at no additional cost to you.
Additionally, some of these links are for products from our own brand, DIYables.

Overview of 2-axis Joystick

You may have encountered a Joystick in various places, such as a game controller, a toy controller, or even a large machine like an excavator controller.

The joystick is made up of two potentiometers arranged in a square shape, and one push button. It provides the following outputs:

  • An analog value ranging from 0 to 1023 that corresponds to the horizontal position (known as the X-coordinate)
  • An analog value ranging from 0 to 1023 that corresponds to the vertical position (known as the Y-coordinate)
  • A digital value of the pushbutton (either HIGH or LOW)

The combination of two analog values can generate 2-D coordinates with the center being the values when the joystick is in its resting position. To determine the actual direction of the coordinates, a test code can be run (presented in the next section).

Some applications may use all three outputs, while others may utilize only some of them.

The Joystick Pinout

A Joystick has 5 pins:

  • GND pin: This must be connected to GND (0V).
  • VCC pin: This must be connected to VCC (5V).
  • VRX pin: This outputs an analog value that corresponds to the horizontal position (known as the X-coordinate).
  • VRY pin: This outputs an analog value that corresponds to the vertical position (known as the Y-coordinate).
  • SW pin: This is the output from the pushbutton inside the joystick. It is normally open. If a pull-up resistor is used in this pin, the SW pin will be HIGH when it is not pressed, and LOW when it is pressed.
joystick pinout

How It Works

  • When you move the joystick's thump to the left or right, the voltage in the VRX pin is changed. This voltage range is from 0V to 5V, with 0V being at the left and 5V being at the right, resulting in a reading value on the Raspberry Pi's analog pin from 0 to 1023.
  • Similarly, when you move the joystick's thump up or down, the voltage in the VRY pin is changed. This voltage range is from 0V to 5V, with 0V being at the top and 5V being at the bottom, resulting in a reading value on the Raspberry Pi's analog pin from 0 to 1023.
  • When you move the joystick's thump in any direction, the voltage in both the VRX and VRY pins is changed in proportion to the projection of the position on each axis.
  • When you push the joystick's thump from the top to the bottom, the pushbutton inside the joystick is closed. If we use a pull-up resistor in the SW pin, the output from the SW pin will change from 5V to 0V, resulting in a reading value on the Raspberry Pi's digital pin changing from HIGH to LOW.

Wiring Diagram

The wiring diagram between Raspberry Pi and Joystick

This image is created using Fritzing. Click to enlarge image

To simplify and organize your wiring setup, we recommend using a Screw Terminal Block Shield for Raspberry Pi. This shield ensures more secure and manageable connections, as shown below:

Raspberry Pi Screw Terminal Block Shield

Raspberry Pi Code

This section will present the following Raspberry Pi example codes:

  • Example code: Obtaining analog values from joystick
  • Example code: Obtaining analog values and button state from joystick
  • Example code: Converting analog value to MOVE_LEFT, MOVE_RIGHT, MOVE_UP, MOVE_DOWN commands
  • Example code: converting analog values to angles for controlling two servo motors (e.g. in pan-tilt camera)

Reads analog values from joystick

Detailed Instructions

  • Make sure you have Raspbian or any other Raspberry Pi compatible operating system installed on your Pi.
  • Make sure your Raspberry Pi is connected to the same local network as your PC.
  • Make sure your Raspberry Pi is connected to the internet if you need to install some libraries.
  • If this is the first time you use Raspberry Pi, See how to set up the Raspberry Pi
  • Connect your PC to the Raspberry Pi via SSH using the built-in SSH client on Linux and macOS or PuTTY on Windows. See to how connect your PC to Raspberry Pi via SSH.
  • Make sure you have the RPi.GPIO library installed. If not, install it using the following command:
sudo apt-get update sudo apt-get install python3-rpi.gpio
  • Install the Adafruit_ADS1x15 library by running the following commands on your Raspberry Pi terminal:
sudo pip install Adafruit-ADS1x15
  • Create a Python script file joystick.py and add the following code:
""" This Raspberry Pi code was developed by newbiely.com This Raspberry Pi code is made available for public use without any restriction For comprehensive instructions and wiring diagrams, please visit: https://newbiely.com/tutorials/raspberry-pi/raspberry-pi-joystick """ import time import Adafruit_ADS1x15 # Create an ADS1115 instance ADC = Adafruit_ADS1x15.ADS1115() # Set the gain to ±4.096V (adjust if needed) GAIN = 1 # Specify the ADC channels for the joystick axes X_CHANNEL = 0 Y_CHANNEL = 1 try: while True: x_value = ADC.read_adc(X_CHANNEL, gain=GAIN) y_value = ADC.read_adc(Y_CHANNEL, gain=GAIN) print(f"X-axis Value: {x_value}, Y-axis Value: {y_value}") time.sleep(0.1) except KeyboardInterrupt: pass
  • Save the file and run the Python script by executing the following command in the terminal:
python3 joystick.py
  • Push the joystick's thump to its maximum and then rotate it in either a clockwise or counterclockwise direction.
  • Check the results on the Terminal.
PuTTY - Raspberry Pi
X-axis Value: 256, Y-axis Value: 256 X-axis Value: 500, Y-axis Value: 500 X-axis Value: 800, Y-axis Value: 800 X-axis Value: 1000, Y-axis Value: 1000 X-axis Value: 1000, Y-axis Value: 1000 X-axis Value: 1000, Y-axis Value: 1000 X-axis Value: 900, Y-axis Value: 900 X-axis Value: 600, Y-axis Value: 600 X-axis Value: 300, Y-axis Value: 300 X-axis Value: 50, Y-axis Value: 50 X-axis Value: 50, Y-axis Value: 50

While turning the joystick's thumb, keep an eye on the Terminal.

If the X value is 0, note or remember the current position as left, with the opposite direction being right.

If the Y value is 0, note or remember the current position as up, with the opposite direction being down.

The script runs in an infinite loop continuously until you press Ctrl + C in the terminal.

Reads analog values and reads the button state from a joystick

Detailed Instructions

  • Create a Python script file joystick_sw.py and add the following code:
""" This Raspberry Pi code was developed by newbiely.com This Raspberry Pi code is made available for public use without any restriction For comprehensive instructions and wiring diagrams, please visit: https://newbiely.com/tutorials/raspberry-pi/raspberry-pi-joystick """ import time import Adafruit_ADS1x15 # Create an ADS1115 instance ADC = Adafruit_ADS1x15.ADS1115() # Set the gain to ±4.096V (adjust if needed) GAIN = 1 # Specify the ADC channels for the joystick axes X_CHANNEL = 0 Y_CHANNEL = 1 # Define the GPIO pin for the push button BUTTON_PIN = 16 # GPIO16 # Initialize the GPIO pin for the button import RPi.GPIO as GPIO GPIO.setmode(GPIO.BCM) GPIO.setup(BUTTON_PIN, GPIO.IN, pull_up_down=GPIO.PUD_UP) # Initialize variable for previous button state prev_button_state = GPIO.HIGH try: while True: x_value = ADC.read_adc(X_CHANNEL, gain=GAIN) y_value = ADC.read_adc(Y_CHANNEL, gain=GAIN) button_state = GPIO.input(BUTTON_PIN) print(f"X-axis Value: {x_value}, Y-axis Value: {y_value}, Button State: {button_state}") # Detect button press event (transition from HIGH to LOW) if prev_button_state == GPIO.HIGH and button_state == GPIO.LOW: print("Button Pressed!") # Detect button release event (transition from LOW to HIGH) if prev_button_state == GPIO.LOW and button_state == GPIO.HIGH: print("Button Released!") prev_button_state = button_state time.sleep(0.1) except KeyboardInterrupt: pass finally: GPIO.cleanup()
  • Save the file and run the Python script by executing the following command in the terminal:
python3 joystick_sw.py
  • Move the joystick's thumb to the left, right, up, or down.
  • Push the joystick's thumb from the top.
  • Check the results on the Terminal.

Converts analog value to MOVE LEFT/RIGHT/UP/DOWN commands

Detailed Instructions

  • Create a Python script file joystick_cmd.py and add the following code:
""" This Raspberry Pi code was developed by newbiely.com This Raspberry Pi code is made available for public use without any restriction For comprehensive instructions and wiring diagrams, please visit: https://newbiely.com/tutorials/raspberry-pi/raspberry-pi-joystick """ import time import Adafruit_ADS1x15 # Create an ADS1115 instance ADC = Adafruit_ADS1x15.ADS1115() # Set the gain to ±4.096V (adjust if needed) GAIN = 1 # Specify the ADC channels for the joystick axes X_CHANNEL = 0 Y_CHANNEL = 1 # Read center values initially to calculate thresholds CENTER_SAMPLES = 100 x_center = sum([ADC.read_adc(X_CHANNEL, gain=GAIN) for _ in range(CENTER_SAMPLES)]) / CENTER_SAMPLES y_center = sum([ADC.read_adc(Y_CHANNEL, gain=GAIN) for _ in range(CENTER_SAMPLES)]) / CENTER_SAMPLES # Calculate thresholds based on center values THRESHOLD_DELTA = 200 # Adjust this value as needed LEFT_THRESHOLD = x_center - THRESHOLD_DELTA RIGHT_THRESHOLD = x_center + THRESHOLD_DELTA UP_THRESHOLD = y_center - THRESHOLD_DELTA DOWN_THRESHOLD = y_center + THRESHOLD_DELTA COMMAND_NO = 0x00 COMMAND_LEFT = 0x01 COMMAND_RIGHT = 0x02 COMMAND_UP = 0x04 COMMAND_DOWN = 0x08 try: while True: value_X = ADC.read_adc(X_CHANNEL, gain=GAIN) value_Y = ADC.read_adc(Y_CHANNEL, gain=GAIN) command = COMMAND_NO if value_X < LEFT_THRESHOLD: command |= COMMAND_LEFT elif value_X > RIGHT_THRESHOLD: command |= COMMAND_RIGHT if value_Y < UP_THRESHOLD: command |= COMMAND_UP elif value_Y > DOWN_THRESHOLD: command |= COMMAND_DOWN if command & COMMAND_LEFT: print("COMMAND LEFT") # TODO: Add your task here if command & COMMAND_RIGHT: print("COMMAND RIGHT") # TODO: Add your task here if command & COMMAND_UP: print("COMMAND UP") # TODO: Add your task here if command & COMMAND_DOWN: print("COMMAND DOWN") # TODO: Add your task here time.sleep(0.1) except KeyboardInterrupt: pass
  • Save the file and run the Python script by executing the following command in the terminal:
python3 joystick_cmd.py
  • Move the joystick in any direction.
  • Check the result in the Terminal.
PuTTY - Raspberry Pi
COMMAND UP COMMAND DOWN COMMAND LEFT COMMAND RIGHT

※ NOTE THAT:

At a given moment, there may be no command, one command, or two commands simultaneously (e.g. UP and LEFT).

Converts analog values to angles to control two servo motors

The specifics can be found in the tutorial titled Raspberry Pi - Joystick controls Servo Motor.

Video Tutorial

Learn More

※ OUR MESSAGES

  • As freelancers, We are AVAILABLE for HIRE. See how to outsource your project to us
  • Please feel free to share the link of this tutorial. However, Please do not use our content on any other websites. We invested a lot of effort and time to create the content, please respect our work!