三亩地 三亩地SAN MU DI · CODE DIARY
ARTICLE DETAIL

日记详情

真实记录编程学习的某一天,欢迎挑你感兴趣的翻一翻。

西门子S7-1200 PLC交通灯控制系统实战:从状态机设计到多模式实现

西门子S7-1200 PLC交通灯控制系统实战:从状态机设计到多模式实现

1. 项目缘起:从“灯亮灯灭”到“车流交响曲”

做工业自动化这行久了,PLC(可编程逻辑控制器)的项目接触过不少,从简单的电机启停到复杂的生产线联动,都离不开它。但最近有个朋友,一个刚入行的电气工程师,跑来问我:“哥,我想用PLC做个交通灯控制系统练手,感觉网上资料要么太简单(就红黄绿三灯循环),要么太复杂(直接上大型路口仿真),有没有那种能让我真正理解PLC在时序控制和逻辑处理上精髓的实战项目?”

他这一问,倒是把我问住了。确实,很多初学者把交通灯系统当作PLC的“Hello World”,但往往只停留在“定时器+计数器”的层面,做完后对实际工程中面临的“车流感知”、“紧急优先”、“夜间模式”等复杂需求依然一头雾水。这个项目看似基础,实则是一个绝佳的、浓缩了工业控制核心思想的微型沙盘。它考验的不仅仅是梯形图或结构化文本的编写能力,更是对系统需求分析、状态机设计、抗干扰处理以及人机交互(HMI)设计的综合理解。

所以,我决定以西门子S7-1200系列PLC为例,抛开那些过于简化的模型,设计一个更贴近真实路口需求的、具备多工作模式的交通信号灯控制系统。这个系统不仅要实现基本的定时循环,还要能模拟感应控制、响应紧急车辆(如消防车、救护车)的优先通行请求,并具备手动调试和夜间黄闪模式。通过这个项目,我希望不仅能复现一个可运行的硬件系统,更能梳理出一套从需求到实现、从编程到调试的完整方法论,让无论是学生还是初级工程师,都能获得超越“点灯”的实战收获。

2. 系统需求分析与整体架构设计

在动手画梯形图之前,花时间把需求理清楚,是避免后期反复修改、代码混乱的关键。一个真实的十字路口交通灯系统,其需求远比我们想象中复杂。

2.1 核心功能需求拆解

首先,我们需要明确这个系统需要干什么。我将其分解为以下几个核心模式:

  1. 常规定时模式:这是基础。一个标准的十字路口分为东西、南北两个方向。每个方向有红、黄、绿三色灯。其循环周期通常为:绿灯亮 -> 黄灯亮 -> 红灯亮。两个方向的信号必须互锁,即一个方向绿灯时,另一个方向必须是红灯。这里的关键是确定各阶段的持续时间,例如:东西绿灯30秒,黄灯3秒,红灯45秒(因为南北绿灯+黄灯共33秒,加上全红缓冲时间2秒,东西红灯总时长=33+2+10?这里需要精确计算)。我们需要建立一个清晰的时间相位图。

  2. 感应控制模式:在车流量较小的时段或方向,让绿灯时间根据车辆的有无进行动态调整。这需要引入传感器(如地感线圈或雷达)。例如,东西方向为主干道,设置基础绿灯时间20秒;若在20秒内检测到南北方向有车辆等待,则在东西绿灯结束后立即切换;若南北方向无车,则东西绿灯可延长至最大30秒。这涉及到定时器与中断的结合使用。

  3. 紧急优先模式:当消防车、救护车等特殊车辆通过时,需要给予其通行方向的绝对绿灯权。这通常通过无线射频识别(RFID)或手动远程按钮触发。一旦触发,系统需在安全的前提下(例如,当前绿灯方向先转黄、再转红),快速将请求方向切换为绿灯,并保持一段时间。

  4. 夜间黄闪模式:在深夜低流量时段,所有信号灯切换为黄灯闪烁,提醒司机注意减速通过。这是一个独立的状态。

  5. 手动调试模式:便于维护人员对单个方向的信号灯进行手动开关控制,用于安装调试或应急处理。

2.2 硬件选型与接线规划

基于以上需求,我们进行硬件选型:

  • PLC:西门子S7-1214C DC/DC/DC。这款PLC数字量I/O点足够(14输入/10输出),支持以太网通信便于后续连接HMI和上位机,性价比较高。
  • 信号灯:采用24V DC LED交通信号灯模块,功耗低、寿命长。每个方向需要红、黄、绿各一盏,共两个方向,计6盏灯。但考虑到实际路口每个方向可能有多个灯组(如左转箭头灯),为简化,本项目先按每组三灯设计。
  • 传感器:用于感应模式,选用24V DC常开(NO)型接近开关模拟地感线圈。每个车道入口处安装一个,东西、南北方向各一个,计2个输入点。
  • 控制按钮:用于模式切换和紧急触发。我们需要:
    • 模式选择旋钮(4位):手动、定时、感应、夜间。
    • 紧急通行按钮(2个):东西优先、南北优先。
    • 手动调试按钮(4个):东西绿/红、南北绿/红(点动)。
  • 电源:24V DC开关电源,为PLC、信号灯、传感器供电。

I/O点分配表是硬件设计的蓝图,务必清晰:

类型地址设备/功能备注
输入(I)I0.0东西方向车辆传感器常开,有车时闭合
I0.1南北方向车辆传感器常开,有车时闭合
I0.2模式选择-手动档旋钮
I0.3模式选择-定时档旋钮
I0.4模式选择-感应档旋钮
I0.5模式选择-夜间档旋钮
I0.6紧急通行-东西优先自复位按钮
I0.7紧急通行-南北优先自复位按钮
I1.0手动-东西绿灯自复位按钮
I1.1手动-东西红灯自复位按钮
I1.2手动-南北绿灯自复位按钮
I1.3手动-南北红灯自复位按钮
输出(Q)Q0.0东西方向-红灯驱动继电器或直接接灯
Q0.1东西方向-黄灯
Q0.2东西方向-绿灯
Q0.3南北方向-红灯
Q0.4南北方向-黄灯
Q0.5南北方向-绿灯
Q0.6系统运行指示灯可选,指示PLC运行

注意:实际接线时,务必在PLC输出端和信号灯之间加入中间继电器进行隔离,尤其是当灯功率较大时。继电器的线圈接PLC输出点,触点接信号灯电源。这能有效保护PLC的输出晶体管免受浪涌电流冲击。

2.3 软件架构:状态机(State Machine)设计

这是本项目的灵魂。用简单的互锁和定时器堆砌,代码会很快变得难以维护。采用状态机设计,逻辑会异常清晰。我们将整个系统视为一个在不同模式间切换的顶层状态机,而每个模式(尤其是定时/感应模式)内部又是一个独立的状态机。

常规定时模式为例,我们可以定义以下几个状态(State):

  • S0:东西绿灯,南北红灯。
  • S1:东西黄灯,南北红灯。
  • S2:全红缓冲(东西红灯,南北红灯)。这个状态很重要,用于清空路口,避免抢行。
  • S3:东西红灯,南北绿灯。
  • S4:东西红灯,南北黄灯。
  • S5:全红缓冲(东西红灯,南北红灯)。

状态之间的转换条件(Transition)就是时间。例如,S0状态下,一个30秒的定时器(T1)开始计时。30秒到,则条件满足,状态从S0跳转到S1。在S1状态,一个3秒定时器(T2)启动,时间到则跳转到S2,以此类推。

在PLC编程中,我们可以用整数变量(如Mode_State)来存储当前状态值(0,1,2,3,4,5),然后在一个主循环或函数块(FB)里,用一个大的CASE语句(在梯形图中可以用多个分支实现)来执行每个状态下的动作(点亮哪些灯,启动哪个定时器),并判断转换条件。

这种结构的最大优点是:增删状态或修改转换条件非常方便,所有逻辑一目了然,调试时只需关注当前状态变量值即可。

3. TIA Portal 编程实现与核心逻辑剖析

我们使用西门子TIA Portal V17进行编程。在项目中,结构化编程和用好函数块(FB)、函数(FC)是关键。

3.1 数据块(DB)规划:变量的“家”

首先创建全局数据块(如DB_Global),用于存放所有关键变量,避免使用分散的M区地址,便于管理。

// 在全局数据块中定义 TYPE “TrafficLight_Data” : STRUCT // 模式与状态 CurrentMode : INT; // 当前模式:0-手动,1-定时,2-感应,3-夜间 CurrentState : INT; // 当前状态(用于定时/感应模式的状态机) PrevState : INT; // 上一个状态,用于某些逻辑判断 // 定时器 T_Green_EW : TIME := T#30S; // 东西绿灯时间 T_Yellow_EW : TIME := T#3S; // 东西黄灯时间 T_Green_NS : TIME := T#25S; // 南北绿灯时间 T_Yellow_NS : TIME := T#3S; // 南北黄灯时间 T_AllRed : TIME := T#2S; // 全红缓冲时间 // 感应模式参数 Sensor_EW : BOOL; // 东西传感器状态(映射自I0.0) Sensor_NS : BOOL; // 南北传感器状态(映射自I0.1) Extend_Time : TIME := T#10S; // 感应模式下最大延长绿灯时间 T_Green_Min : TIME := T#15S; // 感应模式下最小绿灯时间 // 输出映像 Lamp_EW_Red : BOOL; Lamp_EW_Yellow : BOOL; Lamp_EW_Green : BOOL; Lamp_NS_Red : BOOL; Lamp_NS_Yellow : BOOL; Lamp_NS_Green : BOOL; // 紧急标志 Emergency_EW : BOOL; // 东西优先请求 Emergency_NS : BOOL; // 南北优先请求 Emergency_Active : BOOL; // 紧急模式激活标志 Emergency_Timer : TIME := T#20S; // 紧急绿灯保持时间 END_STRUCT END_TYPE VAR_GLOBAL TrafficData : “TrafficLight_Data”; END_VAR

3.2 主程序(OB1)组织块:调度中心

主程序不宜编写复杂逻辑,应作为调度中心,调用各个功能块。

// OB1 主循环组织块 BEGIN // 1. 读取输入映像,更新数据块 #TrafficData.Sensor_EW := “DI_EW_Sensor”; // I0.0 #TrafficData.Sensor_NS := “DI_NS_Sensor”; // I0.1 #TrafficData.Emergency_EW := “DI_Emer_EW”; // I0.6 #TrafficData.Emergency_NS := “DI_Emer_NS”; // I0.7 // 2. 模式选择逻辑 IF “DI_Mode_Manual” THEN // I0.2 #TrafficData.CurrentMode := 0; ELSIF “DI_Mode_Timing” THEN // I0.3 #TrafficData.CurrentMode := 1; ELSIF “DI_Mode_Inductive” THEN // I0.4 #TrafficData.CurrentMode := 2; ELSIF “DI_Mode_Night” THEN // I0.5 #TrafficData.CurrentMode := 3; END_IF; // 3. 根据模式调用对应的功能块 CASE #TrafficData.CurrentMode OF 0: // 手动模式 FC_Manual_Control(); // 调用手动控制函数 1: // 定时模式 FB_Timing_Mode(DB_Timing); // 调用定时模式函数块实例 2: // 感应模式 FB_Inductive_Mode(DB_Inductive); 3: // 夜间模式 FC_Night_Mode(); END_CASE; // 4. 紧急模式处理(最高优先级,可中断其他模式) IF #TrafficData.Emergency_EW OR #TrafficData.Emergency_NS THEN FB_Emergency_Mode(DB_Emergency); END_IF; // 5. 将数据块中的灯控信号写入输出映像 “DO_EW_Red” := #TrafficData.Lamp_EW_Red; // Q0.0 “DO_EW_Yellow” := #TrafficData.Lamp_EW_Yellow; // Q0.1 // ... 其他输出赋值 END.

3.3 核心功能块详解:以定时模式为例

我们创建一个函数块FB_Timing_Mode,它内部维护着自己的状态机。

// FB_Timing_Mode VAR_INPUT Enable : BOOL; END_VAR VAR_IN_OUT StateData : INT; // 连接至 #TrafficData.CurrentState END_VAR VAR T_StateTimer : TON; // 状态保持定时器 StateTimer_Done : BOOL; END_VAR BEGIN IF Enable THEN CASE StateData OF 0: // S0: 东西绿,南北红 #TrafficData.Lamp_EW_Green := TRUE; #TrafficData.Lamp_NS_Red := TRUE; // 其他灯为FALSE T_StateTimer(IN:=TRUE, PT:=#TrafficData.T_Green_EW); IF T_StateTimer.Q THEN StateData := 1; // 切换到S1 T_StateTimer(IN:=FALSE); // 复位定时器 END_IF; 1: // S1: 东西黄,南北红 #TrafficData.Lamp_EW_Yellow := TRUE; #TrafficData.Lamp_NS_Red := TRUE; T_StateTimer(IN:=TRUE, PT:=#TrafficData.T_Yellow_EW); IF T_StateTimer.Q THEN StateData := 2; T_StateTimer(IN:=FALSE); END_IF; 2: // S2: 全红缓冲 #TrafficData.Lamp_EW_Red := TRUE; #TrafficData.Lamp_NS_Red := TRUE; T_StateTimer(IN:=TRUE, PT:=#TrafficData.T_AllRed); IF T_StateTimer.Q THEN StateData := 3; T_StateTimer(IN:=FALSE); END_IF; // ... 状态3,4,5 类似定义,最终状态5完成后跳回状态0 5: // ... 全红缓冲 IF T_StateTimer.Q THEN StateData := 0; // 完成一个完整周期,回到S0 T_StateTimer(IN:=FALSE); END_IF; END_CASE; ELSE // 模式未启用,复位所有输出和状态(可选) StateData := 0; T_StateTimer(IN:=FALSE); END_IF; END_FUNCTION_BLOCK

关键点:每个状态里,先置位输出,再启动定时器,最后判断转换条件。这是状态机编程的标准范式。

3.4 感应模式的关键:动态定时与中断

感应模式FB_Inductive_Mode的结构与定时模式类似,但状态S0和S3(绿灯状态)的定时逻辑不同。它不是固定时间,而是基于传感器。

以东西绿灯状态(S0)为例:

  • 启动一个最小绿灯定时器T_Min(15秒)。
  • T_Min计时期间,无论南北有无来车,都必须保持东西绿灯。
  • T_Min计时结束后,开始检测南北传感器#TrafficData.Sensor_NS
    • 如果南北有车,则启动一个短延时(如3秒,让已过线的车辆通过)后,切换状态。
    • 如果南北无车,则启动一个延长定时器T_Extend(每次检测到无车可重置,但总延长不超过Extend_Time设定的10秒)。直到某次检测到南北有车,或达到最大延长时间,才切换状态。

这需要在状态内使用更复杂的判断逻辑和嵌套定时器。这里最容易出错的地方是定时器的重置逻辑,一定要确保状态切换时,所有该状态的定时器都被正确复位,否则残留的定时器Q点会导致逻辑混乱。

3.5 紧急模式的“插队”逻辑

紧急模式FB_Emergency_Mode必须能打断当前任何模式。其逻辑是:

  1. 收到请求(如东西优先)后,立即置位Emergency_Active标志。
  2. 中断当前模式的状态机运行(可以在主程序中通过条件判断跳过其他模式的调用)。
  3. 执行一个安全的过渡序列:首先强制当前绿灯方向转为黄灯,短暂全红后,立即将请求方向(东西)切换为绿灯,并保持Emergency_Timer(20秒)时间。
  4. 期间,忽略其他所有传感器和模式切换请求。
  5. 时间到后,清除Emergency_Active标志,系统自动恢复到被中断前的模式和状态(这里需要保存中断前的CurrentModeCurrentState),继续运行。

这个“保存现场-中断执行-恢复现场”的过程,是处理高优先级任务的核心思想。

4. 人机界面(HMI)设计与系统调试

一个没有监控的系统是不完整的。我们用TIA Portal内置的WinCC RT Advanced来设计一个简单的触摸屏界面,用于监控和操作。

4.1 HMI画面布局与功能

  1. 主监控画面

    • 动态图形:绘制十字路口示意图,东西南北方向用矩形表示红黄绿灯。将矩形的“背景色”或“填充”属性,与PLC数据块中的Lamp_xx_Red/Green/Yellow变量绑定。当变量为True时,显示红色/绿色/黄色,False时显示灰色。这样就能实时看到灯的变化。
    • 状态显示:用文本域显示当前模式(“定时模式”)、当前状态(“东西绿灯”)、各定时器剩余时间等。
    • 数据可视化:用柱状图或进度条显示绿灯剩余时间,更直观。
  2. 参数设置画面

    • 放置数值输入框,与数据块中的T_Green_EW,T_Yellow_EW等时间变量绑定。设置输入限制(如10-100秒)。
    • 这里有个重要技巧:对于TIME类型的变量,在HMI上输入时,通常以毫秒为单位。可以在PLC端做一个转换函数,或者在HMI上使用“字符串输入+转换”的方式,让用户直接输入“30s”,然后在HMI脚本或PLC中将其转换为T#30S
  3. 模式操作画面

    • 放置与物理旋钮对应的模式选择按钮(带反馈)。
    • 放置紧急通行按钮。
    • 放置手动模式下的点动按钮。

4.2 系统调试与故障排查实录

硬件接线和程序下载后,真正的挑战才开始。以下是我在调试中遇到的几个典型问题及解决方法:

问题一:信号灯闪烁或亮度异常。

  • 现象:灯该亮的时候微亮或闪烁,不该亮的时候有微光。
  • 排查:首先用万用表测量PLC输出点(如Q0.0)在触发时的电压。如果电压正常(接近24V),问题在负载侧。检查继电器触点是否接触良好,信号灯电源接线是否牢固。如果电压被拉低(如只有十几伏),说明负载电流可能过大,超过了PLC输出点的带载能力(通常为0.5A)。必须加中间继电器!如果加了继电器还不行,检查继电器线圈两端是否有续流二极管,感性负载(继电器线圈)断开时会产生高压反电动势,可能损坏PLC输出或导致干扰。
  • 教训:永远不要直接用PLC输出点驱动超过其额定电流的负载,继电器隔离是必须的。

问题二:感应模式下车已离开,但绿灯依然延长。

  • 现象:南北方向来一辆车,触发传感器,东西绿灯延长。但车走后,东西绿灯还在延长,直到最大时间。
  • 排查:检查传感器信号。在HMI上监控Sensor_NS变量。发现车离开后,变量有时不会立即从True变为False,而是有短暂延迟或抖动。这是因为传感器存在一定的检测滞回和响应时间。
  • 解决:在PLC程序中对传感器信号进行软件去抖。创建一个定时器,当传感器从False变True时启动一个100ms的定时,定时到才认为信号有效;从True变False时同理。这样可以滤除短时间的干扰脉冲。
    // 去抖函数示例 (FC_Debounce) IF Sensor_Raw AND NOT DebounceTimer.Q THEN DebounceTimer(IN:=TRUE, PT:=T#100MS); END_IF; IF DebounceTimer.Q THEN Sensor_Filtered := Sensor_Raw; END_IF; // 同理处理下降沿

问题三:模式切换时,信号灯出现短时混乱。

  • 现象:从定时模式切换到手动模式时,所有灯瞬间全灭或全亮一下,再恢复正常。
  • 排查:这是因为模式切换的瞬间,控制权交接。定时模式FB可能还在某个状态中输出,而手动模式FC立即输出了新的值,两者产生冲突。
  • 解决:在模式切换逻辑中加入“过渡区”或“复位区”。在离开一个模式前,先执行该模式FB的Enable输入置False,让FB内部复位其状态和输出。然后,再延时一个PLC扫描周期(可以用一个TON定时器实现1个周期的延时),再激活新模式的FB。确保同一时刻只有一个模式控制输出变量。

问题四:紧急模式后无法恢复原状态。

  • 现象:触发紧急通行后,绿灯保持20秒后,系统没有回到之前的定时模式,而是停住了。
  • 排查:检查“恢复现场”的逻辑。发现用于保存中断前状态的变量(如Saved_Mode,Saved_State)在紧急模式激活时被正确保存了,但在紧急模式退出后,主程序只是简单地将CurrentMode设为了Saved_Mode,却没有同时将CurrentState设为Saved_State,导致定时模式FB从状态0开始运行,而非之前中断的状态。
  • 解决:恢复现场必须是成对的。在退出紧急模式的逻辑中,需要同时恢复模式和状态变量,并且要确保恢复后,对应模式的FB能正确识别这个状态并继续执行。有时甚至需要将中断时各定时器的剩余时间也保存下来,以实现无缝衔接,但这要求更高。对于交通灯这种循环系统,恢复到状态0重新开始通常也可接受,但体验上会有一次“跳变”。

5. 从原型到优化:工程思维的进阶

完成基本功能后,我们可以思考如何让这个系统更健壮、更智能,这体现了从“功能实现”到“工程应用”的跨越。

5.1 增加故障诊断与安全逻辑

  1. 灯故障检测:可以在每个信号灯回路中串联一个电流检测模块或使用带反馈的继电器,将状态读回PLC。如果PLC发出了“亮灯”指令(Q点输出),但检测回路没有电流(反馈点为False),则判断该灯故障,在HMI上报警,并可以自动切换到安全模式(如所有方向黄闪)。
  2. 冲突检测:这是最重要的安全逻辑。必须确保任何情况下,东西和南北方向的绿灯绝对不能同时亮起。除了在程序逻辑中严格互锁外,可以在输出端增加硬件互锁(如通过继电器触点构成互锁电路),实现“软硬双重保险”。在程序中,可以编写一个常时运行的检查函数,实时监测Lamp_EW_GreenLamp_NS_Green,如果两者同时为True,立即强制所有输出为False,进入黄闪故障状态并报警。
  3. 看门狗(Watchdog):确保PLC程序正常运行。TIA Portal中可以在循环中断组织块(如OB30)中定期置位一个“心跳”变量。在主程序或一个专用的监控FB中,检查这个“心跳”是否按时到来。如果超过预定时间(如2秒)没有更新,则认为程序跑飞或死循环,触发系统复位或进入安全状态。

5.2 通讯与上位机管理

单个路口系统是孤立的。真实的交通管理系统是网络化的。

  1. PLC之间通讯:如果是协调控制的多个路口(干线绿波带),相邻路口的PLC需要通过工业以太网(Profinet)或串口进行通讯,同步时钟和相位差。可以使用S7-1200的TSEND_C/TRCV_C指令块进行TCP通讯,或配置PUT/GET指令进行S7通讯,交换各自的状态、定时参数。
  2. 与上位机软件通讯:可以通过OPC UA(S7-1200 V4.2以上固件支持)将PLC数据(车流量、状态、故障信息)上传到上位机监控中心(如WinCC、组态王等)。上位机可以下发调度指令(修改配时方案、强制模式切换)。这为区域自适应交通控制打下了基础。

5.3 模拟仿真与离线测试

在实物调试前,利用TIA Portal的PLC仿真功能(S7-PLCSIM Advanced)和HMI仿真功能,可以进行充分的离线测试。

  • 仿真PLC:创建仿真实例,下载程序。可以在仿真界面中强制修改输入点(I点)的状态,模拟按钮按下、传感器触发。同时监控程序变量,观察状态机跳转、定时器工作是否正常。
  • 仿真HMI:与仿真PLC连接,在电脑上运行HMI仿真画面。你可以像操作真实触摸屏一样点击按钮,观察画面中信号灯的变化是否与PLC逻辑一致。这能极大提高调试效率,提前发现人机交互逻辑的问题。

这个交通灯PLC项目,从简单的红绿灯交替,到融入状态机、多模式、优先级、故障诊断和网络通讯,几乎涵盖了小型工业控制项目的所有核心要素。它像一把钥匙,帮你打开PLC系统化设计的大门。当你再面对更复杂的生产线或设备控制时,你会发现,其内核无非是更庞大的状态机、更复杂的互锁关系和更严格的时序要求。把这个小项目吃透,其方法论的价值,远大于项目本身。

← 返回列表