Machine downtime tracking in a PLC: what to log, and why overlapping stops break your numbers

October 29, 2026
CompactLogix 5380 controller on a workbench beside a clipboard with a handwritten paper downtime log
Published on  Updated on  

The shift report said the line lost 50 minutes after lunch. The operators said it was more like 45, and they were right. Two stops had overlapped for five minutes and the report counted both in full. Nobody lied. The math was just wrong.

That is how machine downtime tracking usually goes. The PLC knows to the millisecond when the machine stopped and started again, and the numbers still end up on a clipboard filled in at the end of the shift, or in a spreadsheet that counts the same minutes twice. Here's how I build it inside the controller instead, Logix specifics included.

Decide what machine downtime tracking counts before you write a rung

Most fights over downtime numbers I've been dragged into weren't about the PLC. They were about definitions. Is a changeover downtime? Is a starved machine down if nothing on it is broken? Is lunch?

Pick the answers once, write them down, and make the code follow the paper. Your plant can draw the lines differently from mine, as long as everybody uses the same ones.

Category

What it looks like

Counts against availability?

Who assigns the reason

Unplanned stop

Fault, jam, E-stop, broken part

Yes

PLC fault code, operator adds detail

Starved or blocked

Infeed empty, discharge full, upstream or downstream not ready

Yes for the line, usually no for the machine itself

PLC, automatically

Planned stop

Changeover, cleaning, scheduled maintenance, break

No, except the overrun

Production schedule or HMI mode

Small stop

Stop shorter than your threshold, cleared in seconds

Tracked separately, usually as a speed loss

PLC, no reason prompt

No production scheduled

No orders, shift not staffed

No, it is outside planned time

Production schedule

 

Availability is the share of planned production time the machine actually ran, so everything in the "Yes" rows eats into it.

The small stop threshold causes the most fights. Too low, and the operator gets a reason prompt every few minutes and starts hitting the first button on the screen. Push it too high and real jams disappear into speed loss. I start somewhere between two and five minutes and move it after a couple of weeks of real data.

The PLC already knows most of the answer

On a typical machine you don't need new sensors for machine downtime tracking. You need three things that are already in the program: a run bit that is true only when the machine is actually producing, the fault word, and the starved and blocked checks the sequence makes before each cycle. The job is to boil them down to one state at a time.

I borrow the state names from PackML, even on machines that don't run a PackML state engine. The names settle arguments. Execute means producing. Held is a pause for a condition inside the machine itself. Suspended is a pause too, but it's waiting on something outside the machine. Aborted is the fault state, and the machine only leaves it after someone fixes the problem and clears it. Stopped is a controlled stop with no fault behind it.

PLC condition

State (PackML number)

Downtime category

Where the reason comes from

Run bit on, cycle active

Execute (6)

Running

Not needed

Fault word not zero, E-stop

Aborting / Aborted (8 / 9)

Unplanned

First fault in the word

Infeed empty or upstream not ready

Suspended (5)

Starved

Automatic

Discharge full or downstream not ready

Suspended (5)

Blocked

Automatic

Machine paused on its own condition (empty glue pot, detected jam)

Held (11)

Unplanned

PLC code, operator confirms

Stop pressed, no fault

Stopped (2)

Depends

Operator, on the HMI

Ready, waiting for a start

Idle (4)

Depends

Operator or schedule

Maintenance or Manual mode selected

Mode, not a state

Planned or maintenance

The mode itself

 

Two rules make this work. Only one state is true at a time, so derive it in one routine with a fixed priority, not in five rungs scattered around the program. And only ask the operator when the PLC can't know the reason, which mostly means Stopped and Idle. Making someone pick "jam" when the PLC saw the jam sensor just teaches them to press anything.

Some plants block the restart until a reason is entered. You get complete data and operators who hate the HMI. If you go that way, keep the list to ten or twelve top-level reasons and watch how often "Other" gets picked. When it climbs, the list is wrong, not the people.

Flowchart of the order a PLC checks mode, fault, run, starved and blocked conditions to set one machine state

For machine downtime tracking, check the conditions in a fixed order and stop at the first true one, so the machine is only ever in one state.

Timers and time stamps in Logix

Most homemade machine downtime tracking I've had to fix treated a timer as the record. A few things about Logix timers matter here:

·       TON and RTO count in milliseconds. The time base is always 1 ms, so a 2-second preset is 2000, not 2. On CompactLogix 5380 and ControlLogix 5580 a timer can also be TIMER_T, where .ACC and .PRE are TIME values with microsecond resolution. Check the tag type before you divide anything.

·       .DN means done, or paused. It's a level, not a pulse: on a TON it stays on as long as the rung is true, on an RTO until a RES. If you need a single event out of it, take the edge with a one-shot.

·       A TON clears .ACC to zero the moment its rung goes false. On an RTO, .ACC stays put until a RES.

·       On the regular TIMER structure, .PRE and .ACC are DINTs. The ceiling is 2,147,483,647 ms, about 24.8 days, and a negative .PRE or .ACC is a major fault. An RTO used as an hour meter on a machine that runs around the clock hits that ceiling in under four weeks.

So the record isn't a timer. A timer does one job here: it decides that a stop has lasted long enough to count as a real stop and not a small one. The record is two time stamps, start and end. The duration is the difference.

The time comes from a GSV on the WallClockTime object. Its LocalDateTime attribute fills a DINT[7] with year, month, day, hour, minute, second and microseconds, adjusted by the controller's time zone and daylight saving settings. That's the one I use, because shifts run on local time. Put that GSV in one task only. If it really has to sit in two tasks that can interrupt each other, wrap it in UID/UIE.

Set the clock from one place. The controller accepts a new wall clock time no more than once every 15 seconds, and if it follows a PTP grandmaster, the grandmaster can overwrite whatever you type in by hand. And don't mix this up with CST. Coordinated system time is a microsecond counter synced inside one chassis, great for telling which of two inputs changed first. It isn't a calendar.

Power loss is the case nobody tests. Lose power in the middle of a stop and that stop has a start and no end. So I write the start stamp the moment the stop begins. On the first scan after power-up, the logic looks for an open record, closes it with the power-up time and books the gap as its own reason, power off. Whatever the timers were doing before, I don't trust them afterward.

Shift changes need splitting too. A stop that starts at 2:50 p.m. and ends at 3:20 p.m. gets split into 10 minutes for first shift and 20 for second. Otherwise one shift owns half an hour it only had for ten minutes.

When two stops overlap

Overlaps produce more bad numbers than any other mistake I run into, and most machine downtime tracking I've seen ignores them. Say the filler jams at 1:00 p.m. and gets cleared at 1:20. At 1:15 the labeler faults and stays down until 1:45. Each event is logged correctly on its own. Add them up and you get 50 minutes. The line was down from 1:00 to 1:45, which is 45.

Method

Filler jam

Labeler fault

Total

The catch

Add the raw durations

20 min

30 min

50 min

The five overlapping minutes are counted twice

First cause keeps the overlap

20 min

25 min

45 min

The labeler looks shorter than it really was

Priority: labeler outranks filler

15 min

30 min

45 min

Needs a priority list everyone agrees on

 

I use first cause by default and a priority table only where the plant asks for one. Either way, the PLC holds one tag with the active cause. When a new cause shows up, the logic decides whether it takes over. If it does, the current segment closes and a new one opens. Segments never overlap, so they always add up to the real downtime.

I keep the raw events too, as a second view. Maintenance wants the 30 minutes the labeler was faulted, because that's how long they worked on it. Production wants the 45 that adds up. Both are true, they just don't belong on one chart.

Partial stops are the same problem in another shape. One station out of a dozen down while the line keeps running slower isn't line downtime. Log it per station and let the line state decide.

Timeline of a filler jam and a labeler fault overlapping 5 minutes: 50 minutes summed raw versus 45 split

The same two events in machine downtime tracking: summed raw, they claim 50 minutes; split into non-overlapping segments, they add up to the 45 minutes the line was really down.

Where to keep the records

In machine downtime tracking the controller should time stamp the event, not serve as the long-term archive. My usual split: the PLC builds the record and buffers it, something else stores it.

Option

Good for

What bites

Array of UDTs loaded with FFL, read out with FFU

Buffering events through a network outage

When it fills up, new records are simply not loaded

HMI or SCADA logging

Quick start, reason screen in one place

If the HMI is off or rebooting, nothing gets recorded

Historian

Long history, trends, easy reports

Fixed-interval sampling misses short stops between samples

SQL database through a gateway or OPC server

Reports that join downtime with orders and counts

Overlap logic in SQL gets slow and hard to debug

 

FFL and FFU share one CONTROL tag. FFL loads until the buffer is full, and then the .DN bit blocks every new record until FFU makes room. FFU on an empty FIFO returns zero, so a reader that doesn't check .EM will happily store a row of zeros. Size the buffer for the longest network outage you expect, and alarm when .POS gets close to .LEN.

Resolve overlaps in the PLC when they happen. Doing it later in SQL means comparing every event with every other one, and that gets slow fast.

Machine downtime tracking data path: signals into PLC state logic, time stamps and FIFO, out to historian or SQL

In this machine downtime tracking setup the PLC decides the state, stamps the time and buffers the record, so a short network dropout costs nothing as long as the FIFO doesn't fill.

What one record should look like

A machine downtime tracking record should be small and boring. One UDT, one row per segment. Here's the labeler segment from the overlap example, after the first cause rule:

Field

Data type

Example

EventID

DINT

48213

MachineID

DINT

3

State

DINT

9 (Aborted)

ReasonCode

DINT

214 (labeler: label web break)

Source

SINT

1 (PLC; 2 would mean operator)

StartTime

DINT[7]

2026, 10, 14, 13, 20, 0, 0

EndTime

DINT[7]

2026, 10, 14, 13, 45, 0, 0

DurationSec

DINT

1500

Shift

SINT

1

CountAtStart

DINT

152340

CountAtEnd

DINT

152340

 

Seconds are plenty for duration. The two counts prove later that the machine really made nothing during the stop. Keep reason codes as numbers in the PLC and their text in one lookup table outside it, so renaming "jam" to "infeed jam" doesn't need a download.

Checks before you trust machine downtime tracking numbers

I run this list every day for the first week on a new install. After that, once a month is plenty.

·       Run time plus every logged stop, planned or not, equals the shift length. A gap means missing events, usually around a power loss or a mode change.

·       The attributed segments for a shift add up to line downtime, with no overlap.

·       The controller clock matches a real clock, and the daylight saving setting is right.

·       Stops that cross a shift change are split.

·       The FIFO never filled up. Alarm on its .DN bit so you find out the same day.

·       "Other" isn't one of your top reasons. If it is, fix the list.

·       Small stops are counted, just not prompted.

FAQ

How can I track downtime for equipment?

Machine downtime tracking starts in the PLC. Turn the run bit, fault word and starved or blocked signals into one machine state, stamp the start and end of every non-running state with the controller's wall clock, and buffer the records until an HMI, historian or database collects them. Operators only get asked for reasons the controller has no way of seeing.

How do I calculate equipment downtime?

Subtract the start time from the end time of each stop and add the stops up per shift. If two stops overlap, split the overlap first, by first cause or by priority. Otherwise the total comes out bigger than the time the machine was actually down.

What is downtime in OEE?

Downtime in OEE is the part of planned production time when the machine wasn't running. That feeds availability, calculated as run time divided by planned production time. Stops outside the production plan don't count, and short stops usually go in as a speed loss instead.

Can I do machine downtime tracking on an older PLC?

Yes. The logic is the same on any controller: a run condition, a fault indication, a clock and somewhere to buffer records. What changes is how the timer and clock instructions behave on that platform, so check them before you copy Logix logic across.

Hardware for machine downtime tracking on an existing line

Most machine downtime tracking I've added went into controllers already running the line: a CompactLogix 5370 like the 1769-L33ER, a ControlLogix 5570 like the 1756-L73, or the newer 5069-L320ER and 1756-L83E. The reason screen fits fine on a PanelView Plus 7 such as the 2711P-T7C21D8S. IQElectro carries all of them as surplus, so a spare for the controller doing the counting can sit on the shelf instead of on a lead time.

Published on  Updated on