REAL_TO_TIME truncates your setpoint, and the compiler is fine with it
An operator sets 2.7 seconds. The PLC runs 2.0. Nothing in the project is marked as wrong: it compiles, downloads and runs. The value was lost in a single line of type conversion.
The line
Somewhere between the HMI value and the timer preset there is a conversion, and it usually looks like this:
tPulse := REAL_TO_TIME(rSetpointSec) * 1000;
// intent: seconds → milliseconds
What actually happens
REAL_TO_TIME does not convert seconds. It takes the number as a count of milliseconds and returns a TIME, whose resolution is one millisecond. So 2.7 becomes T#2ms — the fraction is gone at the conversion. The multiply that follows then scales an already damaged value: T#2ms * 1000 = T#2s.
The setpoint didn't drift. It was rounded down before it was used, and every value between 2.0 and 2.9 produces the same result on the machine.
Why the compiler stays silent
Every step is legal. REAL_TO_TIME accepts a REAL, multiplying a TIME by an integer is defined in IEC 61131-3, and the assignment types match. There is no rule being broken — the meaning is wrong, not the syntax. Type conversion is exactly where a compiler stops being able to help you: it checks that the types line up, not that the number still means what you meant.
The correct conversion
Scale first, convert second — so the fraction is still there when the value becomes milliseconds:
tPulse := REAL_TO_TIME(rSetpointSec * 1000);
// 2.7 → 2700.0 → T#2s700ms
The same mistake in other clothes
The pattern is not specific to REAL_TO_TIME. It appears wherever a conversion narrows a value and a scaling factor is applied afterwards:
iPercent := REAL_TO_INT(rRatio) * 100;
// 0.85 → 1 → 100, not 85
iPercent := REAL_TO_INT(rRatio * 100);
// 0.85 → 85.0 → 85
How to find it in your own project
Without any tool: search the project for _TO_TIME and _TO_INT, and look at what stands to the right of each conversion. If there is a multiplication or a division after the closing parenthesis, read that line twice — a scaling factor outside the conversion is the signature of this bug.
Two more places worth checking while you are there: conversions fed directly from an HMI variable (the operator can enter a fraction the code never expected), and any TIME preset that a colleague once described as “close enough” on site.
Catching it automatically
This is one of the 34 checks in PLC Lint. It reads a PLCopenXML export of your project and reports the conversions where the scaling happens outside — with the POU and the line. You can run it on your own machine so the export never leaves it, or upload it here and get the report in about ten seconds.