Describe the plant, not the program.
A plant is already a set of separate machines — a filler, a capper, a rinse station — each doing its own job at its own pace, each knowing a few things about the others. StateTick keeps that shape instead of flattening it.
Three consequences follow, and they are the whole of this article.
Each machine keeps its own clock
How often a machine looks at the world is a property of that machine.
When you add a machine in StateTick, one of the things you set is how often it runs. A safety interlock might look at its inputs every 2 ms. The recipe sequencer above it is perfectly happy at 50 ms. Both are true at the same time, on the same controller, because they are separate machines with separate clocks.
Nothing about that arrangement is special-cased. It is just what a machine is.
There, scan period belongs to the task, so everything inside it shares one number. Here it belongs to each machine, so changing one machine's rate is a setting on that machine and nothing else moves.
Three worlds, one vocabulary
The logic, the equipment model, and the connection to the outside are three separate places — and only one of them is shared.
A StateTick project is organised into three worlds, and keeping them apart is the point rather than a side effect.
The middle world is the vocabulary. An interface says what a kind of connection offers — a drive has a speed, a running flag, a fault. Equipment gathers the interfaces a device actually has, so a pump is a drive plus an isolation valve plus an outlet pressure. Instances are the devices themselves: feed pump 1, feed pump 2, transfer pump, same shape, their own values.
Both of the other worlds speak that vocabulary, and neither one speaks to the other. Your logic says Pump1.Drive.Speed. The bus mapping says where Pump1.Drive.Speed lives. They meet in the name and nowhere else.
What lives in the mapping world
Everything the outside world insists on and the machine should never have to know: which bus, which direction, the address or node, data type, byte order, unit id, and the scaling from raw counts into engineering units. It is a table you can sort, filter by machine or by bus, and ask a useful question of — what is still unmapped?
Transports are named instances rather than a single channel, so a plant can run several at once: Modbus TCP and RTU, serial, raw TCP, OPC UA, EtherCAT. And because a mapping is just a row, one value can be read from one place and published to as many as you like — the drive on EtherCAT, a copy to the OPC UA server for SCADA, another to a historian — with no copying logic anywhere in your sequence.
The same separation is why you can point a finished plan at a digital twin instead of the plant, run the whole sequence against it, and then swap the mapping back. The FSM world does not notice, because it was never told where anything lived.
There, a tag is a name for an address, and the two are hard to prise apart: scaling a 4–20 mA input is a rung, mirroring a value to SCADA is more logic, and re-addressing means hunting through code for everything that mentioned it.
Here the three worlds are edited separately by the people who own them, and a re-address is a row in a table.
Machines tell each other things
Once machines really do run separately, how they coordinate matters.
A capper often needs to wait for the filler to finish settling. In StateTick you say that directly: the capper's condition refers to the filler being in its settle state. When the filler gets there, it tells the capper. Nothing is polling, and nothing has to be kept in step by hand.
When a machine needs to hand over data rather than just a moment — a batch, a set of measurements, a recipe — it uses a queue. Queues are typed, they carry records and arrays as happily as numbers, and you decide up front what should happen if one ever fills up.
Two sequences usually meet in a shared flag — a bit that means “the filler is settling” because everyone agrees it does. Here the condition points at the filler's actual state, so renaming or removing that state is caught when the plan is built rather than discovered on site.
One idea, followed all the way through
Everything in this article comes from the same starting point.
The machine is the unit. Everything else follows from that.
Start from the machine rather than the program and the answers change on their own. Timing becomes a property of each machine. The equipment model separates from the wiring, because a machine knows what it has and the bus mapping knows where it lives. Coordination becomes something machines do to each other, out in the open, instead of something that happens quietly in shared memory.
That is a dozen machines with different urgencies, several buses, and a SCADA system that wants a copy of everything — described once, in a shape that matches the plant you are actually looking at.
And your team walks straight in. The logic inside a machine is Structured Text, so whoever writes ST today is productive here on the first afternoon.
The Machine, Drawn — the drawing itself: how one machine is laid out, why stopping and pausing come as standard, and how a plan gives the whole project something to discuss.
Three in the Morning — what happens when the phone rings: the live plan, focused observability, and the log that says why.