T18: Equipment Utilisation
Model every machine state as events, prove the durations reconcile to the interval, and build a utilisation breakdown that adds to 100%.
What you will build: a full state model where every minute is accounted for, and a utilisation breakdown that provably sums to 100%.
Time: about 40 minutes.
You need: T07 completed.
Step 1 — The goal: every minute accounted for#
T07 modelled stoppages. That tells you when the machine was not running. This tutorial models every state, so the durations across a day sum to the day.
That property — reconciliation — is what makes a utilisation breakdown trustworthy. A chart of state percentages that adds to 87% invites the immediate question "what was the other 13%", and there is no good answer.
The simulator's FL001.State gives us the states:
| Value | State | Category |
|---|---|---|
0 |
Idle | Not running |
10 |
Setup | Not running |
20 |
Running | Productive |
21, 22, 23 |
Fault | Not running |
30 |
CIP (cleaning) | Not running |
Step 2 — Create the state enumeration#
In the Toolbox, create Machine State with colours chosen deliberately:
| Option | Colour |
|---|---|
| Running | Green |
| Setup | Amber |
| Idle | Grey |
| Fault | Red |
| CIP | Blue |
Green for productive, red for the thing to reduce, blue for necessary and planned, grey for not-a-plant-problem. Those colours will carry into the timeline and make it readable at a glance.
Step 3 — Create the state event scheme#
On Filler 1, create an event scheme called Machine State.
This one is different from Stoppage: instead of a start and end pair around one condition, you want an event for every state, tiling the timeline with no gaps.
Add trigger pairs so that a state event starts when the machine enters that state and ends when it leaves it. The FL001.State values give you the conditions.
Set For Period (s) to about 25 on each, to filter signal bounce — the same reasoning as T07.
Add attributes:
| Attribute | Type | Retrieval | Notes |
|---|---|---|---|
State |
Enumeration | Retrieved from segments | Reads the state tag, mapped to the enumeration |
Duration (min) |
Value | Calculated | Period.Duration.TotalMinutes |
Fault Code |
Value | Retrieved from segments | The specific 21/22/23 value |
Fault Code is worth capturing because the simulator's three distinct fault states let you build a genuinely realistic fault Pareto — separate causes rather than one undifferentiated "fault".
Step 4 — Deploy and reconcile#
Deploy, let it run for a few hours, then do the test that matters.
For one complete hour, add up the durations of every state event overlapping it.
It should come to 60 minutes.
| Result | Meaning |
|---|---|
| ≈ 60 | The model tiles correctly |
| Much more | Events are overlapping — the state conditions are not mutually exclusive |
| Much less | Gaps — some transitions are being missed, often from a hold time set too long |
Do not proceed until it reconciles. Every percentage you build from here divides by the interval length. If the states do not tile the timeline, every utilisation figure is wrong, and the error is invisible on a chart.
This reconciliation check is the single most valuable thing in this tutorial.
If durations sum to much more than the interval, the state conditions overlap — two triggers are both firing for the same period. If much less, either a hold time is swallowing short states or a state value is not covered by any trigger.
Step 5 — Build the duration measures#
One event-aggregated measure per state, all using Active Duration:
| Measure | Interval | Anchor | Filtered to |
|---|---|---|---|
Running Minutes Hourly |
Hour(s) | Active Duration | State = Running |
Setup Minutes Hourly |
Hour(s) | Active Duration | State = Setup |
Idle Minutes Hourly |
Hour(s) | Active Duration | State = Idle |
Fault Minutes Hourly |
Hour(s) | Active Duration | State = Fault |
CIP Minutes Hourly |
Hour(s) | Active Duration | State = CIP |
Active Duration is required. It attributes only the portion of each event that fell inside each interval, which is precisely what makes these five sum to the interval length.
Try one of them with Event Duration (Start) to see the difference: a three-hour CIP beginning at 05:50 puts all 180 minutes into the 05:00 hour, and that hour's states then sum to well over 60.
Step 6 — Verify the sum in Infohub#
Add a check measure:
| Field | Value |
|---|---|
| Name | State Minutes Total Hourly |
| Interval | Hour(s) |
| Unit | min |
(Measure_<runningId>.Value ?? 0) + (Measure_<setupId>.Value ?? 0)
+ (Measure_<idleId>.Value ?? 0) + (Measure_<faultId>.Value ?? 0)
+ (Measure_<cipId>.Value ?? 0)
Put a limit on it: it should be very close to Period.Duration.TotalMinutes. A limit flagging anything below, say, 58 or above 62 turns the reconciliation check into something that monitors itself continuously rather than something you did once.
This is a genuinely good practice — a model that checks its own arithmetic.
Step 7 — Build the utilisation percentages#
Now the percentages, each dividing by the real interval length:
| Field | Value |
|---|---|
| Name | Utilisation Hourly |
| Interval | Hour(s) |
| Unit | % |
| Format | 0.0 '%' |
SafeDivide(Measure_<runningId>.Value, Period.Duration.TotalMinutes) * 100
Repeat for each state. Because the minutes reconcile, the five percentages sum to 100%.
Using Period.Duration.TotalMinutes rather than 60 means these are correct at every interval — hourly, shiftly, daily — and survive daylight-saving days that are twenty-three or twenty-five hours long.
Step 8 — Present it#
Three views, each answering a different question:
A stacked bar chart of the five state percentages by hour or shift. Because they sum to 100%, a stacked chart is honest — each bar is a full period, split by state. This is the single most useful utilisation visualisation.
An Event Based Timeline of the state events, coloured by the enumeration. A shift's worth of states as a coloured strip, readable without a legend.
A widget showing current utilisation, with a limit for colour.
The stacked chart shows the pattern; the timeline shows the story; the widget shows now.
Step 9 — Add a fault Pareto#
You captured Fault Code. Build a Pareto ranking fault duration by code.
Because the simulator provides three distinct fault states, you get a real ranking rather than one bar. In a plant, this is the chart that tells maintenance which failure mode to work on.
Step 10 — Roll up correctly#
For daily and monthly utilisation, aggregate the minutes and recalculate the percentages — do not average the hourly percentages.
SafeDivide(Measure_<runningMinutesDailyId>.Value, Period.Duration.TotalMinutes) * 100
Averaging hourly percentages weights every hour equally regardless of anything else, and produces a number that will not reconcile with the totals. Somebody will check.
What you have learned#
Model every state, not just downtime. It is what lets the durations reconcile.
Reconciliation is the acceptance test. If the states do not sum to the interval, every percentage is wrong.
Active Duration is the only anchor that tiles correctly.
Build a check measure with a limit so the model monitors its own arithmetic.
Divide by Period.Duration, never a hard-coded interval length.
Stacked charts are honest when the parts sum to the whole — and misleading when they do not.
Colours belong on the enumeration.
Roll up the quantities, then recalculate the ratios.
Try this before moving on#
Add a "Not scheduled" state for periods when the line was never meant to run — weekends, or hours outside the production plan.
You will immediately hit the question that makes utilisation political: does utilisation divide by calendar time or by scheduled time? Both are defensible, they give very different numbers, and the argument about which to use is the reason many utilisation programmes stall.
Build both, label them unambiguously, and let the plant choose. That is a better outcome than picking one and defending it.
Next: T19: Building a Model from the CLI — everything you have done, as a script.