Componenti · 5 min di lettura

Come usare un modulo joystick: leggere gli assi X-Y e il pulsante con Arduino

Come funziona un modulo joystick analogico (KY-023)? Pin VRx, VRy e SW, collegamento ad Arduino, zona morta e calibrazione, rilevamento della direzione, controllo di un servo con il joystick, codice per ESP32 e Pico.

Un modulo joystick è la versione per Arduino delle levette dei controller per videogiochi. Muovendo la levetta a destra-sinistra e avanti-indietro, fornisce la sua posizione su due assi, e premendola verso il basso si attiva un pulsante interno. È l'elemento di input più pratico per telecomandi di auto robot, supporti pan-tilt per telecamere, giochi su matrici LED e menu su display. Il modello più diffuso è noto anche come KY-023.

Modulo joystick analogico KY-023
Modulo joystick analogico: contiene due potenziometri per i due assi e un pulsante che si attiva premendo la levetta; ha 5 pin: GND, +5V, VRx, VRy e SW.

Come funziona un modulo joystick?

Sotto la levetta ci sono due potenziometri da 10 kΩ disposti ad angolo retto: uno rileva il movimento sull'asse X, l'altro sull'asse Y. Ogni potenziometro funziona come un partitore di tensione; con la levetta al centro il cursore dà circa 2,5 V e analogRead() legge circa 512. Spingendo la levetta fino a un'estremità il valore si avvicina a 0, all'altra estremità a 1023. Premendo la levetta dall'alto, un piccolo pulsante collega il pin SW a GND.

Posizione della levettaVRx (X)VRy (Y)
Centro (rilasciata)~512~512
Tutta a sinistra~0~512
Tutta a destra~1023~512
Tutta in alto~512~0
Tutta in basso~512~1023

Quale direzione dia 0 e quale 1023 dipende da come tieni il modulo. Se con i pin rivolti verso di te le direzioni non coincidono con questa tabella, nessun problema: nel codice puoi invertire un asse sottraendo il valore da 1023.

Piedinatura e collegamento del joystick

PinFunzioneArduino UnoESP32Raspberry Pi Pico
GNDMassaGNDGNDGND
+5VAlimentazione5V3V33V3
VRxAsse X (analogico)A0GPIO 34GP26
VRyAsse Y (analogico)A1GPIO 35GP27
SWPulsante (a GND quando premuto)D2GPIO 25GP15
Su ESP32 e Pico alimenta il modulo dal pin 3V3, non dal 5V; anche se il pin si chiama "+5V", il modulo funziona senza problemi a 3,3 V. Se lo alimenti a 5 V, ai pin analogici arrivano più di 3,3 V e la scheda può danneggiarsi. Sull'ESP32 non usare i pin 34–39 per SW: non hanno la resistenza di pull-up interna.

Leggere il joystick con Arduino

Il codice qui sotto legge i due assi e il pulsante e li stampa nel Monitor seriale. Poiché il pulsante si collega a GND quando lo premi e la maggior parte dei moduli non ha resistenza di pull-up, il pin SW va impostato come INPUT_PULLUP: così leggi HIGH da rilasciato e LOW da premuto.

Arduino (C++)
1const int X_PIN = A0;
2const int Y_PIN = A1;
3const int SW_PIN = 2;
4
5void setup() {
6  pinMode(SW_PIN, INPUT_PULLUP);   // basınca LOW / LOW when pressed
7  Serial.begin(9600);
8}
9
10void loop() {
11  int x = analogRead(X_PIN);       // 0–1023, ortada ~512 / ~512 at center
12  int y = analogRead(Y_PIN);
13  bool pressed = digitalRead(SW_PIN) == LOW;
14
15  Serial.print("X: ");  Serial.print(x);
16  Serial.print("  Y: "); Serial.print(y);
17  Serial.print("  Buton / button: ");
18  Serial.println(pressed ? "basılı / pressed" : "-");
19  delay(100);
20}
Se apri il Plotter seriale, vedi i due assi sullo stesso grafico. Osservare come cambiano le due linee mentre ruoti lentamente la levetta è il modo più rapido per capire la direzione di ciascun asse.

Zona morta e calibrazione

Nella realtà, con la levetta rilasciata il valore non è esattamente 512: legge qualcosa come 495 o 525 e oscilla di qualche unità. Se non lo correggi, la tua auto robot avanza da sola o il servo trema anche se non tocchi il joystick. La soluzione ha due passi: misurare e salvare il valore centrale all'avvio (calibrazione) e ignorare le piccole deviazioni vicino al centro (zona morta). La funzione qui sotto trasforma ogni asse in un valore pulito da -100 a +100 con il centro esattamente a 0:

Arduino (C++)
1int centerX, centerY;
2const int DEAD_ZONE = 40;
3
4int readAxis(int pin, int center) {
5  int v = analogRead(pin) - center;
6  if (abs(v) < DEAD_ZONE) return 0;                              // ölü bölge / dead zone
7  if (v > 0) return map(v, DEAD_ZONE, 1023 - center, 0, 100);    // sağ ya da aşağı / right or down
8  return map(v, -center, -DEAD_ZONE, -100, 0);                   // sol ya da yukarı / left or up
9}
10
11void setup() {
12  Serial.begin(9600);
13  centerX = analogRead(A0);   // açılışta joystick'e dokunma / don't touch it at startup
14  centerY = analogRead(A1);
15}
16
17void loop() {
18  Serial.print(readAxis(A0, centerX));
19  Serial.print(", ");
20  Serial.println(readAxis(A1, centerY));
21  delay(50);
22}

Rilevare le direzioni: su, giù, sinistra, destra

Nei giochi e nei menu spesso serve solo la direzione, non la posizione esatta. Confrontando i valori con due soglie trasformi il joystick in una croce direzionale a quattro vie. Per muoversi in un menu ogni spinta dovrebbe contare come un solo passo, quindi il codice usa una breve pausa oppure non accetta un nuovo passo finché la levetta non torna al centro.

Arduino (C++)
1void loop() {
2  int x = analogRead(A0);
3  int y = analogRead(A1);
4  if (x < 300)      Serial.println("Sol / left");
5  else if (x > 700) Serial.println("Sağ / right");
6  else if (y < 300) Serial.println("Yukarı / up");
7  else if (y > 700) Serial.println("Aşağı / down");
8  delay(150);
9}

Comandare un servomotore con il joystick

Convertendo un asse del joystick in 0–180 gradi puoi orientare un servo a mano; con due assi e due servo ottieni un supporto pan-tilt che ruota una telecamera a destra-sinistra e su-giù. Per il collegamento del servo e le avvertenze sull'alimentazione, vedi Cos'è un servomotore?

Arduino (C++)
1#include <Servo.h>
2
3Servo panServo;
4
5void setup() {
6  panServo.attach(9);
7}
8
9void loop() {
10  int x = analogRead(A0);
11  int angle = map(x, 0, 1023, 0, 180);   // joystick → açı / joystick → angle
12  panServo.write(angle);
13  delay(15);
14}

Joystick con ESP32 e Raspberry Pi Pico

L'ADC dell'ESP32 è a 12 bit e dà valori da 0 a 4095, ma poiché non è lineare, il centro spesso risulta intorno a 1800–1950 invece di 2048. Per questo la calibrazione vista sopra è ancora più importante sull'ESP32. Se userai il Wi-Fi, collega gli assi ai pin ADC1 (GPIO 32–39). Sul Pico gli ingressi analogici sono GP26–GP28 e read_u16() restituisce valori da 0 a 65535:

MicroPython
1from machine import ADC, Pin
2import time
3
4x_axis = ADC(26)                        # GP26 → VRx
5y_axis = ADC(27)                        # GP27 → VRy
6button = Pin(15, Pin.IN, Pin.PULL_UP)   # SW, basınca 0 / 0 when pressed
7
8while True:
9    x = x_axis.read_u16()               # 0–65535, ortada ~32768 / ~32768 at center
10    y = y_axis.read_u16()
11    print(x, y, "BASILI / PRESSED" if button.value() == 0 else "")
12    time.sleep(0.1)

Idee di progetti con il joystick

  • Telecomando per auto robot: collega il joystick a una scheda trasmittente e invia comandi all'auto tramite nRF24L01 o Bluetooth.
  • Telecamera pan-tilt: orienta una telecamera in ogni direzione con due servo e un joystick.
  • Snake su matrice LED: guida il serpente su una matrice 8x8 con il joystick.
  • Menu su display: scorri le opzioni con su e giù e seleziona con il pulsante; per il display vedi Usare un display LCD I2C.
  • Selettore di colore: comanda un LED RGB scegliendo il colore con l'asse X e la luminosità con l'asse Y.
  • Mouse per computer: trasforma il joystick in un vero mouse USB con un Arduino Leonardo o un Pro Micro.

Errori comuni e come risolverli

  • Il pulsante sembra premuto anche quando non lo è: il pin SW non è in INPUT_PULLUP; il pin resta flottante e legge valori casuali.
  • A riposo non legge 512 e oscilla: è normale; calibra all'avvio e aggiungi una zona morta.
  • Gli assi sono invertiti o scambiati: dipende dall'orientamento del modulo; sottrai il valore da 1023 oppure scambia i fili di VRx e VRy.
  • Sull'ESP32 il centro non è 2048: l'ADC dell'ESP32 non è lineare; misura il centro all'avvio e calcola a partire da quello.
  • Il servo trema o Arduino si riavvia: il servo sovraccarica i 5 V di Arduino; alimentalo con una sorgente da 5 V separata e collega insieme le masse.

Un joystick in fondo è solo due potenziometri e un pulsante, quindi Cos'è un potenziometro? e Come collegare un pulsante ad Arduino rafforzano quello che hai imparato qui. Nell'app BlueGrays trovi progetti di controllo di LED e servo con il joystick e un gioco Snake su matrice LED, con schemi e codice.

Domande frequenti

A cosa servono i pin del modulo joystick?

GND e +5V sono i pin di alimentazione. VRx e VRy forniscono la posizione sugli assi X e Y come tensione analogica e vanno collegati a pin analogici. SW è l'uscita del pulsante, che si collega a GND quando premi la levetta, e va a un pin digitale impostato come INPUT_PULLUP.

Perché il mio joystick non legge esattamente 512 al centro?

Potenziometri e meccanica non sono perfetti; a riposo il valore di solito sta tra 490 e 530 e oscilla di qualche unità. Misurare e salvare il valore centrale all'avvio e usare una zona morta di ±30–50 risolve il problema.

Perché il pin SW passa a caso tra LOW e HIGH?

La maggior parte dei moduli joystick non ha una resistenza di pull-up per il pulsante, quindi il pin resta flottante come se non fosse collegato. Attiva il pull-up interno di Arduino con pinMode(SW_PIN, INPUT_PULLUP) e leggerai HIGH da rilasciato e LOW da premuto.

Quanti servo posso comandare con un joystick?

Un joystick ha due assi, quindi comanda due servo in modo indipendente: ideale per una telecamera pan-tilt. Per più servo aggiungi un secondo joystick; i 6 pin analogici di Arduino Uno bastano per un massimo di tre joystick.

Posso usare il joystick come telecomando senza fili?

Sì. Collega il joystick a un Arduino e invia i valori a un'altra scheda con un modulo radio nRF24L01, un modulo Bluetooth HC-05 o ESP-NOW tra due ESP32. La maggior parte dei progetti di auto robot e radiocomando funziona così.

Il modulo joystick funziona con ESP32 e Raspberry Pi Pico?

Sì, ma va alimentato dal pin 3V3. I valori vanno da 0 a 4095 sull'ESP32 e da 0 a 65535 sul Pico. Sull'ESP32 usa i pin ADC1 (GPIO 32–39), che funzionano con il Wi-Fi attivo, e calibra il centro all'avvio.

Vedi tutti i progetti
Controllo a led con joystick
#59Intermedio
Premium

Controllo a led con joystick

Progetto di controllo che illumina i LED in 4 direzioni diverse in base ai valori degli assi X e Y del modulo joystick. Insegna la lettura analogica del joystick e la logica di rilevamento della direz

4.7(50)
66
Servocomando con joystick
#60Intermedio
Premium

Servocomando con joystick

Progetto di pan-tilt che controlla in modo indipendente due servomotori sugli assi X e Y con un modulo joystick. Insegna la logica dell'integrazione joystick-servo e l'inseguimento della posizione.

4.7(42)
58
Serpente di pixel Matrice 8x8
#88Avanzato
Premium

Serpente di pixel Matrice 8x8

Gioco di serpenti hardware basato su Arduino, sviluppato utilizzando una matrice di LED 8x8 WS2812B NeoPixel e un joystick analogico. Include un algoritmo di velocità dinamica e controlli matematici d

4.7(39)
57
Matrice Snake 16x16
#89Avanzato
Premium

Matrice Snake 16x16

Si tratta di una porta hardware estesa a 256 pixel del classico gioco del serpente che gira su una matrice 16x16 WS2812B NeoPixel. In questo progetto, controllato da Arduino e da un joystick analogico

4.8(52)
67
Servomotore ESP32 (controllo tramite potenziometro)
#118Intermedio
Premium

Servomotore ESP32 (controllo tramite potenziometro)

In questo progetto controlliamo un servomotore SG90 tramite un potenziometro. Regoliamo l'angolo del servomotore mappando il valore analogico letto dal potenziometro su un intervallo compreso tra 0 e 180 gradi. Grazie alla libreria ESP32Servo, qualsiasi GPIO dell'ESP32 può generare un segnale PWM. Si tratta di un metodo di controllo fondamentale per bracci robotici, gimbal per telecamere e meccanismi di porte automatiche.

4.3(29)
42
Gioco Pong - SSD1306
#86Intermedio
Premium

Gioco Pong - SSD1306

Il classico gioco del Pong costruito con Arduino e display OLED SSD1306, dotato di un'intelligenza artificiale (CPU) autonoma che segue istantaneamente i movimenti della palla e reagisce in base alla

4.5(47)
65
OLED T-Rex Run: Gioco del dinosauro con Arduino 🦖
#87Avanzato
Premium

OLED T-Rex Run: Gioco del dinosauro con Arduino 🦖

Abbiamo portato il leggendario gioco dei dinosauri "No Internet" su hardware! Trasformate l'emozione del gioco retrò in una mini console fisica con questo progetto che abbiamo sviluppato utilizzando A

4.7(33)
53
Arduino LCD Runner Game
#98Intermedio
Premium

Arduino LCD Runner Game

Gioco endless runner a scorrimento laterale su schermo LCD a 6x2 caratteri. L'eroe corre automaticamente, il giocatore salta gli ostacoli premendo il pulsante. Sulla riga superiore e inferiore compaiono ostacoli casuali. Il cicalino passivo riproduce la melodia di apertura, il suono di salto, il suono di celebrazione dei 50 punti e la melodia di fine gioco. All'avvio viene visualizzata la schermata iniziale "BlueGrays - Arduino Projects". Il punteggio viene aggiornato istantaneamente nell'angolo

4.7(31)
53

Impara a leggere i due potenziometri e il pulsante di un joystick, correggere la deriva del centro con una zona morta, rilevare le direzioni e comandare un servomotore con il joystick.