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.
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.
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.
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.