Arduino Nano ESP32 - Joystick

In this tutorial, we are going to learn how to use Joystick with Arduino Nano ESP32. In detail, we will learn:

Joystick Pinout

Hardware Preparation

1×Arduino Nano ESP32
1×USB Cable Type-C
1×Joystick
1×Breadboard
1×Jumper Wires
1×(Optional) DC Power Jack
1×(Recommended) Screw Terminal Expansion Board for Arduino Nano
1×(Recommended) Breakout Expansion Board for Arduino Nano

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 Joystick Sensor

You probably see the Joystick somewhere such as a game controller, toy controller, or even a big real machine such as an excavator controller.

The joystick is composed of two potentiometers square with each other, and one push button. Therefore, it provides the following outputs:

  • An analog value (from 0 to 4095) corresponding to the horizontal position (called X-coordinate)
  • An analog value (from 0 to 4095) corresponding to the vertical position (called Y-coordinate)
  • A digital value of a pushbutton (HIGH or LOW)

The combination of two analog values can create 2-D coordinates with the center are values when the joystick is in the rest position. The real direction of the coordinates can be identified simply when you run a test code (in the next part).

Some applications may use all three outputs, some applications may use some of three outputs.

Pinout

A Joystick has 5 pins:

  • GND pin: needs to be connected to GND (0V)
  • VCC pin: needs to be connected to VCC (3.3V)
  • VRX pin: outputs an analog value corresponding to the horizontal position (called X-coordinate).
  • VRY pin: outputs an analog value corresponding to the vertical position (called Y-coordinate).
  • SW pin: is the output from the pushbutton inside the joystick. It’s normally open. If we use a pull-up resistor 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 push the joystick's thump to left/right, the voltage in the VRX pin is changed, The voltage range is from 0 to 3.3V (0 at left and 3.3V at right). The voltage value is in proportion to the position of the thump ⇒ The reading value on ESP32's analog pin is from 0 to 4095
  • When you push the joystick's thump to up/down, the voltage in the VRY pin is changed, The voltage range is from 0 to 3.3V (0 at up and 3.3V at down). The voltage value is in proportion to the position of the thump ⇒ The reading value on ESP32's analog pin is from 0 to 4095
  • When you push the joystick's thump to any direction, the voltage in both VRX and VRY pins is changed in proportion to the projection of position on each axis
  • When you push the joystick's thump from top to bottom, the pushbutton inside the joystick is closed, If we use a pull-up resistor in the SW pin, the output from SW pin will change from 3.3V to 0V ⇒ The reading value on ESP32's digital pin is changed from HIGH to LOW

Wiring Diagram

The wiring diagram between Arduino Nano ESP32 and Joystick

This image is created using Fritzing. Click to enlarge image

How To Program For Joystick

The joystick has two parts: analog (X, Y axis) and digital (pushbutton)

  • For the analog parts (X, Y axis), it just need to read the value from analog input pin by using analogRead() function.
int valueX = analogRead(A0); int valueY = analogRead(A1);
  • For the digital part (pushbutton): it is a button. The most simple and convenient way is to use ezButton library. This library supports debounce for buttons and also enables an internal pull-up resistor. You can see more about button in Arduino Nano ESP32 - Button tutorial. The code will be presented in the next session in this tutorial.

After reading the values from analog pins, we may need to convert them to some controllable values. The next part will provide the example codes for this.

Arduino Nano ESP32 Code

This section will provide the following Arduino Nano ESP32 example codes:

  • Example code: reads analog values from joystick
  • Example code: reads analog values and reads the button state from joystick
  • Example code: converts analog value to MOVE_LEFT, MOVE_RIGHT, MOVE_UP, MOVE_DOWN commands
  • Example code: converts analog values to angles to control two servo motors (e.g. in pan-tilt camere)

Reads analog values from joystick

/* * This Arduino Nano ESP32 code was developed by newbiely.com * * This Arduino Nano ESP32 code is made available for public use without any restriction * * For comprehensive instructions and wiring diagrams, please visit: * https://newbiely.com/tutorials/arduino-nano-esp32/arduino-nano-esp32-joystick */ #define VRX_PIN A0 // The Arduino Nano ESP32 pin connected to VRX pin #define VRY_PIN A1 // The Arduino Nano ESP32 pin connected to VRY pin int valueX = 0; // to store the X-axis value int valueY = 0; // to store the Y-axis value void setup() { Serial.begin(9600); // Set the ADC attenuation to 11 dB (up to ~3.3V input) analogSetAttenuation(ADC_11db); } void loop() { // read X and Y analog values valueX = analogRead(VRX_PIN); valueY = analogRead(VRY_PIN); // print data to Serial Monitor on Arduino IDE Serial.print("x = "); Serial.print(valueX); Serial.print(", y = "); Serial.println(valueY); delay(200); }

Detailed Instructions

To get started with Arduino Nano ESP32, follow these steps:

  • If you are new to Arduino Nano ESP32, refer to the tutorial on how to set up the environment for Arduino Nano ESP32 in the Arduino IDE.
  • Wire the components according to the provided diagram.
  • Connect the Arduino Nano ESP32 board to your computer using a USB cable.
  • Launch the Arduino IDE on your computer.
  • Select the Arduino Nano ESP32 board and its corresponding COM port.
  • Copy the above code and open with Arduino IDE
  • Click Upload button on Arduino IDE to upload code to Arduino Nano ESP32
  • Push the joystick's thump maximally to the limit, and then rotate it in a circle (clockwise or anti-clockwise)
  • Check out the result on the Serial Monitor.
COM6
Send
Autoscroll Show timestamp
Clear output
9600 baud  
Newline  
  • While rotating the joystick' thump, keep watching the Serial Monitor
    • If the X value is 0, mark or memorize the current position as left ⇒ the opposite direction the right
    • If the Y value is 0, mark or memorize the current position as up ⇒ the opposite direction the down

    You may have noticed that the analog value is not proportional to the joystick movement. This issue is not due to the joystick itself, but rather the ADC of the Arduino Nano ESP32. The end of this tutorial will explain why this happens.

    Reads analog values and reads the button state from a joystick

    /* * This Arduino Nano ESP32 code was developed by newbiely.com * * This Arduino Nano ESP32 code is made available for public use without any restriction * * For comprehensive instructions and wiring diagrams, please visit: * https://newbiely.com/tutorials/arduino-nano-esp32/arduino-nano-esp32-joystick */ #include <ezButton.h> #define VRX_PIN A0 // The Arduino Nano ESP32 pin connected to VRX pin #define VRY_PIN A1 // The Arduino Nano ESP32 pin connected to VRY pin #define SW_PIN D2 // The Arduino Nano ESP32 pin connected to SW pin ezButton button(SW_PIN); int valueX = 0; // to store the X-axis value int valueY = 0; // to store the Y-axis value int bValue = 0; // To store value of the button void setup() { Serial.begin(9600); // Set the ADC attenuation to 11 dB (up to ~3.3V input) analogSetAttenuation(ADC_11db); button.setDebounceTime(50); // set debounce time to 50 milliseconds } void loop() { button.loop(); // MUST call the loop() function first // read X and Y analog values valueX = analogRead(VRX_PIN); valueY = analogRead(VRY_PIN); // Read the button value bValue = button.getState(); if (button.isPressed()) { Serial.println("The button is pressed"); // TODO do something here } if (button.isReleased()) { Serial.println("The button is released"); // TODO do something here } // print data to Serial Monitor on Arduino IDE Serial.print("x = "); Serial.print(valueX); Serial.print(", y = "); Serial.print(valueY); Serial.print(" : button = "); Serial.println(bValue); }

    Detailed Instructions

    • Open the Library Manager by clicking on the Library Manager icon on the left navigation bar of Arduino IDE
    • Search “ezButton”, then find the button library by ArduinoGetStarted.com
    • Click Install button to install ezButton library.
    Arduino Nano ESP32 button library
    • Copy the above code and open with Arduino IDE
    • Click Upload button on Arduino IDE to upload code to Arduino Nano ESP32
    • Push the thump of the joystick to left/right/up/down
    • Push the thump of the joystick from the top
    • Check out the result on the Serial Monitor.
    COM6
    Send
    Autoscroll Show timestamp
    Clear output
    9600 baud  
    Newline  

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

    /* * This Arduino Nano ESP32 code was developed by newbiely.com * * This Arduino Nano ESP32 code is made available for public use without any restriction * * For comprehensive instructions and wiring diagrams, please visit: * https://newbiely.com/tutorials/arduino-nano-esp32/arduino-nano-esp32-joystick */ #define VRX_PIN A0 // The Arduino Nano ESP32 pin connected to VRX pin #define VRY_PIN A1 // The Arduino Nano ESP32 pin connected to VRY pin #define LEFT_THRESHOLD 1000 #define RIGHT_THRESHOLD 3000 #define UP_THRESHOLD 1000 #define DOWN_THRESHOLD 3000 #define COMMAND_NO 0x00 #define COMMAND_LEFT 0x01 #define COMMAND_RIGHT 0x02 #define COMMAND_UP 0x04 #define COMMAND_DOWN 0x08 int valueX = 0 ; // to store the X-axis value int valueY = 0 ; // to store the Y-axis value int command = COMMAND_NO; void setup() { Serial.begin(9600); // Set the ADC attenuation to 11 dB (up to ~3.3V input) analogSetAttenuation(ADC_11db); } void loop() { // read X and Y analog values valueX = analogRead(VRX_PIN); valueY = analogRead(VRY_PIN); // converts the analog value to commands // reset commands command = COMMAND_NO; // check left/right commands if (valueX < LEFT_THRESHOLD) command = command | COMMAND_LEFT; else if (valueX > RIGHT_THRESHOLD) command = command | COMMAND_RIGHT; // check up/down commands if (valueY < UP_THRESHOLD) command = command | COMMAND_UP; else if (valueY > DOWN_THRESHOLD) command = command | COMMAND_DOWN; // NOTE: AT A TIME, THERE MAY BE NO COMMAND, ONE COMMAND OR TWO COMMANDS // print command to serial and process command if (command & COMMAND_LEFT) { Serial.println("COMMAND LEFT"); // TODO: add your task here } if (command & COMMAND_RIGHT) { Serial.println("COMMAND RIGHT"); // TODO: add your task here } if (command & COMMAND_UP) { Serial.println("COMMAND UP"); // TODO: add your task here } if (command & COMMAND_DOWN) { Serial.println("COMMAND DOWN"); // TODO: add your task here } }

    Detailed Instructions

    • Copy the above code and open with Arduino IDE
    • Click Upload button on Arduino IDE to upload code to Arduino Nano ESP32
    • Push the thump of joystick to left/right/up/down or any direction
    • Check out the result on the Serial Monitor.
    COM6
    Send
    Autoscroll Show timestamp
    Clear output
    9600 baud  
    Newline  

    ※ NOTE THAT:

    At a time, there may be no command, one command or two commands (e.g. UP and LEFT at the same time)

    Converts analog values to angles to control two servo motors

    The detail is presented on Arduino Nano ESP32 - Joystick controls Servo Motor tutorial

    ※ NOTE THAT:

    This tutorial uses the analogRead() function to read values from an ADC (Analog-to-Digital Converter) connected to a sensor or component. The Arduino Nano ESP32's ADC is suitable for projects that do not require high accuracy. However, for projects needing precise measurements, keep the following in mind:

    • The Arduino Nano ESP32's ADC is not perfectly accurate and might require calibration for correct results. Each Arduino Nano ESP32 board can vary slightly, so calibration is necessary for each individual board.
    • Calibration can be challenging, especially for beginners, and might not always yield the exact results you want.

    For projects requiring high precision, consider using an external ADC (e.g ADS1115) with the Arduino Nano ESP32 or using another Arduino, such as the Arduino Uno R4 WiFi, which has a more reliable ADC. If you still want to calibrate the Arduino Nano ESP32's ADC, refer to the ESP32 ADC Calibration Driver.

Video Tutorial

※ 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!