Arithmetic, units, and numeric mistakes in Structured Text
The Core Idea
A useful calculation has a meaningful result, suitable data types, and consistent units. Structured Text arithmetic needs those choices as well as the correct operators.
What you will learn
Write a calculation with its units and convert between units with a stated factor.
Recognize the inputs that make a calculation meaningless, such as a zero divisor.
Guard a division and report an invalid result instead of letting the program fail.
Why it matters
An expression can execute successfully yet report the wrong quantity. Checking units, precision, and valid inputs makes the result useful to the machine and operator.
The problem
A filling line reports the average fill per bottle for the current batch. A flow totalizer measures the liquid dispensed in kilograms, a counter counts the bottles, and operators read the average in grams.
| Signal | Type | Meaning |
TOTAL_FILL_KG | REAL | Liquid dispensed in the batch, in kg. Starts at 6.0 kg. |
BOTTLE_COUNT | INT | Bottles filled in the batch. Starts at 12. |
AVG_FILL_G | REAL | Average fill per bottle, in g. |
AVG_VALID | BOOL | TRUE while the average means something. |
The program converts kilograms to grams with * 1000.0, divides by the count, and sets AVG_VALID while the count is above 0. Both totals reset to 0 when a new batch starts. The lesson simulator scans every 100 ms.
After you lock in your prediction, set Bottle count to 0 on the human-machine interface (HMI).
See it go wrong
Read the message under the program. Then set the count back to 12 and press Run.
Fix it
Change the program so an empty batch reports 0.0 g with AVERAGE VALID off, and the program never stops. Hidden checks include a large batch and a count that has wrapped negative. Editing pauses the program, so press Run to try your version.
Passing the checks records Structured Text progress on the shared math concept.
What happened and why
A division by zero has no answer, so the program must not reach it. The original program knew a count of 0 was invalid, but it checked after dividing. The guard puts the check first: the division runs only for a count above 0, and the ELSE branch gives an empty batch a defined result.
That result is 0.0 g with AVG_VALID FALSE. A bare 0.0 g would look like a batch of empty bottles. The flag tells the HMI, and any logic that uses the average, that there is no measurement yet.
Units
Put the unit in every name, and convert where the units change:
| Expression | Units | 6.0 kg, 12 bottles |
TOTAL_FILL_KG / BOTTLE_COUNT | kg per bottle | 0.5 |
TOTAL_FILL_KG * 1000.0 / BOTTLE_COUNT | g per bottle | 500.0 |
Read the units across the assignment: kg × (1000 g per kg) ÷ bottles gives g per bottle, which matches AVG_FILL_G. When the units on the right do not match the name on the left, the line is wrong, even if the number looks plausible.
Number ranges
An INT holds −32 768 to 32 767. A batch total in grams passes that limit at about 32.8 kg, and the stored value wraps around to a large negative number. Keep totals and measurements in REAL, and use INT for counts. A counter can wrap too, which is why the guard tests > 0 rather than <> 0.
Common mistakes
Dividing before checking the divisor: a check on a later line never runs. Put the division inside the guard.
Guarding with no
ELSE: when the count drops to 0, the average and the flag keep the last batch's values. Give the invalid case its own result.Forgetting the unit conversion: 0.5 looks like a reasonable number, but it is kilograms in a gram display. Check the units on both sides.
Converting to grams in an
INT: 40.0 kg is 40 000 g, which wraps to −25 536. Keep the total inREAL.Testing
<> 0instead of> 0: a wrapped, negative count passes the test and gives a negative average.
Platform notes
What a controller does on division by zero depends on the platform and the data type. This simulator stops the program and names the line. Real controllers may raise a fault that stops the program, or return an infinite or undefined value and set a status bit. None of those is a usable average, so guard the division on every platform.
In IEC 61131-3 (the international standard for programmable controller languages), dividing an
INTby anINTgives anINTand drops the fraction:7 / 2is 3. This simulator calculates inREALand drops the fraction only when it stores a result in anINT. Convert withINT_TO_REALbefore dividing whenever you need the fraction.
Enable JavaScript to run the embedded simulator and complete the interactive exercises.