AGV 小车 PLC 控制系统 --- 详细设计文档
项目:轻载装配/分拣 AGV 小车 PLC 控制系统
平台:Siemens TIA Portal(SCL 为主)
文档版本:V1.0
日期:2026-08-25
适用场景:人机协同轻载区域(装配线 / 分拣工位物料周转)
关联文档:01_需求设计.md、02_架构设计.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;
NormAngle、PurePursuitPoint为 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 页面:
- 主画面:状态、位姿、任务、电量、报警条。
- 任务页:当前任务/段表/进度。
- 参数页:
DB_AgvParam读写(带权限)。 - 诊断页:报警历史、看门狗状态、伺服状态、传感器原始值。
- 手动页:模式切换、点动/摇杆、对接测试、滚筒测试。
本地按钮:启动/停止/急停/复位/自动-手动。
4. 附录
4.1 关键算法备注
- 纯追踪前视距离
Lk:建议Lk = k·v + L0,速度自适应,避免低速振荡与高速切弯滞后。 - 里程计漂移:纯编码器每 5--10 m 累积误差显著,必须依赖地标修正;人机区建议 3--5 m 布一个二维码。
- 加减速:建议 S 曲线(jerk 限幅)替代梯形,避免启停冲击导致打滑/载物倾倒。
- 对接精度:里程计仅在最后微动段用对接光电闭环,毫米级重复精度依赖机械与光电而非里程计。
4.2 实施建议与里程碑
- 硬件上架台 → Profinet/V90 配置 → 速度闭环验证。
- 里程计 + 静态地标修正 → 直线/弯道循迹验证。
- 避障/安全激光联调 → 安全评估验收。
- OPC UA 信息模型与上位联调 → 任务全流程。
- 对接/上下料时序 → 多任务压力测试。
4.3 可扩展性接口汇总
| 接口 | 默认实现 | 可替换为 |
|---|---|---|
| FB_NavCorrection | 二维码地标 | 磁条/RFID/激光 SLAM |
| 通信 FB_OpcUaInfModel | OPC UA | 可加 Modbus TCP 镜像 |
| 驱动工艺对象 | V90 速度控制 | 步进 PTO/其他伺服 |
| 任务段类型 | 直线/圆弧/转向/对接 | 可加贝塞尔曲线段 |
4.4 待确认事项
- 导航方式"其他"的具体含义(当前按"里程计+二维码修正"默认实现,可插拔替换)。
- 上下料机构形式(滚筒/顶升/料箱)→ 影响 FB_ExchangeStation 时序。
- 是否需要多车调度(当前为单车;多车需上位集中调度)。
- F-CPU 是否最终确定(如改用标准 CPU + 外部安全模块,安全章节需调整)。
- OPC UA 安全策略(用户名/证书)与上位对接规范。
需求依据见 01_需求设计.md,分层与模块划分依据见 02_架构设计.md。