Como usar um módulo joystick: lendo os eixos X-Y e o botão com Arduino
Como funciona um módulo joystick analógico (KY-023)? Pinos VRx, VRy e SW, ligação no Arduino, zona morta e calibração, detecção de direção, controle de servo com joystick e código para ESP32 e Pico.
Um módulo joystick é a versão para Arduino dos analógicos que você vê nos controles de videogame. Conforme você move a alavanca para a esquerda e a direita e para a frente e para trás, ele informa a posição em dois eixos e, quando você aperta a alavanca para baixo, um botão interno é acionado. Ele é a entrada mais prática para controles de carrinho robô, suportes de câmera pan-tilt, jogos em matriz de LED e menus em displays. O modelo mais comum também é conhecido como KY-023.

Como funciona um módulo joystick?
Embaixo da alavanca há dois potenciômetros de 10 kΩ posicionados em ângulo reto entre si: um percebe o movimento no eixo X e o outro no eixo Y. Cada potenciômetro funciona como um divisor de tensão; com a alavanca no centro, o cursor dele dá cerca de 2,5 V e analogRead() lê cerca de 512. Empurre a alavanca até um extremo e o valor se aproxima de 0; empurre até o outro e ele se aproxima de 1023. Aperte a alavanca para baixo e um pequeno botão liga o pino SW ao GND.
| Posição da alavanca | VRx (X) | VRy (Y) |
|---|---|---|
| Centro (solta) | ~512 | ~512 |
| Toda à esquerda | ~0 | ~512 |
| Toda à direita | ~1023 | ~512 |
| Toda para cima | ~512 | ~0 |
| Toda para baixo | ~512 | ~1023 |
Qual direção dá 0 e qual dá 1023 depende de como você segura o módulo. Se as direções forem diferentes desta tabela com os pinos virados para você, não se preocupe; dá para inverter um eixo no código facilmente subtraindo o valor de 1023.
Pinagem e ligação do joystick
| Pino | Função | Arduino Uno | ESP32 | Raspberry Pi Pico |
|---|---|---|---|---|
| GND | Terra | GND | GND | GND |
| +5V | Alimentação | 5V | 3V3 | 3V3 |
| VRx | Eixo X (analógico) | A0 | GPIO 34 | GP26 |
| VRy | Eixo Y (analógico) | A1 | GPIO 35 | GP27 |
| SW | Botão (vai ao GND quando apertado) | D2 | GPIO 25 | GP15 |
Lendo um joystick com o Arduino
O código abaixo lê os dois eixos e o botão e mostra os valores no Monitor Serial. Como o botão liga ao GND quando apertado e a maioria dos módulos não tem resistor de pull-up, o pino SW precisa ser configurado como INPUT_PULLUP; assim ele lê HIGH quando solto e LOW quando apertado.
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}Zona morta e calibração
Na vida real, o valor não é exatamente 512 quando a alavanca está solta; ele lê algo como 495 ou 525 e oscila algumas unidades. Se você não corrigir isso, seu carrinho robô anda sozinho para a frente ou o servo treme mesmo sem você tocar no joystick. A solução tem dois passos: medir e guardar o valor do centro na inicialização (calibração) e ignorar pequenos desvios perto do centro (uma zona morta). A função abaixo transforma cada eixo em um valor limpo de -100 a +100, com o centro em exatamente 0:
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}Detectando direções: cima, baixo, esquerda, direita
Em jogos e menus, muitas vezes você só precisa da direção, e não da posição exata. Comparando os valores com dois limites, você transforma o joystick em um direcional de quatro direções. Para navegar em menus, você quer que cada empurrão conte como um único passo, então o código usa um pequeno atraso, ou ignora novos passos até a alavanca voltar ao centro.
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}Controlando um servo motor com um joystick
Mapeando um eixo do joystick para 0–180 graus, você conduz um servo motor à mão; com dois eixos e dois servos, você tem um suporte pan-tilt que gira uma câmera para a esquerda e a direita e para cima e para baixo. Para a ligação do servo e os avisos sobre alimentação, veja O que é servo motor?
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}Joysticks com o ESP32 e o Raspberry Pi Pico
O ADC do ESP32 é de 12 bits e dá valores de 0 a 4095, mas, como o ADC não é linear, o valor do centro muitas vezes sai em torno de 1800–1950, e não 2048. Isso torna o método de calibração acima ainda mais importante no ESP32. Se você for usar Wi-Fi, ligue os eixos em pinos do ADC1 (GPIO 32–39). No Pico, as entradas analógicas são GP26–GP28, e read_u16() devolve valores de 0 a 65535:
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)Ideias de projetos com joystick
- Controle de carrinho robô: ligue o joystick a uma placa transmissora e envie comandos para o carrinho por nRF24L01 ou Bluetooth.
- Câmera pan-tilt: aponte uma câmera para qualquer direção com dois servos e um joystick.
- Jogo da cobrinha em matriz de LED: conduza a cobrinha em uma matriz 8x8 com o joystick.
- Menu em display: navegue pelas opções para cima e para baixo e selecione com o botão; para a parte do display, veja Como usar um display LCD I2C.
- Seletor de cores: controle um LED RGB definindo a cor com o eixo X e o brilho com o eixo Y.
- Mouse de computador: transforme o joystick em um mouse USB de verdade com um Arduino Leonardo ou Pro Micro.
Erros comuns e como resolvê-los
- O botão parece apertado sem estar: o pino SW não está como INPUT_PULLUP; o pino está flutuando, então lê valores aleatórios.
- O valor em repouso não é 512 e oscila: isso é normal; calibre na inicialização e acrescente uma zona morta.
- Os eixos estão invertidos ou trocados: é uma questão de orientação do módulo; subtraia o valor de 1023 ou troque os fios VRx e VRy.
- O centro não é 2048 no ESP32: o ADC do ESP32 não é linear; meça o centro na inicialização e calcule a partir dele.
- O servo treme ou o Arduino reinicia: o servo está sobrecarregando os 5 V do Arduino; alimente o servo com uma fonte de 5 V separada e ligue os terras entre si.
Um joystick é, na verdade, só dois potenciômetros e um botão, então O que é potenciômetro? e Como ligar um botão no Arduino reforçam o que você aprendeu aqui. No app BlueGrays você encontra projetos de controle de LED e de servo com joystick e um jogo da cobrinha em matriz de LED, com esquemas do circuito e código.
Perguntas frequentes
O que fazem os pinos do módulo joystick?
GND e +5V são os pinos de alimentação. VRx e VRy dão a posição nos eixos X e Y como uma tensão analógica e são ligados em pinos analógicos. SW é a saída do botão, que liga ao GND quando você aperta a alavanca, e vai em um pino digital configurado como INPUT_PULLUP.
Por que meu joystick não lê exatamente 512 no centro?
Potenciômetros e peças mecânicas não são perfeitos; em repouso, o valor costuma ficar em algum ponto entre 490 e 530 e oscila algumas unidades. Medir e guardar o valor do centro na inicialização e usar uma zona morta de ±30–50 resolve o problema.
Por que o pino SW alterna aleatoriamente entre LOW e HIGH?
A maioria dos módulos joystick não tem resistor de pull-up para o botão, então o pino fica flutuando, como se estivesse desconectado. Ative o pull-up interno do Arduino com pinMode(SW_PIN, INPUT_PULLUP) e você vai ler HIGH quando solto e LOW quando apertado.
Quantos servos consigo controlar com um joystick?
Um joystick tem dois eixos, então você controla dois servos de forma independente, o que é ideal para uma câmera pan-tilt. Para mais servos, você acrescenta um segundo joystick; os 6 pinos analógicos do Arduino Uno bastam para até três joysticks.
Posso usar um joystick como controle remoto sem fio?
Sim. Ligue o joystick em um Arduino e envie os valores para outra placa com um módulo de rádio nRF24L01, um módulo Bluetooth HC-05 ou ESP-NOW entre dois ESP32. A maioria dos projetos de carrinho robô e de controle remoto é montada assim.
O módulo joystick funciona com o ESP32 e o Raspberry Pi Pico?
Sim, mas você deve alimentá-lo pelo pino 3V3. Os valores vão de 0 a 4095 no ESP32 e de 0 a 65535 no Pico. No ESP32, use pinos do ADC1 (GPIO 32–39), que funcionam com o Wi-Fi ligado, e calibre o valor do centro na inicialização.
Projetos para montar depois desta leitura
Ver todos os projetos
Controle de LEDs com joystick
Empurre a alavanca do joystick até o fim em qualquer direção e o LED correspondente acende: são quatro cores diferentes para direita, esquerda, cima e baixo. Ao soltar a alavanca, ela volta ao centro

Controle de servos com joystick
Controle dois motores com um joystick, como ao girar uma câmera de segurança. Empurre a alavanca para os lados e o servo motor inferior gira lentamente; mova para cima ou para baixo e o servo superior

Cobrinha em pixels: matriz 8x8
Monte o clássico jogo da cobrinha com as próprias mãos e jogue. Em uma matriz de luzes coloridas 8x8, você guia uma cobra verde com um joystick e come maçãs vermelhas; a cada maçã, a cobra cresce, ace

Cobrinha na matriz 16x16
O clássico jogo da cobrinha, desta vez em um enorme display LED com 256 luzes. Você guia a cobra verde com um joystick e coleta maçãs vermelhas; a cada maçã, a cobra cresce, sua pontuação aumenta em u

Servo motor com ESP32 (controle por potenciômetro)
Neste projeto, controlamos um servo motor SG90 com um potenciômetro. Ajustamos o ângulo do servo mapeando o valor analógico lido do potenciômetro para a faixa de 0 a 180 graus. A biblioteca ESP32Servo gera sinais para o servo nos GPIOs do ESP32 adequados e capazes de operar como saída; este projeto usa o GPIO 18. Esse é um método básico de controle para braços robóticos, estabilizadores de câmera e mecanismos de portas automáticas.

Jogo de bola e raquetes - SSD1306
Uma bola, duas raquetes e você: jogue tênis de mesa, um dos primeiros videogames, em um pequeno display OLED. Dois botões movem sua raquete à direita para cima e para baixo, enquanto o computador cont

Corrida do T-Rex no OLED: jogo do dinossauro com Arduino
O jogo do dinossauro que aparece quando a internet cai, agora na sua mesa: o dinossauro corre pelo pequeno display OLED, os cactos vêm na sua direção e você pula com um único botão. Sua pontuação aume

Jogo de corrida no LCD com Arduino
Jogo de corrida infinita com rolagem lateral em um display LCD de 16x2 caracteres. O herói corre automaticamente, e o jogador pressiona o botão para pular os obstáculos. Obstáculos aleatórios aparecem nas linhas superior e inferior. O buzzer passivo toca a melodia de abertura, o som de pulo, o som de comemoração a cada 50 pontos e a melodia de fim de jogo. A tela de abertura "BlueGrays - Arduino Projects" aparece ao iniciar. A pontuação é atualizada em tempo real no canto superior direito.
Mais artigos
App BlueGrays
Monte este circuito passo a passo pelo celular
Esquema do circuito, código e lista de componentes em uma só tela. Mais de 200 projetos com Arduino, ESP32 e Pico prontos para montar.
Escaneie com seu celular
Aponte a câmera para o código para abrir a loja de aplicativos do seu celular.
ou abrir a loja

