В разработке электронных устройств на МК порой надо как-то посылать в прошивку команды. Обычно такая задача встает при ручном управлении подвижными агрегатами: краны, роверы, игрушечные вертолеты и прочее.

Это можно делать самыми разными способами. По проводам UART-CLI, CAN, RS-485, USB клавиатура и т.п. Или через беспроводные интерфейсы: LoRa, TV пульт. Можно также в частности подключить к электронной плате игровой джойстик.

Джойстики особенно удобны для управления RC роверами и дронами. При разработке RC моделей надо как-то управлять ровером. Желательно обеими руками, ибо действовать надо быстро. ТV пульт не очень удобен. ТВ пульт заточен под одну руку и на простые движения. Для управления моделью, скажем, колёсного транспорта - TV пульт это паллиативное решение. Классическое же решение - это джойстик. К счастью, в продаже существуют готовые беспроводные джойстики самых разных цветов.

Если уж говорить цинично, то джойстик - это переходник между человеком и компьютером (HMI).

Для пуска этого джойстика мне понадобился документ, который называется: "Беспроводной джойстик PS2, Указания к использованию"

Постановка задачи
Научиться опрашивать джойстик от Play Station 2 со стороны ARM Cortex-M микроконтроллера. Осуществить подключение игрового джойстика к STM32 микроконтроллеру. Сделать так, чтобы прошивка в реальном времени узнавала какие кнопки сейчас нажаты на беспроводном контроллере и в каком положении находятся оба рычага.

Теория
SPI - проводной интерфейс передачи байт между микросхемами в пределах одной электронной платы.

полнодуплексный режим - это такой способ передачи информации, когда и прием и передача происходят одновременно

Аппаратная часть

В случае с джойстиком PS2 сеть устройств выглядит так

Что надо из оборудования?

Комплект состоит из самого джойстика и трансивера переходника с BLE на SPI.

Оборудование

Назначение

PS2 джойстик

Переходник между человеком и компьютером HMI

Bluetooth - SPI переходник

Переходник между RF и интерфейсом SPI

Осциллограф

Для отладки SPI

Логический анализатор

Для отладки SPI

Батареи AAA по 1,5V, 2шт. (или аккумуляторы)

Питание джойстика

Зарядное устройство для AAA аккумуляторов

для зарядки батарей в джойстике

Программатор

загрузка и отладка прошивки

Отладочная плата с МК

микроконтроллер будет выступать Host устройством

Вот список кнопок джойстика. Каждый момент времени джойстик может выдать 44 бит информации.

Название
кнопки

Разрешение, bit

байт
кнопки

Бит
кнопки

Комментарий

1

Power

On/Off

2

Analog

3

SELECT

1

3

0

4

Start

1

3

3

5

Up

1

3

4

6

Down

1

3

6

7

Left

1

3

7

8

right

1

3

5

9

X

1

4

6

10

O

1

4

5

11

треугольник

1

4

4

12

квадрат

1

4

7

13

L3

1

3

1

14

R3

1

3

2

15

PSS_RX

8

5

7-0

рычаг

16

PSS_RY

8

6

7-0

рычаг

17

PSS_LX

8

7

7-0

рычаг

18

PSS_LY

8

8

7-0

рычаг

Кнопки можно найти и нащупать по этому изображению

Из Bluetooth - SPI переходника торчит всего девять пинов. Это самый настоящий SPI интерфейс и еще 1 пин GPIO. Прием команд сводится к чтению по интерфейсу SPI.

PinName

Pin num

Direction

Comment

DI/DAT

1

out

Controller -> Host

DO/CMD

2

in

Host - > Controller

Питание мотора (NC)

3

управление вибрацией геймпада

GND

4

in

земля

V3V (VDD)

5

in

Питание VCC может варьироваться от 5 до 3 В.

CS/SEL (Attention)

6

ATT линия «Chip Select» или «Slave Select», которая используется для адресации разных контроллеров на одной шине.

CLK

7

Тактирование SPI

NC

8

--

не подключать

ACK

9

out

подтверждение сигнала от контроллера к Host-у

Спереди RF приемник выглядит так.

Чтобы соединить переходник BLE-SPI и микроконтроллер нужен еще вот переходник на однорядную 6-пиновую PLS вилку. Квадратный пин имеет номер 1.

Это же при увеличении

иероглифы переводятся как "маленький молоток"
иероглифы переводятся как "маленький молоток"

Чтобы монтировать переходник SPI-BLE где- либо надо два отверстия диаметром 3 мм на расстоянии 31 мм между их центрами.

Начертил в MoI 3D
Начертил в MoI 3D

Для проверки работы прибора я подключил его к разъёму J4 на учебно-треннировочной электронной плате DevEBox-STM32F4XX_M_V3.0 согласно вот такому способу.

Function

GPIO

J4

DIR 4 MCU

PS2 terminal

PS2 pin

PS2_CS

PB12

5

out

ATT

4

SPI2_SCK

PB13

4

out

Clock

3

SPI2_MISO

PB14

6

in

DataIn

9

SPI2_MOSI

PB15

3

out

DataOut

8

Подключить пришлось к SPI2.

Программная часть

В микроконтроллере надо активировать SPI в режиме Master. SPI надо настроить на битовую скорость равную 250kBit/s. Данные по SPI передаются младшим битом вперед. Один кадр 8 бит. Режим передача полнодуплексный. Значения битов читаются по отрицательному перепаду на проводе CLK. Выдвижение бита по положительному перепаду на проводе CLK. Прием данных (1 бит) выполняются синхронно по заднему фронту тактового сигнала. При этом включить прерывание по SPI2 c высшим приоритетом. Проводом CS управлять в программном режиме.

На самом деле у джойстика здорово реализован SPI. По факту на проводе MISO биты оказывается можно выхватывать как по положительному, так и по отрицательному перепаду на проводе тактирования. Это достигается за счёт того, что на проводе MISO биты магическим образом переключаются аккуратно по середине бита тактирования. Это отчетливо видно на осциллографе.

Когда нажата какая-либо кнопка в приемном массиве взводится в 1 тот или иной бит. Если при нажатой кнопки наоборот бит обнуляется, значит надо инвертировать байты. То есть нули сделать 1, а 1 - нулями. При движении рычажков вправо-влево команды меняются в диапазоне «0х00-0хFF», также при нажатии рычажков активны значения кнопок L3, R3 соответственно. По сути чтобы получить радиокоманды надо периодически опрашивать джойстик по SPI и производить синтаксический разбор потока принятых битов. Только и всего.

В SPI надо посылать пакет из 9 байт. Чтобы выгрести из джойстика инфу про нажатые кнопки надо отправить массив 0x01 0x42 0x00 0x00 0x00 0x00 0x00 0x00 0x00. Джойстик тут же вернет тоже 9ти байтовый массив. Для приема ответа я завел структуру GamePadPs2RxData_t. Это результат реверс-инжиниринга.

typedef union {
    uint8_t buff[9];
    struct {
        uint8_t idle;
        uint8_t ID;
        uint8_t resp;
        GamePadPs2Data3_t Data3;
        GamePadPs2Data4_t Data4;
        GamePadPs2Data5_t Data5;
        int8_t pss_rx;
        int8_t pss_ry;
        int8_t pss_lx;
    };
}GamePadPs2RxData_t;

typedef union {
    uint8_t byte;
    struct {
        uint8_t DOWN :1;     /* bit:0  */
        uint8_t RIGHT :1;    /* bit:1  */
        uint8_t LEFT :1;     /* bit:2  */
        uint8_t UP :1;       /* bit:3  */
        uint8_t SELECT :1;   /* bit:4 real */
        uint8_t L3 :1;       /* bit:5 real */
        uint8_t R3 :1;       /* bit:6 real */
        uint8_t START :1;    /* bit:7 real  */
    };
}GamePadPs2Data3_t;

typedef union {
    uint8_t byte;
    struct{
        uint8_t UP :1;      /* bit:0  */
        uint8_t RIGHT :1;   /* bit:1  */
        uint8_t DOWN :1;    /* bit:2  */
        uint8_t LEFT :2;    /* bit:4-3  */
        uint8_t L2 :1;      /* bit:5  */
        uint8_t R2 :1;      /* bit:6  */
        uint8_t L1 :1;      /* bit:7  */
    };
}GamePadPs2Data4_t;

typedef union {
    uint8_t byte;
    struct{
        uint8_t R1 :1;        /* bit:0  real */
        uint8_t TRIANGLE :1;  /* bit:1  real */
        uint8_t ROUND :1;     /* bit:2  real */
        uint8_t X :1;         /* bit:3   real */
        uint8_t SQUARE :2;    /* bit:5-4  real*/
        uint8_t RES1 :1;      /* bit:3  */
        uint8_t RES2 :1;        /* bit:2    */
    };
}GamePadPs2Data5_t;

Получается, что информацию про кнопки можно выделить согласно вот такому битовому полю

Кнопка

Байт

бит

разрядность,
bit

расположение

Комментарий

TRIANGLE

5

1

1

справа

ROUND

5

2

1

справа

X

5

3

1

справа

SQUARE

5

5-4

2

справа

SELECT

3

4

1

слева

START

3

7

1

справа

R1

5

1

1

справа

UP

4

0

1

слева

моно кнопка

RIGHT

4

1

1

слева

моно кнопка

DOWN

4

2

1

слева

моно кнопка

LEFT

4

4-3

2

слева

моно кнопка

L2

4

5

1

слева

L3

3

5

1

слева

R2

4

6

1

справа

R3

3

6

1

справа

L1

4

7

1

слева

mode

1

7-0

8

по центру

LX

8

7-0

8

слева

RX

6

7-0

8

справа

RY

7

7-0

8

справа

На пульте кнопка mode задает выбор режима: непрерывной или дискретный. Микроконтроллер узнает об этом глядя на первый байт в принятом массиве.

mode

значение второго байта

разрядность джойстиков, bit

MODE_DISCRETE

0x7C

1

MODE_CONTINUOUS

0x18

8

Левый джойстик в положении шевеления вдоль горизонтальной оси в самом деле показывает линейные координаты. Это очень хорошо. Однако в правом же джойстике наблюдается явный дефект. Правый джойстик не реагирует на шевеление вокруг устойчивого положения и просто транслирует постоянный код 192.

Буквально пара слов про индикацию. Если после включения джойстик не обнаружил приемник, будет мигать красный LED. Если в установленное время джойстик не свяжется с приемником, он переключится в режим ожидания, красный индикатор погаснет. Чтобы выйти из режима ожидания, нажмите кнопку START.

Джойстик PS2 мигает так же в случае потери радио соединения со своим SPI-терминалом.

Недостаток джойстика
1--Game Pad PS2 плох тем, что в его прошивке полностью отсутствует режим самотестирования. В хорошей прошивке должна быть заложены алгоритмы самодиагностики. Например, если Вы пишете прошивку для джойстика, то в прошивке должна быть заложена обработка комбинации кнопок, которая включает вибромотор. Или мигнуть LED-ом, чтобы убедиться, что кнопка нажалась. Это позволит проверить мотор без подключения к Host устройству, просто вставив батарейки в пульт. В данном джойстике такого режима нет. Без подключения к Host устройству вы не проверите, что пульт исправный.

2--Дефект правого курсора. Нарушена непрерывность измерения угла.

3--Даже если пытаться программно включить вибро-моторы по SPI согласно той спеке, то моторы внезапно не включаются. Никакой байт (0-8) не позволяет управлять мотором.

Достоинства джойстика
1++ Феноменальная дальнобойность радиосигнала. Радиосигнал доходит на расстояние более 70 шагов.
2++ Можно передавать сразу два и более нажатий. TV пульты такого делать не позволяют.
3++ Позволяет управлять моделью двумя руками.
4++ Благодаря джойстикам позволяет задавать непрерывные величины, например заполнение PWM. Это не просто кнопку нажать.
5++ Радиосигнал проходит сквозь пластиковую оболочку толщиной 1 мм! Это выгодно отличает game pad управление от инфракрасного TV пульта.

Идеи проектов
Комплект от PS2 можно задействовать для управления динамическими подвижными изделиями.

1--Управлять краном, прожектором, поворотной видео камерой или микроскопом.
2--Управлять фрезерным или сверлильным станком
3--RC моделью ровера или БПЛА
4--Управлять роверами для разминирования снарядов
5--Джойстик можно применить в авиационных тренажерах

Итоги

Удалось получить некоторое начальное представление про то с какой стороны следует подходить к game pad PS2 джойстикам. Задача сводится в чтению и записи по интерфейсу SPI. При этом я настоятельно не рекомендую покупать Game Pad PS2 на Aliexpress. Скорее всего вы, как и я, получите подделку с целым букетом программных багов. Плюс джойстик с Aliexpress, как оказалось, на 70% не соответствует протоколу из известной спеки и, по факту, SPI протокол данного джойстика мне пришлось реверсить, как медвежатнику какому-то.

Тем не менее, даже с такого неоригинального джойстика управлять ровером оказалось значительно удобнее, нежели с обыкновенного TV пульта.

Что касается применения, то я примонтировал переходник BLE-SPI внутри ровера модели УАЗ Буханки для управления этой игрушкой.

Надеюсь, что этот текст поможет и другим разработчикам подключать Game Pad PS2 управление разными агрегатами.

Словарь

Акроним

Расшифровка

PS2

PlayStation 2

RF

Radio Frequency

CS

Chip Select

NC

Not Connected

MISO

Master In Slave Out

MOSI 

Master Out Slave In

PLS

Pins Line Single

SCLK

Serial Clock

УАЗ

Ульяновский автомобильный завод

БПЛА

Беспилотный летательный аппарат

RC

Remote Control

Ссылки

Название

URL

Подключение геймпада \ джойстика к Arduino , беспроводной джойстик 2 4 dualshock от PS2

https://dzen.ru/a/XbB4iCvrSQCtoMRr?ysclid=mh2hzdkdel733192981

Исходный код драйвера джойстика

https://github.com/aabzel/trunk/tree/main/source/sensitivity/game_pad_ps2

Электрическая УАЗ Буханка на Телеуправлении

https://habr.com/ru/articles/957754/

Декодирование IR сигнала с TV (или исследование пультовых лучей)

https://habr.com/ru/articles/950764/

Interfacing a PS2 (PlayStation 2) Controller - Curious Inventor

https://store.curiousinventor.com/guides/PS2

Настройка ToolChain(а) для Win10+GCC+С+Makefile+ARM Cortex-Mx+GDB

https://habr.com/ru/articles/673522/

Подключение джойстика к Arduino , беспроводной джойстик 2.4 dualshock от PS2.mp4

https://rutube.ru/video/1aacdcdf6d0610424e21660ab693e8e2/?ysclid=mh2hz2s01984287226

Вопросы

1--Какой протокол в джойстике поверх SPI?
2--Можно ли послать сигнал в обратном направлении, то есть от микроконтроллера в джойстик? Например дать команду включить моторы внутри рукояток.
3--Сколько бит информации можно прочитать из джойстика за один раз?
4--Где купить оригинальный джойстик, который имеет гарантию, что он точно работает?

Комментарии (2)


  1. DyDkaPro
    08.11.2025 14:55

    а если сразу на esp32 подключить?


  1. Albert2009Zi
    08.11.2025 14:55

    Блин, не в обиду, просто хочу поделиться. Самому сегодня понадобилось. У меня точно такой же старый Rigol этой же модели. Понадобилось снять осциллограмму, раньше делал это утилитой от Rigol Ultrascope. На свежих Windows она не работает. Но есть прога WFM_Viewer, в ней можно открыть осциллограмму, записанную на флешку и записать её в нормальном качестве в jpg и уже вставить в статью. Ну и на осциллограмме - есть же место раздвинуть каналы и как-то подписать MISO (CH2) и CLK (CH1), если я правильно понял.
    Но если неохота заморачиваться, то ладно. Не сочтите за негатив. Статья, как всегда, класс. Спасибо.