2026/10/29 4:53:02

PLC定时器TONR累计时间偏差原因与S7-200 SMART解决方案

PLC定时器TONR累计时间偏差原因与S7-200 SMART解决方案 1. 先把TONR这个累加器的脾气摸清干自动化这行十来年PLC定时器可以说是天天见但真要说清楚TONR为什么累计时间老是对不上很多人第一反应还是程序逻辑没问题啊。我印象特别深的一次是给某设备做运行时长统计程序写得很简单就是TONR累计继电器吸合时间结果现场跑了半天数据和秒表差了将近两成操作工说设备一天到底跑了多久全凭感觉。问题最后查出来不是逻辑写错而是扫描周期与时基的关系没搞明白——TONR的累计值并不是物理时间的忠实记录员它只是按自己的刷新节奏在数数你的程序节奏跟它对不上数出来的当然不准。这篇文章就围绕PLC定时器里最容易翻车的TONR展开重点讲累计时间出错的几类真实原因并给出S7-200 SMART上可以直接照抄的解决方案。适合刚上手PLC编程、正在做设备运行时长统计、故障计时、累计产量节拍这类功能的朋友也适合已经写了两三年程序但一直没细究过定时器刷新机制的老手——后面几个坑我见过不少干了很久的人照样踩。1.1 TON、TONR、TOF三兄弟差的不只是一个字母先把三个最常用的接通延时类指令摆在一起看很多累计错误其实源于用错了指令。指令使能条件断开后的行为复位方式典型用途TON当前值立即清零位复位自动普通延时启动、延时报警TONR当前值保持不变继续记着必须用复位指令或复位线圈累计运行时间、累计故障时长TOF使能接通时清零断开后开始延时自动延时停止、风机后吹TONR最关键的特性就是那行保持不变。它的设计意图很明确让你把多次、断续的接通时间攒起来。比如一台设备一天里启停几十次你想知道它总共跑了多久就得靠TONR。但问题也恰恰出在这里。因为TONR不会自动清零程序里就必须有一个明确的复位动作而这个复位动作放在哪、用什么条件触发直接决定了累计值准不准。我见过最常见的写法是把TONR自己的常开触点串回去做复位看起来到点清零重新开始很合理实际上是个隐藏的坑后面第2章会展开说。另外还有一点必须提前说清楚TONR的当前值是16位有符号整数最大32767。这个上限对累计类应用来说非常要命具体影响在第2.5节细讲。1.2 时基选错精度和量程一起丢S7-200 SMART的定时器按时基分成三档编号是固定分配的不是你想用哪个就用哪个。时基TONR可用编号TON/TOF可用编号单只定时器最大计时1msT0、T1T32、T9632.767秒10msT2T17T33T36、T97T100327.67秒100msT18T31T37T63、T101T2553276.7秒约54.6分钟这张表建议直接打印贴在工位上。我见过有人拿T0做设备运行时长累计跑了三四十秒数值就卡在32767不动了还以为是程序被干扰查了一下午。1ms时基的TONR量程只有32秒出头拿它做时长统计等于用一把30厘米的尺子量操场。时基选择的核心逻辑是精度要求和量程要求是一对矛盾。你要毫秒级精度量程必然短你要几小时的累计只能牺牲精度。实际项目里我的习惯是累计类应用优先用100ms时基除非工艺明确要求误差小于100ms。还有个小细节不同固件版本的编号分配可能略有出入写程序前在编程软件的指令树里点一下定时器编号提示会直接告诉你哪段是1ms、哪段是100ms比你翻手册快。1.3 设定值PT不是秒是时基的个数这是新手最容易懵的地方。S7-200 SMART里TONR的PT引脚填的是整数单位不是秒也不是毫秒而是多少个时基。换算公式很朴素实际延时 PT × 时基举几个例子对照时基PT值实际延时100ms101秒100ms60060秒10ms1001秒1ms10001秒我遇到过一次现场争议程序里TONR T37写的是PT3600工程师坚持说我设的是一小时结果实际只有6分钟——他用的是100ms时基3600×100ms360秒。这种错误在调试阶段还能发现要是放在无人值守的设备上跑一个月统计数据全废。2. 累计时间出错的七个真实原因下面这七条基本覆盖了我这些年遇到过的TONR累计异常。你可以对着自己的程序一条条过命中率很高。2.1 原因一扫描周期大于时基时间被吞掉这是最隐蔽、也最容易被忽略的一条必须先讲。S7-200 SMART的定时器刷新机制按时基不同而不同1ms定时器由系统以1ms为间隔异步刷新跟扫描周期没关系相对最准10ms定时器在每个扫描周期开始时刷新一次100ms定时器在执行到该定时器指令时刷新。关键在于刷新一次只加一个时基。假设你的程序扫描周期是30ms用100ms定时器一个100ms窗口内程序会扫过三四次总有一次执行到指令时已经过了100ms于是当前值加1误差不超过一个扫描周期可以接受。但如果扫描周期因为程序庞大、通讯任务重、或者加了大量浮点运算而涨到120ms情况就变了每120ms才执行一次指令每次只加100ms实际过了120ms却只记了100ms累计值系统性偏小跑得越久差得越多。这就是典型的时间被吞掉。TONR做累计时这个问题被放大得更明显因为累计本身就是长时间行为百分之十几的偏差在几分钟内看不出来跑一天就成了大问题。判断方法很简单在编程软件里看扫描周期状态图表或系统信息里都有如果最大扫描周期接近或超过你的定时器时基基本可以锁定原因。解决思路有两条一是换更小的时基比如从100ms换到10ms让扫描周期远小于时基二是干脆别用定时器直接累计改用第3章的方案二或方案三。我个人的选择是只要累计时长超过十几分钟一律不用TONR直接累直接上双字方案省心。2.2 原因二把IN断开当成复位复位逻辑写反TONR的IN引脚断开只是暂停累计不是清零。这个特性手册上写得明明白白但实际程序里出错的比比皆是。典型的错误写法是这样的用TONR的常开触点去复位自己。LD T37 R T37, 1看起来逻辑闭环了到时间就复位然后重新开始累。实际运行时会出现两种诡异现象一种是累计值永远停在设定值附近上不去另一种是每个扫描周期都在复位与计时之间来回横跳监控里数值疯狂跳动。更常见的是复位条件写成了常闭。比如操作工按一下复位按钮你写的是LDN I0.1按钮没按时这个条件一直为真定时器每个周期都被清零累计永远是0。这种错误在监控画面上表现为数值一动不动很容易被误判成程序没执行。我的写法习惯是复位用独立的复位指令条件用上升沿并且和使能条件做互锁。复位按钮按下的那个扫描周期清零松手后重新开始累计同时保证复位和IN不会同时有效避免清零后立刻重新计时造成的时间丢失。还有一点复位指令应该放在累计判断之后。如果放在前面本周期刚判断完的时间点会被下一次清零覆盖边界上会丢一个时基。2.3 原因三断电保持区没设一上电全归零这个问题在调试阶段几乎发现不了因为调试时你很少断电。等到设备交付、现场断电重启累计值归零用户立马投诉。S7-200 SMART的定时器当前值属于T区能不能掉电保持取决于系统块里保持性范围的设置。默认情况下只有一部分区域被划入保持范围如果你的TONR编号不在这个范围内断电后当前值就丢了。设置路径大致是编程软件里打开系统块找到保持性范围设置里面可以分别配置V区、M区、定时器、计数器的保持范围。把用到的TONR编号段纳入保持区然后下载系统块。这里有个必须提醒的点修改保持区之后要重新下载系统块部分情况下还需要断电重启才完全生效。我见过工程师只下载了程序块没下载系统块改了半天没反应最后以为是硬件问题。另外要有个心理预期这类小型PLC的掉电保持靠内部储能元件维持短时间断电没问题长时间断电比如设备停产一周数据还是会丢。如果你的应用对断电多久都不能丢有硬要求那就别指望定时器直接用第3.3节的RTC方案或者把数据写到EEPROM里定期保存。2.4 原因四T编号重复占用两个逻辑抢一个定时器S7-200 SMART的定时器编号是全局资源整个项目里同一个编号只能被一个逻辑使用主程序、子程序、中断程序都共享这套编号。我排查过一次特别典型的案例主程序里用T37做1秒脉冲发生器子程序里又用T37做某个阀门的延时。结果主程序的秒脉冲忽快忽慢累计值自然一塌糊涂。原因是子程序每次调用都会改写T37的当前值两个逻辑互相踩。还有一种更隐蔽的情况同一个子程序被多次调用子程序内部用了定时器。第一次调用时定时器开始计时第二次调用进来直接把当前值改了两次调用的计时互相干扰。这种情况在多工位、多轴控制的程序里很常见。我的做法是维护一张定时器编号分配表写程序前先规划好哪几个给脉冲发生器哪几个给累计哪几个给报警延时子程序专用哪一段。表贴在项目文档里团队共用。编号段用途责任人T37T40系统秒脉冲、分脉冲主程序T41T45工位一延时子程序1T46T50工位二延时子程序2T51T60报警延时报警子程序表看着土但真能省下大量排查时间。2.5 原因五16位当前值到32767就到顶了前面提过TONR的当前值是16位有符号整数。这意味着不管你用时基多少当前值最大就是32767到了就停住再怎么计时也不涨。换算成实际时间时基累计上限1ms32.767秒10ms327.67秒约5.5分钟100ms3276.7秒约54.6分钟也就是说用TONR直接累计最长只能记54分钟多一点。超过这个时间数值就卡死而PLC不会给你任何报错提示位输出照常置位程序照常运行只有你知道数据是假的。这个坑的杀伤力在于看起来正常。设备运行一小时累计显示54分36秒操作工可能以为是显示问题工程师可能以为是换算问题很少有人第一反应是定时器溢出。解决办法只有一个长时间累计必须用双字32位。用定时器产生基准脉冲再用双字加法或自增指令累加量程直接上到21亿秒够用了。2.6 原因六PT和时基单位混着用换算全乱这条前面提过一半这里补充几个实战中见过的具体错法。第一种把PT当成毫秒填。想要10秒延时100ms时基PT填了10000实际是1000秒。程序跑起来延时长得离谱还以为是定时器坏了。第二种换时基忘了改PT。原来用100ms定时器PT100是10秒后来因为精度不够换成10ms定时器PT还是100变成1秒了。程序行为突变查半天。第三种累计值的单位没统一。有的人累计用秒有的人用毫秒显示的时候除以1000还是除以60全凭感觉最后画面上的数字和实际对不上。我的习惯是全项目统一用秒做累计单位PT换算写在注释里显示的时候再按需转成时、分、秒。这样即使换时基改的也只是产生秒脉冲的那一段累计和显示部分完全不用动。2.7 原因七监控看到的数字不一定是真实累计最后这条不算程序错误但确实误导过不少人。在状态图表里监控TONR的当前值看到的是一个整数在跳。这个整数需要乘以时基才是时间而且受扫描周期影响监控刷新本身也不是实时的。有人盯着监控看发现数值跳着走、有时候停一下就断定程序有问题其实是监控刷新和定时器刷新不同步造成的视觉误差。还有一种情况程序里对累计值做了整数除法显示。比如VD100存的是秒显示分钟时用VD100 / 60余数直接丢掉。结果画面上分钟数从59跳到60之前会卡很久操作工以为计时停了。正确做法是除法取商显示分钟再取余数显示秒两个都用上。3. S7-200 SMART上的三种累计方案理论讲完下面给可以直接抄的方案。三种方案适用场景不同我按从简单到可靠的顺序排。3.1 方案一TONR直接累计只适合短时间粗精度适用场景单次累计不超过几十分钟、精度要求±100ms、逻辑越简单越好。比如某个动作的超时报警累计。// 累计条件接通时开始累加断开保持 LD I0.0 TONR T18, 600 // 读取当前值并换算成秒100ms时基除以10 LD SM0.0 MOVW T18, VW100 ITD VW100, VD102 DTR VD102, VD106 DIV VD106, 10.0, VD110 // VD110即累计秒数 // 复位按钮上升沿清零 LD I0.2 EU R T18, 1这段程序有几个点要注意T18属于100ms时基的TONR段复位用上升沿且和累计条件I0.0在工艺上互锁换算用浮点除避免整数除法丢精度。这个方案的局限很明显上限54.6分钟扫描周期不能超过100ms精度受刷新机制影响。只建议用在短时、非关键的场合。3.2 方案二定时器加双字累加通用性最强这是我日常项目里的默认方案。核心思路是把计时和计数拆开定时器只负责产生一个稳定的秒脉冲累计交给双字指令。产生秒脉冲的写法有两种。用SM0.5最省事它是1秒周期的时钟脉冲0.5秒通、0.5秒断取上升沿就是1秒一次。但SM0.5同样受扫描周期影响扫描周期超过0.5秒时会漏脉冲。所以更稳的写法是用定时器自复位// 1秒脉冲发生器T37为100ms时基PT10即1秒 LDN T37 TON T37, 10 // T37接通的那个扫描周期累计秒数加1 LD T37 EU INCD VD200LDN T37的意思是T37没到时间时保持输入有效到时间后T37置位下一个扫描周期输入断开定时器自动复位如此循环。T37的触点只接通一个扫描周期所以后面加个EU更保险。有了秒脉冲剩下的就是换算和显示// 总秒数换算成时、分、秒 LD SM0.0 DIV VD200, 3600, VD204 // 商为小时 MOVD VD204, VD300 MUL VD204, 3600, VD208 - VD200, VD208, VD212 // 余数 DIV VD212, 60, VD216 // 商为分钟 MOVD VD216, VD304 MUL VD216, 60, VD220 - VD212, VD220, VD224 // 余数为秒 MOVD VD224, VD308VD300、VD304、VD308分别存时、分、秒画面上直接绑这三个变量就行。VD200作为总秒数保留做报表统计、导出历史数据的时候用得上。这个方案的优势是量程大、精度稳定、断电保持也好处理。缺点是要多写几行程序但一次性写好后面所有累计需求都能套用。还有一个变体如果工艺要求分钟级精度就够可以把秒脉冲改成分钟脉冲PT改大一点累计变量直接存分钟。不过我还是建议底层存秒显示层再换算原始数据粒度细一点后面想做任何统计都方便。3.3 方案三BGN_ITIME/CAL_ITIME与RTC做长时间精确统计如果对精度要求更高或者需要跨断电统计S7-200 SMART还提供两个更好用的工具。第一个是BGN_ITIME/CAL_ITIME指令对。BGN_ITIME用来记录一个起始时刻CAL_ITIME用来计算当前时刻与起始时刻的差值单位是毫秒结果存放在双字变量里。分辨率是1ms量程足够覆盖几十天。这个组合特别适合测量单次动作的耗时比如一个气缸从伸出到到位用了多少毫秒、一次焊接过程耗时多长。用法上动作开始时触发BGN_ITIME动作结束时触发CAL_ITIME输出直接就是毫秒数不用自己换算。第二个是读写实时时钟。PLC内部有RTC走的是年月日时分秒。做超长时间统计时我的做法是每隔一段时间比如每分钟读一次RTC和上一次的记录做差把差值累加到双字变量里。这样即使断电重启RTC还在走累计逻辑可以从断点续上。代价是精度只到秒级而且要做RTC数据的BCD码转换程序稍复杂。三个方案横向对比方案精度量程断电保持实现难度推荐场景TONR直接累计±1个时基最长54.6分钟需设保持区低短时超时判断定时器双字累加±1个扫描周期21亿秒需设保持区中常规运行时长统计BGN_ITIME/RTC1ms/1s极大RTC天然保持中高精确测时、跨断电统计实际项目里我经常混用秒脉冲累计做总量统计BGN_ITIME做单次动作分析两个数据互相印证出问题时很容易定位是哪一层出了偏差。3.4 掉电保持与上电初始化收尾的两步不管用哪个方案这两步不能省。保持区设置打开系统块找到保持性范围把V区中存放累计值的地址段、以及用到的定时器编号段纳入保持范围。比如累计值放在VD200VD230就把V区保持起始地址设到200之前长度覆盖到230之后。设置完下载系统块最好断电重启一次验证。上电初始化用SM0.1首次扫描标志做初始化的判断。但注意如果你希望累计值掉电保持就绝对不能用SM0.1去清零累计变量否则每次上电都归零保持区白设了。SM0.1只用来初始化那些不需要保持的中间变量。需要清零的时候用画面上的清零按钮条件用上升沿加个确认提示避免误操作把几个月的统计数据一下抹掉。这个细节我吃过亏——早年间做的设备清零按钮没做防抖也没做确认操作工擦屏幕时误触一个月的产量统计数据没了。4. 现场排查实录五步定位累计偏差程序写完不代表结束现场对不上数才是常态。下面这套流程是我这些年反复用的基本能在半小时内定位问题方向。4.1 第一步先看偏差的方向和量级拿到累计不准的反馈第一件事不是改程序是问清楚怎么个不准法。偏差偏小可能是扫描周期大于时基导致漏计、复位误动作、或者当前值到32767封顶。偏差偏大多半是重复计时、多个脉冲源叠加、或者逻辑里同一个累计变量被加了两次。数值直接归零往掉电保持区、上电初始化、复位逻辑三个方向查。数值来回跳优先怀疑编号冲突或子程序重复调用。量级也很重要。差百分之几是精度问题差几倍是换算或时基错了差一个固定值可能是初值没清。我一般会让现场配合做一次简单验证用秒表掐10分钟对比PLC里的累计值算出偏差百分比。这个数据比任何描述都直观。4.2 第二步拿一个独立基准做对照不要用被怀疑的定时器去验证它自己。我的做法是临时加一段对照程序用SM0.5或者RTC做一个独立的时间基准和被怀疑的累计值同时跑两个数据一起看。如果基准正常、累计异常问题在累计逻辑如果两个都异常问题在扫描周期或者CPU负载如果两个都正常但画面显示不对问题在显示换算。这一步能省掉大量猜测。有一次现场反馈累计快了一倍我加了基准一对比发现累计值每个扫描周期加了两次——原因是有个自保持逻辑让秒脉冲的上升沿被重复触发。没有基准对照这个很难看出来。4.3 第三步查编号和复位编号冲突和复位逻辑是最高频的两个问题建议直接翻程序做静态检查不用等运行。编号检查把程序里所有用到定时器的地方列出来看有没有重复。特别注意子程序里的定时器以及带参数调用的子程序——同一个子程序被多处调用时内部定时器会互相干扰。复位检查找到所有复位指令看触发条件。常闭条件、没有上升沿、复位和使能同时有效这三种都是雷。另外确认复位指令的位置应该在累计判断之后。4.4 第四步查保持区和上电逻辑如果现象是运行中正常、断电重启后归零直接去系统块看保持范围。确认三点地址段覆盖了累计变量、定时器编号段在保持范围内、系统块已经下载。再用SM0.1检查一遍上电初始化逻辑看有没有把不该清的量清了。这个错误很常见尤其是程序从别的项目复制过来的时候初始化段里一堆MOV指令把保持区里的数据全冲了。4.5 常见问题速查表把上面的排查经验整理成表现场可以直接对着看。现象最可能原因快速验证方法处理动作累计值偏小约10%30%扫描周期大于时基查看最大扫描周期换小时基或改双字方案累计值到某数就不动了16位溢出32767监控当前值是否停在32767改双字累计累计值永远为0复位条件常闭或每周期触发监控复位指令前的条件改上升沿、加互锁断电重启后归零保持区未设置检查系统块保持范围设置并下载系统块数值乱跳定时器编号冲突列出全部定时器使用点重新规划编号画面显示卡住不涨整数除法丢余数检查显示换算逻辑商和余数分开计算设定延时和预期差10倍PT与时基单位混用核对PT值和时基按换算公式重填5. 几条踩过坑才明白的经验写到这里技术点基本讲完了最后聊几条不那么正式但很实用的体会。5.1 时基选择上宁可粗一点也别乱选刚开始写程序的时候总觉得时基越小越精确什么都想用1ms。后来发现1ms定时器量程只有32秒稍微长一点的延时就得级联程序复杂不说还容易出错。现在我选时基的顺序是先看工艺要求的精度再看量程需求两个都满足的前提下选大的那个。100ms时基能覆盖绝大部分延时和累计需求1ms时基留给真正需要精确测时的场合比如高速计数、短脉冲捕捉。5.2 累计数据统一单位是省事的根本项目做多了会发现累计类程序出问题八成不是算法难而是单位乱。秒、毫秒、分钟、小时混着用换个工程师接手就看不懂。我现在所有项目的规矩是底层一律存秒双字变量变量名带单位后缀比如RunTime_s显示层再转成时分秒。这条规矩看着笨但真的能省掉无数次沟通成本。5.3 给累计变量留个体检入口我习惯在HMI上做一个调试页面把原始秒数、换算后的时分秒、定时器当前值、扫描周期最大值全放上去。这些数据平时没人看一旦现场反馈数据不对操作工截图发过来我基本能远程判断方向。这个习惯来自一次深夜被叫去现场的教训——当时没有任何中间数据可看只能一行行查程序折腾到凌晨。5.4 复位按钮一定要做防误触前面提过一次这里再强调。累计数据往往是几个月的成果误清一次损失很大。我的做法是清零按钮长按3秒生效或者弹出二次确认再或者加一个清零使能开关平时锁着。多写几行程序省掉的是没法挽回的麻烦。5.5 交付时把编号规划表一起给出去项目交付的时候除了程序和图纸我会额外给一份定时器、计数器、中间变量的编号规划表。后面设备改造、加功能、换人维护接手的人照着表就能找到空闲资源不用满程序翻。这个习惯是从一个改造项目开始养成的——前人没留任何文档我花了两天时间才理清哪些编号能用、哪些不能用那种感觉不想让别人再体验一次。累计时间这件事说到底是个账要记清的问题。定时器只是记账的笔笔好不好用是一回事账本怎么设计、什么时候对账、丢了怎么补才是真正决定数据准不准的东西。把刷新机制、时基量程、保持区这三件事想明白剩下的就是按规矩写程序了。