在PLC编程中,梯形图(LAD)是工业现场最常用的编程语言之一。当处理模拟量信号(如4–20 mA电流、0–10 V电压)时,常需将PLC采集到的整型原始值(如AIW0寄存器中的16位无符号整数0–65535)转换为工程单位(如温度℃、压力bar、液位m)。这一过程看似简单,但若直接使用整型除法,极易因截断式舍入(truncating division) 导致精度丢失——轻则显示值跳变±0.5℃,重则闭环控制失稳、PID调节振荡。本文直击该问题本质,提供可立即落地的五步排查与四类修正方案,所有操作均基于西门子S7-1200/S7-1500、三菱FX系列、欧姆龙CP系列等主流PLC通用逻辑,无需额外硬件或高级指令。
一、问题定位:为什么整型除法会“悄悄”吃掉精度?
PLC梯形图中,DIV(整数除法)指令对两个整数执行向零取整运算。例如:
1000 ÷ 3 = 333(而非333.333…)65535 ÷ 100 = 655(而非655.35)
该特性在模拟量转换公式中放大为系统性误差。典型转换公式如下:
$$ \text{工程值} = \frac{\text{原始值} - \text{下限原始}}{\text{上限原始} - \text{下限原始}} \times (\text{上限工程} - \text{下限工程}) + \text{下限工程} $$
以某压力变送器为例:
- 输入范围:4–20 mA → PLC AD模块映射为整数
0–65535 - 工程范围:0–16 bar
- 原始下限
= 0,原始上限= 65535,工程下限= 0,工程上限= 1600(单位:0.01 bar,即保留两位小数)
若按常规整型思路编写梯形图:
- 计算分子:
原始值 - 0 = 原始值(无损) - 计算分母:
65535 - 0 = 65535(无损) - 执行整除:
原始值 × 1600 ÷ 65535
问题就出在第三步——× 1600 和 ÷ 65535 的顺序。由于PLC不支持浮点中间结果,若先乘后除,中间值可能溢出(如 65535 × 1600 = 104,856,000 > 32位有符号整数最大值2,147,483,647);若先除后乘,则 原始值 ÷ 65535 恒为 0(当原始值 < 65535),彻底归零。
更隐蔽的是“伪安全”写法:用32位整数(DINT)暂存,再做 DIV。此时虽避免溢出,但 DIV 仍强制截断小数部分。例如原始值 32768(对应理论压力8.00 bar):
- 理论计算:$ \frac{32768}{65535} \times 1600 = 799.996 $ → 应显示
7.99996bar ≈8.00bar - 整型执行:
32768 × 1600 = 52,428,800;52,428,800 ÷ 65535 = 800(精确!) - 但原始值
32767:32767 × 1600 = 52,427,200;52,427,200 ÷ 65535 = 799(理论应为799.992,被截为799→ 显示7.99bar,误差0.008bar)
误差虽小,但在0–100%全程累计后,最大偏差可达 ±0.5 工程单位(取决于量程缩放系数),且呈阶梯状跳变——这正是现场仪表显示“抖动”、趋势图呈锯齿状的根本原因。
二、四类实操修正方案(按推荐优先级排序)
方案1:改用浮点除法(首选,兼容性最佳)
所有主流PLC均支持浮点指令,且S7-1200/1500、FX5U、CP1E等已默认启用浮点运算单元。关键在于显式声明数据类型并调用浮点指令:
- 声明变量为REAL类型:在变量表中,将中间变量(如
RawValue、ScaledValue)的数据类型设为REAL,而非INT或DINT。 - 使用浮点除法指令:
- 西门子:拖入
DIV_R指令(非DIV),输入端IN0接REAL型原始值,IN1接REAL型分母(如65535.0)。 - 三菱:使用
DDIV(双字除法)配合浮点转换,或直接调用FRD(Float Read)→FDIV(Float Divide)→FWR(Float Write)。 - 欧姆龙:用
@DIVF指令(F后缀表示浮点)。
- 西门子:拖入
- 公式重构为单步浮点运算:
ScaledValue := (RawValue - 0.0) / 65535.0 * 1600.0;
(注意:所有常数加.0强制为浮点,避免编译器隐式转为整型)
✅ 优势:精度达IEEE 754单精度(约6–7位有效数字),完全覆盖工业需求;逻辑清晰,易于审计。
⚠️ 注意:确保PLC固件版本支持浮点(S7-1200 V2.0+、FX3U+、CP1E-A等均原生支持);避免在高速扫描周期(<10 ms)内大量浮点运算(影响CPU负载)。
方案2:比例缩放法(零浮点,抗干扰强)
当PLC不支持浮点或需极致确定性时,采用预计算缩放系数+定点移位:
-
计算最优缩放因子:
目标是让RawValue × K的结果在32位整数范围内,且K尽可能接近真实比例1600 / 65535 ≈ 0.02441445。
取K = 1000000(10⁶),则:
$$ \text{ScaledValue} = \left\lfloor \frac{\text{RawValue} \times 1000000}{65535} \right\rfloor \div 1000000 \times 1600 $$
但此式仍有两处整除。优化为:
$$ \text{ScaledValue} = \left\lfloor \frac{\text{RawValue} \times 1600 \times 10000}{65535} \right\rfloor \div 10000 $$
此时分子最大值:65535 × 1600 × 10000 = 1,048,560,000,000→ 超32位,故改用64位(LREAL或DINT组合)。 -
PLC实现(以S7-1200为例):
- 声明
Temp_DWORD为DWORD(32位无符号),Temp_LINT为LINT(64位有符号)。 - 第一步:
MOV原始值AIW0到Temp_DWORD。 - 第二步:
D_INT指令将Temp_DWORD转为LINT存入Temp_LINT。 - 第三步:
MUL_R(64位乘法)Temp_LINT × 1600→ 结果存Result_LINT。 - 第四步:
DIV_R(64位除法)Result_LINT ÷ 65535→ 得Scaled_LINT(单位:0.0001 bar)。 - 第五步:
DIVScaled_LINT ÷ 10000→ 最终INT值(单位:bar,小数点后4位隐含)。
- 声明
✅ 优势:全程整数运算,无浮点误差累积;结果可直接用于HMI整数显示控件。
⚠️ 注意:需确认PLC支持64位算术(S7-1200 V4.2+、FX5U全系支持);手动管理小数点位置,调试时需同步修改HMI解析逻辑。
方案3:查表插值法(超低速场景终极方案)
适用于更新率<1 Hz、精度要求极高(如实验室称重)的场合:
- 预生成转换表:在PC上用Excel或Python计算
RawValue从0到65535对应的全部ScaledValue(REAL型),保存为CSV。 - 导入PLC数据块:将CSV转为PLC数组(如
DB1.DBW[0]到DB1.DBW[131070],每个元素占2字节,共65536×2=131072字节)。 - 梯形图查表:
- 读取索引:
RawValue直接作为数组下标(DB1.ARRAY[RawValue])。 - 线性插值(可选):若
RawValue非整数(如经滤波后为小数),取Floor(RawValue)和Ceil(RawValue)对应值,按比例加权。
- 读取索引:
✅ 优势:绝对精度(查表值可预计算至任意精度);CPU占用趋近于零。
⚠️ 注意:占用大量内存(65536×4字节=256KB REAL数组);仅适用于量程固定、无需动态调整的传感器。
方案4:硬件补偿法(规避软件缺陷)
当PLC老旧无法升级、且现场允许硬件介入时:
- 选用带预处理功能的信号隔离器:如Weidmüller ACT20P、Phoenix Contact MINI MCR-SL,配置其内部DSP直接执行浮点转换,输出标准4–20 mA或0–10 V信号。
- PLC侧简化为线性映射:此时输入信号已是工程值(如0–16 bar对应0–10 V),PLC只需
SCALE指令做一次0–10000 → 0–1600整数缩放(误差<0.01%)。
✅ 优势:彻底卸载PLC计算负担;抗EMI能力强(模拟信号经隔离)。
⚠️ 注意:增加采购与接线成本;需重新校准整个信号链路。
三、避坑指南:5个高频错误操作(附正确写法)
以下行为在工程现场出现率超80%,务必对照自查:
| 错误操作 | 后果 | 正确做法 |
|---|---|---|
在 DIV 指令前未将 INT 转为 DINT,且 原始值 × 系数 > 32767 |
中间结果溢出,数值突变为负数 | 使用 CONV 指令先转 DINT,再 MUL 和 DIV |
公式写成 (RawValue / 65535) * 1600(先除后乘) |
RawValue < 65535 时结果恒为 0 |
必须保证乘法在除法前,或改用浮点 |
使用 ROUND 指令对整除结果四舍五入 |
无法修复根本截断误差,仅掩盖现象 | 删除 ROUND,从源头改用浮点或定点缩放 |
HMI画面绑定 INT 型变量直接显示,未设置小数位 |
显示 8 而非 8.00,掩盖精度问题 |
在HMI变量属性中强制设置“小数位数=2”,或PLC侧输出 REAL |
| 依赖PLC系统时钟做毫秒级定时除法(如每10ms触发一次转换) | CPU扫描周期抖动导致除法时机不稳,引入时序误差 | 将转换逻辑置于主循环OB1,禁用条件触发 |
四、验证方法:三步确认精度达标
-
边界值测试:
- 输入
RawValue = 0→ 输出应为0.00(工程下限) - 输入
RawValue = 65535→ 输出应为16.00(工程上限) - 输入
RawValue = 32768→ 输出应为8.00 ± 0.005(理论中点)
- 输入
-
斜坡测试:
用信号发生器以1单位/秒速度线性增加模拟量,观察HMI趋势图:- ✅ 正常:平滑直线,无阶梯、无跳变
- ❌ 异常:每隔若干点出现
0.01级跳变(整除截断特征)
-
反向验证:
任取一个转换后值(如ScaledValue = 7.99),代入逆公式:
$$ \text{RawValue} = \left\lfloor \frac{7.99 \times 65535}{16.00} \right\rfloor $$
计算得RawValue = 32766,再以此值正向转换,确认结果仍为7.99(闭环一致)。
五、延伸提醒:其他易被忽视的精度陷阱
- AD模块分辨率≠有效位数:标称16位AD(65536级)受噪声、温漂影响,实际有效位常为13–14位。若强行按16位满量程计算,底层数值本身已含±2 LSB误差。
- 冷端补偿干扰热电偶:使用热电偶时,PLC内部冷端补偿温度若未校准,会叠加至转换结果,此时整除误差与补偿误差耦合放大。
- HMI刷新率低于PLC扫描周期:即使PLC计算精准,HMI每500ms才更新一次,人眼看到的仍是离散值——需在HMI侧开启“平滑过渡”或增加本地滤波。
修改梯形图中的一处 DIV 为 DIV_R,或增加一个 CONV 指令,即可消除整型除法带来的系统性精度丢失。

暂无评论,快来抢沙发吧!