COM_MOD_MAST sets DONE TRUE for one task cycle after it completes or aborts, so on a 10 ms task the pulse lasts one task interval. Logic that runs before the block, or in a slower task, never sees it. Check DONE together with ERR in the same task pass, immediately after the block call, and latch the result into your own flags.
A Modbus master block that reports with a pulse hides its result from carelessly placed logic. The AC500 manual is explicit about COM_MOD_MAST: when the block completes or aborts on an error, DONE goes TRUE for one cycle and is gone by the next. The miss is silent, because nothing faults. The slave answers, and the handshake step simply never advances. This page gives what one cycle means, the four symptoms that point at a missed pulse, the placement that catches DONE and ERR together, a bench test that shows the fix works, and a timing example with the arithmetic shown.
How long does COM_MOD_MAST hold DONE TRUE?
The AC500 manual gives DONE a single pass. After the block completes or aborts on an error, DONE is TRUE for one cycle. On a task with a 10 ms interval the flag is readable for about that long and is FALSE again by the next pass.
The manual states it in one line:
Two things follow. DONE is a pulse, so any logic that needs the result has to run while the pulse is up; there is no level to poll later. The pulse also carries two meanings, because a clean completion and an error abort raise it alike. ERR read in the same pass tells you which one you got. The pulse is roughly one task interval wide, which is why nobody catches it by watching the variable online.
What does one cycle mean for the block?
One cycle means one pass of the task that calls the block. Measure the pulse from one execution of COM_MOD_MAST to the next: the flag is up during exactly one of those passes.
That is the task model of IEC 61131-3, the standard behind PLC programming. A task calls each of its programs once per cycle, in the order you configure, and one pass is one of those calls. The manual's cycle is that pass. Practically, time the pulse from one execution of COM_MOD_MAST to the next: TRUE for one execution, FALSE at the following one. The pulse lasts one task interval regardless of how long the telegrams took.
Library versions move names around. The AC500 V3 documentation describes its RTU master function block as a wrapper over the ModRtuMast block, adjusting input parameters per function code. A wrapper changes the call, not the placement rule: check the completion outputs in the pass after the call, on the manual page of the block your version exposes.
Why does my logic never see the pulse?
Logic sees the pulse only when it executes after the block within the same task pass. A program called earlier in the task, or a slower task sampling between pulses, reads DONE as FALSE every single time.
Program order inside one task decides it. Take two programs in the same task: comTask calls COM_MOD_MAST and checkTask runs after it. When the block finishes a job during pass 47, DONE is TRUE for the rest of pass 47. checkTask samples it and sees TRUE, and the flag is back to FALSE in pass 48. Swap the call order and checkTask samples before the block reports: it reads FALSE in pass 47, and by pass 48 the pulse has already gone.
A second task samples the pulse from outside. A checker in a 50 ms task runs once for every five passes of the fast task, and a pulse that lives one pass lines up with a sample only now and then. The worked example below puts the hit rate at about 1 in 5.
To find the call order in your own project, trace it the way PLC execution order: tracing logic across task layers describes. One-pass outputs behave the same wherever they surface. If you have chased a pulse that never reached an HMI screen, the article why an R_TRIG pulse never shows on the HMI screen covers the same ordering problem from the screen side.
Which symptoms point at a missed DONE pulse?
Four symptoms fit a missed one-cycle pulse: a handshake step that never advances although the slave answers, an error action that never fires although the slave is gone, success actions that run on failed jobs, and counters that move in bursts.
Match yours to the placement problem it names:
- The handshake step never advances, although the slave answers. The step logic samples DONE after the pulse has passed: it is called before the block in the same task, or it runs in another task.
- The error action never fires, although the slave is gone. DONE went up together with ERR for one pass; the error handler reads ERR in a later pass and finds FALSE. Latch the abort inside the pulse pass.
- Success actions run on failed jobs. DONE read without ERR treats every abort as a good job, because the manual ties DONE to completing and to aborting alike. ERR in the same pass separates the two outcomes.
- Counters move in bursts, or once in a while. The checker runs in a slower task and catches a pulse only when its sample lands inside one; the worked example below shows the arithmetic.
The bench test in the next section tells placement problems and evaluation problems apart. A counter incremented inside the pulse pass shows whether the block reports at all.
How do you catch DONE and ERR in the same pass?
Catch the pulse where it lives: keep the DONE and ERR check in the same task as the block, in a program called after it, and copy the outcome into your own flags before the pass ends.
- Find the task that calls COM_MOD_MAST and list its programs in call order. The checker belongs after the block call.
- Evaluate DONE and ERR together: DONE TRUE with ERR FALSE is a clean job, DONE TRUE with ERR TRUE is an abort.
- Copy the outcome into your own flags and counters inside that pass, in a program the task calls after the block:
(* checkResult: a program the task calls after the master block *)
IF instMaster.DONE THEN
IF instMaster.ERR THEN
abortCount := abortCount + 1; (* abort, latched in the same pass *)
ELSE
okCount := okCount + 1; (* clean completion *)
jobResult := TRUE; (* flag for the rest of the program *)
END_IF
END_IF
Then let every other program and task read your flags. Nothing outside the pulse pass should sample DONE directly.
DONE and ERR are the outputs the block documents. instMaster is the instance name you gave COM_MOD_MAST when you declared it, okCount and abortCount are integer counters you declare, and jobResult is a BOOL you clear wherever the job is consumed.
Recommendation: keep the block call and its DONE and ERR check in one task, with the checker called immediately after the block, and copy the outcome into your own flags inside the pass. If all your logic lives in a single program, put the check on the lines right after the block call, so no call order has to change. Read the flags from slower tasks and other programs, and never sample DONE from outside the pulse pass.
What should you check at the bench?
Verify with counters, not by watching a variable online. A counter incremented in the pulse pass gains exactly one count per finished job, and a second counter on the ERR branch gains exactly one per forced abort.
- One job. Trigger a single read and watch okCount go from 0 to 1. If it stays at 0 while the slave clearly answers, the check still runs in the wrong pass; go back to the call order.
- One forced abort. With the process in a safe state, dial in an unused slave address or pull the slave off a bench rig, so the job aborts on a response timeout. abortCount gains 1 and okCount stays where it was, which shows ERR arrives together with DONE in one pass. Run this test on a bench setup or a stopped line, never by pulling the communication cable on a running cell.
- Ten jobs. Trigger ten single jobs and read okCount. It should read exactly 10; a count of 7 or 8 means the checker is still sampling late, typically from a slower task.
What does the timing look like in a worked example?
In this example a task on a 10 ms interval calls the master block, a poll command triggers one job every 250 ms, and a checker in a 50 ms task catches only two completions out of ten until the check moves into the fast task.
Setup. The poll command starts one read job every 250 ms. The task that calls COM_MOD_MAST runs on a 10 ms interval, so each finished job raises a DONE pulse about one interval wide. A checker in a second task samples DONE every 50 ms.
The miss. In 2.5 s the poll produces 10 jobs (2500 ÷ 250 = 10). The checker takes 50 samples in the same 2.5 s (2500 ÷ 50 = 50), but each sample has only the 10 ms pulse window out of its 50 ms interval to land inside: 10 ÷ 50 = 1 in 5, a 20% hit rate. Ten jobs produce about 2 counts, and 8 completions pass unseen.
The fix. Move the counter into the program the fast task calls right after the block. It now executes inside every pulse pass, so 10 jobs give okCount = 10, and a forced abort adds 1 to abortCount in the same pass. The slave, the baud rate and the poll period never changed; only the placement of the check did.
Decision: with the check in the block's own task you catch 10 of 10 completions; sampled from a 50 ms task you catch about 2 of 10. The gap does the damage: at a 100 ms sampling interval the same one-interval pulse is caught about 1 time in 10 (10 ÷ 100).
Questions
Does the serial baud rate change how long DONE stays TRUE?
No. The pulse is one pass of the task, so its width follows the task interval, whether the slave answers in 5 ms or 50 ms. Baud rate and response timeout set how long the block stays busy. A slower answer only delays the pass in which DONE appears; it does not widen the pulse.
Does DONE need a manual reset after it is caught?
No. One cycle means the block drives the output back to FALSE before the next pass, so there is nothing to clear. Writing FALSE to a function block output from your own code fights the block over the same variable. Copy what you need into your own flag inside the pulse pass and clear your flag where the job is consumed.
What does DONE look like when the job aborts on a timeout?
The manual's sentence covers aborts due to an error, so a dead or misaddressed slave produces the same one-cycle pulse, with ERR TRUE alongside DONE in that pass. That is why the abort counter belongs on the same pass. A timeout never shows up as a level you can read later, only as a pulse you latch while it is up.
Planning information, not legal or engineering advice. Rules differ by place: check codes and permits with your local authority and your licensed trades.