GripperControl.cs 完整解析
GripperControl.cs 完整解析
核心内容:
硬件拓扑— 一条 RS-485 总线挂两个轴(站号0=推压轴 / 站号1=旋转轴),通过 Modbus RTU 与 PC 通讯
Init()— 创建轴对象 → 使能 → 回原点 → 轮询command_finished_15信号等待完成 → 设置重试参数。串口号 COM13 和波特率 9600 硬编码
5 个运动方法—MoveAbs/MoveRelative(旋转轴加速度5000 vs 推压轴300)、Push(力控推压+阻塞等待到位)、WaitAllAxisStop(50ms 轮询IsReached())
调用者 Plugin.ElectricGripper— 通过ObservableCollection<ElecttrictGripperOP>支持多步动作序列编程,6 种操作类型按序执行,位置支持&变量链接动态读取
供应商 Demo— 注释内嵌 100 行完整 API 参考(精密推压、TCP 连接、传感器读取、急停等),方便将来扩展
4 个隐患— COM13 硬编码、无断线重连、无并发保护、限速逻辑散落在 ViewModel 而非本类
文件:
Services\GripperControl.cs(168行 + 注释内嵌供应商Demo)
角色: 增广旋转+夹持电夹爪控制类 — 基于motormaster库通过 Modbus RTU 串口控制双轴电爪
调用者:Plugin.ElectricGripper(电夹爪控制插件)
硬件: 增广电夹爪 (Modbus RTU, COM13, 9600bps, 站号0/1)
1. 硬件连接拓扑
PC (COM13) │ RS-485 / Modbus RTU │ ┌──────────┴──────────┐ ▼ ▼ 站号 0: 旋转轴 站号 1: 推压轴 Axis_Rotate Axis_Push (旋转产品角度) (夹紧/推压产品)两个轴共用一条 RS-485 总线, 通过 Modbus 站号区分。
2. 源码结构 (168行)
GripperControl │ ├── ★ 单例模式 │ └── static GripperControl Ins { get; set; } │ ├── 成员 │ ├── Axis_Rotate ← motormaster.Axis (站号0, 旋转轴) │ ├── Axis_Push ← motormaster.Axis (站号1, 推压轴) │ └── IsConnected ← bool │ ├── Init() │ ├── Axis.CreateModbusRtu("COM13", 9600, 站号) ×2 │ ├── SetServoOnOff(true) → GoHome() ×2 │ ├── 等待回原完成 (轮询 virtual_io.command_finished_15) │ ├── SetRtyTiming(1000, 30) ×2 (重试参数) │ └── Logger + IsConnected │ ├── MoveAbs(AxisID, position, speed) 绝对运动 ├── MoveRelative(AxisID, position, speed) 相对运动 ├── Push(force, distance, speed) 推压运动 ├── WaitAllAxisStop(AxisID) 阻塞等待到位 │ └── 注释内嵌: 供应商 Demo 代码 (~100行)3. 逐方法详解
3.1 Init() — 连接 + 回零
publicvoidInit(){// ① 创建两个 Modbus RTU 轴对象Axis_Push=Axis.CreateModbusRtu("\\\\.\\COM13",9600,0);// 站号0=推压轴Axis_Rotate=Axis.CreateModbusRtu("\\\\.\\COM13",9600,1);// 站号1=旋转轴// 注意: COM13 是硬编码的 — 这是为特定设备定制, 不是通用配置// ② 使能 + 回原点Axis_Push.SetServoOnOff(true);Axis_Push.GoHome();Axis_Rotate.SetServoOnOff(true);Axis_Rotate.GoHome();// ③ 等待两轴回原完成while(!Axis_Rotate.GetOutputSignal("virtual_io.command_finished_15"))Thread.Sleep(10);while(!Axis_Push.GetOutputSignal("virtual_io.command_finished_15"))Thread.Sleep(10);// ④ 设置重试参数 (超时1000ms, 重试30次)Axis_Push.SetRtyTiming(1000,30);Axis_Rotate.SetRtyTiming(1000,30);IsConnected=true;Logger.AddLog("夹爪连接成功!");}问题: 串口号COM13和波特率9600硬编码 — 只适用于特定工控机, 换设备需要改代码。
3.2 MoveAbs() — 绝对运动
publicvoidMoveAbs(intAxisID,floatposition,floatspeed){if(AxisID==0){// 旋转轴: 加速度5000mm/s², 减速度5000mm/s², 定位范围0.1mmAxis_Rotate.MoveAbsolute(position,speed,5000f,5000f,0.1f);}else{// 推压轴: 加速度300mm/s² (较小, 防止冲击)Axis_Push.MoveAbsolute(position,speed,300f,300f,0.1f);}}参数差异: 旋转轴用大加速度(5000), 推压轴用小加速度(300) — 因为旋转是连续转动, 推压需要避免撞击产品。
3.3 MoveRelative() — 相对运动
publicvoidMoveRelative(intAxisID,floatposition,floatspeed){if(AxisID==0)Axis_Rotate.MoveRelative(position,speed,5000f,5000f,0.1f);elseAxis_Push.MoveRelative(position,speed,300f,300f,0.1f);}和MoveAbs完全对称, 唯一区别是调用MoveRelative而非MoveAbsolute。
3.4 Push() — 推压运动 (推压轴专用)
publicvoidPush(floatforce,floatdistance,floatspeed){// force: 出力百分比 (0-1)// distance: 推压距离 mm// speed: 推压速度 mm/sAxis_Push.Push(distance,speed,500f,force,0.1f,10f);// 距离 速度 加速度 出力 定位范围 稳压时间// 阻塞等待到位while(!Axis_Push.IsReached())Thread.Sleep(20);}推压 vs 绝对运动的区别: 推压运动到达目标位置后会保持恒定力 (类似"软着陆"), 绝对运动是精确定位。
3.5 WaitAllAxisStop() — 阻塞等待到位
publicvoidWaitAllAxisStop(intAxisID){if(AxisID==0){while(true){Thread.Sleep(50);if(Axis_Rotate.IsReached())break;}}else{while(true){Thread.Sleep(50);if(Axis_Push.IsReached())break;}}}简单的轮询等待, 每 50ms 检查一次IsReached()信号。
4. 调用者: Plugin.ElectricGripper
电夹爪插件通过GripperControl.Ins单例调用:
// ElectrictGripperViewModel.ExeModule()if(!GripperControl.Ins.IsConnected)GripperControl.Ins.Init();// 首次执行时自动初始化foreach(variteminelecttrictGripperOPS){floatposition=item.GolaPt.StartsWith("&")?(float)Convert.ToDouble(GetLinkValue(item.GolaPt))// 变量链接:(float)Convert.ToDouble(item.GolaPt);// 固定值switch(item.OpDiscription){case"旋转轴绝对运动":GripperControl.Ins.MoveAbs(0,position,speed);break;case"旋转轴相对运动":GripperControl.Ins.MoveRelative(0,position,speed);break;case"推压轴绝对运动":GripperControl.Ins.MoveAbs(1,position,speed);break;case"推压轴推压运动":GripperControl.Ins.Push(0.7f,position,speed);break;case"等待旋转轴到位":GripperControl.Ins.WaitAllAxisStop(0);break;case"等待轴推轴到位":GripperControl.Ins.WaitAllAxisStop(1);break;}}插件通过ObservableCollection<ElecttrictGripperOP>支持多步动作序列编程— 用户可以在 UI 中添加多行操作(绝对运动/相对运动/推压/等待), 运行时按顺序执行。
每条操作数据:
classElecttrictGripperOP{stringOpDiscription;// 操作类型描述stringGolaPt;// 目标位置 (支持 &变量链接)floatSpeed;// 速度 (旋转轴上限1000, 推压轴上限100)boolEnableed;// 是否启用}5. 供应商 Demo 代码 (注释内嵌 100 行)
文件末尾的/* ... */注释块保留了供应商提供的完整 Demo 代码, 展示了motormaster库的全部 API:
API 汇总: ├── Axis.CreateModbusRtu(port, baud, station) // 创建轴对象 ├── Axis.CreateModbusTcp(ip, port, station) // TCP 方式 ├── GoHome() // 回原点 ├── MoveAbsolute(pos, speed, acc, dec, tol) // 绝对运动 ├── MoveRelative(dist, speed, acc, dec, tol) // 相对运动 ├── Push(force, dist, speed) // 推压 ├── PrecisePush(force, dist, speed, tol, time) // 精密推压 ├── TrigCommand(n) // 触发指令 ├── Position() / Velocity() / Torque() // 读取状态 ├── ForceSensor() // 读传感器 ├── ResetError() // 复位 ├── SetServoOnOff(bool) // 使能开关 ├── Stop() // 急停 ├── IsReached() // 是否到位 ├── GetOutputSignal("signal_name") // 读取输出信号 └── SetRtyTiming(timeout, retries) // 重试配置6. 设计分析
优点
- 精简封装: 168 行覆盖了 6 种运动模式, 调用者只需传 AxisID + position + speed
- 单例保证唯一连接: 多个流程/插件共享同一个夹爪实例, 不会重复连接
- 注释保留 Demo: 供应商代码留在注释里, 方便将来扩展 (如精密推压、TCP连接)
隐患
| 问题 | 说明 |
|---|---|
| COM13 硬编码 | 串口号和波特率写死在代码里, 换设备/换端口需要改源码重新编译 |
| 无断线重连 | Init()没有重试逻辑, 连接失败后IsConnected=false但不会自动尝试恢复 |
~GripperControl()析构函数为空 | 没有在析构时断开连接/释放资源 |
| ISpeed 限制写在 ViewModel | ElecttrictGripperOP.Speedsetter 里有限速逻辑 (>1000/>100), 应该属于GripperControl |
| 无并发保护 | 多个流程同时调用MoveAbs/Push可能导致夹爪竞争 |
文档说明: 基于 GripperControl.cs (168行) + Plugin.ElectricGripper 插件代码静态分析生成。硬件基于增广电夹爪, 通讯使用 motormaster 库的 Modbus RTU 协议。当前版本 2026-06-10。
