高级功能块
Darra PLC 提供标准功能块 (Standard FBs) 之外的高级功能块体系,涵盖 PID 闭环控制、运动控制、安全监控以及自定义功能块开发框架。
PID 控制器
PID 功能块 (FB_PID) 实现比例-积分-微分闭环控制,适用于温度、压力、流量等连续过程。
功能块接口
FUNCTION_BLOCK FB_PID
VAR_INPUT
bEnable : BOOL; // 使能
rSetpoint : REAL; // 设定值 (SP)
rFeedback : REAL; // 反馈值 (PV)
rKp : REAL; // 比例增益
rKi : REAL; // 积分增益
rKd : REAL; // 微分增益
rOutMin : REAL; // 输出下限
rOutMax : REAL; // 输出上限
bManual : BOOL; // 手动模式
rManualOut : REAL; // 手动输出值
bReset : BOOL; // 复位积分器
rDeadband : REAL := 0.0; // 死区宽度
END_VAR
VAR_OUTPUT
rOutput : REAL; // 控制输出 (CV)
rError : REAL; // 当前偏差
bAtSetpoint : BOOL; // 到达设定值 (偏差在死区内)
bLimited : BOOL; // 输出已限幅
END_VAR
参数详细说明
PID 控制器的核心参数控制闭环响应的三个维度。正确理解每个参数的作用是调参的基础。
| 参数 | 符号 | 范围 | 作用 | 增大效果 | 减小效果 |
|---|---|---|---|---|---|
| 比例增益 | rKp | 0.0 ~ 1e6 | 偏差的即时放大倍数 | 响应加快,可能振荡 | 响应变慢,稳态误差增大 |
| 积分时间 | rTi | 0.0 ~ 1e6 s | 积分作用的衰减时间,越小积分越强 | 误差快速归零,可能超调 | 稳态误差残留 |
| 微分时间 | rTd | 0.0 ~ 1e6 s | 微分作用的超前时间,越大阻尼越强 | 阻尼增强,抗干扰 | 超调增大,响应变慢 |
| 输出下限 | rOutMin | 任意 | 控制输出最小值 | 限制控制范围 | 可能无法达到设定值 |
| 输出上限 | rOutMax | 任意 | 控制输出最大值 | 放宽控制范围 | 可能无法达到设定值 |
| 积分下限 | rIntMin | 任意 | 积分项独立下限 | 防止积分负饱和 | 限制积分补偿能力 |
| 积分上限 | rIntMax | 任意 | 积分项独立上限 | 防止积分正饱和 | 限制积分补偿能力 |
| 死区 | rDeadBand | ≥ 0 | 偏差在此范围内输出不变 | 动作减少,抑制抖动 | 动作频繁 |
| 微分滤波 | rTauD | ≥ 0 | 微分一阶低通滤波时间常数 | 降低噪声敏感度 | 微分响应滞后 |
输出限幅
输出限幅是安全防护的第一道关卡。当计算出的原始输出超出 rOutMin / rOutMax 范围时,输出被裁剪到边界值,同时 bLimited 置位:
// PID 内部计算
rRawOutput := rProportional + rIntegral + rDerivative;
// 输出限幅
IF rRawOutput > rOutMax THEN
rOutput := rOutMax;
bLimited := TRUE;
ELSIF rRawOutput < rOutMin THEN
rOutput := rOutMin;
bLimited := TRUE;
ELSE
rOutput := rRawOutput;
bLimited := FALSE;
END_IF;
抗积分饱和 (Anti-Windup)
PID 功能块内置两种抗积分饱和机制:
- 条件积分: 输出饱和时暂停积分累积
- 回算法: 将超出限幅的部分反馈到积分器中衰减
手动/自动模式切换时,积分器自动跟踪手动输出值,实现无扰切换 (Bumpless Transfer)。
温度控制示例
PROGRAM OB30 // 10ms 周期中断
VAR
fbPID_Temp : FB_PID;
rActTemp : REAL; // 实际温度 (°C)
rSetTemp : REAL; // 设定温度 (°C)
rHeaterPwr : REAL; // 加热功率 (%)
END_VAR
// 读取温度传感器 (PT100, 4-20mA → 0-200°C)
rActTemp := INT_TO_REAL(%IW100 - 4000) / 16000.0 * 200.0;
// 设定值来自 HMI
rSetTemp := %MD200;
// PID 计算
fbPID_Temp(
bEnable := TRUE,
rSetpoint := rSetTemp,
rFeedback := rActTemp,
rKp := 5.0,
rKi := 0.8,
rKd := 1.2,
rOutMin := 0.0,
rOutMax := 100.0,
bManual := %MX100.0,
rManualOut := %MD104
);
// 输出到加热器 (PWM 或模拟量)
rHeaterPwr := fbPID_Temp.rOutput;
%QW200 := REAL_TO_INT(rHeaterPwr * 327.67);
END_PROGRAM
参数整定建议
Ziegler-Nichols 法适用于大多数过程控制场景:
- 将
rKi和rKd设为 0 - 逐步增大
rKp直到系统产生等幅振荡 - 记录临界增益
Ku和振荡周期Tu - 按下表计算参数:
| 控制器类型 | Kp | Ti/Tu | Td/Tu |
|---|---|---|---|
| P | 0.5 × Ku | — | — |
| PI | 0.45 × Ku | 0.85 | — |
| PID | 0.6 × Ku | 0.5 | 0.125 |
Ziegler-Nichols 法给出初始参数,实际应用中需要根据系统响应微调。建议使用 IDE 的趋势曲线面板观察 SP、PV、CV 的实时波形进行调参。
自整定 (Auto-Tuning)
PID 内置三种自整定算法:
| 算法 | 适用场景 | 耗时 | 精度 |
|---|---|---|---|
| 继电式 (Relay) | 通用,经典方法 | 3~10 周期 | 中 |
| 阶跃响应 (Step) | 大惯性系统 (温度) | 2~5 分钟 | 中高 |
| 频率扫描 (Freq) | 高精度要求 | 10~30 分钟 | 高 |
// 启动自整定 (继电式)
fbTune(
bStart := bBtn_StartTune,
rSetpoint := rSetTemp,
rFeedback := rActTemp,
rRelayAmplitude := 10.0,
rHysteresis := 0.5,
iMaxCycles := 5,
tTimeout := T#10m
);
// 完成时自动写入 PID 参数
IF fbTune.bDone THEN
fbPID.rKp := fbTune.rKp;
fbPID.rKi := fbTune.rKi;
fbPID.rKd := fbTune.rKd;
END_IF;
运动控制功能块
Darra 遵循 PLCopen Motion Control 标准,提供完整的单轴和多轴运动控制功能块。
MC_Power — 轴使能
在使用轴之前必须先使能。Enable 为 TRUE 时轴伺服上电。
VAR
PowerOn : MC_Power;
END_VAR
PowerOn(Axis := Axis1, Enable := TRUE, bRegulatorOn := TRUE);
// PowerOn.Status = TRUE 表示使能成功
// PowerOn.bRegulatorOn — 调节器已激活
MC_MoveAbsolute — 绝对定位
移动到指定位置坐标。
VAR
MoveAbs : MC_MoveAbsolute;
END_VAR
MoveAbs(
Axis := Axis1,
Execute := TRUE,
Position := 100.0, // 目标位置 (mm 或度)
Velocity := 50.0, // 运动速度 (mm/s)
Acceleration := 200.0, // 加速度 (mm/s²)
Deceleration := 200.0, // 减速度 (mm/s²)
Jerk := 1000.0 // 跃度 (mm/s³), 0=禁用
);
// MoveAbs.Done — 到达目标位置
MC_MoveRelative — 相对定位
从当前位置移动指定距离。
VAR
MoveRel : MC_MoveRelative;
END_VAR
MoveRel(
Axis := Axis1,
Execute := TRUE,
Distance := 50.0, // 移动距离 (正=正向, 负=反向)
Velocity := 30.0
);
MC_Halt — 暂停运动
中断当前运动,轴减速停止后保持使能状态。
VAR
HaltCmd : MC_Halt;
END_VAR
HaltCmd(Axis := Axis1, Execute := TRUE, Deceleration := 500.0);
// HaltCmd.Done — 轴已停止并保持使能
MC_Home — 回原点
轴回到参考原点位置。
VAR
HomeCmd : MC_Home;
END_VAR
HomeCmd(
Axis := Axis1,
Execute := TRUE,
HomeMode := HOME_REF_SWITCH, // 回零模式
Position := 0.0 // 原点位置值
);
// HomeCmd.Done — 回零完成
回零模式说明:
| 模式 | 说明 |
|---|---|
HOME_REF_SWITCH | 参考开关 + 编码器 Zero |
HOME_LIMIT_POS | 正限位回零 |
HOME_LIMIT_NEG | 负限位回零 |
HOME_DIRECT | 当前位置设为原点 |
HOME_ABS_ENCODER | 绝对编码器直接读取 |
参数表 (通用)
所有 MC 功能块共享以下接口参数:
| 参数 | 类型 | 说明 |
|---|---|---|
| Axis / Robot | 轴/机器人引用 | 目标对象 |
| Execute | BOOL | 上升沿触发 |
| Done | BOOL (输出) | 完成标志 |
| Busy | BOOL (输出) | 正在执行 |
| Active | BOOL (输出) | 已被接收执行 |
| CommandAborted | BOOL (输出) | 被中止 |
| Error | BOOL (输出) | 错误标志 |
| ErrorID | UINT (输出) | 错误码 |
传送带定位完整示例
PROGRAM ConveyorControl
VAR
Power : MC_Power;
Home : MC_Home;
MoveTo : MC_MoveAbsolute;
State : INT := 0;
END_VAR
// 始终使能
Power(Axis := ConveyorAxis, Enable := TRUE);
CASE State OF
0: // 回原点
Home(Axis := ConveyorAxis, Execute := TRUE);
IF Home.Done THEN
Home(Execute := FALSE);
State := 1;
END_IF;
1: // 等待工件到位
IF %IX0.0 = TRUE THEN
State := 2;
END_IF;
2: // 传送到工位 1
MoveTo(Axis := ConveyorAxis, Execute := TRUE,
Position := 500.0, Velocity := 100.0);
IF MoveTo.Done THEN
MoveTo(Execute := FALSE);
State := 3;
END_IF;
3: // 等待加工完成
IF %IX0.1 = TRUE THEN
State := 4;
END_IF;
4: // 传送到出料位
MoveTo(Axis := ConveyorAxis, Execute := TRUE,
Position := 1000.0, Velocity := 100.0);
IF MoveTo.Done THEN
MoveTo(Execute := FALSE);
State := 1;
END_IF;
END_CASE;
END_PROGRAM
MC_GearIn — 电子齿轮
电子齿轮功能块将从轴与主轴按固定齿轮比同步运动,适用于印刷、包装、纺织等需要主轴-从轴同步的场景。
FUNCTION_BLOCK MC_GearIn
VAR_INPUT
bExecute : BOOL; // 上升沿触发啮合
rRatioNumerator : REAL; // 齿轮比分子
rRatioDenominator : REAL; // 齿轮比分母
rMasterOffset : REAL; // 主轴位置偏移
rMasterStartDistance : REAL; // 主轴启动距离 (提前同步准备)
eMasterValue : E_MasterSource; // 主轴来源
bContinuous : BOOL; // 连续啮合 (TRUE=不解耦)
END_VAR
VAR_OUTPUT
bInGear : BOOL; // 已同步啮合
bBusy : BOOL;
bCommandAborted : BOOL;
bError : BOOL;
udiErrorId : UDINT;
rFollowingError : REAL; // 当前跟随误差
END_VAR
主轴来源可配置:
| 主轴来源 | 说明 | 适用场景 |
|---|---|---|
SET_VALUE | 软件设定值作为主轴 | 模拟主轴、虚拟主轴 |
ACTUAL_POSITION | 物理轴实际位置作为主轴 | 跟随另一个物理轴 |
MODULO_POSITION | 模数轴位置 (旋转轴) | 旋转主轴 |
EXTERNAL_ENCODER | 外部编码器作为主轴 | 飞锯、追剪 |
示例:印刷机色标跟踪,主轴(输送带)与印刷辊 1:1 同步:
fbGearIn(
bExecute := TRUE,
rRatioNumerator := 1.0,
rRatioDenominator := 1.0,
rMasterOffset := 0.0,
eMasterValue := E_MasterSource.ACTUAL_POSITION,
bContinuous := TRUE
);
// 检测啮合完成
IF fbGearIn.bInGear THEN
bSynchronized := TRUE;
END_IF;
MC_Phasing — 相位偏移
在齿轮啮合或凸轮同步状态下,对从轴附加一个相位偏移,用于调整套准误差或补偿机械间隙。
FUNCTION_BLOCK MC_Phasing
VAR_INPUT
bExecute : BOOL; // 上升沿触发相位偏移
rVelocity : REAL; // 相位调整速度
rPosition : REAL; // 相位偏移量
eMode : E_PhaseMode; // 偏移模式
END_VAR
VAR_OUTPUT
bDone : BOOL;
bBusy : BOOL;
bCommandAborted : BOOL;
bError : BOOL;
udiErrorId : UDINT;
END_VAR
相位偏移模式:
| 模式 | 说明 | 示例 |
|---|---|---|
RELATIVE | 相对偏移,在当前相位上增减 | 调整 +5° 套准 |
ABSOLUTE | 绝对偏移,设定目标相位值 | 直接设到 90° |
CONTINUOUS | 连续偏移,保持偏移速度 | 持续补偿同步误差 |
典型应用:印刷机套准调整
// 检测到套准偏差后,在齿轮啮合状态下调整相位
IF ABS(rRegistError) > 0.1 THEN
fbPhasing(
bExecute := TRUE,
rVelocity := 5.0,
rPosition := rRegistError * 0.8, // 按比例补偿
eMode := E_PhaseMode.RELATIVE
);
END_IF;
轴状态机
每个轴维护一个内部状态机,MC 功能块自动管理状态转换:
Disabled (未使能)
↓ Power.Enable = TRUE
Standstill (静止就绪)
↓ ↑
Homning (回零中) → Standstill (回零完成)
↓ ↑
DiscreteMotion (单次定位) → Standstill (到达)
↓ ↑
ContinuousMotion (连续运动)
↓ ↑
SynchronizedMotion (同步运动)
↓ ↑
ErrorStop (故障停止) → Standstill (故障复位)
状态可通过 Axis.GetState() 在程序中读取:
CASE Axis1.GetState() OF
E_AxisState.DISABLED: sState := '未使能';
E_AxisState.STANDSTILL: sState := '就绪';
E_AxisState.HOMING: sState := '回零中';
E_AxisState.DISCRETE_MOTION: sState := '定位中';
E_AxisState.CONTINUOUS_MOTION: sState := '连续运动';
E_AxisState.SYNCHRONIZED_MOTION: sState := '同步运动';
E_AxisState.ERROR_STOP: sState := '故障停止';
END_CASE;
安全功能块
Darra 提供 13 个安全功能块,遵循 IEC 61800-5-2 和 IEC 62061 规范,经认证 SIL 2 / PL d。
| 功能块 | 名称 | 功能 |
|---|---|---|
SF_MonitoredStop | 安全监控停止 | 监控减速停止过程 |
SF_SafeStop1 | 安全停止 1 (SS1) | 受控减速后 STO |
SF_SafeStop2 | 安全停止 2 (SS2) | 受控减速后 SOS |
SF_SafeOperatingStop | 安全操作停止 (SOS) | 监控静止状态 |
SF_SafeLimitedSpeed | 安全限速 (SLS) | 速度超限检测 |
SF_SafeLimitedPosition | 安全限位 (SLP) | 位置超限检测 |
SF_SafeTorqueOff | 安全力矩关断 (STO) | 切断电机力矩输出 |
SF_EmergencyStop | 急停 | IEC 13850 紧急停止 |
SF_SafetyDoorMonitor | 安全门监控 | 防护门状态检测 |
SF_BrakeControl | 安全制动控制 | 制动器安全管理 |
完整的接口说明和示例见 安全功能块。
自定义功能块开发
用户可以使用 SCL 语言创建自定义功能块,封装重复使用的控制逻辑。
FB 基本结构
FUNCTION_BLOCK FB_MyControl
TITLE := '自定义控制块'
AUTHOR := '工程师'
VERSION := '1.0'
VAR_INPUT
bEnable : BOOL;
rSetpoint : REAL;
rFeedback : REAL;
END_VAR
VAR_OUTPUT
bReady : BOOL;
rOutput : REAL;
udiStatus : UDINT;
END_VAR
VAR
rIntegral : REAL;
tonDelay : TON;
END_VAR
// 主执行逻辑
IF bEnable THEN
tonDelay(IN := TRUE, PT := T#500ms);
bReady := tonDelay.Q;
// 工艺计算
rIntegral := rIntegral + (rSetpoint - rFeedback) * 0.1;
rOutput := LIMIT(0.0, rIntegral, 100.0);
udiStatus := 0;
ELSE
tonDelay(IN := FALSE);
bReady := FALSE;
rIntegral := 0.0;
rOutput := 0.0;
udiStatus := 1;
END_IF;
END_FUNCTION_BLOCK
方法与属性
功能块可以包含方法(METHOD)和属性(PROPERTY),实现面向对象风格的封装:
FUNCTION_BLOCK FB_RecipeManager
VAR
arRecipes : ARRAY[0..9] OF STRING[32];
iActive : INT;
END_VAR
// 方法:激活配方
METHOD Activate : BOOL
VAR_INPUT
iIndex : INT;
END_VAR
IF iIndex >= 0 AND iIndex <= 9 THEN
iActive := iIndex;
Activate := TRUE;
ELSE
Activate := FALSE;
END_IF;
END_METHOD
// 方法:获取当前配方名
METHOD GetActiveName : STRING[32]
GetActiveName := arRecipes[iActive];
END_METHOD
// 属性:只读当前配方
PROPERTY ReadOnly pActiveName : STRING[32]
GET
pActiveName := arRecipes[iActive];
END_GET
END_PROPERTY
END_FUNCTION_BLOCK
开发规范
- 单一职责: 每个 FB 只做一件事,不要混合 PID 逻辑和通讯逻辑
- 输入参数验证: 在 FB 入口检查输入合法性,非法输入给出明确的诊断码
- 内部状态封装: FB 内部变量对外部不可见,通过属性和方法暴露必要接口
- 初始化路径:
bReset或首次调用时应能回到已知初始状态 - 版本管理: 修改 FB 逻辑后递增 VERSION,便于现场排查
- 错误输出: 所有 FB 都应输出
bError+udiErrorId,不要静默失败 - 诊断属性: 每个 FB 暴露
sDiagMsg : STRING便于在线监视 - 避免深层继承: 继承层级不超过 3 层
三种扩展方式
当内置 FB 无法满足需求时,可以通过三种方式扩展:
| 方式 | 性能 | 安全 | 适用场景 |
|---|---|---|---|
| SCL 源码库 | 中 | 高 | 纯算法、流程控制、逻辑封装 |
| C/C++ DLL | 最高 | 低 | 数学计算、图像处理、实时算法 |
| .NET 程序集 | 中 | 中 | 通讯协议、数据库、复杂协议解析 |
FB 类型与实例化
类型定义
功能块是一种用户定义的数据类型,包含数据和算法。每个功能块实例拥有独立的内部状态副本。
| 要素 | 说明 | 生命周期 |
|---|---|---|
| VAR_INPUT | 调用者传入的参数 | 每个扫描周期更新 |
| VAR_OUTPUT | 返回给调用者的结果 | 每个扫描周期计算 |
| VAR_IN_OUT | 兼作输入和输出的参数 | 引用传递 |
| VAR | 内部状态变量 | 跨扫描周期保持 |
| VAR_STAT | 静态变量 | 跨调用保持 |
| VAR_TEMP | 临时变量 | 单扫描周期内有效 |
| METHOD | 功能块内部方法 | 调用时执行 |
| PROPERTY | 功能块属性 | 调用时计算 |
单实例与多实例
// 单实例
VAR
fbConveyor : FB_ConveyorControl;
END_VAR
// 多实例数组
VAR
fbAxes : ARRAY[0..5] OF FB_AxisControl;
END_VAR
// 多实例 — 命名实例
VAR
fbTempZone1 : FB_PID;
fbTempZone2 : FB_PID;
fbTempZone3 : FB_PID;
END_VAR
实例初始化
功能块实例可以指定初始值:
VAR
fbPID1 : FB_PID := (
rKp := 2.0,
rTi := 1.5,
rTd := 0.3,
rOutMin := 0.0,
rOutMax := 100.0
);
END_VAR
多重背景数据块
实例的数据可以存储在独立的数据块中,便于调试和持久化:
// 背景数据块定义
DATA_BLOCK DB_PID_Background
fbPID_Zone1 : FB_PID;
fbPID_Zone2 : FB_PID;
fbPID_Zone3 : FB_PID;
END_DATA_BLOCK
// 访问
DB_PID_Background.fbPID_Zone1.rKp := 2.5;
功能块调用约定
// 方式一:标准调用(推荐)
fbPID(
bEnable := TRUE,
rSetpoint := rSetTemp,
rFeedback := rActTemp
);
// 方式二:连续赋值(适用于状态机)
fbPID.bEnable := TRUE;
fbPID.rSetpoint := rSetTemp;
fbPID.rFeedback := rActTemp;
fbPID(); // 执行 FB
// 方式三:CAL 关键字
CAL fbPID(bEnable := TRUE, rSetpoint := rSetTemp);
相关文档
- 标准功能块 — 内置标准 FB 库
- 安全功能块 — 安全 FB 详细说明
- PID 控制器 — PID 完整调参指南
- 运动控制 PLCopen — 运动控制 FB 完整规范
- DB 块访问 — 功能块数据存储