Componentes · 5 min de leitura

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.

Módulo joystick analógico KY-023
Módulo joystick analógico: ele tem dois potenciômetros para os dois eixos e um botão que funciona quando você aperta a alavanca; são 5 pinos: GND, +5V, VRx, VRy e SW.

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 alavancaVRx (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

PinoFunçãoArduino UnoESP32Raspberry Pi Pico
GNDTerraGNDGNDGND
+5VAlimentação5V3V33V3
VRxEixo X (analógico)A0GPIO 34GP26
VRyEixo Y (analógico)A1GPIO 35GP27
SWBotão (vai ao GND quando apertado)D2GPIO 25GP15
No ESP32 e no Pico, alimente o módulo pelo pino 3V3, e não pelo 5V; mesmo que o pino esteja marcado como "+5V", o módulo funciona bem com 3,3 V. Se você alimentá-lo com 5 V, os pinos analógicos vão receber mais de 3,3 V e a placa pode ser danificada. No ESP32, não use os pinos 34–39 para o SW; eles não têm resistor de pull-up interno.

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.

C++ (Arduino IDE)
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 você abrir o Plotter Serial, pode ver os dois eixos no mesmo gráfico. Observar as duas linhas mudando enquanto você gira a alavanca devagar é o jeito mais rápido de entender a direção de cada eixo.

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:

C++ (Arduino IDE)
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.

C++ (Arduino IDE)
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?

C++ (Arduino IDE)
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:

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)

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.

Ver todos os projetos
Controle de LEDs com joystick
#59Intermediário
Premium

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

4.7(50)
67
Controle de servos com joystick
#60Intermediário
Premium

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

4.7(42)
58
Cobrinha em pixels: matriz 8x8
#88Avançado
Premium

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

4.7(39)
57
Cobrinha na matriz 16x16
#89Avançado
Premium

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

4.8(52)
67
Servo motor com ESP32 (controle por potenciômetro)
#118Intermediário
Premium

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.

4.3(29)
42
Jogo de bola e raquetes - SSD1306
#86Intermediário
Premium

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

4.5(47)
65
Corrida do T-Rex no OLED: jogo do dinossauro com Arduino
#87Avançado
Premium

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

4.7(33)
53
Jogo de corrida no LCD com Arduino
#98Intermediário
Premium

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.

4.6(32)
55