In this tutorial, we will learn to interface KY-023 Analog Joystick module with Raspberry Pi Pico. First, we will see some introduction, pinout, and working of the module, After that, we will look at a Raspberry Pi Pico MicroPython sketch for the joystick module to read its state such as x-axis, y-axis, etc. In other words, we will read 2-axis motion.
Before we start this lesson, make sure you are familiar with and have the latest version of Python3 installed in your system and set up MicroPython in your Raspberry Pi Pico. Additionally, you should have a running Integrated Development Environment(IDE) to do the programming. We will be using the same Thonny IDE as we have done previously when we learned how to blink and chase LEDs in MicroPython here:
If you are using uPyCraft IDE, you can check this getting started guide:
KY-023 Joystick module
The Joystick module is a very simple self-centered spring-loaded module similar to PS2 (PlayStation 2). It consists of two variable resistors and a push button. Variable resistors provide output in the form of analog voltage and push-button provides output in digital form either low state or high state. One Potentiometer is for x-axis control and another Potentiometer is for Y-axis control.
An important thing to note here is that the Joystick features two 10k potentiometers one for each axis that provides variable voltage. The KY-023 joystick module aims to provide two-dimensional (x-axis and y-axis) motion to a microcontroller.
There is a push-button at the center which is used to control the z-axis dimension. It is turned on when you press the black cap down.
The joystick module consists of 5 pins. The description of each pin is given below:
|Pin Number||Pin Name||Description|
|1||GND||Connect to ground terminal of Raspberry Pi Pico|
|2||+5v||Connect 5-volt pin of Raspberry Pi Pico|
|3||VRx||It provides voltage w.r.t x-axis position of the joystick. (left/right)|
|4||VRy||It provides voltage w.r.t Y-axis position of the joystick. (up/down)|
|5||SW||Switch at the center. This pin gives the output obtained from the push button. When the push button is released the output will be HIGH and when it will be pressed the output will be LOW.|
The internal circuit diagram of the joystick module is shown below:
Joystick Module Working
The Joystick Module works on the basic principle of two potentiometers and a Gimbal Mechanism. These two mechanisms make it easier to determine the position of the Joystick (right, left, up, and down) using Raspberry Pi Pico.
Each potentiometer is connected to each of the Joystick’s shafts. They are used to determine the position of the rod. The position is interpreted as analog values from the microcontroller.
The resistance of the potentiometer changes as the joystick’s physical position is varied. This change is measured through the ADC pins of the board. In Raspberry Pi Pico, there is a 12-bit SAR type ADC. Hence, the digital value will be between 0-4095.
When we move the joystick module on the left or the right side value of VRX varies. When we move this module up or down, the value of VRY varies. When we move it in diagonal direction values of both VRX and VRY vary. When we press it in the middle position, the SW pin becomes high.
Raspberry Pi Pico ADC Channels
Raspberry Pi Pico has a 12-bit resolution which we can change according to our needs. It supports four 12-bit SAR based analog to digital converters. But only three analog channels are exposed to pinout. The fourth analog channel is internally connected to the internal temperature sensor. Therefore, if we want to measure temperature, we can directly use build-in temperature by reading the analog value of ADC4. The following table shows that the input signal for ADC0, ADC1 and ADC2 can be connected with GP26, GP27, and GP28 pins, respectively.
|ADC Module||GPIO Pins|
A/D conversion can be performed in polling, interrupt, and FIFO with DMA mode.
ADC conversion speed per sample is 2μs that is 500kS/s. Because RP2040 microcontroller operates on 48MHZ clock frequency which comes from USB PLL. ADC takes 96 CPU clock cycles to perform one conversion. Therefore, the sampling frequency is
96 x 1 / 48MHz) = 2 μs per sample (500kS/s).
Interfacing Joystick Module with Raspberry Pi Pico
Following components are required:
- Raspberry Pi Pico
- Joystick Module
- Connecting Wires
Follow the schematic diagram below:
As you may see, the Joystick module has 5 pins which we will connect with the Raspberry Pi Pico board. Connect +5V pin of joystick module with 5V pin of Raspberry Pi Pico. Then connect both the GND pins together. We have used analog pins GP27 and GP26 of the Raspberry Pi Pico board to connect with VRx and VRy pins of the joystick module respectively. Additionally, we have connected GP22 of Raspberry Pi Pico with the SW pin of the module. You can use any appropriate analog pin of Raspberry Pi Pico to connect with VRx and VRy pins and any appropriate GPIO pin of the board to connect with SW.
MicroPython Sketch: Reading analog/digital input from Joystick Module
Open your Thonny IDE and go to File > New to open a new file. Copy the code given below in that file.
This sketch will display on the shell monitor, the Joystick physical positions in terms of x and y coordinates. Moreover, the switch output will be shown as well.
from machine import Pin, ADC from time import sleep VRX = ADC(Pin(27)) VRY = ADC(Pin(26)) SW = Pin(22,Pin.IN, Pin.PULL_UP) while True: xAxis = VRX.read_u16() yAxis = VRY.read_u16() switch = SW.value() print("X-axis: " + str(xAxis) + ", Y-axis: " + str(yAxis) + ", Switch " + str(switch)) if switch == 0: print("Push button pressed!") print(" ") sleep(1)
How the Code Works?
Firstly in order to read the Analog input, we will import the ADC class. The Pin class is also imported in order to interact with the GPIOs. We will import the machine module that contains classes to interact with the GPIOs. The sleep module is also imported for use in delays.
from machine import Pin, ADC from time import sleep
Next, we will define the analog pins that we have connected with the VRx and VRy pins of the module. Also, we will configure GP22 that we have connected with SW pin of the module as an input pin with a pull-up resistor. This will set the SW pin to HIGH initially. The SW pin is HIGH when the push button is not pressed.
VRX = ADC(Pin(27)) VRY = ADC(Pin(26)) SW = Pin(22,Pin.IN, Pin.PULL_UP)
Inside the infinite while loop we will first acquire the x and y-axis positions of the joystick. Using the read_u16() method, we will read the value of VRX and VRY and store them in the variables ‘xAxis’ and ‘yAxis’ respectively.
To read the Analog value, we use read_u16() method on the ADC object to get the required value. We will get readings from 0-65535 as the 12-bit resolution has been scaled to 16 bit here.
xAxis = VRX.read_u16() yAxis = VRY.read_u16()
We will also read the switch output and store it in the variable ‘switch’. This will be achieved using SW.value(). It will return ‘1’ if the SW output is HIGH and ‘0’ if the SW output is LOW. Note that a HIGH output means push button is not pressed and a LOW output means the push button is pressed.
switch = SW.value()
After every second, all these three readings will be displayed on the serial monitor.
print("X-axis: " + str(xAxis) + ", Y-axis: " + str(yAxis) + ", Switch " + str(switch))
Whenever the switch output is low, the shell terminal will print the message “Push button pressed!”
if switch == 0: print("Push button pressed!")
After copying the above code to a new file, click on the “Save” icon. This gives two options to save this file either to your computer or directly to your devices such as Raspberry Pi Pico. That means we can also directly upload files to a device. But for now, save it on your computer. You can select any location in your computer where you want to save this file. Save it as main.py (You can use any other name as well just make sure it ends in .py)
Now click on the “Run” button to upload code to Raspberry Pi Pico. Before uploading code make sure the correct board is selected.
Move the joystick in different directions and you will be able to view the corresponding x-axis and y-axis positions along with the switch output. Now press the push button. The switch output will now be ‘0’ and you will receive a message displaying that the push button was pressed.
The KY-023 joystick we used was analog and it provided more accurate readings than the simple directional joysticks. However, the Joystick is not very sensitive to positional changes because Raspberry Pi Pico ADC conversion is not that precise.
You may like to read:
- Joystick module interfacing with pic microcontroller
- Interface MG995 Servo Motor with Arduino – Example Code
- Joystick based servo motor control using arduino
- KY-038 Microphone Sound Sensor Module with Arduino
- MAX6675 K-Type Thermocouple with Arduino
Other Raspberry Pi Pico tutorials:
- TM1637 4-Digit 7 Segment Display Module with Raspberry Pi Pico
- Data Logger with Raspberry Pi Pico and Micro SD Card
- Interface Micro SD Card Module with Raspberry Pi Pico
- RC522 RFID Reader Module with Raspberry Pi Pico
- NEO-6M GPS Module with Raspberry Pi Pico using MicroPython
- 28BYJ-48 Stepper Motor with Raspberry Pi Pico using MicroPython