亿迅智能制造网
工业4.0先进制造技术信息网站!
首页 | 制造技术 | 制造设备 | 工业物联网 | 工业材料 | 设备保养维修 | 工业编程 |
home  MfgRobots >> 亿迅智能制造网 >  >> Manufacturing Technology >> 制造工艺

用 PS2 无线手柄控制 Arduino 坦克机器人

组件与物料

组件数量
Arduino UNO 开发板1
SparkFun 双 H 桥驱动模块 L2981
DIY 履带坦克底盘套件1
索尼 PS2 无线手柄(含接收器)1
18650 3.7V 锂电池 ×31组
3 节 18650 电池盒(串联)1
18650 电池充电器1
公母/公公跳线若干1套
Type-B USB 数据线1
焊锡铁、焊锡线、EVA 泡棉垫、双面胶、剪刀各1

所需软件

项目简介

本教程演示如何使用 PlayStation 2 无线手柄遥控一辆履带式坦克机器人。核心控制器为 Arduino Uno,接收手柄指令并驱动两路直流电机。相同原理可移植到 NodeMCU、FireBeetle 等开发板,也适用于其他差速驱动机器人。

作者此前已完成 Wi-Fi/Blynk 控制坦克、语音控制机器人 及 自制底盘 FPV 小车,本项目专注于“低延迟、免联网、手柄操控”的经典体验。

步骤 1:工具与材料准备

除上表元件外,还需:

步骤 2:机械组装

采用成品坦克底盘套件(含电机、齿轮、履带、螺丝、工具)。组装要点:

步骤 3:电路接线

供电

3 节 18650 串联(11.1V)经电池盒接入 L298N 的 12V 与 GND,同时给 Arduino Vin 供电(或通过 5V 引脚)。

L298N 与 Arduino 接线表

Arduino 引脚L298N 引脚功能
D3ENA左电机 PWM 使能
D4IN2左电机方向控制
D5IN1左电机方向控制
D6ENB右电机 PWM 使能
D7IN4右电机方向控制
D8IN3右电机方向控制
5V5V逻辑电源
GNDGND共地

电机输出

PS2 接收器接线

接收器引脚Arduino 引脚说明
1 (Data)D12数据
2 (Command)D11命令
4 (GND)GND地
5 (VCC)3.3V供电 3.3V
6 (Attention)D10片选
7 (Clock)D13时钟

步骤 4:Arduino IDE 环境配置

  1. 官网下载安装最新 Arduino IDE
  2. 解压 PS2X 库至 Documents/Arduino/libraries
  3. 重启 IDE,菜单 草图 → 包含库 → PS2X 验证导入成功

步骤 5:PS2X 库核心 API 速查

// 创建手柄对象
PS2X ps2x;

// 初始化并配置引脚:clock, command, attention, data, pressures?, rumble?
error = ps2x.config_gamepad(13, 11, 10, 12, true, true);

// 读取数字按键(返回 true/false)
ps2x.Button(PSB_PAD_UP);    // 方向键上
ps2x.Button(PSB_R2);        // 右扳机 R2
ps2x.Button(PSB_L2);        // 左扳机 L2
// ... 其余按键常量见库文档

// 读取模拟摇杆(返回 0~255)
ps2x.Analog(PSS_LX);  // 左摇杆 X
ps2x.Analog(PSS_LY);  // 左摇杆 Y
ps2x.Analog(PSS_RX);  // 右摇杆 X
ps2x.Analog(PSS_RY);  // 右摇杆 Y

步骤 6~9:四种控制模式示例代码

所有示例共用相同接线与初始化,仅 loop() 逻辑不同。完整代码见文末“代码”区。

模式 1:方向键(D-Pad)全速控制

模式 2:左摇杆 X 轴转向 + L2/R2 油门/刹车

模式 3:双摇杆差速驱动(推荐)

模式 4:单左摇杆混合控制(Arcade Drive)

步骤 10:常见问题与调试

完整代码(四合一)

下方代码已整合四种模式,通过 #define MODE 1~4 切换。上传前请确认引脚定义与接线一致。

#define MODE 3   // 1=D-Pad, 2=L-Stick+L2/R2, 3=Dual-Stick, 4=Single-Stick
#include <PS2X_lib.h>

#define ENA 3
#define MOTORA_1 4
#define MOTORA_2 5
#define MOTORB_1 8
#define MOTORB_2 7
#define ENB 6

PS2X ps2x;
int error = 0;
byte type = 0;
byte vibrate = 0;

void setup() {
  pinMode(ENA, OUTPUT); pinMode(MOTORA_1, OUTPUT); pinMode(MOTORA_2, OUTPUT);
  pinMode(ENB, OUTPUT); pinMode(MOTORB_1, OUTPUT); pinMode(MOTORB_2, OUTPUT);
  digitalWrite(ENA, 0); digitalWrite(ENB, 0);
  Serial.begin(57600);
  error = ps2x.config_gamepad(13, 11, 10, 12, true, true);
  if (error == 0) Serial.println(F("手柄连接成功"));
  else if (error == 1) Serial.println(F("未检测到手柄,检查接线或复位"));
  else if (error == 2) Serial.println(F("手柄拒绝命令"));
  else if (error == 3) Serial.println(F("不支持压力/震动模式"));
  type = ps2x.readType();
  if (type == 1) Serial.println(F("DualShock 手柄"));
  else if (type == 2) Serial.println(F("GuitarHero 手柄"));
  else Serial.println(F("未知手柄类型"));
}

void loop() {
  if (error == 1) return;
  ps2x.read_gamepad(false, vibrate);

  #if MODE == 1
    // D-Pad 全速控制
    if (ps2x.Button(PSB_PAD_UP))      { setMotors(LOW, HIGH, HIGH, LOW, 1023, 1023); }
    else if (ps2x.Button(PSB_PAD_DOWN)) { setMotors(HIGH, LOW, LOW, HIGH, 1023, 1023); }
    else if (ps2x.Button(PSB_PAD_LEFT)) { setMotors(LOW, HIGH, LOW, HIGH, 1023, 1023); }
    else if (ps2x.Button(PSB_PAD_RIGHT)){ setMotors(HIGH, LOW, HIGH, LOW, 1023, 1023); }
    else { stopMotors(); }
  #elif MODE == 2
    // 左摇杆 X + L2/R2
    int nJoyL = map(ps2x.Analog(PSS_LX), 0, 255, 1023, -1023);
    int spdR = 1023, spdL = 1023;
    if (nJoyL < 0) spdR += nJoyL;
    if (nJoyL > 0) spdL -= nJoyL;
    if (ps2x.Button(PSB_R2))      setMotors(LOW, HIGH, HIGH, LOW, spdR, spdL);
    else if (ps2x.Button(PSB_L2)) setMotors(HIGH, LOW, LOW, HIGH, spdR, spdL);
    else stopMotors();
  #elif MODE == 3
    // 双摇杆差速
    int nJoyL = map(ps2x.Analog(PSS_LY), 0, 255, 1023, -1023);
    int nJoyR = map(ps2x.Analog(PSS_RY), 0, 255, -1023, 1023);
    driveTrack(nJoyR, MOTORA_1, MOTORA_2, ENA);
    driveTrack(nJoyL, MOTORB_1, MOTORB_2, ENB);
  #elif MODE == 4
    // 单摇杆 Arcade Drive
    int nJoyX = map(ps2x.Analog(PSS_LX), 0, 255, -1023, 1023);
    int nJoyY = map(ps2x.Analog(PSS_LY), 0, 255, 1023, -1023);
    arcadeDrive(nJoyX, nJoyY);
  #endif
  delay(50);
}

void setMotors(byte a1, byte a2, byte b1, byte b2, int spdA, int spdB) {
  digitalWrite(MOTORA_1, a1); digitalWrite(MOTORA_2, a2);
  digitalWrite(MOTORB_1, b1); digitalWrite(MOTORB_2, b2);
  analogWrite(ENA, spdA); analogWrite(ENB, spdB);
}
void stopMotors() { analogWrite(ENA, 0); analogWrite(ENB, 0); }
void driveTrack(int joy, byte in1, byte in2, byte en) {
  if (joy > 50)      { digitalWrite(in1, HIGH); digitalWrite(in2, LOW); analogWrite(en, 1023); }
  else if (joy < -50){ digitalWrite(in1, LOW); digitalWrite(in2, HIGH); analogWrite(en, 1023); }
  else               { analogWrite(en, 0); }
}
void arcadeDrive(int x, int y) {
  // 简化版混合算法,完整版见原教程 Sketch #4
  float fwd = y / 1023.0;
  float turn = x / 1023.0;
  int left = constrain((fwd + turn) * 1023, -1023, 1023);
  int right = constrain((fwd - turn) * 1023, -1023, 1023);
  driveTrack(left, MOTORA_1, MOTORA_2, ENA);
  driveTrack(right, MOTORB_1, MOTORB_2, ENB);
}

原理图

用 PS2 无线手柄控制 Arduino 坦克机器人 用 PS2 无线手柄控制 Arduino 坦克机器人


💡 进阶建议:加装超声波避障、舵机云台、FPV 摄像头,或将手柄换为 ESP-NOW/蓝牙手柄实现免接收器控制。祝玩得开心!

制造工艺

  1. Arduino与树莓派构建互联网控制视频流机器人完整指南
  2. Unopad:基于 Arduino 的无缝 Ableton Live MIDI 控制器
  3. 舵机驱动避障机器人:基于 Arduino 与 HC-SR04 构建
  4. Arduino + Android 蓝牙控制 Roomba Create 2 扫地机器人完整指南
  5. Arduino Mega 驱动 Wii Nunchuk 控制 6 自由度机械臂
  6. Arduino Nano + 摇杆控制双步进电机:Visuino 图形化教程
  7. DIY Arduino 手柄方向盘 - 游戏竞速模拟器自制指南
  8. 使用 PS2 手柄打造遥控对战机器人
  9. 通过专用 Android App 蓝牙控制 Arduino 机械臂
  10. 手把手打造Arduino Nano喂食机器人
  11. 四轮 Arduino 机器人:Dabble App 蓝牙手柄遥控
  12. MeArm 机械臂精准手柄控制器:基于 Arduino UNO 的轨迹记录与回放