IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> PS4 + ESP32 制作无线遥控器 -> 正文阅读

[嵌入式]PS4 + ESP32 制作无线遥控器

一. 说明

通过微控制器控制 PS4 手柄大概有两套方案,第一种是使用 PS4-esp32 库,通过 ESP32 芯片的蓝牙与 PS4 建立连接。另一种是使用 USB_Host_Shield_2.0 中的 PS4BT 库,通过蓝牙接收器和 PS4 手柄配对,再通过 USB 芯片完成主控和蓝牙接收器间的通信。

我采用的是第一种方案,成功使用一块 ESP32 开发板实现对 PS4 的控制,但我非常不推荐这种方案,因为它还有很多问题没有解决,我把我尝试的整个流程记录下来也只是方便其他人继续研发,如果是基于成本考虑,或者是完全出于兴趣,可以尝试这种方案;如果只是想快速稳定地建立手柄和控制器间的连接,我还是推荐第二种成熟的方案。

二. 准备工作

1. PS4 手柄

PS4 手柄尽量选择正版,盗版手柄有可能无法连接(事实上我没有遇到这个问题),在 Issue#7Issue#19Issue#38 中提到了这个问题,没有人给出解决方案,也没有确定可以使用 PS4-esp32 库的盗版手柄。

判别手柄是否为正版可以参考这篇文章

2. ESP32 开发板

PS4 仅支持使用 BT (Bluetooth) 进行连接,故要选择 ESP32 芯片,C2, C3, S2, S3 系列芯片均不支持 BT (Bluetooth) ( 注意 BluetoothBluetooth LE 的区别 ),详见 芯片概览。我使用的是 NodeMCU-32S 开发板。

3. 修改手柄 Mac 地址

必须保证 ESP32 的 Mac 地址和手柄的 Mac 地址相同才可以连接,使用 SixaxisPairTool 工具读取并修改手柄的 Mac 地址,Mac 地址在保证单播的情况下可以任取,例如1a:2b:3c:01:01:01。记住此处设置的手柄的 Mac 地址,之后要填写到 ESP32 的程序中。

注意:如果之前手柄已经和电脑配过对,此时手柄的 Mac 地址会被修改成电脑蓝牙的 Mac 地址,不要使用和电脑蓝牙相同的 Mac 地址!!

三. 程序编写

使用 VSCode + PlatformIO 基于 Arduino 框架进行开发。

新建 PlatformIO 工程,根据所用板子型号配置 platformio.ini 文件。

; platformio.ini
[env:nodemcu-32s]
platform = espressif32
board = nodemcu-32s
framework = arduino
monitor_speed = 115200

将整个 PS4-esp32 项目放到工程的 lib 文件夹下,文件树如下图所示:

请添加图片描述
编写 main.cpp

/*main.cpp*/
#include <Arduino.h>
#include <PS4Controller.h>
#include <WiFi.h>

int r = 255, g = 0, b = 0;

// Calculates the next value in a rainbow sequence
void nextRainbowColor()
{    
    if (r > 0 && b == 0) 
    {
        r--;
        g++;
    }
    if (g > 0 && r == 0) 
    {
        g--;
        b++;
    }
    if (b > 0 && g == 0) 
    {
        r++;
        b--;
    }
}

void setup() 
{
    Serial.begin(115200);
    PS4.begin("14:5A:FC:1B:02:CE"); // 替换此处的Mac地址!
    Serial.println("Ready.");
}

void loop() 
{
    int cnt = 0;
    // Below has all accessible outputs from the controller
    if (PS4.isConnected()) 
    {
        if(++cnt == 100) // 1000ms
        {
            if (PS4.LStickX()) Serial.printf("Left Stick x at %d\n", PS4.LStickX());
            if (PS4.LStickY()) Serial.printf("Left Stick y at %d\n", PS4.LStickY());
            if (PS4.RStickX()) Serial.printf("Right Stick x at %d\n", PS4.RStickX());
            if (PS4.RStickY()) Serial.printf("Right Stick y at %d\n", PS4.RStickY());
            if (PS4.Charging()) Serial.println("The controller is charging");
            if (PS4.Audio()) Serial.println("The controller has headphones attached");
            if (PS4.Mic()) Serial.println("The controller has a mic attached");
            Serial.printf("Battery Level : %d\n", PS4.Battery());
            Serial.println();
            nextRainbowColor();
            cnt = 0;
        }
        
        if (PS4.Right()) Serial.println("Right Button");
        if (PS4.Down()) Serial.println("Down Button");
        if (PS4.Up()) Serial.println("Up Button");
        if (PS4.Left()) Serial.println("Left Button");

        if (PS4.Square()) Serial.println("Square Button");
        if (PS4.Cross()) Serial.println("Cross Button");
        if (PS4.Circle()) Serial.println("Circle Button");
        if (PS4.Triangle()) Serial.println("Triangle Button");

        if (PS4.UpRight()) Serial.println("Up Right");
        if (PS4.DownRight()) Serial.println("Down Right");
        if (PS4.UpLeft()) Serial.println("Up Left");
        if (PS4.DownLeft()) Serial.println("Down Left");

        if (PS4.L1()) Serial.println("L1 Button");
        if (PS4.R1()) Serial.println("R1 Button");

        if (PS4.Share()) Serial.println("Share Button");
        if (PS4.Options()) Serial.println("Options Button");
        if (PS4.L3()) Serial.println("L3 Button");
        if (PS4.R3()) Serial.println("R3 Button");

        if (PS4.PSButton()) Serial.println("PS Button");
        if (PS4.Touchpad()) Serial.println("Touch Pad Button");

        if (PS4.L2()) Serial.printf("L2 button at %d\n", PS4.L2Value());
        if (PS4.R2()) Serial.printf("R2 button at %d\n", PS4.R2Value());

        // Sets the color of the controller's front light
        // Params: Red, Green,and Blue
        // See here for details: https://www.w3schools.com/colors/colors_rgb.asp
        PS4.setLed(r, g, b);

        // Sets how fast the controller's front light flashes
        // Params: How long the light is on in ms, how long the light is off in ms
        // Range: 0->2550 ms, Set to 0, 0 for the light to remain on
        PS4.setFlashRate(PS4.LStickY() * 10, PS4.RStickY() * 10);

        // Sets the rumble of the controllers
        // Params: Weak rumble intensity, Strong rumble intensity
        // Range: 0->255
        PS4.setRumble(PS4.L2Value(), PS4.R2Value());
        // Sends data set in the above three instructions to the controller
        PS4.sendToController();
        // Don't send data to the controller immediately, will cause buffer overflow
        delay(10);
    }
    else
    {
        Serial.println("Connecting...");
        delay(1000);
    }
}

使用 PlatformIO 插件编译并上传代码。

四. 其他

  • 如果不能连接,尝试擦除 ESP32 的闪存并重新烧录,可能需要 ESP32 每次上电前都擦除一次:

    pip install esptool
    esptool --chip esp32 erase_flash
    

    该问题在 Issue#2Issue#4Issue#9Issue#18 中被提到过。

  • rickwinter2 提到使用 esp-wroom-32 dev module v3 连接会更稳定,不需要频繁地擦除闪存,我没有进行尝试。

  • 之前出现过的很多问题都是蓝牙配对/连接的方式导致的,比如盗版手柄可以很容易的和 PS 主机或者电脑进行连接,但却无法和 ESP32 进行连接,本质上其实是 PS4-esp32 库没办法模拟与 PS4 手柄配对的过程。

    关于 PS4-esp32 库与 PS4 手柄的配对问题,作者在 Issue#11 中进行了解释,我没有完全理解,大意是由于 ESP32 硬件的限制,ESP32 不像无线蓝牙接收器那样支持很多配对协议。

  • PS4 配对过程和 ESP32 芯片的蓝牙功能进行进一步研究,解决好配对问题,PS4-esp32 库 + ESP32 的方案一定会成为主流,毕竟 USB_Host_Shield_2.0 方案需要昂贵的蓝牙接收器和 USB 芯片,接收器和板子的价格甚至与一个盗版手柄的价格相当。因为我只是想快速制作一个机器人遥控器,并没有兴趣与时间去深入研究蓝牙,故转向了 USB_Host_Shield_2.0 方案。

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2022-09-04 01:27:45  更:2022-09-04 01:28:18 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 22:46:19-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码