ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

EtherCAT断线监测:用ST语言写PLC状态锁存与自动恢复程序

EtherCAT断线监测:用ST语言写PLC状态锁存与自动恢复程序 干过现场调试的人都知道这样一个场景设备跑得好好的突然整条线停了触摸屏上弹出报警——EtherCAT通讯故障。你赶紧打开CODESYS在线监控一眼发现某个从站状态不对或者干脆整条总线都掉下来了。最头疼的不是掉线本身而是你不知道它是从哪一帧开始断的、断了多久、为什么断。所以在这篇文章里我把常用的EtherCAT状态监测方案整理成了一份可以直接落地的ST语言程序包含完整代码和使用思路。这套东西的核心就一句话让PLC在断线发生的第一时间抓住现场证据把故障节点、故障状态、故障时间全部锁存下来该报警报警该恢复恢复。我建议做运动控制、多轴同步、远程IO站点的朋友都把这套逻辑存一份真到现场冒烟的时候它能帮你少走至少半天弯路。1. 先搞懂EtherCAT断线到底是怎么发生的很多人一看到通讯故障就开始改程序、调参数结果折腾一整天发现是水晶头压得不好。要写出靠谱的状态监测程序你首先得理解EtherCAT断线的几种典型场景因为不同原因导致的断线现象完全不一样后续处理逻辑也不一样。1.1 断线现场最常见的3种现象第一种是整体掉线。整条总线上一个从站都访问不到了主站报通讯超时所有从站的状态灯全异常。这种场景下问题通常出在主站网卡、主站侧网线、或者给整条总线供电的电路上。也不排除极端情况比如某个从站的输入端口短路把整个段的总线电平拉崩了造成“一个人感冒全家吃药”的效果。第二种是单个从站掉线。总线上其他站都正常就某站的ALStatus跳到了非OP状态或者干脆在设备树里刷新不出来了。这种一般就是本段网线问题、这个从站的接线端子松了、或者这个从站本身供电出问题。也有遇到过从站硬件损坏的情况但概率相对低毕竟EtherCAT从站控制器芯片本身挺皮实的。第三种最烦人是偶发闪断。设备可能跑几小时、几天才掉一次而且恢复后看起来一切正常日志里啥也查不到。这种大多数和电磁干扰、供电纹波、网线屏蔽层接地不规范有关系也有可能是DC时钟同步漂移导致的看门狗超时。1.2 排查顺序先物理后软件别反着来我自己踩过最大的坑就是一遇到断线就钻进程序里找原因结果浪费了一整天。后来总结出一个比较省时间的排查顺序基本能覆盖八成以上的现场故障排查顺序检查内容常见故障源1网线和水晶头压接不良、屏蔽层未接地、线序错误2从站供电24V跌落、电源容量不足、共地问题3拓扑结构分支不合理、超出单段距离、站间线缆过长4主站网卡与驱动网卡驱动不稳定、实时补丁没打好5周期时间与看门狗任务周期过短、看门狗配置过紧没有使用DC同步、主站和从站时钟不同步6程序逻辑状态字判断错误、输出映射漏配这里想多提一句现场“按下葫芦浮起瓢”的情况很多。你换了一根网线看似好了过了两天又断往往断的是同一个物理根源只是表现位置变了。所以排查时一定把整个链路从主站到末端全部捋一遍别只盯着报警的那个点。2. 状态监测程序的整体设计思路搞清楚断线是怎么发生的下一步才是设计程序。这里有个关键选择要先说清楚为什么状态监测用ST语言写而不是用梯形图。2.1 为什么用ST而不是梯形图梯形图在逻辑控制里好使但它不适合处理数组、循环、状态机这类结构化逻辑。EtherCAT状态监测的典型需求是遍历一到十六个从站的状态字逐个和期望值比较任何一个不对就锁存故障。这在梯形图里要写一大片而且不好维护。换成ST语言一个FOR循环搞定代码量少可读性也高。另外ST语言对功能块封装的支持很好。你可以把整套监测逻辑封装成一个独立的FB输入是启停、从站数量、检测周期、期望状态值输出是通讯正常标志、故障标志、故障节点、故障状态、故障时间。这样不管项目是小型单机还是几十个站点的产线调用方式完全一样换项目只改参数不动核心代码。2.2 状态监测到底要“测”什么EtherCAT的通讯状态不是简单的“通”和“断”它分为几个阶段Init、PreOp、SafeOp、Op还有一些中间状态。标准的状态值定义如下状态值状态名称含义0x01INIT从站刚上电不能进行过程数据通信0x02PREOP邮箱通信正常参数可以读写0x04SAFEOP输入有效输出处于安全状态0x08OP正常运行状态输入输出均有效其他BOOT/错误或其他异常码正常运行中每个从站的ALStatus都应该是0x08。如果通讯断了从站可能回到SAFEOP甚至退回PREOP或INIT。你的状态监测程序要做的就是周期性地把主站状态和所有从站状态都读一遍一旦发现不等于期望值立刻判断故障点。除了ALStatus还建议加上一个辅助判断数据刷新心跳。拿一个实时变化的输入数据比如伺服的实际位置或温度模块的测量值做循环比较如果连续几个周期都没变化即使ALStatus还是OP也要怀疑是不是主站已经收不到新数据了。这种情况在EMC干扰严重的现场遇到过属于ALStatus还没来得及更新、数据已经停了属于“隐形掉线”。2.3 状态监测的“检测周期”怎么选检测周期太短CPU占用高还可能因为读取瞬时抖动导致误报检测周期太长故障发生半天才反应过来失去监测意义。我的经验是20ms到200ms之间比较合适具体看项目对实时性的要求。如果你的系统周期是1ms或2ms建议在独立的“慢任务”里跑这个监测功能块不要在快速任务里做否则会拉高扫描时间反而增加掉线风险。我在一个现场就碰到过把状态监测放到主任务里跑任务周期从2ms涨到了3ms结果触发了从站看门狗反而导致频繁闪断。后来把监测挪到单独的10ms任务里问题就消失了。3. 核心代码实现ST语言状态监测程序这一节我直接给出完整的ST代码。为了让你能看懂每一步在干什么我会先讲变量规划和地址映射再讲功能块主体逻辑最后讲自动恢复和扩展接口。3.1 变量规划与地址映射在CODESYS里EtherCAT从站的ALStatus是可以映射成PLC地址的。操作路径大致是这样设备树 → 选中EtherCAT主站 → 打开从站设备的“诊断信息”把每个从站的ALStatus映射到连续的字节区比如MB100开始然后把主站状态映射到单独的一个字节比如MB50。不同版本菜单名称会有差异但思路一致把诊断对象映射成普通字节变量供ST程序读取。声明一个全局变量表VAR_GLOBAL g_bMasterState AT %MB50 : BYTE; // EtherCAT主站状态 g_abSlaveState AT %MB100 : ARRAY[1..16] OF BYTE; // 从站状态区按拓扑顺序排列 END_VAR映射完成后你在线监控里看到g_abSlaveState[1]的值是8就说明1号从站工作在OP状态一切正常。见到4、2、1之类的值按状态表对照就知道它停在哪个阶段了。3.2 功能块主体逻辑故障捕捉与状态锁存这个功能块是整个方案的核心。它负责周期检测主站状态和所有从站状态捕获故障时刻锁存故障节点并统计故障次数。FUNCTION_BLOCK FB_EcatMonitor VAR_INPUT bEnable : BOOL; // 总使能TRUE开始检测 iSlaveCount : INT : 8; // 实际从站数量 byExpectedState : BYTE : 16#08; // 期望状态默认OP tCheckCycle : TIME : T#200MS; // 检测周期 bAutoRecover : BOOL : FALSE; // 启用自动恢复请求 tRecoverDelay : TIME : T#5S; // 故障持续多久后触发恢复请求 END_VAR VAR_OUTPUT bCommNormal : BOOL; // 通讯正常 bFault : BOOL; // 通讯故障 uiFaultNode : UINT; // 故障节点0主站1~n从站 byFaultState : BYTE; // 故障时的实际状态 tFaultTime : TIME; // 故障发生时刻PLC运行时间 tRecoverTime : TIME; // 故障恢复时刻 udiFaultCounter : UDINT; // 累计故障次数 bRecoverRequest : BOOL; // 自动恢复请求信号 END_VAR VAR bInit : BOOL : TRUE; bFaultActive : BOOL : FALSE; bResultOK : BOOL : TRUE; tNextCheck : TIME; tFaultStart : TIME; i : INT; uiTempNode : UINT; byTempState : BYTE; END_VAR实现部分IF NOT bEnable THEN bCommNormal : TRUE; bFault : FALSE; bRecoverRequest : FALSE; bFaultActive : FALSE; RETURN; END_IF // 上电或使能后初始化 IF bInit THEN bInit : FALSE; bFaultActive : FALSE; tFaultStart : T#0S; tNextCheck : TIME() tCheckCycle; END_IF // 周期检测 IF TIME() tNextCheck THEN RETURN; END_IF tNextCheck : TIME() tCheckCycle; // ---------- 本轮检测 ---------- bResultOK : TRUE; uiTempNode : 0; byTempState : 0; // 1. 检查主站状态 IF g_bMasterState byExpectedState THEN bResultOK : FALSE; uiTempNode : 0; byTempState : g_bMasterState; END_IF // 2. 主站正常时检查各从站状态 IF bResultOK THEN IF iSlaveCount 0 THEN FOR i : 1 TO iSlaveCount DO IF g_abSlaveState[i] byExpectedState THEN bResultOK : FALSE; uiTempNode : INT_TO_UINT(i); byTempState : g_abSlaveState[i]; EXIT; END_IF END_FOR END_IF END_IF // ---------- 结果处理 ---------- IF NOT bResultOK THEN // 新故障发生锁存信息 IF NOT bFaultActive THEN bFaultActive : TRUE; tFaultStart : TIME(); udiFaultCounter : udiFaultCounter 1; uiFaultNode : uiTempNode; byFaultState : byTempState; tFaultTime : tFaultStart; tRecoverTime : T#0S; END_IF bCommNormal : FALSE; bFault : TRUE; // 自动恢复请求 IF bAutoRecover THEN IF (TIME() - tFaultStart) tRecoverDelay THEN bRecoverRequest : TRUE; END_IF END_IF ELSE // 通讯恢复 IF bFaultActive THEN bFaultActive : FALSE; tRecoverTime : TIME(); bRecoverRequest : FALSE; END_IF bCommNormal : TRUE; bFault : FALSE; END_IF这段代码的逻辑链很清晰先查主站主站正常再查从站发现异常后用bFaultActive区分“新故障”和“故障持续中”避免同一个故障反复锁存计数等状态全部恢复正常后再把bFault清除并记录恢复时间。这里有一个细节值得注意tFaultTime锁存的是“故障首次发生的时刻”tRecoverTime记录的是“故障消失的时刻”。这两个时间戳对现场溯源非常有用比如你能看到设备每天凌晨三点断了一次结合交接班记录就能猜出是有人动过设备。3.3 自动恢复逻辑能用但别乱用bAutoRecover这个功能我默认设成FALSE原因是自动恢复有风险。通讯断开的瞬间从站输出可能进入安全状态或保持上一状态如果你自动把总线重新初始化输出会重新刷新设备可能突然动作。在带伺服、气缸这类执行机构的现场自动恢复前必须确认系统处于安全状态。如果确实需要自动恢复典型做法有两种。第一种是程序级恢复把bRecoverRequest接到一个执行重启的功能块或设备树里的“重新启动从站”触发位上让主站把掉线从站重新拉回OP状态。第二种是硬件级恢复把bRecoverRequest接到一个中间继电器驱动故障从站段的24V电源断开1到2秒再恢复强制从站重新上电。硬件级恢复对网口卡死的从站特别有效但动作粗暴必须评估设备安全。无论哪种方式都建议在恢复动作之前确认系统处于安全停车状态比如伺服使能已经被断开或者有机械抱闸保护。3.4 把状态数据送出去HMI和PLC-Recorder程序写完了数据显示在哪里也是要提前想的。状态监测的几个核心变量bFault、uiFaultNode、byFaultState、tFaultTime、tRecoverTime、udiFaultCounter建议都在符号配置里标记成“可访问”这样HMI可以直接绑定上位机也能通过OPC UA或Modbus TCP读取。如果项目里要用PLC-Recorder这类工具做数据追溯那就把上述变量做成可发布的趋势变量按秒或按事件触发记录。掉线前几秒的IO数据、速度指令、伺服实际位置全部记录下来事后复盘会非常轻松。有些项目中还建了数据库表用alongwu第三方库或ODBC接口把故障记录写到MySQL留着后续做设备OEE分析。这块涉及不同第三方库接口差异代码就不展开了思路是状态监测功能块只管采集和锁存数据怎么消费由上层接口决定。4. 实测验证拔掉网线看看程序什么反应代码写完了得实际验证才知道逻辑到底靠不靠谱。我拿一个树莓派4B跑CODESYS Control SL做EtherCAT主站外接两个从站模块来测试这里面的过程基本涵盖了现场会遇到的所有情况。4.1 搭建一个可复现的测试环境主站方面树莓派4B加一张Intel USB千兆网卡就能跑EtherCAT。也有不少人在正点原子RK3568这类ARM板卡上跑CODESYS Control SL用板载或USB网卡做EtherCAT主站原理一样。从站用一个步进驱动器和一个远程IO模块最低配置一个从站也能测试但建议至少两个这样能验证“单个从站掉线”和“整条链路掉线”两种场景。配置要点主站任务周期设为2ms因为后面要测断线后的输出保持行为。开启DC同步从站工作在OP状态确认两个从站的ALStatus都是8。把你写的监视功能块放到一个10ms轮询任务里tCheckCycle设200ms。把g_bMasterState、g_abSlaveState[1]、g_abSlaveState[2]拖到在线监控窗口同时把功能块的输出变量也拖进去。一切都正常时你应该看到主站状态是8两个从站状态都是8bCommNormal为TRUEbFault为FALSE。4.2 实测场景拔线、恢复、再拔主站线第一步拔掉第一个从站到第二个从站之间的网线。预期结果第一个从站的ALStatus立刻从8跳到4或者2第二个从站因为连在第一个从站后面也会掉线。功能块输出bFault变TRUEuiFaultNode等于1byFaultState显示非8状态tFaultTime是当前运行时间udiFaultCounter加1。第二步插回网线。主站会自动重新初始化从站大约一两秒后两个从站重新进入OP状态bFault变FALSEtRecoverTime被刷新bCommNormal变TRUE。第三步拔掉主站网线。这次是主站状态异常g_bMasterState掉出OPuiFaultNode应该等于0表示主站故障。这时候即使从站本身的ALStatus还是8也不能继续运行因为主站已经失去通信能力了。这个逻辑在代码里通过“先查主站再查从站”的顺序保证了优先级。下面是测试中记录到的现象对照表测试场景uiFaultNodebyFaultStatebFaulttFaultTime说明正常运行时08FALSE0无故障拔从站1网线14或2TRUE记录当前时间从站1退到SAFEOP/PREOP插回从站1网线08FALSE锁存保持通讯自动恢复拔主站网线0非8TRUE记录当前时间主站掉出OP主站网线恢复08FALSE锁存保持从站随之恢复OP4.3 测试中最容易踩的几个细节第一个坑是地址映射错位。有人把从站ALStatus映射到了MB100后面但设备树的从站顺序和你程序里ARRAY[1..16]的索引对不上结果明明掉线的是第三个站程序报的是第二个。排查方法是在线监控里手动拨掉每个从站网线验证uiFaultNode指向的到底是不是物理上的那个站一次测完再交付。第二个坑是BYTE和整数比较的隐式转换。CODESYS里16#08按BYTE存储直接比较没问题但如果你把期望状态写成了常量8而不是16#08某些版本可能因为你声明成了BYTE类型导致语法检查不通过。建议统一用16进制写法看着也直观。第三个坑是检测周期与故障事件的竞争。如果你把tCheckCycle设成500ms但掉线只持续300ms程序可能根本检测不到。这时候不是逻辑问题而是采样太慢。要么缩小检测周期要么承认这种毫秒级瞬时闪断只能靠EtherCAT的分布式时钟和从站看门狗去捕捉应用层监测程序抓不到是正常的。5. 常见问题与避坑经验速查代码和验证都过了最后还是要把现场最常见的几个问题整理成清单以后排查的时候按这个表走就行省得东翻西找。5.1 常见问题速查表现象可能原因处理措施整条链路全部掉线主站网卡驱动异常、主站侧网线故障、总线供电异常先查主站网线压接再看网卡驱动最后量24V电源固定某一个从站掉线从站网口损坏、该段网线异常、从站供电不足替换该段网线检查该从站网口单独供电测试掉线后恢复运行一段时间又掉从站供电容量不足、该段屏蔽层未接地给从站增加独立供电检查屏蔽接地修改任务周期后掉线周期过短总线无法完成扫描恢复原周期优化任务划分偶发闪断无法复现电磁干扰、DC时钟同步不稳检查布线、更换屏蔽网线、升级主站实时驱动从站ALStatus是8但数据不更新数据链路阻塞、映射失效用心跳变量辅助判断检查映射和看门狗配置这里想专门强调一下“从站供电不足”这个原因因为它的隐蔽性特别强。表面看从站指示灯都正常ALStatus也是OP但一负载起来比如伺服使能或IO全部输出总线上电压跌落从站控制器就复位了。测量时要看动态电压不是空载电压。挂上示波器或者用带记录功能的万用表看24V在负载切换瞬间的跌落幅度低于19V就需要注意了。5.2 一点我的实操体会状态监测程序这个东西属于“平时看着不起眼出事才知道真香”的典型。我后来接的每个带EtherCAT的项目不管甲方有没有要求都会把这个功能块预埋进去不占多少资源真到调设备的时候能救命。有一次现场设备半夜掉线操作工说没碰任何东西靠监测程序锁存的时间戳和节点号发现掉线时间正好和隔壁产线大功率变频器启动的时间重合顺藤摸瓜解决了困扰两周的干扰问题。最后再分享一个小细节如果你的现场有多个从站建议在状态监测程序里额外加一个“首个故障从站索引”的输出就是第一个报错的从站编号。因为EtherCAT主站重新初始化是很快的有时候操作工按下复位总线恢复故障从站已经回到OP状态了等你跑过去看监控ALStatus全是8啥也查不到。有了锁存功能至少能看到“刚才1号站先掉后面其他站跟着掉”这个先后顺序对判断故障源头非常有帮助。这套程序后续还可以扩展成自动发短信、自动弹HMI页面思路都是一样的先把现场证据抓到手再说。
返回列表