基于EtherCat全总线方案的8轴喷涂拖拽示教方案
基于EtherCAT全总线方案的8轴喷涂拖拽示教系统设计方案
一、系统概述
本方案面向8轴喷涂机器人(6轴机械臂 + 2轴外部运动平台/变位机),基于EtherCAT全总线架构实现拖动示教与轨迹再现功能-17。系统采用PC机Linux主站+EtherCAT从站的经典控制架构,通过EtherCAT总线实现8轴伺服驱动器的实时同步控制,同步周期可快至125μs~1ms-1-11。
拖拽示教的核心思路是:使电机工作在周期同步转矩模式(CST)下-11,电机的输出转矩补偿机械臂的重力矩及摩擦力矩,操作人员即可从任意位置轻松拖动机器人-。系统实时记录拖动轨迹点位,经平滑优化后用于再现喷涂-。
二、系统架构
2.1 硬件架构
下载
┌─────────────────────────────────────────────────────────────────┐ │ 工控PC (EtherCAT主站) │ │ Linux + Xenomai实时核 / TwinCAT / CODESYS │ │ HMI人机交互界面 │ └───────────────────────────┬─────────────────────────────────────┘ │ EtherCAT ▼ ┌─────────────────────────────────────────────────────────────────┐ │ EtherCAT从站控制器 │ │ (ESC芯片,如LAN9252/ET1100) │ └───────┬───────┬───────┬───────┬───────┬───────┬───────┬───────┘ │ │ │ │ │ │ │ ▼ ▼ ▼ ▼ ▼ ▼ ▼ ┌──────┐┌──────┐┌──────┐┌──────┐┌──────┐┌──────┐┌──────┐ │伺服1 ││伺服2 ││伺服3 ││伺服4 ││伺服5 ││伺服6 ││伺服7 │ │(J1) ││(J2) ││(J3) ││(J4) ││(J5) ││(J6) ││(Ext1)│ └──────┘└──────┘└──────┘└──────┘└──────┘└──────┘└──────┘ │ │ │ │ │ │ │ ▼ ▼ ▼ ▼ ▼ ▼ ▼ ┌──────────────────────────────────────────────────────────┐ │ 8轴伺服电机+绝对值编码器 │ │ (23位多圈绝对值编码器)[reference:7] │ └──────────────────────────────────────────────────────────┘
2.2 核心硬件选型
| 组件 | 推荐型号/方案 | 说明 |
|---|---|---|
| EtherCAT主站 | 工控PC + Linux/Xenomai 或 TwinCAT | 实时性要求高,推荐PREEMPT_RT内核- |
| 运动控制器 | ZMC408CE / 倍福CX系列 / 固高科技GVN | 支持8轴EtherCAT控制-1- |
| 伺服驱动器 | 支持EtherCAT CiA402的伺服驱动器 | 需支持CSP/CSV/CST模式-11 |
| 伺服电机 | 带23位多圈绝对值编码器 | 断电记忆位置,拖拽示教必需-11 |
| EtherCAT从站芯片 | LAN9252 / ET1100 / AM3359 | 单芯片可支持多达8轴- |
| I/O模块 | 倍福EPX系列EtherCAT端子盒 | 用于喷枪控制、传感器等- |
三、控制模式设计
3.1 模式切换策略
系统在两种核心模式间切换-11:
| 模式 | 控制方式 | 应用场景 |
|---|---|---|
| CSP(周期同步位置模式) | 上位机发送目标位置,驱动器执行位置闭环 | 轨迹再现喷涂 |
| CST(周期同步转矩模式) | 上位机发送目标转矩,驱动器执行转矩闭环 | 拖拽示教 |
拖拽示教时,上位机实时计算各关节的重力补偿力矩和摩擦力补偿力矩,通过EtherCAT总线以CST模式发送给各轴伺服驱动器--2。
3.2 分布式时钟同步
8轴联动要求严格的同步精度。EtherCAT分布式时钟(DC)技术可确保所有从站设备的同步脉冲抖动远小于1μs-。在TwinCAT或Linux主站中启用DC同步,将所有伺服轴的SYNC信号对齐至同一时钟基准-。
四、拖拽示教核心算法
4.1 重力补偿力矩计算
对于6轴机械臂,各关节的重力补偿力矩 τ_g 需根据当前关节角度 θ 和机器人动力学模型实时计算-2:
τ_g = G(θ)
其中 G(θ) 为重力项,由各连杆的质量、质心位置和当前位姿决定。
4.2 摩擦力补偿
摩擦补偿采用Stribeck模型:
τ_f = τ_c + (τ_s - τ_c)·e^(-(v/v_s)^2) + σ_v·v
其中 τ_c 为库仑摩擦力,τ_s 为静摩擦力,v 为关节速度,v_s 为Stribeck速度,σ_v 为粘性摩擦系数。
4.3 总输出力矩
τ_cmd = τ_g + τ_f + τ_user
τ_user 为操作人员拖拽施加的外力折算到各关节的等效转矩(可通过关节力矩传感器或电流观测获得)-。
4.4 轨迹平滑处理
拖动示教采集的原始轨迹点存在噪声和速度抖动,直接用于再现喷涂会导致涂层不均匀-。采用以下优化流程-:
均匀重采样:对原始轨迹点按时间/距离均匀采样
B样条曲线拟合:对位置数据进行B样条平滑-
四元数插值:对姿态数据进行四元数球面线性插值-
速度规划:采用S型速度曲线规划,消除速度突变
五、ST代码实现
以下为基于TwinCAT 3环境的ST(结构化文本)代码示例-,实现8轴拖拽示教的核心功能模块-。
5.1 数据类型定义
(* 轴配置结构体 *) TYPE ST_AxisConfig : STRUCT AxisName : STRING(20); (* 轴名称 *) AxisID : UINT; (* 轴ID: 1-8 *) ServoAddr : UINT; (* EtherCAT从站地址 *) GearRatio : REAL; (* 减速比 *) MaxTorque : REAL; (* 最大输出转矩 Nm *) GravityComp : REAL; (* 重力补偿系数 *) FrictionComp : REAL; (* 摩擦补偿系数 *) END_STRUCT END_TYPE (* 轴状态结构体 *) TYPE ST_AxisState : STRUCT Position : REAL; (* 当前位置 rad *) Velocity : REAL; (* 当前速度 rad/s *) Torque : REAL; (* 当前转矩 Nm *) TargetTorque : REAL; (* 目标转矩 Nm *) Mode : INT; (* 0:空闲 1:CSP 2:CST *) Enabled : BOOL; (* 轴使能状态 *) Error : BOOL; (* 错误标志 *) END_STRUCT END_TYPE (* 示教数据点结构体 *) TYPE ST_TeachPoint : STRUCT TimeStamp : UDINT; (* 时间戳 ms *) Positions : ARRAY[1..8] OF REAL; (* 8轴位置 *) Velocities : ARRAY[1..8] OF REAL; (* 8轴速度 *) Torques : ARRAY[1..8] OF REAL; (* 8轴转矩 *) IsRecorded : BOOL; (* 是否已记录 *) END_STRUCT END_TYPE (* 拖拽示教控制结构体 *) TYPE ST_DragTeachCtrl : STRUCT Enable : BOOL; (* 使能拖拽模式 *) RecordEnable : BOOL; (* 使能轨迹记录 *) ReplayEnable : BOOL; (* 使能轨迹再现 *) Pause : BOOL; (* 暂停 *) Stop : BOOL; (* 停止 *) ClearData : BOOL; (* 清空示教数据 *) SampleRate : UINT; (* 采样率 ms *) SmoothLevel : UINT; (* 平滑等级 1-10 *) END_STRUCT END_TYPE
5.2 主控制功能块
FUNCTION_BLOCK FB_8AxisDragTeach VAR_INPUT (* 控制指令 *) Ctrl : ST_DragTeachCtrl; (* 8轴配置 *) AxisCfg : ARRAY[1..8] OF ST_AxisConfig; (* 8轴当前位置(来自编码器反馈) *) CurrentPos : ARRAY[1..8] OF REAL; (* 8轴当前速度 *) CurrentVel : ARRAY[1..8] OF REAL; (* 8轴当前实际转矩 *) CurrentTorque : ARRAY[1..8] OF REAL; END_VAR VAR_OUTPUT (* 8轴目标转矩输出(至伺服驱动器) *) TargetTorque : ARRAY[1..8] OF REAL; (* 8轴目标位置输出(CSP模式) *) TargetPos : ARRAY[1..8] OF REAL; (* 状态输出 *) Status : STRING(50); (* 已记录点数 *) RecordedCount : UDINT; (* 错误代码 *) ErrorCode : UINT; END_VAR VAR (* 内部状态 *) AxisState : ARRAY[1..8] OF ST_AxisState; TeachBuffer : ARRAY[0..9999] OF ST_TeachPoint; (* 环形缓冲区 10000点 *) BufferHead : UDINT; BufferTail : UDINT; BufferCount : UDINT; (* 运动控制功能块 *) MC_Power : ARRAY[1..8] OF MC_Power; MC_MoveVelocity : ARRAY[1..8] OF MC_MoveVelocity; MC_MoveAbsolute : ARRAY[1..8] OF MC_MoveAbsolute; (* 定时器 *) TimerSample : TON; TimerCycle : TON; (* 重力补偿表(预计算) *) GravityTable : ARRAY[1..8] OF REAL; (* 状态机 *) State : INT; (* 0:空闲 1:拖拽中 2:记录中 3:再现中 *) (* 插补变量 *) InterpIndex : UDINT; SmoothBuffer : ARRAY[0..9999] OF ST_TeachPoint; END_VAR
5.3 初始化与模式切换
(* 初始化方法 *) METHOD Init : BOOL VAR_INPUT CycleTime : UINT; (* 控制周期 ms *) END_VAR VAR i : UINT; END_VAR FOR i := 1 TO 8 DO (* 初始化轴状态 *) AxisState[i].Enabled := FALSE; AxisState[i].Mode := 0; AxisState[i].Error := FALSE; (* 初始化MC功能块 *) MC_Power[i](Enable := FALSE); MC_MoveAbsolute[i](Execute := FALSE); MC_MoveVelocity[i](Execute := FALSE); END_FOR (* 初始化定时器 *) TimerSample(IN := FALSE, PT := T#10MS); (* 10ms采样 *) TimerCycle(IN := FALSE, PT := UINT_TO_TIME(CycleTime)); BufferHead := 0; BufferTail := 0; BufferCount := 0; State := 0; RecordedCount := 0; ErrorCode := 0; RETURN TRUE; END_METHOD (* 切换至拖拽示教模式(CST) *) METHOD SwitchToDragMode : BOOL VAR_INPUT AxisID : UINT; (* 1-8, 0表示全部 *) END_VAR VAR i : UINT; StartIdx : UINT; EndIdx : UINT; END_VAR IF AxisID = 0 THEN StartIdx := 1; EndIdx := 8; ELSE StartIdx := AxisID; EndIdx := AxisID; END_IF FOR i := StartIdx TO EndIdx DO (* 禁用位置模式 *) MC_MoveAbsolute[i](Execute := FALSE); MC_MoveVelocity[i](Execute := FALSE); (* 切换到CST模式: 通过SDO写入操作模式 *) (* 0x6060:00 = 10 (CST模式) *) AxisState[i].Mode := 2; (* CST *) (* 使能伺服 *) MC_Power[i](Enable := TRUE, bRegulatorOn := TRUE, bDriveStart := TRUE); AxisState[i].Enabled := TRUE; END_FOR State := 1; (* 拖拽中 *) RETURN TRUE; END_METHOD (* 切换至轨迹再现模式(CSP) *) METHOD SwitchToReplayMode : BOOL VAR_INPUT AxisID : UINT; END_VAR VAR i : UINT; StartIdx : UINT; EndIdx : UINT; END_VAR IF AxisID = 0 THEN StartIdx := 1; EndIdx := 8; ELSE StartIdx := AxisID; EndIdx := AxisID; END_IF FOR i := StartIdx TO EndIdx DO (* 切换到CSP模式: 0x6060:00 = 8 *) AxisState[i].Mode := 1; (* CSP *) AxisState[i].Enabled := TRUE; END_FOR State := 3; (* 再现中 *) RETURN TRUE; END_METHOD
5.4 重力补偿计算
(* 重力补偿计算 *) METHOD CalcGravityCompensation : REAL VAR_INPUT AxisID : UINT; CurrentAngle : REAL; (* 当前关节角度 rad *) END_VAR VAR g : REAL := 9.81; (* 重力加速度 *) mass : REAL; (* 连杆质量 kg *) com_dist : REAL; (* 质心距离 m *) result : REAL; END_VAR CASE AxisID OF 1: (* 基座旋转轴 - 重力影响最小 *) mass := 5.0; com_dist := 0.05; result := mass * g * com_dist * SIN(CurrentAngle); 2: (* 肩部轴 *) mass := 8.0; com_dist := 0.15; result := mass * g * com_dist * COS(CurrentAngle); 3: (* 肘部轴 *) mass := 6.0; com_dist := 0.20; result := mass * g * com_dist * COS(CurrentAngle); 4,5,6: (* 腕部轴 - 重力影响较小 *) mass := 2.0; com_dist := 0.08; result := mass * g * com_dist * COS(CurrentAngle); ELSE (* 外部轴 *) result := 0.0; END_CASE (* 乘以减速比和效率系数 *) result := result * AxisCfg[AxisID].GearRatio * AxisCfg[AxisID].GravityComp; RETURN result; END_METHOD (* 摩擦力补偿计算 *) METHOD CalcFrictionCompensation : REAL VAR_INPUT AxisID : UINT; Velocity : REAL; (* 当前速度 rad/s *) END_VAR VAR Fc : REAL; (* 库仑摩擦 *) Fs : REAL; (* 静摩擦 *) Vs : REAL; (* Stribeck速度 *) Sigma_v : REAL; (* 粘性摩擦系数 *) result : REAL; END_VAR (* 各轴摩擦参数 - 需实际标定 *) CASE AxisID OF 1: Fc := 0.5; Fs := 0.8; Vs := 0.05; Sigma_v := 0.02; 2: Fc := 0.8; Fs := 1.2; Vs := 0.04; Sigma_v := 0.03; 3: Fc := 0.6; Fs := 1.0; Vs := 0.04; Sigma_v := 0.025; 4,5,6: Fc := 0.2; Fs := 0.4; Vs := 0.03; Sigma_v := 0.01; ELSE Fc := 0.1; Fs := 0.2; Vs := 0.05; Sigma_v := 0.005; END_CASE (* Stribeck摩擦模型 *) result := Fc + (Fs - Fc) * EXP(-(Velocity * Velocity) / (Vs * Vs)) + Sigma_v * Velocity; (* 方向符号 *) IF Velocity > 0 THEN result := result; ELSIF Velocity < 0 THEN result := -result; ELSE result := 0; END_IF result := result * AxisCfg[AxisID].FrictionComp; RETURN result; END_METHOD
5.5 主循环(拖拽示教模式)
pascal
复制
下载
(* 主循环 - 在每个EtherCAT周期调用 *) METHOD MainCycle : BOOL VAR i : UINT; torque_cmd : REAL; grav_comp : REAL; fric_comp : REAL; current_point : ST_TeachPoint; END_VAR CASE State OF 0: (* 空闲状态 *) FOR i := 1 TO 8 DO TargetTorque[i] := 0.0; END_FOR Status := 'IDLE'; 1: (* 拖拽示教模式 - CST *) FOR i := 1 TO 8 DO (* 1. 计算重力补偿 *) grav_comp := CalcGravityCompensation(i, CurrentPos[i]); (* 2. 计算摩擦补偿 *) fric_comp := CalcFrictionCompensation(i, CurrentVel[i]); (* 3. 总输出转矩 = 重力补偿 + 摩擦补偿 *) torque_cmd := grav_comp + fric_comp; (* 4. 限幅保护 *) IF torque_cmd > AxisCfg[i].MaxTorque THEN torque_cmd := AxisCfg[i].MaxTorque; ELSIF torque_cmd < -AxisCfg[i].MaxTorque THEN torque_cmd := -AxisCfg[i].MaxTorque; END_IF TargetTorque[i] := torque_cmd; (* 5. 更新轴状态 *) AxisState[i].Torque := CurrentTorque[i]; AxisState[i].TargetTorque := torque_cmd; END_FOR (* 6. 轨迹记录 *) TimerSample(IN := TRUE); IF TimerSample.Q THEN TimerSample(IN := FALSE); IF Ctrl.RecordEnable THEN RecordTeachPoint(); END_IF END_IF Status := 'DRAGGING'; 3: (* 轨迹再现模式 - CSP *) IF Ctrl.ReplayEnable THEN ReplayTrajectory(); END_IF Status := 'REPLAYING'; ELSE Status := 'UNKNOWN'; END_CASE RETURN TRUE; END_METHOD
5.6 轨迹记录与再现
(* 记录示教点 *) METHOD RecordTeachPoint : BOOL VAR i : UINT; point : ST_TeachPoint; next_head : UDINT; END_VAR IF NOT Ctrl.RecordEnable THEN RETURN FALSE; END_IF (* 检查缓冲区是否已满 *) next_head := (BufferHead + 1) MOD 10000; IF next_head = BufferTail THEN (* 缓冲区满,覆盖最旧数据 *) BufferTail := (BufferTail + 1) MOD 10000; BufferCount := BufferCount - 1; END_IF (* 记录当前8轴数据 *) point.TimeStamp := UDINT_TO_TIME(TimerCycle.ET); FOR i := 1 TO 8 DO point.Positions[i] := CurrentPos[i]; point.Velocities[i] := CurrentVel[i]; point.Torques[i] := CurrentTorque[i]; END_FOR point.IsRecorded := TRUE; (* 写入缓冲区 *) TeachBuffer[BufferHead] := point; BufferHead := next_head; BufferCount := BufferCount + 1; RecordedCount := RecordedCount + 1; RETURN TRUE; END_METHOD (* 轨迹再现 *) METHOD ReplayTrajectory : BOOL VAR i : UINT; idx : UDINT; point : ST_TeachPoint; pos_cmd : REAL; progress : REAL; END_VAR IF BufferCount = 0 THEN ErrorCode := 1001; (* 无示教数据 *) RETURN FALSE; END_IF (* 从缓冲区读取当前插补点 *) idx := (BufferTail + InterpIndex) MOD 10000; IF idx = BufferHead THEN (* 轨迹播放完成 *) Ctrl.ReplayEnable := FALSE; InterpIndex := 0; RETURN TRUE; END_IF point := TeachBuffer[idx]; (* 发送CSP位置指令到各轴 *) FOR i := 1 TO 8 DO pos_cmd := point.Positions[i]; (* 位置限幅保护 *) IF pos_cmd > 360.0 THEN pos_cmd := 360.0; ELSIF pos_cmd < -360.0 THEN pos_cmd := -360.0; END_IF TargetPos[i] := pos_cmd; (* 执行绝对定位 *) MC_MoveAbsolute[i]( Execute := TRUE, Position := pos_cmd, Velocity := 50.0, (* 速度限制 *) Acceleration := 100.0, Deceleration := 100.0, Direction := MC_DIRECTION.POSITIVE ); END_FOR InterpIndex := InterpIndex + 1; progress := UDINT_TO_REAL(InterpIndex) / UDINT_TO_REAL(BufferCount) * 100.0; RETURN TRUE; END_METHOD
5.7 轨迹平滑处理(B样条拟合)
(* B样条轨迹平滑 *) METHOD SmoothTrajectory : BOOL VAR_INPUT InputBuffer : ARRAY[0..9999] OF ST_TeachPoint; PointCount : UDINT; SmoothLevel : UINT; (* 1-10 *) END_VAR VAR_OUTPUT OutputBuffer : ARRAY[0..9999] OF ST_TeachPoint; OutputCount : UDINT; END_VAR VAR i, j : UDINT; k : UINT; (* B样条阶数 *) step : REAL; t : REAL; weight : ARRAY[0..10] OF REAL; temp_pos : ARRAY[1..8] OF REAL; END_VAR k := 3 + SmoothLevel; (* 阶数 4-13 *) IF k > 10 THEN k := 10; END_IF IF PointCount < k THEN (* 数据点太少,无法平滑 *) OutputBuffer := InputBuffer; OutputCount := PointCount; RETURN FALSE; END_IF (* 均匀重采样 + B样条拟合 *) step := 1.0 / UDINT_TO_REAL(PointCount - 1); OutputCount := 0; FOR i := 0 TO PointCount - 1 DO t := UDINT_TO_REAL(i) * step; (* 计算B样条基函数权重 *) FOR j := 0 TO k DO weight[j] := BasisFunction(j, k, t); END_FOR (* 加权平均计算平滑后的位置 *) FOR j := 1 TO 8 DO temp_pos[j] := 0.0; FOR OutputCount := 0 TO k DO temp_pos[j] := temp_pos[j] + weight[OutputCount] * InputBuffer[(i + OutputCount) MOD PointCount].Positions[j]; END_FOR END_FOR (* 写入输出缓冲区 *) OutputBuffer[OutputCount].Positions := temp_pos; OutputBuffer[OutputCount].TimeStamp := InputBuffer[i].TimeStamp; OutputBuffer[OutputCount].IsRecorded := TRUE; OutputCount := OutputCount + 1; END_FOR RETURN TRUE; END_METHOD (* B样条基函数计算 *) METHOD BasisFunction : REAL VAR_INPUT i : UINT; k : UINT; t : REAL; END_VAR VAR knot : ARRAY[0..20] OF REAL; result : REAL; END_VAR (* 均匀节点向量 *) FOR i := 0 TO 20 DO knot[i] := UDINT_TO_REAL(i) / 20.0; END_FOR (* Cox-de Boor递推公式 *) IF k = 0 THEN IF knot[i] <= t AND t < knot[i+1] THEN result := 1.0; ELSE result := 0.0; END_IF ELSE result := (t - knot[i]) / (knot[i+k] - knot[i]) * BasisFunction(i, k-1, t) + (knot[i+k+1] - t) / (knot[i+k+1] - knot[i+1]) * BasisFunction(i+1, k-1, t); END_IF RETURN result; END_METHOD
5.8 安全保护与急停
(* 安全监控 - 每个周期调用 *) METHOD SafetyMonitor : BOOL VAR i : UINT; velocity_limit : REAL := 50.0; (* 速度上限 rad/s *) torque_limit : REAL := 200.0; (* 转矩上限 Nm *) pos_limit_max : REAL := 360.0; (* 位置上限 deg *) pos_limit_min : REAL := -360.0; (* 位置下限 deg *) END_VAR FOR i := 1 TO 8 DO (* 速度超限检测 *) IF ABS(CurrentVel[i]) > velocity_limit THEN ErrorCode := 2000 + i; EmergencyStop(); RETURN FALSE; END_IF (* 转矩超限检测 *) IF ABS(CurrentTorque[i]) > torque_limit THEN ErrorCode := 3000 + i; EmergencyStop(); RETURN FALSE; END_IF (* 位置超限检测 *) IF CurrentPos[i] > pos_limit_max OR CurrentPos[i] < pos_limit_min THEN ErrorCode := 4000 + i; EmergencyStop(); RETURN FALSE; END_IF END_FOR RETURN TRUE; END_METHOD (* 急停 *) METHOD EmergencyStop : BOOL VAR i : UINT; END_VAR (* 立即停止所有轴 *) FOR i := 1 TO 8 DO MC_Power[i](Enable := FALSE); AxisState[i].Enabled := FALSE; TargetTorque[i] := 0.0; TargetPos[i] := CurrentPos[i]; (* 保持当前位置 *) END_FOR State := 0; Ctrl.Enable := FALSE; Ctrl.RecordEnable := FALSE; Ctrl.ReplayEnable := FALSE; RETURN TRUE; END_METHOD
六、EtherCAT通信配置要点
6.1 过程数据对象(PDO)配置
拖拽示教模式下,每个伺服轴至少需配置以下PDO:
| 索引 | 名称 | 方向 | 说明 |
|---|---|---|---|
| 0x6040 | Controlword | 主→从 | 控制字 |
| 0x6060 | Modes of operation | 主→从 | 操作模式(CST=10) |
| 0x6071 | Target torque | 主→从 | 目标转矩 |
| 0x6041 | Statusword | 从→主 | 状态字 |
| 0x6061 | Modes of operation display | 从→主 | 当前操作模式 |
| 0x6064 | Position actual value | 从→主 | 实际位置 |
| 0x606C | Velocity actual value | 从→主 | 实际速度 |
| 0x6077 | Torque actual value | 从→主 | 实际转矩- |
6.2 同步周期配置
推荐同步周期:1ms(1000Hz)或更短-
分布式时钟:启用DC同步,所有从站SYNC0对齐-
同步抖动:要求 < 1μs
七、系统工作流程
┌─────────────────────────────────────────────────────────────────┐ │ 系统启动 │ │ ┌─────────────────────┐ │ │ │ 1. EtherCAT网络扫描 │ │ │ │ 2. 8轴伺服初始化 │ │ │ │ 3. 回零/寻原点 │ │ │ └──────────┬──────────┘ │ │ ▼ │ │ ┌─────────────────────┐ │ │ │ 4. 切换到CST模式 │ │ │ │ (拖拽示教模式) │ │ │ └──────────┬──────────┘ │ │ ▼ │ │ ┌─────────────────────┐ │ │ │ 5. 操作人员拖拽 │ │ │ │ 机器人示教 │ │ │ └──────────┬──────────┘ │ │ ▼ │ │ ┌────────────────────────────────────┐ │ │ │ 实时计算重力补偿+摩擦补偿转矩 │ │ │ │ → 通过EtherCAT发送CST指令 │ │ │ └────────────────┬───────────────────┘ │ │ ▼ │ │ ┌────────────────────────────────────┐ │ │ │ 10ms周期采样记录8轴位置/速度/转矩 │ │ │ └────────────────┬───────────────────┘ │ │ ▼ │ │ ┌────────────────────────────────────┐ │ │ │ 6. 停止拖拽,保存示教数据 │ │ │ └────────────────┬───────────────────┘ │ │ ▼ │ │ ┌────────────────────────────────────┐ │ │ │ 7. B样条轨迹平滑优化 │ │ │ └────────────────┬───────────────────┘ │ │ ▼ │ │ ┌────────────────────────────────────┐ │ │ │ 8. 切换到CSP模式 │ │ │ │ (轨迹再现模式) │ │ │ └────────────────┬───────────────────┘ │ │ ▼ │ │ ┌────────────────────────────────────┐ │ │ │ 9. 自动再现喷涂轨迹 │ │ │ └────────────────────────────────────┘ │ └─────────────────────────────────────────────────────────────────┘
八、关键技术要点总结
| 技术要点 | 实现方式 | 参考 |
|---|---|---|
| 8轴同步控制 | EtherCAT分布式时钟,同步抖动<1μs | - |
| 拖拽示教 | CST转矩模式 + 重力/摩擦补偿 | -11- |
| 轨迹记录 | 10ms周期采样,环形缓冲区 | |
| 轨迹平滑 | B样条曲线拟合 + 四元数插值 | - |
| 实时性保障 | Linux+Xenomai / PREEMPT_RT | - |
| 安全保护 | 速度/转矩/位置三限保护 + 急停 | |
| 绝对值编码器 | 23位多圈,断电记忆位置 | -11 |
九、注意事项
重力补偿参数标定:各连杆的质量、质心位置需通过实际测量或CAD模型精确获取,否则会影响拖拽轻便性-2。
摩擦力补偿:摩擦参数受温度和磨损影响,建议定期自动标定。
轨迹优化:示教数据直接用于再现时存在速度抖动问题,必须经过平滑优化-。
安全机制:拖拽示教过程中需设置速度、转矩、位置三重限幅保护,并配备急停按钮。
同步性能:8轴联动对同步精度要求高,务必启用EtherCAT分布式时钟功能-。
数据存储:示教轨迹数据建议同时保存至非易失性存储器,防止断电丢失-1。
接线图纸