问题:
现在知道的是plc 梯形图是从上到下,从左到右执行的,那么如果是以下这种情况:第一行的运行结果是y0=1,然后第5行运行结果是y0=0,梯形图总共有10行,那么是当运行到第一行完成后就让y0对应的灯泡亮起来,然后等执行完第5行后再把y0对应的灯泡熄灭,还是说将这10行全部执行完后,将最终的结果y0等于0,执行让y0对应的灯泡保持熄灭就行了?
这个问题非常关键,因为它涉及 PLC 最核心的概念之一:扫描周期(Scan Cycle)和 I/O 映像区。
对于描述的典型 PLC 扫描执行方式,答案更接近第二种:
第1行算出 Y0=1,并不意味着物理 Y0 端子上的灯立刻亮;第5行又算出 Y0=0,最终一个扫描周期结束后输出刷新时,物理 Y0 得到最终结果 0,因此灯保持熄灭。
不过这里需要把"程序里的 Y0 状态"和"物理输出端子 Y0"严格区分开。
1. PLC 不是"执行一行就立即控制一次硬件"
可以先建立这个最经典的 PLC 扫描模型:
一个扫描周期 Scan Cycle
┌──────────────────────────────┐
│ ① 输入采样 │
│ │
│ 读取所有物理输入 X │
│ X0、X1、X2...... │
└──────────────┬───────────────┘
↓
┌──────────────────────────────┐
│ ② 执行用户程序 │
│ │
│ 第0行 │
│ ↓ │
│ 第1行 │
│ ↓ │
│ 第2行 │
│ ↓ │
│ ...... │
│ ↓ │
│ 第10行 │
└──────────────┬───────────────┘
↓
┌──────────────────────────────┐
│ ③ 输出刷新 │
│ │
│ 把输出映像区 Y 的最终状态 │
│ 写到物理输出端子 │
└──────────────┬───────────────┘
↓
下一个扫描周期
↓
再次输入采样......
所以 PLC 本质上是在疯狂循环:
读输入
→
执行整个程序
→
刷新输出
→
读输入
→
执行整个程序
→
刷新输出
→
......
可能一个周期只有几毫秒。
2. 就拿你的 10 行程序来模拟
假设:
第1行:
X0 ──────────( Y0 )
此时 X0 = 1
执行到这里以后,PLC 内部的输出映像状态变成:
Y0 = 1
但是:
此时通常还没有把这个结果刷新到物理输出端子。
继续执行。
假设第 5 行:
X1 ──────────( Y0 )
此时 X1 = 0
普通线圈的逻辑是:
条件成立 → Y0 = 1
条件不成立 → Y0 = 0
所以执行第5行以后:
Y0 = 0
继续:
第6行
第7行
第8行
第9行
第10行
假设后面没人再写 Y0。
程序扫描结束:
最终:
Y0 = 0
然后进入:
输出刷新阶段
PLC 才把:
Y0 = 0
写给物理输出。
所以灯:
不会因为第1行短暂得到 Y0=1,就真的闪一下。
最终还是灭的。
3. 但是有一个特别重要的细节
虽然物理输出没有立即变化:
PLC 程序内部,Y0 的状态已经发生变化了。
这句话非常重要。
假设:
第1行:
X0 ─────────────( Y0 )
X0 = 1
执行以后:
内部 Y0 = 1
紧接着第2行:
Y0 ─────────────( M0 )
那么执行第2行的时候,它读到的通常就是:
Y0 = 1
于是:
M0 = 1
即使后面第5行:
X1 ─────────────( Y0 )
X1 = 0
又把:
Y0 = 0
了。
因此同一个扫描周期可能发生:
程序执行顺序:
第1行
Y0 = 1
↓
第2行读取Y0
发现Y0 = 1
→ M0 = 1
↓
......
第5行
Y0 = 0
↓
......
第10行
扫描结束
↓
输出刷新
↓
物理Y0 = 0
所以要同时建立两个概念:
【程序内部】
Y0的状态可以在扫描过程中变化
≠
【物理端子】
通常扫描结束统一刷新
4. 这就是为什么 PLC "从上到下执行"非常重要
比如:
第1行:
X0 ─────────( Y0 )
第2行:
Y0 ─────────( M0 )
和:
第1行:
Y0 ─────────( M0 )
第2行:
X0 ─────────( Y0 )
可能产生不同结果。
因为程序是顺序执行的。
这跟你以前写代码其实一样:
y0 = true;
if (y0)
{
m0 = true;
}
y0 = false;
显然执行 if(y0) 的时候:
y0 == true
虽然这个函数最后:
y0 == false
5. 那么为什么非常不建议一个 Y 被多个普通线圈控制?
你刚才自己构造的例子其实恰好引出了一个 PLC 编程大坑:
第1行 → Y0 = 1
第5行 → Y0 = 0
这叫类似:
双线圈 / 重复线圈(Double Coil)问题。
例如:
第1行:
X0 ─────────( Y0 )
第5行:
X1 ─────────( Y0 )
如果:
X0 = 1
X1 = 0
你可能直觉认为:
X0成立
→ Y0应该ON
但程序实际执行:
第1行:
X0 = 1
→ Y0 = 1
↓
第5行:
X1 = 0
→ Y0 = 0
↓
扫描结束:
Y0最终 = 0
于是:
后面的线圈把前面的结果覆盖掉了。
这就是为什么看别人 PLC 程序的时候,如果发现:
Y0
在多个地方作为普通线圈输出,就要提高警惕。
6. 更好的方式通常是先计算"条件",最后统一输出
例如不要:
自动程序:
条件A ─────────( Y0 )
手动程序:
条件B ─────────( Y0 )
而可以组织成:
自动模式 自动条件
-------------| |-------| |---------+
|
手动模式 手动条件 |
-------------| |-------| |---------+
|
+----( Y0 )
逻辑就是:
Y0 =
(自动模式 AND 自动条件)
OR
(手动模式 AND 手动条件)
这样:
Y0 最终只有一个地方真正输出。
程序更容易理解,也减少覆盖问题。
复杂一点甚至:
自动程序
↓
M100 自动要求气缸伸出
手动程序
↓
M101 手动要求气缸伸出
M100
OR
M101
AND
安全条件
AND
无报警
AND
无急停
↓
Y0
这就开始形成比较好的程序结构了。
7. X 输入也有类似的"映像"概念
这个你也应该顺便理解。
假设 PLC 扫描开始的时候:
读取物理X0
物理X0 = 0
↓
输入映像区 X0 = 0
然后开始执行10行程序。
假设执行到第5行的时候:
现实中的按钮突然被按下了。
物理电压已经变化。
但是经典的周期扫描模型下:
当前扫描周期:
X0仍然 = 0
PLC不会执行到第5行突然重新采样一次 X0。
等:
第10行执行完成
↓
输出刷新
↓
下一个扫描周期
↓
重新输入采样
这时候才:
X0 = 1
所以整个思想是:
现实世界
传感器 ──→【输入采样】
↓
输入映像区 X
↓
┌─────────────┐
│ PLC程序扫描 │
│ │
│ 第1行 │
│ 第2行 │
│ ... │
│ 第10行 │
└──────┬──────┘
↓
输出映像区 Y
↓
【输出刷新】
↓
Y端子
↓
灯/阀/继电器
你现在可以把 PLC 扫描周期记成四句话
第一:
X 通常在扫描开始集中采样,因此这一轮程序看到的是一份相对稳定的输入快照。
第二:
梯形图从上到下、从左到右执行,执行过程中 M、D、Y 等内部状态可以立即被后面的程序看到。
第三:
普通 Y 输出通常先修改输出映像,扫描结束再集中刷新到物理端子。
第四:
同一个 Y 被多处普通线圈写入时,后执行的逻辑可能覆盖前面的结果,所以通常要避免重复线圈。
这四句话掌握以后,你再去理解上升沿、SET/RST、定时器、扫描周期、为什么有些程序顺序不能乱,就会顺很多。
另外严格来说,PLC 还存在立即输入/立即输出、刷新指令、中断程序、运动控制等打破这个简化模型的机制。但现阶段先不要拿这些例外干扰主线,先把上面这个经典扫描模型吃透。