Tutorials / Input
Analog joystick
Two potentiometers and a button in one stick: two ADC channels and one digital input.
- Joystick
- RGB LED
What it is
The KY-023 joystick module is two potentiometers at right angles, moved by the stick, plus a push button you reach by pressing the stick down. At rest both wipers sit in the middle, so a resting joystick reads about 2048 on each axis; the button is a normal contact to ground.
In the simulator
The block is the module seen from above. Drag the cap: it moves within a circle, like the real lever, and both readings follow; release it and it springs back to the center. Press SW for the button. The Y axis setting flips the direction of Y — modules on the market disagree about which way is up, and here you match yours.
Pins
| Pin | What it is |
|---|---|
| VX | X axis — to a GPIO with an ADC |
| VY | Y axis — to a GPIO with an ADC |
| SW | the stick's push button — to a GPIO (LOW when pressed) |
| 3V3 | power — to a 3V3 symbol |
| GND | ground — to a GND symbol |
Wiring
The circuit below is the example RGB LED colors with a joystick from the lab — open it with Project → Open example… and it comes ready to run.
| Joystick pin | Goes to |
|---|---|
| VX | D34 on the board (GPIO 34) |
| VY | D35 on the board (GPIO 35) |
| SW | D33 on the board (GPIO 33) |
| 3V3 | a 3V3 symbol |
| GND | a GND symbol |
Settings
Double-click the block's title bar to open its card, then the Settings tab. Changes apply to the running simulation right away.
| Setting | Accepts | Default | Notes |
|---|---|---|---|
| Y axis | Normal (up = lower) · Inverted (up = higher) | Normal (up = lower) | Joystick modules disagree on the Y axis direction; here you match yours. |
Code
#include <Arduino.h>
const int VX = 34; // joystick X axis (ADC)
const int VY = 35; // Y axis (ADC)
const int SW = 33; // joystick button
const int R = 25, G = 26, B = 27;
void setup() {
Serial.begin(115200);
pinMode(R, OUTPUT); pinMode(G, OUTPUT); pinMode(B, OUTPUT);
pinMode(SW, INPUT_PULLUP);
}
void loop() {
int x = analogRead(VX); // 0..4095, at rest ~2048
int y = analogRead(VY);
bool apertado = digitalRead(SW) == LOW;
digitalWrite(R, x > 2800 ? HIGH : LOW);
digitalWrite(B, y > 2800 ? HIGH : LOW);
digitalWrite(G, apertado ? HIGH : LOW);
Serial.printf("x=%d y=%d button=%d\n", x, y, apertado);
delay(100);
}
Two analogRead calls and one digitalRead with the pull-up on. The example compares each axis with 2800 to decide whether a channel of the RGB LED lights; the button lights green.
Run it
Press Build and run. The first build of a project takes a while; after that, only what changed is rebuilt.
Drag the cap to the right: red. Drag it up: blue. Press SW: green. The serial monitor prints x, y and the button on every pass.
How the simulation models it
- X and Y are ADC counts from 0 to 4095, 2048 at the center, following the cap linearly along each axis; the cap's travel is circular, so full deflection on both axes at once is not possible — as on the real lever.
- SW drives its pin like a button: HIGH at rest, LOW while pressed.
- Both axes are sent at start-up as 2048, so a sketch that calibrates the center on boot sees a centered stick.
Try this
- Print the direction as text (“north”, “south-east”…) instead of numbers, using a dead zone around the center.
- Drive the servo of another example with the X axis.
See also
- Potentiometer — A variable resistor whose wiper divides 3.3 V — the first analog input, read with analogRead().
- Push button — A momentary contact: HIGH while released, LOW while pressed — the first digital input.
- RGB LED — Three LEDs in one package, one GPIO each — red, green and blue mix into eight colors.