В разработке электронных устройств на МК порой надо как-то посылать в прошивку команды. Обычно такая задача встает при ручном управлении подвижными агрегатами: краны, роверы, игрушечные вертолеты и прочее.
Это можно делать самыми разными способами. По проводам 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 мм между их центрами.

Для проверки работы прибора я подключил его к разъёму 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;
Получается, что информацию про кнопки можно выделить согласно вот такому битовому полю
Кнопка |
Байт |
бит |
разрядность, |
расположение |
Комментарий |
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 |
|
Декодирование IR сигнала с TV (или исследование пультовых лучей) |
|
Interfacing a PS2 (PlayStation 2) Controller - Curious Inventor |
|
Настройка ToolChain(а) для Win10+GCC+С+Makefile+ARM Cortex-Mx+GDB |
|
Подключение джойстика к Arduino , беспроводной джойстик 2.4 dualshock от PS2.mp4 |
https://rutube.ru/video/1aacdcdf6d0610424e21660ab693e8e2/?ysclid=mh2hz2s01984287226 |
Вопросы
1--Какой протокол в джойстике поверх SPI?
2--Можно ли послать сигнал в обратном направлении, то есть от микроконтроллера в джойстик? Например дать команду включить моторы внутри рукояток.
3--Сколько бит информации можно прочитать из джойстика за один раз?
4--Где купить оригинальный джойстик, который имеет гарантию, что он точно работает?
Комментарии (2)

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