Компоненты · 4 мин чтения

Модуль джойстика: читаем оси X-Y и кнопку с Arduino

Как работает аналоговый модуль джойстика (KY-023)? Пины VRx, VRy и SW, подключение к Arduino, мёртвая зона и калибровка, определение направления, управление сервоприводом, код для ESP32 и Pico.

Модуль джойстика — это вариант стиков с игровых геймпадов, удобный для Arduino. Когда двигаешь ручку влево-вправо и вперёд-назад, он сообщает её положение по двум осям, а если нажать на ручку, срабатывает кнопка внутри. Это самый практичный способ ввода для пультов машинок-роботов, поворотных платформ для камер (pan-tilt), игр на светодиодной матрице и меню на дисплее. Самая распространённая модель известна также как KY-023.

Аналоговый модуль джойстика KY-023
Аналоговый модуль джойстика: внутри два потенциометра для двух осей и кнопка, которая срабатывает при нажатии на ручку; у него 5 пинов: GND, +5V, VRx, VRy и SW.

Как работает модуль джойстика?

Под ручкой стоят два потенциометра по 10 kΩ, расположенные под прямым углом друг к другу: один чувствует движение по оси X, другой — по оси Y. Каждый потенциометр работает как делитель напряжения; когда ручка в центре, его движок даёт около 2,5 V, а analogRead() показывает примерно 512. Если отвести ручку до упора в одну сторону, значение приближается к 0, в другую — к 1023. Если нажать на ручку, маленькая кнопка соединяет пин SW с GND.

Положение ручкиVRx (X)VRy (Y)
Центр (отпущена)~512~512
До упора влево~0~512
До упора вправо~1023~512
До упора вверх~512~0
До упора вниз~512~1023

Какое направление даёт 0, а какое 1023, зависит от того, как держать модуль. Если направления не совпадают с таблицей, когда пины смотрят на тебя, не переживай: ось легко перевернуть в коде, вычтя значение из 1023.

Распиновка и подключение джойстика

ПинНазначениеArduino UnoESP32Raspberry Pi Pico
GNDЗемляGNDGNDGND
+5VПитание5V3V33V3
VRxОсь X (аналоговый)A0GPIO 34GP26
VRyОсь Y (аналоговый)A1GPIO 35GP27
SWКнопка (при нажатии замыкается на GND)D2GPIO 25GP15
На ESP32 и Pico питай модуль от пина 3V3, а не от 5V; хоть пин и подписан «+5V», модуль прекрасно работает от 3,3 V. Если подать 5 V, на аналоговых пинах окажется больше 3,3 V, и плата может выйти из строя. На ESP32 не используй для SW пины 34–39: у них нет внутреннего подтягивающего резистора.

Чтение джойстика с Arduino

Код ниже читает обе оси и кнопку и выводит их в монитор порта. Кнопка при нажатии замыкается на GND, а на большинстве модулей нет подтягивающего резистора, поэтому пин SW нужно настроить как INPUT_PULLUP (внутренняя подтяжка, pull-up); тогда он читает HIGH, когда кнопка отпущена, и LOW, когда нажата.

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}
Если открыть плоттер по последовательному соединению (Serial Plotter), обе оси видны на одном графике. Медленно вращать ручку и смотреть, как меняются две линии, — самый быстрый способ понять направление каждой оси.

Мёртвая зона и калибровка

В жизни отпущенная ручка показывает не ровно 512, а что-то вроде 495 или 525, и значение дрожит на несколько единиц. Если это не исправить, машинка-робот ползёт вперёд или сервопривод дёргается, хотя к джойстику никто не прикасается. Решение в два шага: при запуске измерить и сохранить центральное значение (калибровка) и игнорировать небольшие отклонения около центра (мёртвая зона). Функция ниже превращает каждую ось в чистое значение от -100 до +100, где центр ровно 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}

Определение направлений: вверх, вниз, влево, вправо

В играх и меню часто нужно не точное положение, а только направление. Сравнивая значения с двумя порогами, можно превратить джойстик в четырёхпозиционную крестовину. Для навигации по меню нужно, чтобы каждое отклонение считалось одним шагом, поэтому в коде есть короткая задержка, или новые шаги игнорируются, пока ручка не вернётся в центр.

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}

Управление сервоприводом джойстиком

Если отобразить одну ось джойстика на 0–180 градусов, сервоприводом можно управлять вручную; с двумя осями и двумя сервоприводами получится поворотная платформа pan-tilt, которая поворачивает камеру влево-вправо и вверх-вниз. Про подключение сервопривода и питание читай в статье Что такое сервопривод?

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}

Джойстик с ESP32 и Raspberry Pi Pico

АЦП у ESP32 12-битный и даёт значения от 0 до 4095, но из-за его нелинейности центр часто получается около 1800–1950, а не 2048. Поэтому способ калибровки, описанный выше, на ESP32 ещё важнее. Если будешь использовать Wi-Fi, подключай оси к пинам ADC1 (GPIO 32–39). На Pico аналоговые входы — GP26–GP28, а read_u16() возвращает значения от 0 до 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)

Идеи проектов с джойстиком

  • Пульт для машинки-робота: подключи джойстик к плате-передатчику и отправляй команды машинке через nRF24L01 или Bluetooth.
  • Камера pan-tilt: направляй камеру в любую сторону двумя сервоприводами и одним джойстиком.
  • Змейка на светодиодной матрице: управляй змейкой на матрице 8x8 джойстиком.
  • Меню на дисплее: перемещайся по пунктам вверх и вниз и выбирай кнопкой; про дисплей читай в статье I2C LCD-дисплей.
  • Выбор цвета: управляй RGB-светодиодом, задавая цвет осью X, а яркость — осью Y.
  • Компьютерная мышь: преврати джойстик в настоящую USB-мышь с Arduino Leonardo или Pro Micro.

Частые ошибки и как их исправить

  • Кнопка кажется нажатой, хотя её не трогают: пин SW не настроен как INPUT_PULLUP; пин «висит» в воздухе и читает случайные значения.
  • В покое значение не 512 и дрожит: это нормально; откалибруй центр при запуске и добавь мёртвую зону.
  • Оси перевёрнуты или перепутаны: дело в ориентации модуля; вычти значение из 1023 или поменяй местами провода VRx и VRy.
  • На ESP32 центр не 2048: АЦП ESP32 нелинейный; измерь центр при запуске и считай от него.
  • Сервопривод дрожит или Arduino перезагружается: сервопривод перегружает 5 V Arduino; питай его от отдельного источника 5 V и соедини земли.

Джойстик — это, по сути, два потенциометра и кнопка, поэтому статьи Что такое потенциометр? и Как подключить кнопку к Arduino закрепят то, что ты здесь узнаешь. В приложении BlueGrays есть проекты с управлением светодиодами и сервоприводами от джойстика и игра «Змейка» на светодиодной матрице — со схемами подключения и кодом.

Частые вопросы

Для чего нужны пины модуля джойстика?

GND и +5V — пины питания. VRx и VRy выдают положение по осям X и Y в виде аналогового напряжения и подключаются к аналоговым пинам. SW — выход кнопки, который при нажатии на ручку замыкается на GND; он подключается к цифровому пину, настроенному как INPUT_PULLUP.

Почему джойстик в центре показывает не ровно 512?

Потенциометры и механика не идеальны; в покое значение обычно где-то между 490 и 530 и дрожит на несколько единиц. Проблему решают измерение и сохранение центра при запуске и мёртвая зона ±30–50.

Почему пин SW случайно переключается между LOW и HIGH?

На большинстве модулей джойстика нет подтягивающего резистора для кнопки, поэтому пин «висит», как будто ни к чему не подключён. Включи внутреннюю подтяжку Arduino командой pinMode(SW_PIN, INPUT_PULLUP), и ты будешь читать HIGH, когда кнопка отпущена, и LOW, когда нажата.

Сколькими сервоприводами можно управлять одним джойстиком?

У джойстика две оси, поэтому можно независимо управлять двумя сервоприводами — идеально для камеры pan-tilt. Для большего числа сервоприводов добавляют второй джойстик; 6 аналоговых пинов Arduino Uno хватает на три джойстика.

Можно ли использовать джойстик как беспроводной пульт?

Да. Подключи джойстик к одной Arduino и отправляй его значения на другую плату через радиомодуль nRF24L01, Bluetooth-модуль HC-05 или ESP-NOW между двумя ESP32. Так устроено большинство проектов машинок-роботов и радиоуправления.

Работает ли модуль джойстика с ESP32 и Raspberry Pi Pico?

Да, но питать его нужно от пина 3V3. На ESP32 значения идут от 0 до 4095, на Pico — от 0 до 65535. На ESP32 используй пины ADC1 (GPIO 32–39), которые работают при включённом Wi-Fi, и калибруй центр при запуске.

Все проекты
Управление светодиодами джойстиком
#59Средний
Premium

Управление светодиодами джойстиком

Наклони рычажок джойстика до упора в любую сторону, и загорится светодиод этого направления: вправо, влево, вверх и вниз — четыре разных цвета. Отпусти рычажок, он вернётся в центр, и все светодиоды п

4.7(50)
67
Управление сервоприводом джойстиком
#60Средний
Premium

Управление сервоприводом джойстиком

Управляй двумя моторами джойстиком, как будто поворачиваешь камеру наблюдения. Наклони рычажок влево или вправо, и нижний сервопривод медленно поворачивается, наклони вверх или вниз — верхний сервопри

4.7(42)
58
Пиксельная змейка на матрице 8x8
#88Продвинутый
Premium

Пиксельная змейка на матрице 8x8

Собери классическую игру «Змейка» своими руками и сыграй в неё. На цветной светодиодной матрице 8x8 ты джойстиком управляешь зелёной змейкой и ешь красные яблоки; с каждым яблоком змейка растёт, немно

4.7(39)
57
Змейка на матрице 16x16
#89Продвинутый
Premium

Змейка на матрице 16x16

Классическая игра «Змейка», на этот раз на огромном светодиодном дисплее из 256 огоньков. Ты джойстиком управляешь зелёной змейкой и собираешь красные яблоки; с каждым яблоком змейка растёт, счёт увел

4.8(52)
67
Сервопривод на ESP32 (управление потенциометром)
#118Средний
Premium

Сервопривод на ESP32 (управление потенциометром)

В этом проекте сервопривод SG90 управляется потенциометром. Угол сервопривода задаётся сопоставлением аналогового значения потенциометра с диапазоном 0–180 градусов. Библиотека ESP32Servo формирует сигналы сервопривода на подходящих выходных пинах GPIO у ESP32; этот проект использует GPIO 18. Это базовый способ управления для роборук, подвесов камер и механизмов автоматических дверей.

4.3(29)
42
Игра в пинг-понг — SSD1306
#86Средний
Premium

Игра в пинг-понг — SSD1306

Мяч, две ракетки и ты: на маленьком OLED-экране ты играешь в настольный теннис — одну из самых первых видеоигр. Две кнопки двигают твою ракетку справа вверх и вниз, а левой ракеткой управляет компьюте

4.5(47)
65
OLED T-Rex Run: игра с динозавром на Arduino
#87Продвинутый
Premium

OLED T-Rex Run: игра с динозавром на Arduino

Игра с динозавром, которая появляется, когда пропадает интернет, теперь у тебя на столе: динозавр бежит по маленькому OLED-экрану, навстречу едут кактусы, а прыгаешь ты одной кнопкой. Счёт растёт в ре

4.7(33)
53
Игра-бегалка на LCD с Arduino
#98Средний
Premium

Игра-бегалка на LCD с Arduino

Бесконечная игра-бегалка с горизонтальной прокруткой на символьном LCD-экране 16x2. Герой бежит сам, а игрок перепрыгивает препятствия нажатием кнопки. Случайные препятствия появляются в верхней и нижней строке. Пассивный зуммер играет вступительную мелодию, звук прыжка, праздничный звук на 50 очков и мелодию конца игры. При запуске показывается заставка «BlueGrays - Arduino Projects». Счёт обновляется сразу в правом верхнем углу экрана.

4.6(32)
55