主题
4.5 实战案例集
这里给几个可以直接照抄、改改参数就能用的完整自定义块,覆盖最常用的几类技巧:时间累计、限幅、线性标定、PI 调节、多输出。每个案例都给出引脚定义表和完整 Lua,接口含义见 4.3。
案例 1:运行时间累加器(用 state + scan_ms)
用途:设备使能期间累计运行时间,输出累计小时,用于保养提醒。
| 类型 | key | 显示名 | 默认值 |
|---|---|---|---|
| 输入 | in1 | 使能(1=运行) | — |
| 输出 | out1 | 累计小时 | — |
lua
return function(I)
I.state.secs = I.state.secs or 0 -- 首次初始化为 0
if I.inputs[1] ~= 0 then
I.state.secs = I.state.secs + I.scan_ms / 1000 -- 累加这一周期的秒数
end
return I.state.secs / 3600 -- 换成小时输出
end接线:输入接风机 / 泵的运行状态,输出送一个寄存器(如 D300)。同一块再拖一份接另一台设备,两份累计互不影响。断电重下发才清零。
案例 2:限幅器(多个参数)
用途:把输出夹在下限和上限之间,防止给定越界。
| 类型 | key | 显示名 | 默认值 |
|---|---|---|---|
| 输入 | in1 | 原始值 | — |
| 参数 | lo | 下限 | 0 |
| 参数 | hi | 上限 | 100 |
| 输出 | out1 | 限幅后 | — |
lua
return function(I)
local v = I.inputs[1]
local lo, hi = I.params.lo or 0, I.params.hi or 100
if v < lo then v = lo elseif v > hi then v = hi end
return v
end案例 3:两点线性标定(传感器换算)
用途:把原始读数(如 4~20mA 对应的 0~4000)线性换算成工程量(如 0~100℃),并把结果限制在量程内。参数是两个对应点。
| 类型 | key | 显示名 | 默认值 |
|---|---|---|---|
| 输入 | in1 | 原始读数 | — |
| 参数 | xin | 输入量程下限 | 0 |
| 参数 | xax | 输入量程上限 | 4000 |
| 参数 | yin | 输出下限 | 0 |
| 参数 | yax | 输出上限 | 100 |
| 输出 | out1 | 工程量 | — |
lua
return function(I)
local p = I.params
local span = (p.xax or 4000) - (p.xin or 0)
if span == 0 then return p.yin or 0 end -- 防除零
local t = (I.inputs[1] - (p.xin or 0)) / span
if t < 0 then t = 0 elseif t > 1 then t = 1 end -- 超出量程按端点算
return (p.yin or 0) + t * ((p.yax or 100) - (p.yin or 0))
end案例 4:简易 PI 调节器(state 记积分项)
用途:按「设定值 - 测量值」做比例积分调节,输出带限幅、积分带抗饱和,常用于风阀 / 水阀开度、变频给定。
| 类型 | key | 显示名 | 默认值 |
|---|---|---|---|
| 输入 | in1 | 设定值 SP | — |
| 输入 | in2 | 测量值 PV | — |
| 参数 | kp | 比例系数 | 1 |
| 参数 | ki | 积分系数 | 0.1 |
| 参数 | olo | 输出下限 | 0 |
| 参数 | ohi | 输出上限 | 100 |
| 输出 | out1 | 调节输出 | — |
lua
return function(I)
local p = I.params
local dt = I.scan_ms / 1000
local err = I.inputs[1] - I.inputs[2] -- SP - PV
I.state.integral = I.state.integral or 0
I.state.integral = I.state.integral + err * (p.ki or 0.1) * dt
-- 积分抗饱和:把积分项也夹在输出量程内
local lo, hi = p.olo or 0, p.ohi or 100
if I.state.integral < lo then I.state.integral = lo
elseif I.state.integral > hi then I.state.integral = hi end
local out = (p.kp or 1) * err + I.state.integral
if out < lo then out = lo elseif out > hi then out = hi end
return out
end要点:积分项存在 I.state.integral,每个扫描周期累加,因此是连续调节而不是每拍从头算;想做无扰动,可再加一个输入做复位(复位时把 I.state.integral = 0)。
案例 5:一台块出两个结果(多返回值)
用途:两台设备运行状态输入,同时输出「运行台数」和「是否全部运行」,演示一个块带两个输出。
| 类型 | key | 显示名 |
|---|---|---|
| 输入 | in1 | 1#运行(1/0) |
| 输入 | in2 | 2#运行(1/0) |
| 输出 | out1 | 运行台数 |
| 输出 | out2 | 全部运行(1/0) |
lua
return function(I)
local n = (I.inputs[1] ~= 0 and 1 or 0)
+ (I.inputs[2] ~= 0 and 1 or 0)
return n, (n == 2 and 1 or 0) -- 第1个输出=台数,第2个输出=全部运行标志
end照抄步骤
按表格在制作器里加好引脚和参数(key 必须和代码里一致)→ 贴入 Lua → 保存 → 拖到主循环接线。跑不通时先看 4.6 常见问题。