Store the first valid analog sample into MIN and MAX, then compare every new sample once per scan and overwrite whichever limit it beats. MAX minus MIN is the runout spread for the operator's panel. Never seed MIN at zero: on a 0-10 V input scaled to 1.000 mm, a zero-seeded MIN pins the differential at the full reading, about eleven times the true spread.
To catch the lowest and highest readings from an analog signal, store the first valid sample into two variables, MIN and MAX, then compare every new sample against them once per scan and overwrite whichever limit the sample beats. The operator panel shows MIN, MAX and their difference, and that difference is the runout spread for the tube in the V-blocks. The step that ruins this measurement is the reset. Writing zero into MIN hides every real reading, because runout readings all sit above zero. Seed both limits from the first valid sample instead, and the difference field reads 0.000 at the start of each part and the true spread at the end of one full turn.
What you need
- An analog input the PLC reads every scan, plus the module's per-channel update time and your program's scan time, the two numbers the turning-pace arithmetic below uses.
- Two numeric variables for MIN and MAX, one for the difference, one bit for the first-sample flag.
- Three numeric fields and one reset pushbutton on the operator panel.
Start from the first valid sample, not zero
After a reset the temptation is to write 0 into both variables. MAX recovers on its own, because any real reading sits higher than 0. MIN never recovers on a runout measurement: every valid sample sits above zero, so a MIN held at 0 is never beaten and the displayed difference climbs to the largest reading itself. On a 0-10 V sensor scaled to a 1.000 mm span, true readings between 0.487 and 0.535 mm would display a difference of 0.535 - 0.000 = 0.535 mm against a true spread of 0.048 mm, about eleven times too high (0.535 / 0.048 = 11.1).
Two resets work. Preset MIN to the top of the scaled range, 1.000 mm here, and MAX to the bottom, and the first turn overwrites both. Or clear a first-sample flag so the next valid sample seeds both limits, which is the method this article builds. The flag method carries no hard-coded range, so a change of sensor or span needs no edit to the reset logic.
The capture logic, step by step
- Create a first-sample flag. A plain bit, cleared at power-up and cleared by the reset button. While it is cleared, the program is waiting to seed.
- Seed on the first valid sample. On a scan where the flag is cleared and the analog value is valid, copy the sample into MIN and MAX and set the flag. Both limits now equal the current reading, so the difference is 0.000.
- Update once per scan. While the flag is set and the sample is valid: a sample below MIN overwrites MIN, a sample above MAX overwrites MAX, and a sample between the limits changes neither.
- Compute the difference each scan as MAX minus MIN. That single subtraction is the runout number the panel shows.
- Reset by clearing the flag only. Never write zeros into the limits. The next valid sample re-seeds both, so a previous part's numbers cannot carry into the new measurement.
- Let the values hold. Nothing in the logic clears them on a timer, so MIN, MAX and the difference stay readable after the part stops, until the operator resets for the next one.
// Illustrative names, types and initial values. Map the compares and the
// flag onto the compare, move and system instructions your software offers.
FIRST_SAMPLE_DONE : BOOL := FALSE // cleared at power-up and by RESET
MIN_MM : REAL := 0.0
MAX_MM : REAL := 0.0
DIFF_MM : REAL := 0.0
SAMPLE_MM : REAL // this scan's scaled reading in mm
// Seed both limits from the first valid sample
IF NOT FIRST_SAMPLE_DONE AND INPUT_VALID THEN
MIN_MM := SAMPLE_MM
MAX_MM := SAMPLE_MM
FIRST_SAMPLE_DONE := TRUE
END_IF
// Update once per scan while capture is armed
IF FIRST_SAMPLE_DONE AND INPUT_VALID THEN
IF SAMPLE_MM < MIN_MM THEN MIN_MM := SAMPLE_MM END_IF
IF SAMPLE_MM > MAX_MM THEN MAX_MM := SAMPLE_MM END_IF
DIFF_MM := MAX_MM - MIN_MM
END_IF
// Reset arms the next capture; it never writes zeros
IF RESET_PUSHED THEN
FIRST_SAMPLE_DONE := FALSE
END_IF
INPUT_VALID stands for the module's own fault or out-of-range condition. If your project provides one, use it, so an unplugged sensor cannot seed or update the limits. The stationary check at the top of the final checklist is the test of this seed path.
Scan time and input update time set the turning pace
The PLC reads the input register once per scan; the module converts on its own clock and usually updates slower than the scan. In the worked example below the scan is 3 ms and the input update is 12 ms, so each fresh conversion sits in the register for about four scans (12 / 3 = 4). Comparing on every scan costs nothing and cannot miss a new value; the accuracy limit is the number of fresh conversions per revolution.
A 12 ms update is about 83 conversions per second (1000 / 12 = 83.3). A part turned once per 3 seconds offers about 250 conversions per turn (3000 / 12 = 250). The same part turned once per 0.5 seconds offers about 41 (500 / 12 = 41.7), and then two conversions can straddle the high point: the stored MAX is whichever landed closest, and it reads low.
If the input card converts its channels in turn, each channel updates once per full sweep, so a four-channel card stretches this wait to four times as long. Put your own scan time and the module's per-channel update time into the same divisions.
The classic sampling rule puts the sample rate at least twice the rate of the measured signal, but a sharp runout peak needs a sample to land close to it, so the deciding test is practical: measure the same turn at two paces, and if the stored difference falls at the quicker pace, that pace misses the peak.
Worked example: one turn of tube, in numbers
Scenario: a steel tube in V-blocks, an analog proximity sensor with a 1.000 mm span and a 0-10 V output watching the surface, and a 12-bit analog input counting 0 to 4095.
Scaling first. 10 V across 4096 counts is 2.44 mV per count (10 / 4096 = 0.00244 V), and 1.000 mm across the same counts is 0.000244 mm per count. With the part stationary the sensor reads 0.512 mm, about 2098 counts (0.512 / 0.000244 = 2098). The reset seeds MIN = MAX = 0.512 mm and the difference field shows 0.000 mm.
One safety point before the spin: a long tube turned by hand can whip at the overhang, so support both ends in the blocks and keep hands clear of the rotating section.
The operator turns one full revolution in about 3 seconds. At the 3 ms scan that is 1000 scans (3000 / 3 = 1000), and at the 12 ms update about 250 fresh conversions (3000 / 12 = 250), each held for about four scans. Capture stores MIN = 0.487 mm and MAX = 0.535 mm, so the panel shows 0.535 - 0.487 = 0.048 mm. That is 0.048 / 25.4 = 0.0019 in, call it 1.9 thousandths, and 197 counts (0.048 / 0.000244 = 197).
The same part turned once per 0.5 seconds offers 41 conversions. This time two conversions straddle the high point, the stored MAX is 0.531 mm, and the difference falls to 0.531 - 0.487 = 0.044 mm, about 1.7 thousandths (0.044 / 25.4 = 0.0017). The 0.004 mm drop between the two paces is the missed peak, which is the two-pace repeat doing its job.
Decision: at the example's 12 ms update, the 3-second pace stored the full swing and the half-second pace clipped it. The two-pace repeat is what sets the pace for the work instruction.
One unit everywhere
Capture the limits in raw counts and scale all three numbers for display, or scale every sample first and capture in engineering units. Either is fine; mixing the two is not. A scaled live sample compared against limits held in raw counts compares two different units, and the result is meaningless. In the example the capture runs in counts and the panel scales: 197 counts times 0.000244 mm per count comes back to 0.048 mm on the difference field.
Show the three numbers on the panel
Give MIN, MAX and the difference their own numeric fields in the same unit and the same decimal format; three decimals suits millimeter work. Put the reset pushbutton on the same screen, labeled so the operator knows it arms the next part. If a field stays blank while the PLC holds a good value, the tag address is the first suspect, which is the fix in HMI numeric display shows nothing: check the tag address first.
Power cuts and retentive values
If the limits and the flag come back cleared after a power cut, this design heals itself: the cleared flag waits for the first valid sample and re-seeds both limits. If the limits are retentive, yesterday's numbers reappear with no part under the sensor, and the operator can read a stale result as this part's. Choose the behavior deliberately; non-retentive limits with the seed flag fit this measurement. Clearing a flag at power-up is the same first-scan habit that puts control bits into a known state after an outage, which we cover in Initialize PLC bits to a safe state after a long power outage. The HMI side of values that vanish at power loss is in why an HMI setpoint resets to zero after a power loss.
How to check it worked
- Part stationary, press reset: the first valid sample must set MIN and MAX both to the current reading, and the difference field must show 0.000. This is the test of the seed path.
- Nudge the sensor to a slightly smaller gap: only MIN falls. Nudge to a larger gap: only MAX rises. Bring the sensor back to mid-span: neither limit moves.
- Complete one full turn and stop: all three numbers hold after the part stops, and the difference field still equals MAX minus MIN.
- Press reset mid-turn by accident: the next valid sample re-seeds both limits, and nothing from the aborted turn survives.
- Repeat the whole measurement at two paces. If the stored difference falls at the quicker pace, slow the pace in the work instruction until repeats agree.
Recommendation: Seed MIN and MAX from the first valid analog sample, update both once per scan while capture is armed, and reset by clearing the seed flag, never by writing zeros into the limits. Keep the hand turn at one revolution per 2 to 3 seconds for an input updating every 12 ms, and confirm that pace with the two-pace repeat: once slowing the part no longer changes the stored difference, write that pace into the work instruction.
Questions
Does this change with a 4-20 mA sensor?
The compare logic is identical. The difference is the live zero. On a 12-bit input that maps the full 0-20 mA across the counts, 4 mA reads about 819 counts, one fifth of 4096, so a valid 4-20 mA signal never falls below it and counts under 819 mean a broken wire or a dead sensor. Add that threshold to the valid-sample condition. If the card maps 4-20 mA to the full count range instead, its under-range fault does the same job.
Is the captured differential the true runout?
The stored differential is the largest spread among the samples the PLC kept, so it is a floor on the true peak-to-valley swing. A stored sample rarely lands exactly on the high point, and the quicker the part turns, the further the closest sample can fall from it. A dial indicator follows the surface through every position, so treat the panel number as a process check and the indicator as the acceptance measurement.
Why do MIN and MAX keep yesterday's numbers after a power cut?
The variables were made retentive, so the PLC restores the last stored limits with no part under the sensor, and the operator can read a stale result as this part's. Make the limits and the seed flag non-retentive: a cleared flag waits for the first valid sample and re-seeds both limits on its own. If your platform holds values unless you clear them in the program, clear the flag on the first scan after power-up.
Planning information, not legal or engineering advice. Rules differ by place: check codes and permits with your local authority and your licensed trades.