03_详细设计(AGV小车PLC控制)

AGV 小车 PLC 控制系统 --- 详细设计文档

项目:轻载装配/分拣 AGV 小车 PLC 控制系统

平台:Siemens TIA Portal(SCL 为主)

文档版本:V1.0

日期:2026-08-25

适用场景:人机协同轻载区域(装配线 / 分拣工位物料周转)

关联文档:01_需求设计.md02_架构设计.md


0. 设计假设与约定(务必先读)

本设计基于以下确认结果与假设。带 ★ 的为本次确认项;带 ◆ 的为默认假设,可在详细设计阶段调整。

取值 说明
★ 驱动结构 差速双轮 + 万向从动轮 左右两轮差速控制转向
★ 上位通信 OPC UA(S7-1500 内置 Server) 暴露信息模型给 WMS/WCS
★ 应用场景 轻载装配/分拣(载重 ≤ 200 kg,人机协同) 安全等级要求较高
★ 导航方式 可插拔导航层(轮式里程计 + 地标修正) 接口化,便于替换
◆ PLC 型号 SIMATIC S7-1516F-3 PN/DP F-CPU,兼顾标准+F安全
◆ 驱动器 2× SIEMENS V90 PN(Profinet IRT,速度控制) 左右独立速度给定
◆ 安全激光 2D 安全激光扫描仪(SICK microScan3 或同类) 经 F-CPU failsafe 评估
◆ 默认导航实现 轮式里程计(编码器)+ 二维码地标修正 + 可选 IMU 二维码修正模块可换为磁条/激光 SLAM
◆ 上下料对接 滚筒/顶升机构 + 对接光电 用于目标交换站对接

目录

  • [3.1 数据类型定义(UDT)](#3.1 数据类型定义(UDT))
  • [3.2 主控状态机 FB_AgvMainControl](#3.2 主控状态机 FB_AgvMainControl)
  • [3.3 差速运动学 FB_DiffDriveKinematics](#3.3 差速运动学 FB_DiffDriveKinematics)
  • [3.4 轨迹规划 FB_TrajectoryGenerator](#3.4 轨迹规划 FB_TrajectoryGenerator)
  • [3.5 轮式里程计 FB_WheelOdometry](#3.5 轮式里程计 FB_WheelOdometry)
  • [3.6 定位修正 FB_NavCorrection(可插拔)](#3.6 定位修正 FB_NavCorrection(可插拔))
  • [3.7 避障控制 FB_ObstacleAvoidance](#3.7 避障控制 FB_ObstacleAvoidance)
  • [3.8 安全控制 FB_SafetyControl](#3.8 安全控制 FB_SafetyControl)
  • [3.9 任务调度 FB_TaskScheduler](#3.9 任务调度 FB_TaskScheduler)
  • [3.10 上下料对接 FB_ExchangeStation](#3.10 上下料对接 FB_ExchangeStation)
  • [3.11 OPC UA 信息模型与节点设计](#3.11 OPC UA 信息模型与节点设计)
  • [3.12 报警与诊断设计](#3.12 报警与诊断设计)
  • [3.13 HMI 与本地操作](#3.13 HMI 与本地操作)
  • [4. 附录](#4. 附录)

3.1 数据类型定义(UDT)

SCL 类型定义(TIA Portal 用户数据类型 UDT)。以下用 SCL 风格描述结构。

UDT_Pos2D(二维位姿)

scl 复制代码
TYPE UDT_Pos2D
  x      : LReal;   // 纵向位移 [m]
  y      : LReal;   // 横向位移 [m]
  theta  : LReal;   // 航向角 [rad],-PI..PI
END_TYPE

UDT_VelCmd(速度命令)

scl 复制代码
TYPE UDT_VelCmd
  v      : LReal;   // 线速度 [m/s]
  w      : LReal;   // 角速度 [rad/s]
  valid  : Bool;    // 命令有效
END_TYPE

UDT_WheelVel(左右轮速度)

scl 复制代码
TYPE UDT_WheelVel
  vLeft  : LReal;   // 左轮线速度 [m/s]
  vRight : LReal;   // 右轮线速度 [m/s]
END_TYPE

UDT_PathSeg(路径段表项)

scl 复制代码
TYPE UDT_PathSeg
  segId      : DInt;
  segType    : Int;   // 0=直线 1=圆弧 2=原地转向 3=对接微动
  targetX    : LReal;
  targetY    : LReal;
  targetTheta: LReal;
  endV       : LReal; // 段末速度
  maxV       : LReal; // 段内限速
  done       : Bool;
END_TYPE

UDT_TaskItem(任务项)

scl 复制代码
TYPE UDT_TaskItem
  taskId   : DInt;
  fromStation : Int;
  toStation   : Int;
  segCount : Int;
  segs     : Array[0..31] of UDT_PathSeg;
  state    : Int;   // 0=空闲 1=已接受 2=执行 3=取货 4=运输 5=放货 6=完成 7=取消 8=异常
  priority : Int;
END_TYPE

UDT_AgvParam(整定参数,HMI 可改)

scl 复制代码
TYPE UDT_AgvParam
  wheelDiameter : LReal;   // 轮径 [m]
  trackWidth    : LReal;   // 轮距 [m]
  maxLinVel     : LReal;   // 最大线速度
  maxAngVel     : LReal;   // 最大角速度
  maxLinAcc     : LReal;   // 最大线加速度
  maxAngAcc     : LReal;   // 最大角加速度
  safeLinVel    : LReal;   // 安全限速(人机区)
  kpHeading     : LReal;   // 航向PID
  kdHeading     : LReal;
  kpLateral     : LReal;   // 横向PID
  kdLateral     : LReal;
  lookahead     : LReal;   // 纯追踪前视距离
  stallMs       : LReal;   // 障碍停留超时 [ms]
END_TYPE

UDT_AgvState(状态镜像,OPC UA 源)

scl 复制代码
TYPE UDT_AgvState
  mode         : Int;     // 0=停机 1=自动 2=手动
  mainState    : Int;     // 主状态机码
  pos          : UDT_Pos2D;
  velCmd       : UDT_VelCmd;
  wheelVel     : UDT_WheelVel;
  batteryPct   : Real;    // 电量百分比
  taskState    : Int;     // 任务状态
  alarmCode    : DWord;   // 报警位码
  heartbeatIn  : DInt;   // 上位心跳入
  heartbeatOut : DInt;   // 本机心跳出
  odometer     : LReal;   // 里程
  uptimeS      : Time;    // 运行时长
END_TYPE

3.2 主控状态机 FB_AgvMainControl

职责:顶层状态机,协调任务层、运动层、安全层、对接层。

状态定义:

状态 进入条件 出口动作
0 INIT 上电 自检通过→IDLE
1 IDLE 自检OK/任务结束 收到任务→PLANNING
2 PLANNING 任务已接受 规划完成→MOVING
3 MOVING 轨迹已生成 到站点→DOCKING 或 障碍→PAUSED
4 DOCKING 到站点 对接完成→EXCHANGE
5 EXCHANGE 对接到位 上下料完成→MOVING/IDLE
6 PAUSED 障碍/避让/暂停 障碍离开→MOVING
7 ESTOP 安全触发 复位→IDLE
8 FAULT 故障 故障清→IDLE
9 MANUAL 手动模式 切回自动→IDLE

接口:

scl 复制代码
FUNCTION_BLOCK FB_AgvMainControl
{ S7_Optimized_Access := 'TRUE' }
VAR_INPUT
  cmdAuto        : Bool;   // 切自动
  cmdManual      : Bool;   // 切手动
  cmdStart       : Bool;   // 启动
  cmdStop        : Bool;   // 停止
  cmdReset       : Bool;   // 复位
  safetyOK       : Bool;   // F层安全就绪
  faultActive    : Bool;   // 存在故障
  taskAccepted   : Bool;   // 任务已接受
  trajReady      : Bool;   // 轨迹就绪
  segDone        : Bool;   // 当前段完成
  dockDone       : Bool;   // 对接完成
  exchDone       : Bool;   // 上下料完成
  obstacleActive : Bool;   // 避障激活
END_VAR
VAR_OUTPUT
  mainState    : Int;
  velEnable    : Bool;     // 允许伺服使能
  runLight     : Bool;
  faultLight   : Bool;
END_VAR
VAR
  state : Int := 0;
  tonResume : TON;          // 恢复延时
END_VAR

SCL 主循环(节选):

scl 复制代码
// 安全优先
IF NOT safetyOK OR cmdStop THEN
  state := 7;              // ESTOP/暂停
END_IF;

CASE state OF
  0: // INIT
    velEnable := FALSE;
    IF safetyOK AND NOT faultActive THEN
      state := 1;
    END_IF;

  1: // IDLE
    velEnable := FALSE;
    IF cmdManual THEN state := 9;
    ELSIF taskAccepted THEN state := 2;
    END_IF;

  2: // PLANNING
    IF trajReady THEN state := 3; END_IF;

  3: // MOVING
    velEnable := TRUE;
    IF obstacleActive THEN state := 6;
    ELSIF segDone THEN state := 4;       // 到站点
    END_IF;

  4: // DOCKING
    velEnable := TRUE;                   // 微动使能
    IF dockDone THEN state := 5; END_IF;

  5: // EXCHANGE
    velEnable := FALSE;
    IF exchDone THEN state := 1; END_IF; // 任务完成回空闲

  6: // PAUSED
    velEnable := FALSE;
    tonResume(IN := NOT obstacleActive, PT := T#2S);
    IF tonResume.Q THEN state := 3; END_IF;

  7: // ESTOP
    velEnable := FALSE;
    IF safetyOK AND cmdReset THEN state := 1; END_IF;

  8: // FAULT
    velEnable := FALSE;
    IF NOT faultActive AND cmdReset THEN state := 1; END_IF;

  9: // MANUAL
    velEnable := FALSE;                  // 由手动FB直接控制伺服
    IF cmdAuto THEN state := 1; END_IF;
END_CASE;

mainState  := state;
runLight   := (state IN [3,4]) AND NOT obstacleActive;
faultLight  := (state IN [7,8]);

3.3 差速运动学 FB_DiffDriveKinematics

职责

  • 逆运动学:由 (v, ω) → (vL, vR),并按轮径/轮距换算成每轮转速。
  • 限幅:速度/加速度限幅 + 安全限速 + 避障系数。
  • 输出伺服速度给定(V90 速度控制对象)。

接口:

scl 复制代码
FUNCTION_BLOCK FB_DiffDriveKinematics
VAR_INPUT
  velCmd       : UDT_VelCmd;        // 期望 v,ω
  obstacleGain : LReal;             // 避障速度系数 0..1
  safetyLimit  : LReal;            // 安全限速
  param        : UDT_AgvParam;
  enable       : Bool;
END_VAR
VAR_OUTPUT
  wheelVel     : UDT_WheelVel;     // 实际下发
  nLeftRPM     : LReal;            // 左轮转速 RPM
  nRightRPM    : LReal;            // 右轮转速 RPM
  satLimit     : Bool;             // 触发限幅
END_VAR
VAR
  vRampOut, wRampOut : LReal;       // 斜率限幅中间量
  rampV : FB_RampLimiter;           // 限速/斜率实例(见 FC_Limit 通用)
  rampW : FB_RampLimiter;
END_VAR

SCL 主体:

scl 复制代码
IF NOT enable THEN
  wheelVel.vLeft  := 0.0;
  wheelVel.vRight := 0.0;
  nLeftRPM  := 0.0;
  nRightRPM := 0.0;
  RETURN;
END_IF;

// 1) 限速(取安全与命令最小)
#vMax := MIN(param.maxLinVel, safetyLimit);
#vCmd := LIMIT(-#vMax, velCmd.v, #vMax) * obstacleGain;
#wCmd := LIMIT(-param.maxAngVel, velCmd.w, param.maxAngVel) * obstacleGain;

// 2) 加速度斜率限幅(梯形)
rampV(in := #vCmd, maxAcc := param.maxLinAcc, dt := #dt, out => #vRampOut);
rampW(in := #wCmd, maxAcc := param.maxAngAcc, dt := #dt, out => #wRampOut);

// 3) 逆运动学:vL = v - w*L/2 ; vR = v + w*L/2
wheelVel.vLeft  := #vRampOut - #wRampOut * param.trackWidth * 0.5;
wheelVel.vRight := #vRampOut + #wRampOut * param.trackWidth * 0.5;

// 4) 转速换算:n = v / (π·D) * 60
#factor := 60.0 / (PI * param.wheelDiameter);
nLeftRPM  := wheelVel.vLeft  * #factor;
nRightRPM := wheelVel.vRight * #factor;

// 5) 写伺服(速度控制对象,示意)
"V90_Left".SpeedSetpoint  := nLeftRPM;
"V90_Right".SpeedSetpoint := nRightRPM;

注:"V90_Left/Right" 为 V90 在 Profinet 下的工艺对象/背景 DB。若用 TO_SpeedControl,则调用其 SetSpeed

3.4 轨迹规划 FB_TrajectoryGenerator

职责:依据当前位姿与目标点/段,输出期望 (v, ω)。

采用 纯追踪(Pure Pursuit)+ 航向 PID 组合:

  • 纯追踪:在路径上取前视点,计算横向偏差产生 ω。
  • 航向 PID:消除航向误差。
  • 直线段/圆弧段统一以"前视点跟随"处理;原地转向单独处理。

接口:

scl 复制代码
FUNCTION_BLOCK FB_TrajectoryGenerator
VAR_INPUT
  curPos       : UDT_Pos2D;
  pathSegs     : Array[0..31] of UDT_PathSeg;  // 引用任务段表
  segIndex     : Int;
  enable       : Bool;
  param        : UDT_AgvParam;
END_VAR
VAR_OUTPUT
  velCmd       : UDT_VelCmd;
  segDone      : Bool;
  lookaheadPt  : UDT_Pos2D;
END_VAR
VAR
  pidHeading   : FB_PID;
  acc : LReal;
END_VAR

SCL 主体(简化):

scl 复制代码
IF NOT enable THEN
  velCmd.v := 0.0; velCmd.w := 0.0; velCmd.valid := FALSE;
  RETURN;
END_IF;
velCmd.valid := TRUE;

// 取当前段目标
#seg := pathSegs[segIndex];

// 距离与航向偏差
#dx := #seg.targetX - curPos.x;
#dy := #seg.targetY - curPos.y;
#dist := SQRT(#dx*#dx + #dy*#dy);
#angToTgt := ATAN2(#dy, #dx);
#headErr := NormAngle(#angToTgt - curPos.theta);  // 归一到 -PI..PI

CASE #seg.segType OF
  2: // 原地转向
    velCmd.v := 0.0;
    velCmd.w := LIMIT(-param.maxAngVel, #headErr * param.kpHeading, param.maxAngVel);
    IF ABS(#headErr) < 0.02 THEN segDone := TRUE; END_IF;

  3: // 对接微动(交给 FB_ExchangeStation)
    velCmd.v := 0.0; velCmd.w := 0.0;

  ELSE // 0/1 直线/圆弧:纯追踪
    // 前视距离随速度自适应
    #lk := MAX(param.lookahead, ABS(curVelEst) * 0.4);
    lookaheadPt := PurePursuitPoint(curPos, #seg, #lk);
    // 横向偏差角 α
    #alpha := NormAngle(ATAN2(lookaheadPt.y - curPos.y, lookaheadPt.x - curPos.x) - curPos.theta);
    // 角速度:纯追踪公式 w = 2*v*sin(α)/Lk
    #v := #seg.maxV;
    velCmd.v := #v;
    velCmd.w := LIMIT(-param.maxAngVel,
                      2.0 * #v * SIN(#alpha) / #lk + #headErr * param.kdHeading,
                      param.maxAngVel);
    IF #dist < 0.03 THEN
      velCmd.v := #seg.endV;
      segDone := TRUE;
    END_IF;
END_CASE;

NormAnglePurePursuitPoint 为 FC 工具函数(归一化角与计算前视点)。

3.5 轮式里程计 FB_WheelOdometry

职责:由左右轮实际速度(来自 V90 反馈)做正运动学,更新 (x, y, θ),并累计里程。

接口与 SCL 主体:

scl 复制代码
FUNCTION_BLOCK FB_WheelOdometry
VAR_INPUT
  vLeftFb  : LReal;
  vRightFb : LReal;
  imuYawRate : LReal;    // 可选 IMU 角速度(=0 则纯编码器)
  dt       : LReal;
  param    : UDT_AgvParam;
  enable   : Bool;
END_VAR
VAR_OUTPUT
  pos : UDT_Pos2D;
  odometer : LReal;
END_VAR
VAR
  v, w : LReal;
END_VAR

IF NOT enable THEN RETURN; END_IF;

#v := 0.5 * (vLeftFb + vRightFb);
#w := (vRightFb - vLeftFb) / param.trackWidth;
// 若 IMU 可用,融合角速度(取权重)
IF imuYawRate <> 0.0 THEN
  #w := 0.7 * #w + 0.3 * imuYawRate;
END_IF;

pos.theta := NormAngle(pos.theta + #w * dt);
pos.x := pos.x + #v * COS(pos.theta) * dt;
pos.y := pos.y + #v * SIN(pos.theta) * dt;

odometer := odometer + ABS(#v) * dt;

3.6 定位修正 FB_NavCorrection(可插拔)

职责:定义统一修正接口;默认实现为二维码地标修正。可派生磁条/激光 SLAM 实现替换。

接口(抽象):

scl 复制代码
FUNCTION_BLOCK FB_NavCorrection
VAR_INPUT
  enable    : Bool;
  curPos    : UDT_Pos2D;       // 当前里程计位姿
  landmarkAvail : Bool;        // 地标命中
  landmarkX  : LReal;          // 地标绝对坐标
  landmarkY  : LReal;
  landmarkTheta : LReal;
END_VAR
VAR_OUTPUT
  corrected  : UDT_Pos2D;
  applied    : Bool;
  correction : LReal;         // 修正量(用于诊断)
END_VAR

默认二维码实现(命中即替换 + 低通融合):

scl 复制代码
IF landmarkAvail THEN
  // 命中:低通融合,避免跳变
  corrected.x     := curPos.x     * 0.3 + landmarkX     * 0.7;
  corrected.y     := curPos.y     * 0.3 + landmarkY     * 0.7;
  corrected.theta := NormAngle(landmarkTheta) * 0.9
                     + NormAngle(curPos.theta) * 0.1;
  applied := TRUE;
  correction := SQRT(POW(landmarkX-curPos.x,2) + POW(landmarkY-curPos.y,2));
ELSE
  corrected := curPos;        // 无地标沿用里程计
  applied := FALSE;
  correction := 0.0;
END_IF;

替换说明:磁条实现改为输入"偏移量",输出横向修正;激光 SLAM 实现改为订阅 SLAM 位姿并直接校正。三者接口不变,仅内部逻辑替换,FB_NavCorrection 调用方无需改动。

3.7 避障控制 FB_ObstacleAvoidance

职责 :依据安全激光扫描的警告/保护区状态,输出速度系数 obstacleGain ∈ [0,1],并置 obstacleActive

接口与 SCL 主体:

scl 复制代码
FUNCTION_BLOCK FB_ObstacleAvoidance
VAR_INPUT
  warnZone   : Bool;   // 警告区触发
  protZone   : Bool;   // 保护区触发
  enable     : Bool;
END_VAR
VAR_OUTPUT
  obstacleGain  : LReal;
  obstacleActive : Bool;
END_VAR
VAR
  gainRamp : LReal := 1.0;
END_VAR

IF NOT enable THEN
  obstacleGain := 1.0; obstacleActive := FALSE; RETURN;
END_IF;

IF protZone THEN
  obstacleGain := 0.0;          // 立即停
  obstacleActive := TRUE;
ELSIF warnZone THEN
  obstacleGain := 0.3;          // 减速
  obstacleActive := FALSE;
ELSE
  obstacleGain := 1.0;          // 全速
  obstacleActive := FALSE;
END_IF;

安全激光的"停车"在 F 层(FB_SafetyControl)也独立评估并可直接 STO,此处仅为标准层软减速/软停,双重保障。

3.8 安全控制 FB_SafetyControl(F 程序)

职责:F-CPU 内执行,评估急停/触边/限速/激光保护区,输出 STO 伺服失能与安全速度上限。

设计要点:

  • 急停/触边双通道冗余,差异检测。
  • 安全限速:给定速度经 F 截断,超阈值置 STO。
  • 保护区触发:F 输出 STO。
  • 警告区触发:F 输出"减速"信号给标准层。

接口(F-CPU):

scl 复制代码
FUNCTION_BLOCK FB_SafetyControl
VERSION(1)
MODE(FAILSAFE)
VAR_INPUT
  estopFrontA, estopFrontB : Bool;   // 急停前双通道
  estopRearA,  estopRearB  : Bool;   // 急停后双通道
  bumpFrontA,  bumpFrontB  : Bool;   // 触边前
  bumpRearA,   bumpRearB   : Bool;   // 触边后
  scanProtZone : Bool;              // 激光保护区
  scanWarnZone : Bool;              // 激光警告区
  resetAck     : Bool;              // 复位确认
END_VAR
VAR_OUTPUT
  stoLeft, stoRight : Bool;        // 安全转矩关断(接伺服 STO)
  safeSpeedLimit : LReal;          // 安全限速给标准层
  warnSlowdown   : Bool;           // 警告减速给标准层
  safetyOK       : Bool;           // 安全区就绪(给主控)
END_VAR

评估逻辑(伪 SCL,F 通过 F-FB 编译):

scl 复制代码
// 双通道差异与下降沿触发
#estop := (estopFrontA XOR estopFrontB) OR (estopRearA XOR estopRearB)
          OR (NOT estopFrontA) OR (NOT estopFrontB)
          OR (NOT estopRearA)  OR (NOT estopRearB);
#bump  := (NOT bumpFrontA) OR (NOT bumpFrontB)
          OR (NOT bumpRearA) OR (NOT bumpRearB);

#danger := #estop OR #bump OR scanProtZone;

// STO:danger 有效即失能;需 resetAck 释放
stoLeft  := #danger OR NOT resetAck;
stoRight := #danger OR NOT resetAck;

warnSlowdown   := scanWarnZone AND NOT #danger;
safeSpeedLimit := IIF(scanWarnZone, 0.15, 0.3);   // 人机区基线 0.3 m/s
safetyOK       := NOT #danger AND resetAck;

STO 信号同时硬线到 V90 的 STO 端子,确保 F 层与标准层互不依赖。

3.9 任务调度 FB_TaskScheduler

职责 :解析 OPC UA 命令 → 填 DB_Task;按段表推进 segIndex;管理任务状态机;与主控交互。

接口与 SCL 主体(节选):

scl 复制代码
FUNCTION_BLOCK FB_TaskScheduler
VAR_INPUT
  newTask    : Bool;        // OPC UA 命令到达沿
  taskItem   : UDT_TaskItem;
  segDone    : Bool;
  exchDone   : Bool;
  enable     : Bool;
END_VAR
VAR_OUTPUT
  segIndex   : Int;
  trajReady  : Bool;
  taskState  : Int;
  accepted   : Bool;
END_VAR
VAR
  cur : UDT_TaskItem;
  riseTask : RTrig;
END_VAR

riseTask(CLK := newTask);

IF riseTask.Q AND enable AND cur.state = 0 THEN
  cur := taskItem;
  cur.state := 1;        // 已接受
  accepted := TRUE;
END_IF;

IF cur.state = 1 THEN
  // 校验段表非空、站点合法 → 规划
  IF cur.segCount > 0 THEN
    cur.state := 2; trajReady := TRUE; segIndex := 0;
  END_IF;
END_IF;

IF cur.state = 2 THEN
  IF segDone THEN
    segIndex := segIndex + 1;
    IF segIndex >= cur.segCount THEN
      cur.state := 6;    // 完成
    END_IF;
  END_IF;
END_IF;

IF exchDone AND cur.state = 5 THEN cur.state := 6; END_IF;

taskState := cur.state;

3.10 上下料对接 FB_ExchangeStation

职责:到达站点后的微动对接、与交换站握手、滚筒上下料时序。

时序(状态机):

复制代码
APPROACH -> DOCKED -> HANDSHAKE -> LOAD/UNLOAD -> CONFIRM -> RELEASE

接口:

scl 复制代码
FUNCTION_BLOCK FB_ExchangeStation
VAR_INPUT
  dockPhotoL, dockPhotoR : Bool;  // 对接光电
  stationReady : Bool;            // 站点就绪
  materialOn   : Bool;             // 有货
  enable       : Bool;
  action       : Int;             // 0=上料 1=下料
END_VAR
VAR_OUTPUT
  vMicro : LReal;                 // 微动速度
  wMicro : LReal;
  rollerFwd : Bool;
  rollerRev : Bool;
  handshakeOut : Bool;
  dockDone  : Bool;
  exchDone  : Bool;
END_VAR
VAR
  st : Int := 0;
  tonLoad : TON;
END_VAR

SCL(节选):

scl 复制代码
CASE st OF
  0: // APPROACH 微动靠近
    vMicro := 0.05;
    IF dockPhotoL AND dockPhotoR THEN st := 1; END_IF;
  1: // DOCKED
    vMicro := 0.0;
    IF stationReady THEN st := 2; END_IF;
  2: // HANDSHAKE
    handshakeOut := TRUE;
    IF stationReady THEN st := 3; END_IF;
  3: // LOAD/UNLOAD
    IF action = 0 THEN rollerFwd := TRUE;   // 上料
    ELSE            rollerRev := TRUE; END_IF;
    tonLoad(IN := TRUE, PT := T#8S);
    IF tonLoad.Q AND materialOn THEN st := 4; END_IF;
  4: // CONFIRM/RELEASE
    rollerFwd := FALSE; rollerRev := FALSE;
    handshakeOut := FALSE;
    exchDone := TRUE;
    st := 0;
END_CASE;

3.11 OPC UA 信息模型与节点设计

命名空间 ns=3 (AGV),文件夹与节点:

复制代码
/AGV
 ├── /Status
 │     Mode            (Int, R)        0=停机 1=自动 2=手动
 │     MainState       (Int, R)
 │     TaskState        (Int, R)
 │     BatteryPct       (Real, R)
 │     HeartbeatOut     (DInt, R)      本机心跳
 │     Odometer         (LReal, R)
 ├── /Position
 │     X, Y, Theta      (LReal, R)
 ├── /VelCmd
 │     V, W             (LReal, R)
 ├── /Task
 │     CurrentTaskId    (DInt, R)
 │     SegIndex         (Int, R)
 │     ProgressPct      (Real, R)
 ├── /Command
 │     NewTask          (Bool, RW)     上升沿触发任务
 │     TaskData         (结构, RW)     下发任务体
 │     Cancel           (Bool, RW)
 │     Reset           (Bool, RW)
 │     HeartbeatIn      (DInt, RW)    上位心跳
 ├── /Alarm
 │     AlarmCode        (DWord, R)
 │     AlarmText        (String, R)
 └── /Param
       (映射 DB_AgvParam 关键项, RW,写后落 Flash)

心跳与降级:

  • HeartbeatOut 每 1 s 自增;上位读后写 HeartbeatIn
  • 若本机读 HeartbeatIn 超过 3 s 未变,置"上位通信断链"报警,主控进入 PAUSED 并报上位"等待上位"。

安全: 启用用户名/口令 + 证书加密;命令节点仅授权用户可写。

3.12 报警与诊断设计

报警码(位码 DWord,便于上位解析)

名称 级别 处置
0 ESTOP 安全 主控 ESTOP
1 BUMP 安全 主控 ESTOP
2 SCAN_PROT 安全 主控 ESTOP
3 SCAN_WARN 警告 减速
4 SERVO_LEFT_FAULT 故障 停机
5 SERVO_RIGHT_FAULT 故障 停机
6 COMMS_UPLOSS 警告 PAUSED
7 LOW_BATTERY(<20%) 警告 完成后回充
8 TASK_TIMEOUT 警告 取消任务
9 NAV_NO_LANDMARK 信息 提示修正源缺失
10 ENCODER_MISMATCH 故障 停机自检

看门狗(FB_AlarmDiag):

  • Profinet 站点在线(OB86 反馈)。
  • 伺服就绪信号心跳。
  • 激光扫描仪在线。
  • OPC UA 上位心跳。

维护统计: 里程、运行小时、上电次数、急停次数、避障次数,存非易失 DB。

3.13 HMI 与本地操作

HMI 页面:

  1. 主画面:状态、位姿、任务、电量、报警条。
  2. 任务页:当前任务/段表/进度。
  3. 参数页:DB_AgvParam 读写(带权限)。
  4. 诊断页:报警历史、看门狗状态、伺服状态、传感器原始值。
  5. 手动页:模式切换、点动/摇杆、对接测试、滚筒测试。

本地按钮:启动/停止/急停/复位/自动-手动。


4. 附录

4.1 关键算法备注

  • 纯追踪前视距离 Lk:建议 Lk = k·v + L0,速度自适应,避免低速振荡与高速切弯滞后。
  • 里程计漂移:纯编码器每 5--10 m 累积误差显著,必须依赖地标修正;人机区建议 3--5 m 布一个二维码。
  • 加减速:建议 S 曲线(jerk 限幅)替代梯形,避免启停冲击导致打滑/载物倾倒。
  • 对接精度:里程计仅在最后微动段用对接光电闭环,毫米级重复精度依赖机械与光电而非里程计。

4.2 实施建议与里程碑

  1. 硬件上架台 → Profinet/V90 配置 → 速度闭环验证。
  2. 里程计 + 静态地标修正 → 直线/弯道循迹验证。
  3. 避障/安全激光联调 → 安全评估验收。
  4. OPC UA 信息模型与上位联调 → 任务全流程。
  5. 对接/上下料时序 → 多任务压力测试。

4.3 可扩展性接口汇总

接口 默认实现 可替换为
FB_NavCorrection 二维码地标 磁条/RFID/激光 SLAM
通信 FB_OpcUaInfModel OPC UA 可加 Modbus TCP 镜像
驱动工艺对象 V90 速度控制 步进 PTO/其他伺服
任务段类型 直线/圆弧/转向/对接 可加贝塞尔曲线段

4.4 待确认事项

  1. 导航方式"其他"的具体含义(当前按"里程计+二维码修正"默认实现,可插拔替换)。
  2. 上下料机构形式(滚筒/顶升/料箱)→ 影响 FB_ExchangeStation 时序。
  3. 是否需要多车调度(当前为单车;多车需上位集中调度)。
  4. F-CPU 是否最终确定(如改用标准 CPU + 外部安全模块,安全章节需调整)。
  5. OPC UA 安全策略(用户名/证书)与上位对接规范。

需求依据见 01_需求设计.md,分层与模块划分依据见 02_架构设计.md

相关推荐
abnH_1 小时前
精度焦虑与预算博弈:高性价比DD马达如何守住自动化产线的“底线精度”?
人工智能·机器人·自动化·制造
shujudang2 小时前
从数据闭环到 Agent 协同:企业营销自动化如何演进为智能运营?
大数据·运维·人工智能·数据分析·自动化
戴西软件2 小时前
国内有哪些数据轻量化格式转换软件?
数据库·算法·安全·信息可视化·自动化·rpa
代码方舟4 小时前
零信任架构实战:基于天远普通维保查询构建自动化汽车后市场供应链网关
人工智能·架构·自动化·汽车
天远Date Lab4 小时前
零信任架构实战:基于天远普通维保查询构建自动化车辆收车评估网关
运维·人工智能·架构·自动化
网安蟹佬霸5 小时前
区块链与智能合约安全实战:从Solidity审计到DeFi漏洞深度剖析
运维·前端·网络·安全·自动化·区块链·智能合约
志栋智能6 小时前
告警来袭?超自动化3分钟精准定界故障根因
运维·自动化
ai_coder_ai6 小时前
pc浏览器网页如何实现自动化操作
运维·自动化
FORCECON16 小时前
力控SCADA工程升级:信创跨平台迁移方案,快速搭建安全自主的工业监控系统
linux·windows·自动化·信创·scada·监控组态软件