We will learn how to connect a Raspberry Pi Pico to a KY-023 Analog Joystick module in this tutorial. First, we’ll look at the module’s introduction, pinout, and operation. After that, we’ll look at a Raspberry Pi Pico MicroPython sketch that allows us to read the joystick module’s state, including the x-axis, y-axis, and other variables. We shall, therefore, read 2-axis motion.
KY-023 Joystick module
The Joystick module resembles the PS2 in that it is a very basic self-centered spring-loaded module (PlayStation 2). It comprises a push button and two variable resistors. Push-button output can be either low state or high state while variable resistor output is in the form of analog voltage. A potentiometer is used to control the x-axis, and another potentiometer controls the y-axis.
The Joystick has two 10k potentiometers, one for each axis, that provide variable voltage, which is an important point to note. The KY-023 joystick module intends to give a microcontroller two-dimensional (x- and y-axis) motion.
The z-axis dimension is controlled via a pushbutton located in the middle. When you depress the black cap, it turns on.
Joystick Module PinOut
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. |
Joystick Module Working
Two potentiometers and a gimbal mechanism serve as the foundation for how the joystick module operates. Using the Raspberry Pi Pico, it is simpler to ascertain the joystick’s position (right, left, up, and down) thanks to these two methods.
Each shaft of the joystick is attached to a separate potentiometer. They are used to establish the rod’s location. The microcontroller’s analogue values are translated into the position.
As the joystick’s physical position is altered, the potentiometer’s resistance varies. The board’s ADC pins are used to measure this change. An 12-bit SAR type ADC is present in the Raspberry Pi Pico. As a result, the digital value will range from 0 to 4095.
When we move the joystick module on the left or the right side, the value of VRX varies. When we move this module up or down, the value of VRY varies. When we move it in a 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
The 12-bit resolution of the Raspberry Pi Pico can be altered to suit our needs. Four 12-bit SAR-based analogue to digital converters are supported. But the pinout only shows three analogue channels. The internal temperature sensor is coupled to the fourth analogue channel internally. So, if we want to measure temperature, we can simply read the analogue value from ADC4 and utilize the built-in temperature. According to the following table, GP26, GP27, and GP28 pins can be used to link the input signals for ADC0, ADC1, and ADC2, respectively.
A/D conversion can be carried out in FIFO with DMA, interrupt, and polling modes.
ADC conversion speed per sample is 2μs that is 500kS/s. Because RP2040 microcontroller operates on a 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).
How to Connect Joystick Module with Raspberry Pi Pico?
Following components are required:
- Raspberry Pi Pico
- Joystick Module
- Connecting Wires
Follow the schematic diagram below:
Raspberry Pi Pico with Joystick Module connection diagram
As you can see, there are 5 pins on the joystick module that we will attach to the Raspberry Pi Pico board. Connect the Raspberry Pi Pico’s 5V pin to the +5V pin of the joystick module. Following that, join the GND pins. The Raspberry Pi Pico board’s analogue pins GP27 and GP26 were utilized to link to the VRx and VRy pins of the joystick module, respectively. Additionally, we linked the SW pin of the module with GP22 of the Raspberry Pi Pico. Any suitable GPIO pin of the board may be used to link with SW, and any suitable analogue pin of the Raspberry Pi Pico can be used to connect with VRx and VRy pins.
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 does 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 the 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.
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!”)
Demonstration
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.