Two cartoners and a case packer on a 5069-L320ER each, all three running a cut-down PackML state model already. Plant manager wants OEE on a screen by the end of the quarter and the MES people want a reason code attached to every stop, not a number at the end of the shift.
Where I've got stuck is who owns the state. I tried building the downtime table in the SCADA from the run bit and a timestamp, because that was the quickest thing to stand up, and it counts a 4 second jam and a 40 minute changeover as the same event. It also loses everything when the server reboots.
Does the state logic belong in the controller, or am I making work for myself that the historian is meant to do?
Historian doesn't decide anything, it stores what you send it. That's the whole argument in one line.
Before the design though, what is it actually? SQL behind a SCADA, or a proper historian? And can the MES side read tags directly or is it waiting on the SCADA to push?
SQL behind FactoryTalk View SE, and the MES lot talk to it through a stored procedure someone wrote in 2019 that nobody will touch.
They can't read tags. Everything goes through that table, which is part of why the stop events look the way they do.
We did ours off the run bit in the SCADA for two years and it was fine. You put a 5 second filter on the transition so short jams roll up, and a dropdown the operator picks from when a stop lasts longer than a minute. Nobody wrote a line of ladder for it.
Trend it for a week before you rebuild anything, the 4 second events might be all one machine and one photoeye.
That works right up to the first network hiccup, then you've no idea what the machine was doing for ninety seconds and the operator gets a dropdown for a stop that never happened.
The controller is the only thing that knows the machine stopped at the instant it stopped. One DINT state, a priority so blocked beats starved beats faulted, a timer per state and a reason code latched on the transition out of Execute. The SCADA reads four tags and writes rows. That's it for the PLC side, maybe 40 rungs across all three machines.
Built the state DINT on the first cartoner and it's better, I can see blocked and starved separating out properly now.
The reason code is where it falls over, and I'm not sure the answer to that one is in the controller at all. A jam sets the code, the operator clears it, the machine runs, and the SCADA polls at 1 second so short ones never make it into the table at all.
Polling is the wrong shape for events. Latch the reason code and a sequence number into a small event buffer in the controller, say 32 deep, and have the SCADA read the buffer and acknowledge what it took. Then a 400 ms stop still gets its row and a server reboot costs you nothing, the buffer is still sitting there when it comes back.
Someone did a decent article on the counting side of it: https://plctr.com/utilizing-plc-for-lean-manufacturing-and-six-sigma/
All three machines are on it as of Friday. State DINT with the priority order, timers per state, and a 32 deep event buffer with a sequence number that the SCADA acknowledges after it writes the row.
What was actually wrong was the SCADA deciding what a stop was. It was polling at 1 second and inventing the boundaries, so anything shorter than the poll never existed and a reboot took the rest with it. Moving the decision into the L320 and leaving the SQL side as a dumb writer fixed both.
The stored procedure still wants the old column order so there's a translation step I'm not proud of. Thanks suel, mattr and wandak.
Fair enough on the buffer, our short stops were always a guess.