两种PS2遥控器兼容性设置
两种用于遥控机器人PS2手柄的兼容设置细节
两种遥控器的对比
图一中描述的遥控器处理器为ESP32S2,可以通过程序下载口对手柄遥控器进行个性化编程。无线通信采用JDY-41模块,JDY-41手册标称通信距离为150米(无遮挡环境)。

对比JDY-41手柄,RC-TANK手柄不可进行个性化编程,但RC-TANK手柄的摇杆校正功能及匹配上位机软件较为健全。
对两款手柄进行兼容性设计的原因有三:
1. RC-TANK手柄的无线信号接收器需要特殊匹配,且接收器在正常工作时发热严重,且不能通过手柄控制当前机器人的无线控制方式(由手柄切换至计算机)。
2. RC-TANK手柄的成本是JDY-41的4倍。
3. RC-TANK不能通过编程对手柄内部的指示灯,振动器等配件进行个性化控制,对控制机器人进行操作反馈不友好。
基于以上原因,在后续开展的遥控试验中,将使用JDY-41遥控器逐步替代。通过个性化编程方式,将JDY-41按键及摇杆对应的无线传输数据帧格式与RC-TANK的进行兼容,以此达到平行替换目的。

RC-TANK无线通信协议
通信数据帧的格式:帧头 + 通信代码 + 帧长度 + 数据 + 校验
数据帧长度:13
帧头:2 字节,固定为 0xAAAA,用于表示一次通信的开始,或者区分不同数据帧。
通信代码:1 字节,用来区分通信的类型(详见通信代码表)
帧长度:1 字节,本次通信数据帧长度,指包含帧头、通信代码、帧长度、数据和校验在内的总长度。
数据:若干字节,数据载荷,长度可变。
校验:16 位 CRC 校验值,MODBUS 格式。
通信代码 | 说明 |
---|---|
0x01 | 遥控指令,这是一条从手柄发往接收机的指令。手柄通过这条指令将摇杆、按键、手柄电量在内的所有信息发送给接收机,接收机再通过串口输出。发送频率为 50Hz。 |
0x09 | 反馈指令,这是一条从接收机发往手柄的指令,用来触发手柄震动。用户通过接收机的串口把这条指令发送给接收机,然后接收机通过无线发送给手柄,手柄发出震动。没有发送频率限制,用户可以根据需要去触发手柄震动。 |
0x15 | 下行透传指令,上位机通过 USB 把指令发送给手柄,手柄将指令发送给接收机,然后接收机通过串口输出。注意:长度不可以超过 26 字节。 |
0x1D | 上行透传指令,用户通过接收机的串口把这条指令发送给接收机,然后接收机通过无线发送给手柄,手柄通过 USB 接口输出该指令。注意:长度不可以超过 26 字节 |
CRC 算法 | 多项式公式 | 宽度 | 多项式 | 初始值 | 异或值 | 输入反转 | 输出反转 |
---|---|---|---|---|---|---|---|
MODBUS | x16 + x15 + x2 + 1 | 16 | 8005 | 0xFFFF | 0x0000 | true | true |
CRC 算法的参考程序,见例程或校准软件。CRC16 计算页面链接(注意选 MODBUS 算法)https://www.23bei.com/tool-59.html
以下代码块为CRC16-modbus CRC校验代码(CRC-16-modbus (LSB-MSB)):
CRC16-modbus 头文件
#ifndef _CRC_16_H_
#define _CRC_16_H_
#include <arduino.h>
void update_crc(uint8_t* crc_sum, uint8_t *data_blk_ptr, uint8_t data_blk_size);
#endif
CRC16-modbus 源文件
/*standard CRC check cpp files*/
//CRC-16-modbus (LSB-MSB)
//calculation tools online:https://www.23bei.com/tool-59.html
//mode: CRC-16(Modbus)
#include "CRC16.h"
/*--------------------------------------------------------------------*/
/**
* function: Modbus CRC16(LSB-MSB) calculation
* update in 2022/03/17
* input paramenter:
* data_blk_ptr: inital address of waiting calculation data,
* usDataLen: length of data frame
* output parameter:
* crc_sum: CRC16-modbus results' inital address
* returned value:
* checked result - TRUE or FALSE (bool)
*/
void update_crc(uint8_t* crc_sum, uint8_t *data_blk_ptr, uint8_t data_blk_size)
{
unsigned int i;
unsigned short crc = 0xFFFF;
unsigned short crcl;
while(data_blk_size--){
crc ^= *data_blk_ptr++;
for (i = 0; i < 8; ++i){
if (crc & 1)
crc = (crc >> 1) ^ 0xA001;
else
crc = (crc >> 1);
}
}
crcl = crc;
crc_sum[1] = (unsigned char)(crc>>8);
crc_sum[0] = (unsigned char)(crcl);
}
/*----------------------End of file----------------------------------*/
RC-TANK手柄通信示例
0x01 指令:该指令是所有指令中最重要的指令,只有理解它的含义,才可以弄清楚手柄是如何控制其他设备的。指令中所有数据均为 16 进制,下边给出 0x01 指令的具体示例:
示例: AA AA 01 0D DF 7F 7F 7F 7F 00 00 D7 51
第 1、2 字节 0xAA,0xAA 为帧头,标志着一帧数据的开始。
第 3 字节 0x01 为命令代码。
第 4 字节 0x0D 为帧长度,这条指令长度为 13 个字节,用 16 进制表示就是 0x0D。
第 5 字节 0xDF 表示手柄电池此时的电压,计算公式:(0xDF +200)÷100=4.23V,此时手柄电池电压为 4.23V,其它值时以此类推。手柄低电量提醒电压为 3.8V,自动关机电压为3.75V。
第 6 字节为模拟通道 1,对应手柄左侧摇杆的水平方向,取值范围为 0x00~0xFF,中值为 0x7F。摇杆往左打极限值为 0xFF,往右打极限值为 0x00。
第 7 字节为模拟通道 2,对应手柄左侧摇杆的垂直方向,取值范围为 0x00~0xFF,中值为 0x7F。摇杆往下打极限值为 0xFF,往上打极限值为 0x00。
第 8 字节为模拟通道 3,对应手柄右侧摇杆的水平方向,取值范围为 0x00~0xFF,中值为 0x7F。摇杆往左打极限值为 0xFF,往右打极限值为 0x00。
第 9 字节为模拟通道 4,对应手柄右侧摇杆的垂直方向,取值范围为 0x00~0xFF,中值为 0x7F。摇杆往下打极限值为 0xFF,往上打极限值为 0x00。
第 10、11 字节,这两个字总共 16 位,对应手柄的 16 个通道。从最高位第 16 位到第 1 位,依次是:L2、L1、LU、LL、LD、LR、SE、ST、RL、RD、RR、RU、R1、R2、R-KEY、L-KEY。其中 R-KEY 和 L-KEY 为摇杆往下按对应的按键。
第 12、13 字节为校验值,计算前 11 个字节的 CRC16 校验值得到 0x51D7,按照小端模式,低字节 0xD7,高字节 0x51 依次排列。
0x09 指令:接收机发往该指令给手柄,用于触发手柄震动。
示例:AA AA 09 07 01 0E 32
第 1、2 字节 0xAA,0xAA 为帧头,标志着一帧数据的开始。
第 3 字节 0x09 为命令代码。
第 4 字节 0x07 为帧长度,这条指令长度为 7 个字节。
第 5 字节 0x01 表示触发手柄左侧电机振动,如果要触发右侧电机则应为 0x02。该字节只能取 0x01 或者 0x02。
第 6、7 字节为校验值,计算前 5 个字节的 CRC16 校验值得到 0x320E,按照小端模式,低字节 0x0E,高字节 0x32 依次排列。
0x15 指令:上位机通过手柄透传给接收机的数据,然后通过接收机的串口输出。
示例:AA AA 15 07 00 0E 34
第 1、2 字节 0xAA,0xAA 为帧头,标志着一帧数据的开始。
第 3 字节 0x15 为命令代码。
第 4 字节 0x07 为帧长度,这条指令长度为 7 个字节。
第 5 字节 0x00 上位机发出的数据,字节长度可变,但不可超过 26 字节。因为一次通信最多发送 32 字节数据,其他部分已占据 6 字节。
第 6、7 字节为校验值,计算前 5 个字节的 CRC16 校验值得到 0x340E,按照小端模式,低字节 0x0E,高字节 0x34 依次排列。
0x1D 指令:用户通过接收机的串口把这条指令发送给接收机,然后接收机通过无线发送给手柄,手柄通过 USB 口输出给上位机。
示例:AA AA 1D 07 00 8F F6
第 1、2 字节 0xAA,0xAA 为帧头,标志着一帧数据的开始。
第 3 字节 0x1D 为命令代码。
第 4 字节 0x07 为帧长度,这条指令长度为 7 个字节。
第 5 字节 0x00 接收机透传给上位机的数据,字节长度可变,但不可超过 26 字节。因为一次通信最多发送 32 字节数据,其他部分已占据 6 字节。
第 6、7 字节为校验值,计算前 5 个字节的 CRC16 校验值得到 0xF68F,按照小端模式,低字节 0x8F,高字节 0xF6 依次排列。
兼容内容
兼容分两部分组成,首先是按键的IO口对应编码兼容,其次是和摇杆对应的ADC采集数值映射关系。
由于JDY-41遥控器并没有开源硬件,固按键对应IO口,需要通过实验得出与RC-TANK相同顺序,其正确的IO顺序如下表所示:
按键位置 | L2 | L1 | LU | LL | LD | LR | SE | ST | RL | RD | RR | RU | R1 | R2 | R-KEY | L-KEY |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
对应IOK口 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 21 | 17 | 33 | 34 | 35 | 45 | 18 | 6 | 7 |
注: JDY-41手柄按键值未按下为高,应取反,与RC-TANK兼容。
摇杆ADC数值采集兼容中,由于JDY-41手柄的摇杆硬件设置与RC-TANK不同,固摇杆在对应动作上,ADC数值按照如下图所示做映射。

通过以上方式,让两个手柄在对无线控制机器人数据帧完全兼容。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构