Calibration machines that verify flow-rate behaviour on small fluid components require a deterministic way to decide whether the observed response of the part matches the expected response. On a typical Omron CJ2M / CP1H / CP2E platform programmed with CX-Programmer, a 0–10 V signal from a flow meter is scaled into engineering units, sampled at a fixed period, and stored in a 30-point circular buffer. The buffer is then evaluated in a single scan to flag the part as ideal, blocked, leaking or stripped using a combination of linear regression and second-derivative (slope-change) statistics.
This reference describes the math, the threshold selection, the structured text function block that performs the classification, and the commissioning steps that take the algorithm from a fresh CX-Programmer project to a verified production recipe.
1. Application Overview
A flow-calibration station takes a part, drives a small DC gear motor that turns an adjustment screw, and waits for the flow to ramp from 0 to a setpoint over a 6 second window. The expected behaviour of a good part is a near-linear ramp whose slope corresponds to the screw’s pitch. The four classes the cell must distinguish are:
| Class | Visual signature | Process meaning |
|---|---|---|
| Ideal | ~45° straight line from 0 to setpoint | Accept the part, release to next station |
| Blocked | Sharp upward spike then plateau | Orifice plugged, route to reject bin |
| Leaking | Near-horizontal line, slope ≈ 0 | Seal failure, rework at the seat |
| Stripped | Parabolic / S-curve, slope changes sign | Screw threads damaged, scrap |
The operator wants a single pass/fail decision plus a class code, and the customer wants the recipe held as CX-Programmer data so the part number drives the thresholds on a changeover.
2. Signal Conditioning and Scaling
Raw flow-meter output enters an Omron CP1W-AD041 or CJ1W-AD041-V1 analog input. Resolution is 1/6000 (0–10 V → 0000–1770 hex). Scaling is performed with the SCL2 instruction using the parameters listed below.
| Parameter | Address (D-word) | Value | Comment |
|---|---|---|---|
| Raw AI word | CIO 200 | 0–1770 hex | From AD041 channel 0 |
| Scaled flow (L/min) | D100 | REAL (0.0–50.0) | Output of SCL2 |
| Setpoint (L/min) | D102 | REAL, recipe | Operator target |
| Sampling period (s) | D104 | 0.2 | 5 Hz sample rate |
| Sample count | D106 | 30 | 6 seconds total window |
For a CP1H, the AD041 input range word CIO 200 must be set to 0000 for 0–10 V. For a CJ2M built-in analog, the same scaling is performed in ST and stored directly into D100.
3. Data Acquisition: 30-Point Circular Buffer
A 0.2 s self-resetting timer drives a pointer that writes D100 into an array of 30 REAL registers, D200[0] through D200[29]. The timer is implemented with TIM 0000 200 on a CP1H (0.1 s base) and a divide-by-two counter when 0.2 s is required. On the CJ2M-CPU33 the TIMX instruction accepts a 1 ms base, so TIMX 0000 #200 gives an exact 200 ms period.
The acquisition is gated by a TEST_RUN flag (W0.00) that starts the timer and a TEST_DONE flag (W0.01) that latches when the index reaches 30. Both flags are reset when the operator presses “Start” on the HMI.
0.0 on the rising edge of TEST_RUN using a BSET-style block move. Residual values from a previous bad part will corrupt the slope statistics.4. Linear Regression Fundamentals
The classical least-squares fit returns a slope b and intercept a for the model y = a + b·x. With N=30 and xi = i·0.2 s:
slope b = (N·ΣXY − (ΣX)(ΣY)) / (N·ΣX² − (ΣX)²)
intercept a = (ΣY − b·ΣX) / N
For an evenly spaced time axis with xi = 0.2·i, the closed-form sums can be hard-coded constants to save PLC scan time:
| Constant | Symbolic form | Numeric value (N=30, dt=0.2) |
|---|---|---|
| ΣX | dt·N(N−1)/2 | 87.0 |
| ΣX² | dt²·N(N−1)(2N−1)/6 | 1738.0·dt² (0.2) |
| ΣX / N | mean time | 2.9 |
Replacing ΣX and ΣX² with constants reduces the regression to a single pass that only needs to accumulate ΣY and ΣXY. This is the version that should be deployed on CP1L / CP1E targets where scan time is critical.
5. Goodness of Fit: Sum of Squared Errors
Linear regression alone is not enough — the regression line is fit to any 30 points, including the parabolic stripped-unit curve. A separate metric is required to reject non-linear responses. The Sum of Squared Errors (SSE) is the standard choice:
SSE = Σi=0…29 (yi − (a + b·xi))²
A small SSE means the regression line tracks the data closely (ideal class). A large SSE means the data is not linear (stripped or blocked-then-flat). A flat line (leaking) has a small SSE because a horizontal line fits well, so a second test is needed for that class.
6. Second-Derivative (Slope-Change) Method
The second derivative of a sequence A[i] is a discrete three-tap filter:
d²A/di² ≈ A[i+2] − 2·A[i+1] + A[i]
For a straight line this quantity is zero at every index. For a parabola opening up it is a positive constant; for a parabola opening down it is a negative constant; for a flat line it is also zero. The Sum of Slope Change Squared (SSCS) test is:
SSCS = Σi=0…27 (A[i+2] − 2·A[i+1] + A[i])²
The SSCS test is cheaper than SSE because it does not need a regression — it is a direct three-tap filter applied to the 30 points and accumulated into a single double-precision register. On a CP1H this runs in roughly 1.6 ms; on a CJ2M-CPU33 in 0.4 ms.
7. Classification Logic and Thresholds
The four classes are separated by three metrics: net rise (A[29] − A[0]), SSCS, and the maximum single-step delta:
| Class | net rise | SSCS | max_step | Action |
|---|---|---|---|---|
| Ideal | ≥ SETPOINT·0.9 | ≤ SSCS_OK | ≤ SETPOINT·0.20 | Pass |
| Leaking | < SETPOINT·0.10 | ≤ SSCS_OK | ≤ SETPOINT·0.20 | Rework |
| Blocked | ≥ SETPOINT·0.5 | ≤ SSCS_OK | > SETPOINT·0.30 | Reject |
| Stripped | any | > SSCS_OK | any | Scrap |
SSCS_OK is calibrated by recording 50 good parts, computing the SSCS distribution, and setting the threshold at mean + 6σ. A typical value at 5 Hz sampling on a 50 L/min full scale is SSCS_OK = 0.45 (L/min)². The 0.20/0.30 spike ratios are dimensionless and stay valid across part numbers when flow is normalised to setpoint.
8. CX-Programmer Implementation
CX-Programmer is the IEC 61131-3 programming environment for the CJ, CP, and NSJ families, supporting ladder, structured text, and function blocks. The classification logic is best held in an ST function block so the statistics, thresholds, and pass/fail decision can be moved between projects intact — CX-Programmer’s program-comparison feature will then highlight which thresholds changed when comparing two recipe revisions.
The FB takes the 30-point array as an ARRAY[0..29] OF REAL input and exposes the result as a structure output:
FUNCTION_BLOCK FlowClassify
VAR_INPUT
Y : ARRAY[0..29] OF REAL; (* scaled flow samples, L/min *)
Setpoint : REAL; (* recipe target, L/min *)
SSCS_OK : REAL; (* linearity threshold *)
END_VAR
VAR_OUTPUT
NetRise : REAL;
SSCS : REAL;
MaxStep : REAL;
Class : INT; (* 0=Ideal 1=Leak 2=Block 3=Strip *)
END_VAR
VAR
i : INT;
sscs_acc : REAL;
step : REAL;
END_VAR
NetRise := Y[29] - Y[0];
SSCS := 0.0;
MaxStep := 0.0;
FOR i := 0 TO 27 DO
sscs_acc := sscs_acc + (Y[i+2] - 2.0*Y[i+1] + Y[i])*(Y[i+2] - 2.0*Y[i+1] + Y[i]);
END_FOR;
SSCS := sscs_acc;
FOR i := 1 TO 29 DO
step := ABS(Y[i] - Y[i-1]);
IF step > MaxStep THEN MaxStep := step; END_IF;
END_FOR;
IF SSCS > SSCS_OK THEN
Class := 3; (* Stripped *)
ELSIF MaxStep > 0.30 * Setpoint THEN
Class := 2; (* Blocked *)
ELSIF NetRise < 0.10 * Setpoint THEN
Class := 1; (* Leaking *)
ELSE
Class := 0; (* Ideal *)
END_IF;
END_FUNCTION_BLOCK
The FB is called once on the rising edge of TEST_DONE. The result Class is written to D300 and displayed on the HMI through a numeric indicator tied to a message table.
8.1 Ladder glue
The ladder that surrounds the FB has four rungs:
- Reset
TEST_RUNon operator “Start” and clear D200…D229. - Run
TIMX 0000 #200with its contact driving anINCon the sample index. - On
Index=30, raiseTEST_DONEand call the FB instanceFlowClassify_0. - On
FlowClassify_0.Classchange, route the part withMOVto one of four reject gates (P_1, P_2, P_3, P_4).
Using the FB once per cycle keeps the cycle-time impact under 5 ms on a CP1H and under 1 ms on a CJ2M-CPU33.
9. Threshold Tuning Procedure
SSCS_OK and the spike ratios must be tuned against a known-good population. The procedure below is the field-validated sequence used to bring a new part into production:
- Build 50 good parts. Run the recipe and record
SSCS,MaxStep, andNetRiseto a CSV on the HMI SD card. - Compute mean and σ for
SSCS. SetSSCS_OK = mean + 6σ. - Compute the 99th percentile of
MaxStep / Setpointacross the 50 parts. Set the blocked threshold at the 99th percentile rounded up to the next 0.05. Typical: 0.20. - Set the leaking threshold at
0.10·Setpointas a fixed fraction; verify it is below the lowest acceptable ramp on the good population. - Inject 10 deliberately bad parts per failure mode (blocked, leaking, stripped) and confirm 100 % classification.
10. Verification and Diagnostics
Verification consists of three checks per shift:
-
Static check: short the analog input to 5.000 V; the FB must report Leaking with
NetRise = 0.0. - Step check: apply a 0 V → 8 V step; the FB must report Stripped because the second derivative of a step is a delta at the transition.
-
Reference run: run a calibrated orifice plate; confirm Ideal class and that
NetRise / Setpointis between 0.95 and 1.05.
A live HMI page should expose SSCS, MaxStep, NetRise, and Class as numerical indicators. On a NB7W-TW01B or NS5 panel this is four numeric displays and a status indicator; the status indicator maps Class 0…3 to the colour-coded messages shown in the table in section 7.
11. Cycle-Time and Memory Budget
| CPU | FB execution time | Data memory used | EM banks touched |
|---|---|---|---|
| CP1E-E30DR-A | 4.8 ms | 248 bytes | none |
| CP1H-X40DR-A | 1.6 ms | 248 bytes | none |
| CJ2M-CPU33 | 0.4 ms | 248 bytes | none |
| CJ2H-CPU68 | 0.18 ms | 248 bytes | none |
The 30-point REAL array plus the FB’s working variables occupy 248 bytes, well within the DM area of any CJ or CP CPU. The recipe thresholds add another 32 bytes per part number. For 200 recipes on a CP1E-N40DR-A, store the thresholds in the DM Area (D00000…D19999); on a CJ2M, the recipe set is more conveniently placed in the EM Area bank 0 with a bank-switching task.
12. Common Failure Modes and Remedies
| Symptom | Likely cause | Remedy |
|---|---|---|
| Every part flagged Stripped | SSCS_OK too tight or analog noise > 1 % | Add a 3-point moving-average filter on D100; recompute SSCS_OK on filtered data |
| Blocked false positives on a steady ramp | Sampling period too short, capturing electrical noise as a step | Increase TIMX preset to 0.4–0.5 s, halve N if window must remain 6 s |
| Leaking flagged on good parts with low setpoint | 0.10·Setpoint is below the resolution of the meter | Use a fixed floor in L/min (e.g., 0.5 L/min) below the meter’s smallest reading |
| Class changes between two good parts with identical recipes | SSCS_OK computed on a sample set with outliers | Use median + 4·MAD instead of mean + 6σ when the population is < 30 |
| Cycle time exceeded on CP1E | FB inlined in ladder instead of a real FB | Wrap the algorithm in a FUNCTION_BLOCK; CX-Programmer will produce tighter native code |
13. Extension: Adding Goodness of Fit (SSE) When Stripped/Blocked Ambiguity Persists
If the spike ratio and SSCS still confuse blocked and stripped parts on a new product, add the SSE test from section 5. The FB grows by ~80 bytes and 0.3 ms on a CP1H. Use it as a tie-breaker: a Blocked call from the spike rule is upgraded to Stripped when SSE > 3·SSCS_OK. The Anscombe quartet is the textbook reminder that the regression line alone cannot disambiguate curves that differ in shape but share first- and second-moment statistics — the SSE / SSCS combination is what makes the four-class decision robust.
14. Comparison to Pure Ladder Implementation
A ladder-only implementation of linear regression on a CP1H is feasible but requires at least 60 rungs of ADD, MUL, and DDIV instructions and consumes 18–22 ms per classification. The ST function block reduces that to a single FOR loop and is the recommended path on every CJ/CP CPU. CX-Programmer’s enhanced program comparison also tracks the FB interface and the threshold constants so a recipe change is visible in a diff view — see the product page at industrial.omron.eu/en/products/cx-programmer for the feature set.
15. Putting It Together: Commissioning Checklist
- Wire the analog input, set the range word for 0–10 V, and confirm D100 tracks a handheld calibrator.
- Build the project in CX-Programmer, add the FB, and download to the CPU.
- Force
TEST_RUNfrom the CX-Programmer watch window and confirm D200…D229 are populated within 6.0 s. - Run the 50-good / 30-bad calibration described in section 9 and lock the threshold values into the recipe.
- Run the three verification checks in section 10 every shift and log the result.
How many samples do I need for the second-derivative (SSCS) test?
A minimum of 5 points is required to evaluate one second-derivative term; the recommended buffer is 30 points at 5 Hz so the SSCS accumulator sums 28 terms, which is enough to reject a single-point spike and still detect a parabolic curve with confidence.
Why not use the correlation coefficient R² instead of SSCS?
R² is a single number that summarises a linear fit and will be high for a clean straight line, but it is also high for a tilted parabola that the SSE or SSCS would reject. R² alone cannot separate ideal from stripped parts. Use SSCS as the linearity gate and the spike ratio as the blocked gate.
Can the algorithm run on a CP1E-N14DR-D with only 2 kB of user program memory?
Yes. The ST function block compiles to about 1100 steps on a CP1E; the rest of the ladder, including the timer and the HMI handshaking, fits in another 600 steps, leaving headroom for diagnostics. The 30-point REAL array fits in the DM area without touching EM.
How do I keep the recipe thresholds version-controlled when the part number changes?
Hold the three thresholds (SSCS_OK, the 0.30 spike ratio, the 0.10 floor) in three consecutive DM words and key them off the part number. CX-Programmer’s program comparison will flag any threshold change between two project revisions so the change is documented in the recipe diff.
What is the minimum detectable flow spike on this scheme?
With 0.2 s sampling and a 0.10 L/min noise floor, a 15 % setpoint jump is reliably flagged as Blocked. Below that, the SSCS gate will read the spike as a smooth step and may call the part Ideal; if smaller spikes must be detected, lower the sampling period to 0.1 s and double the buffer size to 60 points.