How do you modernise PLC software without rewriting the whole machine?
12 min read · By the neexo engineering team · Vejle, Denmark
Published: 11 October 2026
If your existing machine works but every software change risks delaying delivery, a complete PLC rewrite may be the wrong first investment. Compare the cost of maintaining the current system with the risks of replacing it. Often the sensible first project is one bounded module, a clear interface and repeatable tests, with proven logic left in place.
Should you modernise the current PLC software or replace it?
The management decision is whether the next release can be made predictable without taking the whole machine apart. Keeping an unmaintainable control system can make every change slower; replacing it without a test baseline may introduce new faults and downtime. Compare the scope of both risks before committing to a rewrite.
Start by separating business risk from coding style. If the machine has a stable process, known PLC hardware and proven motion sequences, a staged migration often preserves more value than rewriting every function block. If the controller is unsupported, critical interfaces cannot be verified or the current architecture prevents safe maintenance, a broader replacement may be justified.
The decision is not simply old code versus new code. Ask what must improve: variant handling, testability, operator diagnosis, recovery after a stop, performance, deployment time or future maintainability. Set a measurable acceptance condition for each. A rewrite without an agreed baseline can reproduce all the old problems in a newer programming style.
- Keep stable, proven process and motion behaviour until a replacement is tested
- Replace isolated weaknesses where interface ownership and expected behaviour are known
- Escalate unsupported hardware, unmanaged risk and safety-related modifications to a separate engineering and risk-assessment decision
- Reject claims of automatic cost or downtime reductions before measuring the current machine
Modernise the interfaces first, replace internals only where the risk and benefit justify it, and verify every change against the behaviour of the existing machine.
What do you need to know before approving the budget?
Ask your team where changes actually consume time: understanding old behaviour, testing variants, commissioning, diagnosing stops or recovering from faults. A short inventory of the machine and three repeatable problem scenarios is more useful for this decision than a source-code line count.
Trace a complete operating cycle: start from Stopped, reset and start, feed a product, process it, discharge it, then force a controlled stop and recover. Which function block owns each transition? Which bits can command movement? Which conditions are only diagnostics and which are permissives? Where does fault handling propagate?
Keep a baseline test record of timing, state changes and operator actions. Use accessible evidence: an I/O map, a module/contract table, a list of high-impact variants and a small trace from a repeatable test. Without a baseline it is difficult to prove that a modernisation changed only what was intended.
- Inventory: PLC, motion, HMI, fieldbus, variants and software releases
- Ownership: one authoritative writer for each command, actuator and mode
- Interfaces: commands, feedback, readiness, faults, handshakes and timing limits
- Test cases: normal production, missing product, downstream blocked, stop, abort and recovery
Choose a pilot module, not a machine-wide rewrite
A first pilot should have one visible outcome: for example, the outfeed reports its actual reset status, so operators no longer see the whole machine as ready while it is still recovering.
Write an interface contract before refactoring. Define who requests Start and Stop, what Ready actually means, when State Complete is reported, how a fault is escalated and what is required before a Reset. Keep the old function behind an adapter if its internals do not need to change yet.
An adapter is useful only if it has one owner and one direction of authority. Do not run the old and new controllers as concurrent masters of the same actuators. Read-only monitoring can be compared during transition; command authority must switch under a controlled, testable procedure.
Prefer a thin compatibility layer to a new architecture that duplicates every old flag. If the adapter becomes a second sequencing engine, it is increasing complexity instead of containing it.
- Contract example: StartRequest, StopRequest, CurrentState, Ready, FaultId and StateComplete
- Keep application-specific interlocks, positions and recipes inside the owning module
- Name timing and readiness assumptions explicitly instead of hiding them in HMI tags
- Make rollback possible by retaining a verified release, configuration and recovery procedure
Example module contract: from scattered flags to verifiable behaviour (illustrative)
Main reports Ready while the outfeed is still resetting
- Proposed contract
- Outfeed owns CurrentState and StateComplete; Main waits for confirmed completion
- How to verify
- Trace Main and Outfeed through Reset; Main must not reach Idle early
Stop behaves differently across stations
- Proposed contract
- One documented StopRequest owner with state and fault feedback
- How to verify
- Test Stop during Execute and while a downstream station is blocked
An optional station prevents reset when not installed
- Proposed contract
- Participation is explicit for the active machine configuration
- How to verify
- Test the station installed, disabled and absent
Operator cannot tell the first fault from later consequences
- Proposed contract
- Preserve original fault cause and distinguish acknowledgement from recovery
- How to verify
- Inject one fault; verify cause remains visible and reset keeps interlocks effective
| Existing problem | Proposed contract | How to verify |
|---|---|---|
| Main reports Ready while the outfeed is still resetting | Outfeed owns CurrentState and StateComplete; Main waits for confirmed completion | Trace Main and Outfeed through Reset; Main must not reach Idle early |
| Stop behaves differently across stations | One documented StopRequest owner with state and fault feedback | Test Stop during Execute and while a downstream station is blocked |
| An optional station prevents reset when not installed | Participation is explicit for the active machine configuration | Test the station installed, disabled and absent |
| Operator cannot tell the first fault from later consequences | Preserve original fault cause and distinguish acknowledgement from recovery | Inject one fault; verify cause remains visible and reset keeps interlocks effective |
Where PackML helps teams coordinate modules
PackML provides a shared language for machine and unit states, modes and commands. It is useful when a supervisor, HMI and several modules need consistent answers to questions such as whether a unit is Stopped, Resetting, Idle, Starting, Execute or Aborting. It is not a requirement to copy an entire state model into every sensor or axis function block.
The PackML approach is documented by OMAC and in the ISA-TR88.00.02-2022 Use the applicable state model and subset deliberately. Parent/child module architecture and adapters here are practical design choices, not requirements imposed on every function block.
For an existing machine, introduce the common external state contract first. A parent can wait in Resetting until the participating child modules have completed their own transitions. The HMI can show which module is still busy instead of indicating that the whole machine is ready too early.
PackML is not functional safety, and the Aborting state is not an emergency-stop circuit. A PLC programme, simulation or shared state model cannot validate safety functions or replace the required machine risk assessment and physical verification.
- Agree on the meaning and ownership of states and commands before adding new code
- Let a child report actual completion; do not fabricate Ready in its parent
- Handle optional or inactive modules explicitly when deciding which children block a transition
- Preserve independent safety functions and validate them through the appropriate safety process
What a phased upgrade looks like on a three-station machine
Consider a three-station OEM machine. The infeed delivers parts, the process station performs the operation and the outfeed receives finished parts. All three stations work, but each uses different Reset and fault flags. Operators sometimes see Main as Ready while the outfeed is still recovering.
Iteration one keeps the process and motion logic untouched. Add a documented state adapter around the outfeed. It exposes an agreed Resetting, Idle and Execute status and distinguishes a completed reset from a pending reset. The top-level controller waits for the outfeed's real completion feedback rather than a generic Ready bit.
Iteration two applies the same contract to the infeed. Test what happens when the outfeed is blocked or a product is missing. The machine must not transfer a part simply because the new state names look consistent. The old physical and process interlocks stay authoritative until explicitly re-engineered and validated.
Iteration three simplifies Main only after both contracts have proven themselves. The HMI can now explain that a transition is waiting for Outfeed and display the local fault reason. This is an illustrative architecture example, not a claim about a specific customer project or achieved time saving.
- Before: MainReady is true while an outfeed internal reset is unfinished
- Contract: Outfeed.State = Resetting until its documented work and permissives are complete
- After: Main waits for every relevant child's completed transition before reporting Idle
- Evidence: trace state transitions, permissives and alarms during normal and fault sequences
Need to modernise your existing machine software?
We can help separate stable PLC and motion logic from the interfaces that are slowing down your next project, then define a testable first implementation slice.
See machine software engineeringHow do you know the change is safe to release?
Build the smallest regression suite that exposes the real risks. A code review and a successful PLC build are necessary, but they do not prove that a machine sequence behaves as required. Compare the old and new contracts on normal operation and deliberately selected failures.
Where appropriate, connect the actual control logic to a virtual machine model, a software test harness or suitable controller test setup. Test repeatable handshakes, timing and fault-recovery sequences. A simulation must state what it models and what it does not: mechanics, process physics, network timing, safety functions and real drives can behave differently.
Promote a slice only after it passes the agreed tests, the operator can understand new status messages, and the team has a versioned rollback path. Record software version, test scenario, expected behaviour, observed behaviour and remaining open points. Repeat key checks on the physical machine in the approved commissioning process.
- Normal path: Stop, Reset, Start, run and controlled Stop
- Interlocks: upstream starvation, downstream blocked and missing product
- Recovery: faults that arrive while other modules are stopping or resetting
- Variants: an optional module disabled, enabled and unavailable
- Acceptance: new software reproduces critical verified behaviour without bypassing machine safety
A phased plan with clear acceptance points
Run a short architecture and evidence workshop first. The output is not a fresh rewrite estimate; it is a bounded list of risks, interfaces, candidate modules and testable outcomes. Agree which code is deliberately left alone.
In the first implementation slice, establish shared diagnostics and one module contract. In the next, migrate one more module and its HMI diagnostics. Finally, reduce duplicate command handling in the supervisor, add automated regression tests and document the release process. Each slice should be independently useful and releasable.
Estimate engineering effort by module and integration risk rather than by counting source-code lines. Retrofitting a machine with known hardware, available test rigs and a clean I/O map is a different task from reconstructing undocumented equipment with safety-critical dependencies. State these assumptions openly in the proposal.
A successful project makes the next change easier to specify, test and recover from. It does not promise that an older machine becomes fully modular overnight.
- Deliverable 1: architecture and risk map with one agreed pilot module
- Deliverable 2: explicit command/state/fault contract and a tested adapter
- Deliverable 3: regression evidence, HMI diagnostics and rollback documentation
- Deliverable 4: backlog of later slices ranked by value, effort and risk
A bounded three-step modernisation
- 1MapRecord actual interfaces, versions, variants, failure paths and baseline traces.
- 2PilotIntroduce one owned module contract without re-implementing proven process logic.
- 3Prove and extendCompare behaviour, verify recovery and rollback, then migrate the next bounded module.
Questions to ask your team and engineering partner
Before commissioning a modernisation, ask the engineering partner to show the boundaries: what stays, what changes, who owns commands, how faults propagate, how variants are tested and what happens if a release must be rolled back.
A useful proposal should name one pilot station, relevant controller/runtime versions, acceptance tests and the point where a safety review or machine downtime will be needed. It should distinguish a known fixed-price slice from risks that cannot be estimated until the existing machine is understood.
If your machine already has working sequences but difficult interfaces between stations, a staged approach can be a sensible starting point. If critical architecture or hardware has reached an end-of-support condition, the assessment may point to a broader controlled replacement instead.
- Which module has a clear boundary and an expensive recurring problem?
- Can the existing logic be built, versioned, observed and tested?
- What will demonstrate equivalent behaviour on the real machine?
- Who signs off the release, the rollback and any safety-related change?
Frequently asked questions
Do we need to rewrite the PLC program to introduce PackML?
No. You can often introduce shared machine or unit state interfaces around proven logic first. Decide which legacy internals genuinely need refactoring only after their contracts and tests are defined.
Can we keep our existing B&R, Beckhoff or Siemens controller?
Often yes, depending on firmware support, libraries, hardware lifecycle and testability. The migration decision should be based on the specific controller and machine architecture, not just the PLC brand.
Can virtual commissioning replace physical acceptance testing?
No. It can provide repeatable checks of selected control and machine behaviour, but real-machine commissioning, risk assessment and physical safety verification remain necessary.
Should we migrate every module at once?
Usually start with one bounded module and defined evidence. Expand when the pilot proves the state contract, diagnostics, timing, variants and rollback work as intended.
Read next
Before asking for a full rewrite quote, select one troublesome module and write down three things: the current failure or delay, the behaviour the replacement must preserve, and the test that would prove it. This gives the team a concrete starting point.
Talk to neexo about machine software