A PLC without floating-point instructions still runs a decimal formula exactly: scale every term by 1,000, multiply and add in integer math, and store the result in a double word. With the pulse count in V2000, the ladder steps MUL K1711, ADDD K780, OUTD V2100 store thousandths, and a BCD Int 32 tag with 3 decimal positions shows 125 pulses as 214.655.
A small PLC with no floating-point instructions can still produce a decimal wind speed, flow, or rate to three places. The fix is representation, not instruction hunting: scale every term of the formula by 1,000, run the multiply and add in integer math, store the result in a double word, and let the panel's decimal-positions setting put the point back. With the pulse count in V2000, the ladder steps MUL K1711, ADDD K780, OUTD V2100 store the answer in thousandths, and a 32-bit panel tag shows a count of 125 as 214.655.
What fixed point means
A fixed-point value is an integer that carries an implied scale: the controller stores 214655 and the program treats it as 214.655 because every term was written in thousandths. The integer instructions behind it are exact. An integer multiply and add never round or drift, so a wrong digit can only enter through the scale you chose or the settings that interpret the result.
This controller offers no floating-point (Real) functions, so no search of the instruction set will produce a decimal multiply. Stop looking for one. The controller keeps working in whole numbers, and the scale does the decimal work.
Scale every term by the same factor
Find the term with the most decimal places and scale every term to that place. The multiplier 1.711 carries three places and the offset 0.78 carries two, so thousandths cover both: multiply each coefficient by 1,000 and enter the results as integer constants. The stored result is the wind speed in thousandths, so the offset constant adds 0.780 in displayed units, exactly what the original formula means.
A term left unscaled shifts every reading by its own unscaled value, and a multiplier truncated to a whole number collapses the reading entirely. The plausible wrong numbers near the end of this page show what each mistake looks like on screen.
| Term | Formula value | Stored constant |
|---|---|---|
| Multiplier | 1.711 | K1711 |
| Offset | 0.78 | K780 |
| Result at 125 pulses | 214.655 | 214655 |
Keep the result in a double word
The product outgrows a single word long before the display looks large. A 16-bit word holds at most 65535 unsigned or 32767 signed, and the first working count already passes both, because 125 × 1711 = 213875. The double word carries the full product and the offset across two consecutive words, V2100 and V2101.
Reserve both words for this one result and read them together as a 32-bit object starting at V2100. A single-word tag reads half of the pair and displays a number unrelated to the count.
Run the math in the one-second interrupt
Put the steps in the existing 1-second interrupt, O1, where the count is already current:
LD V2000loads the pulse count collected over the 1-second interval.MUL K1711multiplies by the scaled coefficient and leaves the double-word product in the accumulator.ADDD K780adds the scaled offset.OUTD V2100stores the double word to V2100/V2101.
Do not add a second timing routine or change the interrupt period to suit the math. The input side already works, and the calibration constants assume a 1-second interval, so a different period skews every reading. Keep the raw count at V2000 untouched, so a counting fault can be told apart from a math fault later.
Worked example: 125 pulses in one second
The inputs, with their sources:
- Count: 125 pulses in the 1-second interval, delivered by the high-speed input (HSIO) into V2000.
- Multiplier: 1.711 per pulse, from the sensor's calibration, scaled to K1711.
- Offset: 0.78, from the same calibration, scaled to K780.
- Panel tag: BCD Int 32 starting at V2100, decimal positions set to 3.
The rule in words: displayed wind speed × 1,000 = pulse count × 1711 + 780.
The arithmetic, written out:
- 125 × 1711 = 213875, the accumulator after the multiply.
- 213875 + 780 = 214655, the accumulator after the add.
The result: OUTD writes 214655 to V2100/V2101, the BCD Int 32 tag reads the pair, and the 3 decimal positions render it as 214.655.
The decision this example hands you: if the monitored pair reads 214655 and the screen shows 214.655, the chain from counter to screen checks out. If the pair reads 214655 but the screen shows 214655 with no point, only the decimal-positions setting is wrong. If the pair does not read 214655, check the count in V2000 first, then the operands of the multiply and add. The margin is wide: the tag's 99999999 ceiling corresponds to 58444 counts per interval, so a working count of 125 uses about 0.2 percent of it.
Set the panel tag to match the scale
Define the tag as BCD Int 32 starting at V2100 and set the numeric object's decimal positions to 3. The 32-bit width reads the whole pair, and the positions setting supplies the implied point, so the stored integer renders with the point three places from the right.
A tag typed as floating point or as a single word reads the same bytes the wrong way and displays a number unrelated to the count. If a panel shows implausibly large positive numbers, the tag's data format is the first suspect; the companion fix is covered in set the signed decimal data format on an HMI tag.
When a value arrives with no point at all, the positions setting is sitting at zero. The same symptom on a compact controller, with its own cause and fix, is worked through in decimal places not displayed on a controller display. When a different project needs more resolution, the same positions setting carries it, as showing more decimal places on an HMI numeric display describes.
Check the count range before you commission
Work the formula at the worst count the sensor can deliver in one second and compare it with what the storage holds. A signed 32-bit integer in binary form tops out at 2147483647, which puts the count ceiling at (2147483647 - 780) / 1711 = 1255103 pulses per interval. The BCD Int 32 tag carries 8 decimal digits, at most 99999999, which puts its ceiling at (99999999 - 780) / 1711 = 58444 per interval. Either ceiling sits far above any rate a cup sensor can pulse in 1 second, so the calculation as scaled has room to spare for this job.
If a future formula needs a finer scale, redo this check first, because the ceiling falls in step with the scale: at 10,000, the constants become K17111 and K7800, and the BCD ceiling drops to (99999999 - 7800) / 17111 = 5843 counts per interval.
Plausible wrong numbers and their causes
- The screen shows 214655 with no point: the decimal positions are at 0. Set 3; no other change is needed.
- The screen reads 213.956 where 214.655 was expected: the offset went in unscaled, so every reading is short by exactly 0.780.
- The screen reads 0.905: the multiplier was truncated to 1, which collapses the calculation to its offset.
- The screen shows a number unrelated to the count: the tag is typed as floating point or as a single word and interprets the double word as something it is not.
- The controller pair is wrong too: the count source is at fault, not the math. Check V2000 against the pulses expected in 1 second, then the operands K1711 and K780.
The decision
Recommendation: keep the chain integer from count to screen. Scale every term to the same place value, set by the term that carries the most decimal places; run the four ladder steps in the existing 1-second interrupt; reserve the two result words and read them only as the 32-bit pair; and type the panel tag as the 32-bit integer with decimal positions matching the scale. Change the scale only when a formula's worst term carries more places, and recheck the count ceiling at the new scale before you commission.
Questions
Why scale by 1,000 and not by 100?
The scale must cover the term with the most decimal places. The multiplier 1.711 carries three and the offset 0.78 carries two, so a scale of 100 would drop the third digit of the coefficient and bias every reading. At 1,000 the arithmetic is exact and the panel needs exactly 3 decimal positions. If a future formula carries four places, move the whole calculation to a scale of 10,000 and recheck the count ceiling at that scale first.
What units does the displayed 214.655 carry?
Whatever units the sensor's calibration converts pulses into. The scale changes only where the decimal point is implied; the constants 1.711 per pulse and the 0.78 offset are the sensor's own numbers, stored exactly. If the calibration sheet gives mph, the display reads mph, and if it gives m/s, the display reads m/s. Put the unit on the display object so nobody has to guess.
At what count would a single word overflow?
A 16-bit binary word tops out at 65535 unsigned, and 1711 × 39 = 66729 passes it, so the product overflows once the 1-second count reaches 39. In BCD the same single word holds only four digits, at most 9999, and 1711 × 6 = 10266, so it overflows at a count of 6. That is why the product lives in a double word even though the display shows only three digits before the point.
Can I divide the result by 1,000 to show whole units?
Integer division discards the remainder: 214655 / 1000 leaves 214, and the 0.655 is gone for good. If operators only need whole units, store thousandths anyway and set the object's decimal positions to 0, or compare alarm thresholds directly in thousandths. Keeping the raw pulse count at V2000 also lets you tell a counting fault from a math or display fault.
Planning information, not legal or engineering advice. Rules differ by place: check codes and permits with your local authority and your licensed trades.