PS2手柄控制6轴机械臂程序设计与实现

简介: 使用PS2手柄作为输入设备,通过Arduino主控板(如Arduino Mega 2560或Uno)控制6轴舵机机械臂(如SMALLROBOTAM机械臂),实现无线遥控操作。系统核心是将PS2手柄的摇杆、按键信号转换为舵机角度指令,通过PWM信号驱动6个舵机(对应机械臂的6个自由度:底座旋转、大臂、小臂、手腕俯仰、手腕旋转、夹爪),适用于教育演示、工业抓取、娱乐互动等场景。

一、系统概述

使用PS2手柄作为输入设备,通过Arduino主控板(如Arduino Mega 2560或Uno)控制6轴舵机机械臂(如SMALLROBOTAM机械臂),实现无线遥控操作。系统核心是将PS2手柄的摇杆、按键信号转换为舵机角度指令,通过PWM信号驱动6个舵机(对应机械臂的6个自由度:底座旋转、大臂、小臂、手腕俯仰、手腕旋转、夹爪),适用于教育演示、工业抓取、娱乐互动等场景。

二、系统架构与硬件组成

2.1 硬件清单

组件 型号/参数 数量 功能说明
主控板 Arduino Mega 2560(或Uno) 1 处理PS2手柄信号,生成PWM控制舵机
PS2手柄 PlayStation 2原装或兼容手柄 1 提供摇杆、按键输入(无线/有线)
PS2接收器 PS2无线接收器模块 1 接收手柄信号,通过SPI与Arduino通信
舵机 MG996R(扭矩11kg·cm)或SG90(扭矩1.8kg·cm) 6 驱动机械臂6个关节(建议大关节用MG996R,小关节用SG90)
舵机驱动板 PCA9685(16路PWM,I2C)或直接接Arduino PWM引脚 1(可选) 扩展PWM输出,减轻Arduino负担
机械臂结构 SMALLROBOTAM 6轴机械臂套件(或3D打印) 1套 包含舵机支架、连接件、夹爪等
电源 5V/10A开关电源(舵机单独供电) 1 为舵机提供足够电流(避免Arduino电源过载)

2.2 接线示意图

PS2接收器 → Arduino
  DAT (数据) → 引脚11 (MISO)
  CMD (命令) → 引脚12 (MOSI)
  SEL (片选) → 引脚10 (SS)
  CLK (时钟) → 引脚13 (SCK)
  VCC → 5V
  GND → GND

舵机 → Arduino/PCA9685
  舵机1(底座) → 引脚9(或PCA9685通道0)
  舵机2(大臂) → 引脚10(或PCA9685通道1)
  舵机3(小臂) → 引脚11(或PCA9685通道2)
  舵机4(手腕俯仰) → 引脚12(或PCA9685通道3)
  舵机5(手腕旋转) → 引脚13(或PCA9685通道4)
  舵机6(夹爪) → 引脚14(或PCA9685通道5)
  舵机VCC → 5V/10A电源(独立供电)
  舵机GND → 与Arduino共地

注意:若使用PCA9685舵机驱动板,需通过I2C(SDA→A4,SCL→A5)连接Arduino,可同时驱动16路舵机,避免Arduino PWM引脚不足。

三、软件设计:PS2手柄库与舵机控制

3.1 开发环境与库安装

  • IDE:Arduino IDE(1.8.x或更高)

  • 必需库

    1. PS2X_lib:PS2手柄通信库(下载地址

    2. Servo:Arduino内置舵机库(或Adafruit_PWMServoDriver,若使用PCA9685)

  • 库安装:将下载的PS2X_lib文件夹放入Arduino的libraries目录,重启IDE。

3.2 程序结构

image.png

3.3 核心代码实现

3.3.1 头文件与全局变量

#include <PS2X_lib.h>  // PS2手柄库
#include <Servo.h>     // 舵机库
// 若使用PCA9685,则包含 #include <Adafruit_PWMServoDriver.h>

// PS2手柄引脚定义(SPI接口)
#define PS2_DAT        11  // MISO(黄色线)
#define PS2_CMD        12  // MOSI(橙色线)
#define PS2_SEL        10  // SS(蓝色线)
#define PS2_CLK        13  // SCK(红色线)

// 舵机引脚定义(Arduino直接驱动)
#define SERVO_BASE     9   // 底座舵机
#define SERVO_SHOULDER 10  // 大臂舵机
#define SERVO_ELBOW    11  // 小臂舵机
#define SERVO_WRIST_P  12  // 手腕俯仰
#define SERVO_WRIST_R  13  // 手腕旋转
#define SERVO_GRIPPER  14  // 夹爪舵机

// 舵机角度限制(根据机械臂结构调整)
#define BASE_MIN       0
#define BASE_MAX       180
#define SHOULDER_MIN   30
#define SHOULDER_MAX   150
#define ELBOW_MIN      50
#define ELBOW_MAX      170
#define WRIST_P_MIN    0
#define WRIST_P_MAX    180
#define WRIST_R_MIN    0
#define WRIST_R_MAX    180
#define GRIPPER_MIN    0   // 夹爪闭合
#define GRIPPER_MAX    90  // 夹爪张开

// 全局变量
PS2X ps2x;  // PS2手柄对象
Servo servo_base, servo_shoulder, servo_elbow, servo_wrist_p, servo_wrist_r, servo_gripper;
int error;  // 手柄连接错误码
int pressures = 0;  // 是否启用压力感应(0=禁用)
int rumble = 0;     // 是否启用手柄震动(0=禁用)

// 当前舵机角度
int angle_base = 90, angle_shoulder = 90, angle_elbow = 90;
int angle_wrist_p = 90, angle_wrist_r = 90, angle_gripper = 0;

3.3.2 初始化函数(setup)

void setup() {
   
  Serial.begin(115200);
  delay(300);  // 等待手柄初始化

  // 初始化PS2手柄
  error = ps2x.config_gamepad(PS2_CLK, PS2_CMD, PS2_SEL, PS2_DAT, pressures, rumble);
  if (error == 0) {
   
    Serial.println("PS2手柄初始化成功!");
  } else {
   
    Serial.println("PS2手柄初始化失败,错误码: " + String(error));
  }

  // 初始化舵机(若使用PCA9685,则替换为pwm.begin())
  servo_base.attach(SERVO_BASE);
  servo_shoulder.attach(SERVO_SHOULDER);
  servo_elbow.attach(SERVO_ELBOW);
  servo_wrist_p.attach(SERVO_WRIST_P);
  servo_wrist_r.attach(SERVO_WRIST_R);
  servo_gripper.attach(SERVO_GRIPPER);

  // 设置舵机初始位置(机械臂“归零”姿势)
  servo_base.write(angle_base);
  servo_shoulder.write(angle_shoulder);
  servo_elbow.write(angle_elbow);
  servo_wrist_p.write(angle_wrist_p);
  servo_wrist_r.write(angle_wrist_r);
  servo_gripper.write(angle_gripper);

  delay(1000);  // 等待舵机到位
}

3.3.3 主循环(loop)与手柄映射

void loop() {
   
  ps2x.read_gamepad(false, 0);  // 读取手柄数据(不震动)

  // 1. 左摇杆控制底座(LX)和大臂(LY)
  if (ps2x.Analog(PSS_LX) < 50) {
           // 左摇杆向左
    angle_base = constrain(angle_base - 1, BASE_MIN, BASE_MAX);
    servo_base.write(angle_base);
  } else if (ps2x.Analog(PSS_LX) > 200) {
    // 左摇杆向右
    angle_base = constrain(angle_base + 1, BASE_MIN, BASE_MAX);
    servo_base.write(angle_base);
  }

  if (ps2x.Analog(PSS_LY) < 50) {
           // 左摇杆向上(大臂向上)
    angle_shoulder = constrain(angle_shoulder - 1, SHOULDER_MIN, SHOULDER_MAX);
    servo_shoulder.write(angle_shoulder);
  } else if (ps2x.Analog(PSS_LY) > 200) {
    // 左摇杆向下(大臂向下)
    angle_shoulder = constrain(angle_shoulder + 1, SHOULDER_MIN, SHOULDER_MAX);
    servo_shoulder.write(angle_shoulder);
  }

  // 2. 右摇杆控制小臂(RY)和手腕俯仰(RX)
  if (ps2x.Analog(PSS_RY) < 50) {
           // 右摇杆向上(小臂向上)
    angle_elbow = constrain(angle_elbow - 1, ELBOW_MIN, ELBOW_MAX);
    servo_elbow.write(angle_elbow);
  } else if (ps2x.Analog(PSS_RY) > 200) {
    // 右摇杆向下(小臂向下)
    angle_elbow = constrain(angle_elbow + 1, ELBOW_MIN, ELBOW_MAX);
    servo_elbow.write(angle_elbow);
  }

  if (ps2x.Analog(PSS_RX) < 50) {
           // 右摇杆向左(手腕向下)
    angle_wrist_p = constrain(angle_wrist_p - 1, WRIST_P_MIN, WRIST_P_MAX);
    servo_wrist_p.write(angle_wrist_p);
  } else if (ps2x.Analog(PSS_RX) > 200) {
    // 右摇杆向右(手腕向上)
    angle_wrist_p = constrain(angle_wrist_p + 1, WRIST_P_MIN, WRIST_P_MAX);
    servo_wrist_p.write(angle_wrist_p);
  }

  // 3. 按键控制手腕旋转和夹爪
  if (ps2x.Button(PSB_L1)) {
     // L1:手腕逆时针
    angle_wrist_r = constrain(angle_wrist_r - 2, WRIST_R_MIN, WRIST_R_MAX);
    servo_wrist_r.write(angle_wrist_r);
  }
  if (ps2x.Button(PSB_R1)) {
     // R1:手腕顺时针
    angle_wrist_r = constrain(angle_wrist_r + 2, WRIST_R_MIN, WRIST_R_MAX);
    servo_wrist_r.write(angle_wrist_r);
  }

  if (ps2x.Button(PSB_L2)) {
     // L2:夹爪闭合
    angle_gripper = constrain(angle_gripper - 3, GRIPPER_MIN, GRIPPER_MAX);
    servo_gripper.write(angle_gripper);
  }
  if (ps2x.Button(PSB_R2)) {
     // R2:夹爪张开
    angle_gripper = constrain(angle_gripper + 3, GRIPPER_MAX, GRIPPER_MAX);
    servo_gripper.write(angle_gripper);
  }

  // 4. 功能键:复位到初始位置(SELECT + START)
  if (ps2x.Button(PSB_SELECT) && ps2x.Button(PSB_START)) {
   
    angle_base = 90; angle_shoulder = 90; angle_elbow = 90;
    angle_wrist_p = 90; angle_wrist_r = 90; angle_gripper = 0;
    servo_base.write(angle_base);
    servo_shoulder.write(angle_shoulder);
    servo_elbow.write(angle_elbow);
    servo_wrist_p.write(angle_wrist_p);
    servo_wrist_r.write(angle_wrist_r);
    servo_gripper.write(angle_gripper);
    delay(500);
  }

  // 5. 串口打印当前角度(调试用)
  Serial.print("Base:"); Serial.print(angle_base);
  Serial.print(" Shoulder:"); Serial.print(angle_shoulder);
  Serial.print(" Elbow:"); Serial.print(angle_elbow);
  Serial.print(" WristP:"); Serial.print(angle_wrist_p);
  Serial.print(" WristR:"); Serial.print(angle_wrist_r);
  Serial.print(" Gripper:"); Serial.println(angle_gripper);

  delay(10);  // 控制循环频率(约100Hz)
}

参考代码 PS2手柄控制SMALLROBOTAM6轴机械臂程序 www.youwenfan.com/contentali/183209.html

四、PS2手柄按键映射方案(6轴机械臂)

手柄部件 映射功能 动作说明 代码对应
左摇杆(LX) 底座旋转 左/右转动机械臂底座 ps2x.Analog(PSS_LX)
左摇杆(LY) 大臂俯仰 上/下控制大臂抬起/放下 ps2x.Analog(PSS_LY)
右摇杆(RY) 小臂俯仰 上/下控制小臂抬起/放下 ps2x.Analog(PSS_RY)
右摇杆(RX) 手腕俯仰 左/右控制手腕上下摆动 ps2x.Analog(PSS_RX)
L1按钮 手腕旋转(逆时针) 按住持续逆时针旋转 ps2x.Button(PSB_L1)
R1按钮 手腕旋转(顺时针) 按住持续顺时针旋转 ps2x.Button(PSB_R1)
L2按钮 夹爪闭合 按住持续闭合夹爪 ps2x.Button(PSB_L2)
R2按钮 夹爪张开 按住持续张开夹爪 ps2x.Button(PSB_R2)
SELECT+START 复位姿势 同时按下回到初始位置 ps2x.Button(PSB_SELECT) && ps2x.Button(PSB_START)
方向键(上/下) 预留功能 可扩展为速度调节/模式切换 ps2x.Button(PSB_PAD_UP/DOWN)

五、调试与优化技巧

5.1 常见问题排查

问题现象 可能原因 解决方案
手柄无响应 接线错误、手柄未配对 检查PS2接收器接线(DAT→11,CMD→12,SEL→10,CLK→13);长按手柄“MODE”键配对
舵机抖动/不动 电源不足、信号干扰 舵机单独用5V/10A电源供电;信号线远离电源线;增加滤波电容(100μF+0.1μF)
机械臂运动不流畅 舵机速度过快、角度突变 使用servo.writeMicroseconds()替代servo.write(),实现平滑移动;增加delay(20)
角度范围超限 机械结构限制 根据实际机械臂调整#define中的角度限制(如SHOULDER_MIN/MAX

5.2 性能优化

  1. 使用PCA9685驱动板:若舵机数量多(>6),建议使用PCA9685(I2C接口),避免Arduino PWM引脚不足,同时提供更稳定的PWM信号。

  2. 平滑运动算法:避免角度突变,采用“缓动函数”(easing function)实现平滑移动:

    void smoothMove(Servo &servo, int targetAngle, int speed) {
         
      int current = servo.read();
      while (current != targetAngle) {
         
        current += (current < targetAngle) ? 1 : -1;
        servo.write(current);
        delay(speed);  // speed越小,移动越慢
      }
    }
    
  3. 保存预设姿势:利用手柄按键(如△○×□)保存/调用预设姿势,实现“一键抓取”、“一键放置”等动作。

六、扩展功能

  1. 轨迹记录与回放:添加SD卡模块,记录舵机角度序列,实现“示教再现”。

  2. 无线升级:通过蓝牙(HC-05)或Wi-Fi(ESP8266)接收上位机指令,实现手机APP控制。

  3. 力反馈:在夹爪添加压力传感器(FSR),当夹持力过大时,手柄震动(需支持震动的PS2手柄)。

  4. 视觉辅助:添加摄像头(如OpenMV),实现目标识别与自动抓取。

七、总结

本程序实现了PS2手柄对6轴机械臂的实时控制,通过摇杆模拟量控制(底座、大臂、小臂、手腕俯仰)与按键数字量控制(手腕旋转、夹爪),提供了直观的人机交互方式。代码采用模块化设计,便于扩展为更多自由度或添加高级功能(如轨迹规划)。硬件上注意电源分离(舵机独立供电)与信号抗干扰,软件上通过角度限制与平滑移动确保机械臂运动安全、流畅。

相关文章
|
10月前
|
程序员 编译器 C#
C#语言中使用"using"关键字的介绍
以上就是 C# 中 "using" 关键字的主要用法。了解并熟练应用这个关键字,对于提高代码质量、解决命名冲突、管理资源都有着重要的作用。它是 C# 编程中不可或缺的一部分,无论是对初学者还是有经验的开发者而言,掌握它都是提高编写高效、清晰、可维护代码的关键。
329 7
|
2天前
|
人工智能 运维 监控
Agent从一问一答到自主执行面临哪些挑战?
AI任务调度平台(MSE)解决开源Agent定时任务的五大痛点:高可用性、统一运维、细粒度权限、全链路可观测、弹性降本。支持OpenClaw/Hermes/百炼/Dify等多框架,提供任务批处理、自进化、会话管理等企业级能力,现开放免费公测。
Agent从一问一答到自主执行面临哪些挑战?
|
2天前
|
人工智能 移动开发 自然语言处理
2026互联网医院系统源码开发方案:APP+小程序+HIS一体化
随着智慧医疗快速发展,互联网医院系统正在成为医疗机构数字化转型的重要方向。本文从行业趋势出发,深入解析2026互联网医院系统源码开发方案,包括APP、小程序、HIS系统一体化搭建模式,并详细介绍在线问诊、电子处方、AI导诊、私有化部署等核心功能。适合医疗机构、创业团队及软件开发企业参考阅读。
|
3天前
|
Java
MATLAB中实现自定义二维码生成
MATLAB中实现自定义二维码生成,可通过调用第三方库(如ZXing)或使用MATLAB原生函数(需工具箱支持
31 4
|
5天前
|
人工智能 iOS开发 MacOS
炸裂, AI帮我排查出sublime显示中文文件名乱码问题!
AI助我揪出Sublime中文文件名乱码元凶!根源竟是macOS内置老旧rsync 2.6.9(2006年版)UTF-8支持缺陷,即使locale配置正确仍会转义中文。终极解法:`brew install rsync` 升级至新版即可彻底解决!
|
10天前
|
人工智能 搜索推荐 新能源
AI时代Geo优化:应对模型引用规则变化的“核心+驱动”策略
文章将从E-E-A-T原则、结构化内容、SEO关键词规则以及文献/数据精准引用等多个维度,为企业提供系统性的Geo优化策略,以适应AI时代的信息检索新范式。
86 5
|
10天前
|
传感器 计算机视觉 开发者
FOC(磁场定向控制)的Simulink仿真模型实现
FOC(磁场定向控制)的Simulink仿真模型实现
98 0
|
22天前
|
存储 前端开发 API
海外仓+集运转运,taocarts如何构建跨境代购物流闭环?
跨境代购的核心竞争力,除了货源和价格,就是物流体验——海外用户下单后,物流时效、包裹安全性、轨迹可追踪性,直接决定用户复购率。很多代购创业者因无法解决海外仓存储、集运转运难题,导致包裹丢失、时效过长,最终失去客户。taocarts跨境独立站系统作为海外仓代购系统、代购集运系统的核心解决方案,集成海外仓管理、集运转运、物流轨迹追踪功能,基于React Native、Laravel技术框架,构建了“采购-仓储-转运-配送”的全流程物流闭环,适配代购集运系统、转运系统建站的核心需求。
144 3
|
2天前
|
人工智能 自然语言处理 供应链
零成本无影JVS Claw 7个月畅用指南+手把手教你GeoMind地理情报可视化AI助手改造教程
在AI智能体快速普及的当下,JVS Claw凭借轻量化运行、技能扩展灵活、云端稳定在线等特点,成为许多用户进行自动化办公、信息处理、内容生成的实用工具。但不少用户面临使用时长不足、积分有限、功能无法满足专业场景等问题。本文将详细介绍基于学生认证实现7个月低成本使用无影JVS Claw的完整方法,同时手把手讲解如何通过开源项目GeoMind,将通用JVS Claw改造为专注科研与产业地理情报的可视化智能助手,实现飞书文档解析、实体抽取、产业链关系建模、地理编码、地图可视化等专业能力,让AI工具真正服务于科研分析、产业研究、供应链观测等实际场景。
40 0
|
2天前
|
人工智能 JSON 机器人
OpenClaw 飞书机器人搭建指南 远程 AI 操控电脑配置
OpenClaw飞书机器人配置教程|一键对接飞书,聊天下达AI指令!适配v2.3.12/v2.4.1,Win10/11免配置部署。完成配置后,即可在飞书直接发送自然语言指令(如“整理桌面”“发消息给同事”),OpenClaw自动拆解任务、操控电脑执行,实现远程AI办公。(239字)