A duplicate output warning means two or more rungs write the same output address and the last write in the scan decides the terminal. End each mode's rung on its own internal request bit, OR the bits on one final rung that drives the physical output, and both the warning and the order dependence disappear.
Your program check is telling the truth: two or more rungs write the same output address. The report calls it a warning, so the program still loads and runs, but the machine runs on execution order. In auto, the main program writes the output; later in the same scan, the manual routine writes it again, and the last write wins. That is why the panel buttons work and the auto cycle does not, or the reverse, depending on which section runs last. The fix is structural. End each mode's rung on its own internal request bit, then drive the physical output from one final rung that ORs the requests. The duplicate output warning disappears because every output has exactly one writer, and no later rung can erase a valid request.
What the duplicate output warning means
The checker compares instruction addresses across the whole project and flags any output written from more than one place. Vendor user manuals document this duplicate reference check, and on most packages it runs as part of the program check: the report shows warnings while the program still loads and runs.
The scan model explains why the warning matters. The controller solves rungs in order, top to bottom, writes results into an output image, and copies the image to the terminals at the end of the scan. A small machine PLC commonly completes that cycle in a few milliseconds; a 3 ms scan is a typical figure. When two instructions write one address in the same scan, the value left by the last write is the one that reaches the terminal.
Coil style decides what a false rung writes. A coil that follows its rung condition writes 0 when its contacts are false, so a later false rung erases an earlier true write in the same scan. A set-dominant style leaves the bit unchanged on a false rung, so two writes act like an OR on one CPU and like an override on another. The warning marks exactly that ambiguity, and one writer per output removes it on every controller.
Symptoms and what each points to
- Manual works, auto never starts the output. The routine's write lands after the main program's write in the scan, and its false condition clears the auto request before the image reaches the terminals.
- A panel button moves the output while the machine is in auto. The manual rung has no mode contact in series, so its write executes in auto too.
- The output drops whenever the panel returns to a certain screen. A screen-change routine is writing the address; that is the separate case covered in clearing a PLC coil range when the HMI returns to a screen.
- An unrelated edit changes machine behavior with no new warning. The edit moved a rung or a routine call, and order-dependent writes changed hands.
- Warnings on a machine that runs fine today. The result depends on scan order and instruction type, so today's behavior holds until something reorders the program.
Checks to run first
- Read the whole program-check report and write down each flagged address. On a machine with 16 outputs and 6 warnings, this first pass takes about 5 minutes.
- Search the project for each address and list every instruction that writes it: main program rungs, every subroutine, and any block move or clear whose target range covers the address.
- Mark execution order. Your controller's manual documents the order in which the main program and routines execute; note which write runs last in auto and which runs last in manual.
- Write the mode rules before you edit: a panel button commands an output in manual only, and the permissives that must hold in both modes belong on the final output rung.
The fix: one writer per output
- Back up the project.
- In the auto section, replace the write to the output with a write to
Widget_On_Auto, keeping the sensing contacts on the rung: Auto_Mode AND Part_Present → Widget_On_Auto. - In the manual routine, end the rung on
Widget_On_Manualwith the mode contact in series: Manual_Mode AND HMI_Button → Widget_On_Manual. The series mode contact is what keeps the panel from commanding outputs in auto. The command-bit layout is the same one described in make an HMI button turn on a PLC output through a command bit. - Add one final rung, in one place, that drives the physical output: the two request bits in parallel, shared permissives in series. As a logic line:
Y7 = (Widget_On_Auto OR Widget_On_Manual) AND Guard_OK. The contact names are illustrative; keep your own tag names. - Delete every other write to Y7, including the writes inside the subroutine. Some CPUs offer an instruction called OROUT that merges writes into an output address; availability and exact behavior vary by CPU, and a visible two-bit rung reads faster during a breakdown, so the plain rung is the default here.
- Repeat for every flagged address, then run the program check again and confirm the warnings for those addresses are gone, 0 duplicate references left.
Worked example: one output through auto and manual
A filler machine has 16 outputs. 6 of them are also operable from the panel in manual, and the program check reports 6 duplicate coil warnings. Follow the conveyor output, Y7 in this example. Main program rung 18 reads Auto_Mode AND Part_Present AND Guard_OK → Y7. The manual routine executes after the main program, and its rung 4 reads Manual_Mode AND HMI_Button → Y7. Take the scan at 3 ms, in the ordinary few-millisecond range for a small machine PLC: 1 ÷ 0.003 s ≈ 333 scans each second, so both writes land on Y7 333 times every second.
Before the fix, with both rungs writing Y7 directly:
| Case | Rung 18 writes | Routine rung 4 writes | Y7 at end of scan |
|---|---|---|---|
| Auto, part present | 1 | 0 | 0, auto command lost |
| Manual, button pressed | 0 | 1 | 1 |
Auto: 1 then 0, last write wins, Y7 = 0. Manual: 0 then 1, Y7 = 1. The buttons work and the auto cycle does not, which matches what the floor sees.
After the fix, with Y7 = (Widget_On_Auto OR Widget_On_Manual) AND Guard_OK and Guard_OK healthy in every row:
| Case | Widget_On_Auto | Widget_On_Manual | OR of the two | Y7 |
|---|---|---|---|---|
| Auto, part present | 1 | 0 | 1 OR 0 = 1 | 1 |
| Manual, button pressed | 0 | 1 | 0 OR 1 = 1 | 1 |
| Auto, operator taps the button | 1 | 0 AND 1 = 0 | 1 OR 0 = 1 | 1 |
All 6 warnings clear. The conveyor follows the auto cycle, a stray button press in auto moves nothing, and manual control passes through the same guard contact as auto.
Recommendation: whenever the program check names an output address more than once, give that address one writer. End each mode's rung on its own internal bit, OR the bits on a single final rung with the shared permissives in series, and gate the manual request with the manual-mode contact so the panel cannot move outputs in auto. On the example machine that is two request bits and one output rung for each of the 6 flagged addresses, and the warnings go away together with the order dependence.
Verify both modes before production
One boundary stays fixed: emergency stop and guard circuits stay in the safety layer, hardwired or safety-rated as your machine standard requires, and this rework only rearranges ordinary command writes.
- Put the machine in a safe state for the first runs: movers disconnected or the drive in a commissioning state.
- Run auto for at least 10 minutes and confirm each output follows its auto request. Tap a panel button during auto: Widget_On_Manual stays 0 because Manual_Mode is 0, and the output holds its auto state.
- Switch to manual and confirm the button drives the output through the permissives. Release the button and the request drops, because a panel button is momentary; holding an output through a timed sequence is a timing design, covered in the timer-rung fix for an HMI button output that only stays on while pressed.
- Watch the final rung solve live: put the request bits and the outputs on one monitor screen; displaying 16 PLC input and output bits on one screen shows the layout.
- Run the program check once more and confirm 0 duplicate references on the 6 addresses, then return the machine to service.
When the same line also owes the crew a status board readable from the aisle, that is a separate screen doing a separate job; see shop-floor screens and andon-style boards.
Questions
Where does a second write hide when an output looks like it is written once?
In a subroutine that two different callers both run, so its output write executes twice in one scan; in a block move or block clear whose target range covers the address; in a routine added for one job and left in the project; and in rungs nobody has opened since commissioning. Search for the address itself and for every range instruction that covers it, then list each hit with its location before you change anything.
Can I just switch off the duplicate coil check?
Many programming packages include an option that turns off duplicate-coil or duplicate destructive-bit detection. The option removes the message and nothing else. The writes stay order-dependent, a later edit can still flip which rung wins, and the next person to open the project has no flag pointing at the problem. Leave the check on and give each output one writer.
Is a duplicate output warning an electrical fault?
No. The program check compares instruction addresses inside the project file, so it speaks only about software writes. A wiring, fuse or output-driver fault shows up the other way: the output stays dead or stuck no matter what the logic writes, and a meter at the output terminal settles it. Clean the logic for the warning; take the meter to a dead output.
Planning information, not legal or engineering advice. Rules differ by place: check codes and permits with your local authority and your licensed trades.