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.

SignalTypeMeaning
TOTAL_FILL_KGREALLiquid dispensed in the batch, in kg. Starts at 6.0 kg.
BOTTLE_COUNTINTBottles filled in the batch. Starts at 12.
AVG_FILL_GREALAverage fill per bottle, in g.
AVG_VALIDBOOLTRUE 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:

ExpressionUnits6.0 kg, 12 bottles
TOTAL_FILL_KG / BOTTLE_COUNTkg per bottle0.5
TOTAL_FILL_KG * 1000.0 / BOTTLE_COUNTg per bottle500.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 in REAL.

  • Testing <> 0 instead 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 INT by an INT gives an INT and drops the fraction: 7 / 2 is 3. This simulator calculates in REAL and drops the fraction only when it stores a result in an INT. Convert with INT_TO_REAL before dividing whenever you need the fraction.

Enable JavaScript to run the embedded simulator and complete the interactive exercises.