Troubleshooting Omron PID(190) Zero Output on CP1/CJ PLCs
Problem Description
Symptom: the PID(190) instruction on a CP1L, CP1H, CP1E, or CJ1/CJ2 PLC executes every scan, the completion flag turns ON, and the analog PV (process variable) input word updates correctly, but the manipulated variable (MV) output word remains at 0x0000 indefinitely. In a few cases the MV alternates between 0x0000 and 0x0FD0 (4048 decimal). No instruction error bit is set. The controlled actuator — a damper, EC fan, VFD speed reference, or proportional valve — never responds to changes in the setpoint or PV.
Typical field use case (from the source report): a 0–10 V airflow transmitter scaled to 0–10 m/s is wired to an analog input module at I:2002. The setpoint is loaded into D900. The user expects the PID block to drive the output word D1000 between 0 and 4000 (0–100%) to command a 0–10 V analog output to a fan-speed controller. PID(190) never produces a non-zero MV regardless of the setpoint or PV value.
How the PID(190) Instruction Works
PID(190) is the standard PID/PI control instruction in the CP1 and CJ families. It is a derivative-of-error (PV-driven) controller that combines proportional, integral, and derivative terms according to the configured band, time constants, and sampling period. The instruction reads its tuning parameters from a ten-word parameter table that you place in any word area, then writes the calculated MV to a separate output word. See the Omron PID control glossary entry for the underlying control law and the relationship between the three terms.
Each PID(190) call performs these steps:
- Read the setpoint (SP) from word C.
- Read the PV from the specified input word.
- Compute error = SP − PV (reverse action) or PV − SP (direct action).
- Compute the proportional output contribution from the P-band and the current error.
- Accumulate the integral output contribution from the I-time and the running error.
- Add the derivative output contribution from the D-time and the rate of PV change.
- Clamp the combined result between the lower and upper MV limits.
- Write the clamped value to the output word.
If any parameter-table value is zero where it should be non-zero, is out of range, or is stored in the wrong data type, the instruction still executes and still sets its completion flag — but the MV sits at 0 because the proportional contribution has been neutralized and the integral cannot build up against a non-zero error.
PID(190) Parameter Table Layout
The first operand of PID(190) is the starting word C of a ten-word parameter table. Each word has a fixed meaning, and writing the wrong value to the wrong slot is the most common cause of zero MV. The parameter table for the example in the source begins at D900:
| Word | Parameter | BCD Range | Binary Range | Notes |
|---|---|---|---|---|
| C (D900) | Setpoint (SP) | 0000–9999 | 0000–FFFF | Same engineering units as PV per range setting |
| C+1 (D901) | Proportional band (P) | 001–9999 | 0001–270F | 9999 disables P (MV drops to 0); 0 is invalid |
| C+2 (D902) | Integral time (I) | 0–9999 s | 0000–270F | 9999 disables integral action |
| C+3 (D903) | Derivative time (D) | 0–9999 s | 0000–270F | 0 disables derivative action |
| C+4 (D904) | Sampling period (Ts) | 0.1–25.5 (×100 ms) | 001–0FF (hex) | 0 = execute every scan (must be ≥ scan time) |
| C+5 (D905) | Control word 1 (bits 0–15) | — | 0000–FFFF | Action, ranges, mode flags |
| C+6 (D906) | Control word 2 (bits 16–31) | — | 0000–FFFF | Alarm and auxiliary bits |
| C+7 (D907) | MV lower limit | 0000–9999 | 0000–FFFF | Default 0 |
| C+8 (D908) | MV upper limit | 0000–9999 | 0000–FFFF | Default 100.0% / 4095 |
| C+9 (D909) | Work word | — | — | Used internally; do not write from user program |
The control words C+5 and C+6 are bit-mapped. The most important bits are C+5.00 (control action), C+5.12 (auto/manual), and C+5.14 (control type):
| Bit | Name | = 0 | = 1 |
|---|---|---|---|
| C+5.00 | Control action | Reverse (MV increases as PV drops) | Direct (MV increases as PV rises) |
| C+5.01–03 | Input range | 000 = 0–4000 BIN, 001 = 0–100.0 BCD, 010 = ±100.0, 011 = 0–9999 | |
| C+5.04–07 | Setpoint range | Same encoding as input range | |
| C+5.08–11 | Output range | Same encoding as input range | |
| C+5.12 | Mode | Manual (MV held) | Auto (PID computes MV) |
| C+5.13 | Input error MV | MV held at last value | MV forced to lower limit on input error |
| C+5.14 | Control type | PID/PI (continuous) | Two-position (on/off) |
| C+5.15 | Execution | Execute every scan | Execute only on sampling period |
| C+6.00–11 | Alarm settings | Deviation alarm limits (optional) | |
Root Cause Analysis
Five interrelated failure modes account for nearly every "MV stays at zero" report on PID(190). All five produce the same observable symptom, so the diagnostic order in the next section walks the user from most likely to least likely cause based on the field data in the source.
Cause 1 — Data type mismatch in the parameter-table words
The CP1 PLC Setup has a "DM area data type" flag (in the DM Area Setup section of the PLC Setup for CP1L/CP1H) that selects whether DM words are interpreted as BCD or binary. The PID(190) instruction reads its tuning parameters using the currently active data type. If you write your values with MOV(021) using binary source constants (&2000, &0100) but the DM area is set to BCD, the binary pattern is stored correctly but the instruction reads the BCD digits of that pattern as if they were the value. &2000 = 0x07D0; the BCD digits of 0x07D0 are 0, 7, D, 0 — the instruction interprets this as the BCD value 0700, shifting your setpoint from 2000 to 0700 on a 0–9999 BCD scale.
Worse, the source example writes #0494 to D906, where #0494 is a hex literal of 0x0494. In a BCD-mode DM area, the value stored is the BCD pattern 0x0494, but the instruction reads it as the BCD integer 494 — interpreted as a 12-bit binary pattern, the control word becomes 0x0494 = 0100 1001 0100, which sets the input range selector to "0–100.0", the setpoint range to "0–9999" (mismatched), and the output range to "0–9999". The unit mismatch drives the controller to 0 MV in steady state. The reverse case — writing &2000 (binary) into a binary-mode DM and the controller interpreting it as 2000 in BCD — produces a setpoint of 2000 BCD = 0x07D0 = 2000 decimal; this is consistent, but the setpoint is on a BCD scale, not the binary scale the analog input is producing, so the error calculation is wrong and the MV may still drop to 0.
Symptom: PV is correct, setpoint looks correct in the watch window, but the controller behaves as if SP and PV are in totally different units. First diagnostic step: read the parameter table back with both BCD and binary viewers in CX-Programmer.
Cause 2 — Proportional band interpretation reversed
Omron's PID(190) accepts a proportional BAND, not a gain. A P-band of 100 means "100 engineering units of error produces 100% MV." A P-band of 1 means "1 unit of error produces 100% MV." A P-band of 9999 effectively disables the P-term, and the MV falls to 0 in steady state because the integral alone can only drive the MV away from 0 if the error is non-zero and the I-term is short enough to integrate up to a non-zero value before windup clamps the loop. Field users often set P to "100" thinking it is a gain of 100, but on a 0–4000 scale, 100 actually means a moderate band — 2.5% of full scale. The two cases both produce zero or unstable MV, but for opposite reasons.
Quick sanity check: MV (proportional contribution) = 100% × (|SP − PV| / P-band). If P = 100 and the error is 200, the proportional output is 200% — the upper MV limit (D908) trims it to 100%. If P = 9999 and the error is 200, the proportional output is 2% — small but non-zero. If P = 9999 and I-time is also 9999 (no integral), the MV is 0 forever. The source example set P = &100, which is a 2.5% band; that is aggressive but not zero-causing by itself.
Cause 3 — Sampling period incompatible with data type or scan time
The C+4 sampling period is specified in tenths of a second. A value of &50 in D904 means 0.5 s × 100 = 50 in BCD; if the DM area is binary, &50 = 80 decimal = 8.0 s. A sampling period of 8.0 s on a loop whose error is moving at 1 unit/s is effectively a frozen controller — the derivative term computes dPV/dt across an 8-second window and the I-term updates only every 8 seconds, so the MV appears stuck at 0 for several seconds at a time.
Symptom: MV does not move for several seconds, then jumps. First diagnostic step: change C+4 to 0 (execute every scan) and watch the MV. If the MV now moves, the sampling-period value was incompatible with the scan time or the data type.
Cause 4 — Control word forces manual or two-position mode
If bit 12 of C+5 (mode) is 0, the controller is in manual mode and the MV is held at the value in C+9 (or a separate manual MV word depending on the CP1 variant). If bit 14 of C+5 (control type) is 1, the controller is in two-position (on/off) mode and the output toggles between the lower and upper MV limits. The reported symptom of "MV is either 0x0000 or 0x0FD0" — 0x0FD0 = 4048 decimal, very close to the configured upper limit of 4000 — is a textbook on/off controller saturating at the lower and upper MV limits. The fix is to clear bit 14 of C+5 (set C+5 = 0x0000 or 0x1000) and set bit 12 to 1 for auto PID.
Symptom: MV is binary, jumps between 0 and upper limit, ignores P-band and I-time. First diagnostic step: examine C+5 as a 16-bit hex value and confirm bits 12 and 14 match the desired mode.
Cause 5 — Setpoint and PV on different ranges
The range selectors in C+5 bits 1–3 (input range), 4–7 (setpoint range), and 8–11 (output range) must all be set consistently with the engineering units you are using. A common field mistake is to set the input range to "0–4000 (binary)" because the analog input is a 12-bit converter, but to set the setpoint range to "0–100.0" because the operator HMI displays 0.0 to 100.0. The controller then compares a 0–4000 PV against a 0–1000 SP, so a setpoint of "50.0" is actually 50 on a 1000-unit scale, and the error is 4000 − 50 = 3950 units, which is far outside the P-band and saturates the MV at the lower limit (or upper limit, depending on action).
Symptom: MV pegs to upper or lower limit immediately, no proportional response. First diagnostic step: set all three range selectors to the same value.
Diagnostic Procedure
- Verify the instruction is actually executing. Watch the PID(190) output word (D1000 in the example) in online mode. If the value never changes even when the input changes, check that the input condition to PID(190) is ON. PID(190) requires an ON execution condition; a P_On or a normally-closed bit in series will silently keep the output at 0.
- Read the parameter table in both display formats. In CX-Programmer, select the parameter words (D900–D908) and view them as BCD, then as binary. If &2000 shows as 2000 in both, the data type is consistent. If it shows as 8192 in binary, you are writing BCD-formatted hex into a binary area.
- Verify SP and PV are in the same units. Subtract D900 (SP) from the analog input word in a work word. If the result is larger than the P-band, the controller is saturating. If the result is zero, the SP and PV are the same and the MV is correctly 0.
- Confirm the control action. Read C+5 bit 0. For a heating or "increase MV when PV drops below SP" loop, set bit 0 = 0 (reverse). For a cooling or "increase MV when PV rises above SP" loop, set bit 0 = 1 (direct).
- Zero out I and D to isolate the P-term. Temporarily write 9999 (decimal) to C+2 (integral) and 0 to C+3 (derivative). The MV should then respond proportionally to the error. If it does, re-introduce I and D terms one at a time.
- Check the sampling period. Write 0 to C+4 to force execution every scan. If the MV now moves, the sampling period value was incompatible with the scan time or the data type.
- Inspect C+5 and C+6 as hex values. Confirm bits 12 (auto/manual) and 14 (PID/two-position) match the intended control strategy. Convert the bit pattern to a hex word and compare with the table in the parameter-layout section.
- Confirm the C+9 work word is not being written by the user program. The instruction overwrites C+9 on every scan. If a MOV(021) in another part of the program is writing to D909, the internal state of the controller is corrupted on every scan.
Step-by-Step Solution
Apply the fixes in the order the diagnostic procedure produced evidence. The two most common root-cause fixes are data type configuration and proportional band interpretation.
Fix 1 — Correct the DM area data type
Open CX-Programmer, connect to the PLC, and select PLC → Edit → PLC Setup. Navigate to the DM Area section. For PID(190) used with binary data sources (values written with & prefix), set the data type to Binary. For PID(190) used with BCD sources (# prefix), set the data type to BCD. Transfer the new setup to the PLC and cycle power if required.
Fix 2 — Re-write the parameter table with consistent data type
Once the DM area is set to binary (the most common configuration for modern programs), rewrite the parameter table using binary source constants:
MOV(021) &2000 D900 ; SP = 5.0 m/s on 0-4000 scale
MOV(021) &0400 D901 ; P-band = 400 (10% of full scale)
MOV(021) &0100 D902 ; Integral time = 100 s (start conservative)
MOV(021) &0000 D903 ; Derivative time = 0 (disabled for first test)
MOV(021) &0005 D904 ; Sampling period = 0.5 s
MOV(021) #1000 D905 ; Control word 1: auto, reverse, 0-4000 ranges
MOV(021) #0000 D906 ; Control word 2: no alarms
MOV(021) &0000 D907 ; MV lower limit = 0
MOV(021) &0FA0 D908 ; MV upper limit = 4000 (0x0FA0)
The value 0x0494 written to D906 in the original example is the hex pattern for a control word with input range = 0–100.0, setpoint range = 0–100.0, output range = 0–100.0, and reverse action. If the rest of the loop is on a 0–4000 binary scale, that range setting forces a unit mismatch and the MV will sit at 0. Replace #0494 with #0000 to keep all three ranges on 0–4000 binary.
Fix 3 — Confirm P-band, I-time, and D-time are within range
Verify the final parameter table in online mode:
- D900 = 0x07D0 (SP = 2000)
- D901 = 0x0190 (P-band = 400, 10% of 0–4000 scale)
- D902 = 0x0064 (I-time = 100 s, conservative)
- D903 = 0x0000 (D-time, disabled)
- D904 = 0x0005 (sampling = 0.5 s)
- D905 = 0x1000 (auto, reverse action, 0–4000 ranges, PID mode)
- D906 = 0x0000 (no deviation alarms)
- D907 = 0x0000 (MV low = 0)
- D908 = 0x0FA0 (MV high = 4000)
Fix 4 — Force auto mode and disable two-position control
Confirm bit 12 of D905 is 1 (auto) and bit 14 is 0 (PID/PI, not on/off). In binary representation, a D905 value of 0x1000 sets bit 12. A D905 value of 0x4000 sets bit 14. To set both auto and PID with reverse action, D905 = 0x1000 (bit 12 = 1, bit 0 = 0, bits 1–11 = 0). For direct action, D905 = 0x1001. The most common production value is D905 = 0x1000 (auto, reverse) or D905 = 0x1001 (auto, direct).
Fix 5 — Apply bumpless transfer logic
If the application toggles between manual and auto modes, write the current MV into the C+9 work word just before switching to manual, and write C+9 into the output word just after switching to auto. PID(190) uses C+9 as the manual MV value; if C+9 is not initialized to the current output, the MV will step on every mode change.
Verification
- Step test with P-only control. With I = 9999 and D = 0, force the PV to a value 10% below SP and watch the output word. Expected MV = upper limit (4000) because the error exceeds the P-band. If the MV does not peg to the upper limit, the control action is reversed (toggle bit 0 of C+5 to swap direction).
- Step test with PI control. Restore I to a reasonable value (for example, 100 s) and D = 0. Force a 5% step change in the PV and observe the MV. Expected: proportional jump on the first scan, then integral ramp to the new steady-state value. Time-to-steady should be roughly 4 × I-time.
- Bumpless transfer check. Toggle bit 12 of C+5 (auto/manual) and verify the MV does not step. If it does, the manual MV value in C+9 is not equal to the current MV — set C+9 = current MV before switching to manual.
- Long-term stability check. With the controller in auto and the loop closed, log the MV over 10 minutes. Expected: small steady-state oscillation around a mean value within the proportional band, no sustained saturation. If the MV saturates at the upper or lower limit, the I-term is winding up — increase the I-time or add an external anti-windup clamp.
- Direction check. With reverse action (bit 0 = 0), drop the PV by 20% of scale and confirm the MV increases. With direct action (bit 0 = 1), drop the PV by 20% of scale and confirm the MV decreases. Reverse this if the response is backwards.
Parameter Reference (CP1L/CP1H/CP1E/CJ1 PID(190))
| Word | Parameter | Value (typical airflow loop) | Engineering meaning |
|---|---|---|---|
| C (D900) | Setpoint | &2000 | 5.0 m/s on 0–10 m/s / 0–4000 scale |
| C+1 (D901) | Proportional band | &0400 | 10% of full scale = 400 units |
| C+2 (D902) | Integral time | &0100 | 100 s (start conservative) |
| C+3 (D903) | Derivative time | &0000 | 0 = no derivative action |
| C+4 (D904) | Sampling period | &0005 | 0.5 s |
| C+5 (D905) | Control word 1 | &1000 | Auto, reverse action, 0–4000 ranges, PID mode |
| C+6 (D906) | Control word 2 | &0000 | No deviation alarms |
| C+7 (D907) | MV lower limit | &0000 | 0% output |
| C+8 (D908) | MV upper limit | &0FA0 | 100% output (4000) |
| C+9 (D909) | Work word | (read-only) | Do not write from user program |
Fault Symptom Matrix
| Symptom | Most likely cause | First check | Fix |
|---|---|---|---|
| MV always 0x0000, PV updates correctly | Data type mismatch in DM area | Read C…C+8 in both BCD and BIN | Set PLC Setup DM area to match MOV source format |
| MV pegs to upper or lower limit immediately | Range mismatch between SP, PV, MV | Read C+5 bits 1–11 | Set all three range selectors to the same value |
| MV toggles between 0 and upper limit | Two-position (on/off) mode selected | Read C+5 bit 14 | Clear bit 14 (C+5.14 = 0) |
| MV held at last value, ignores setpoint change | Manual mode selected | Read C+5 bit 12 | Set bit 12 (C+5.12 = 1) for auto |
| MV moves only every few seconds | Sampling period incompatible with data type | Read C+4 as BCD vs BIN | Set C+4 to 0 (every scan) or 0x0005 for 0.5 s |
| MV unstable, oscillates | P-band too small (high gain) | Increase C+1 by 2× | Raise P-band to 5–20% of full scale |
| MV stable but offset from setpoint | Integral action disabled | Read C+2 | Set I-time to 50–200 s (avoid 9999) |
| MV spikes on setpoint change | Derivative action on setpoint | Read C+3 | Set D-time to 0 or use PV-derivative only |
| MV steps on mode change | Bumpless transfer not implemented | Read C+9 vs current MV | Write current MV into C+9 before manual |
Safety and Commissioning Notes
- Always start a new PID loop with the I-term disabled (I = 9999) and the D-term disabled (D = 0). Tune the P-term first to confirm the loop responds in the right direction, then re-introduce I and finally D.
- The C+9 work word is overwritten by the instruction on every execution. Do not write to C+9 from the user program; the result is undefined MV behavior and can produce intermittent zero-MV faults.
- If the loop controls a final control element (valve, damper, VFD speed reference) with hard limits, set the MV lower and upper limits (C+7 and C+8) to the scaled values of those limits, not to 0 and 100%. A 4–20 mA valve that closes fully at 0% will need a 0% floor; a 0–10 V damper that stalls below 5% will need a 5% floor.
- For CJ-series PLCs, the same PID(190) instruction applies, but the parameter table must be located in a word area that is not used for I/O refreshing (typically DM, EM, or H). The I/O area (CIO), work area (WR), and timer/counter areas (TIM, CNT) cannot be used as the parameter table base.
- For loops with long dead time (greater than 30% of the time constant), PID(190) will not perform well. Use PIDAT(191) autotuning to identify a Smith-predictor configuration, or move the loop to a higher-level controller.
- On CP1H and CP1L, the PID(190) instruction executes in approximately 0.5–1.0 ms. On CJ2M, the execution time is similar. Add this to the scan time when calculating the effective loop period.
Related Instructions and Platform Variants
PIDAT(191) is the autotuning variant of PID(190) on the CP1H and CJ2M. It uses the same parameter table layout and the same control word structure, plus a 30-word work area starting at the operand following the parameter table. If PID(190) returns zero after the fixes above, switching to PIDAT(191) with the same parameter table will not help — the parameter table problem is identical. Tune PID(190) first to confirm the loop is wired correctly, then enable PIDAT(191) for autotuning.
For loops that do not need true PID behavior, the simpler TPO(685) (time-proportional output) on CJ-series PLCs provides on/off or time-proportional control without the parameter table overhead. TPO(685) is appropriate for solenoid valves, contactors, and electric heaters where the final element is binary.
For NX/NJ-series controllers (NexSys), the equivalent instruction is part of the PID function block library in Sysmac Studio. The same five root causes apply — data type, proportional band interpretation, sampling period, control word, and range mismatch — but the parameter structure is configured in the function block instance instead of a ten-word table.
FAQ
Why does my Omron PID(190) output stay at exactly 0 even though the input is changing?
Three causes account for most of these reports. First, the DM area is set to one data type in the PLC Setup but you are writing the other data type into the parameter table — read D900–D908 as both BCD and binary and check for consistency. Second, the proportional band is 9999 (effectively disabling P-action) or the integral time is 9999 with the P-band unable to hold the setpoint — temporarily set I = 9999 and D = 0 to isolate the P-term. Third, the control word forces manual or two-position mode — read D905 as hex and verify bit 12 = 1 (auto) and bit 14 = 0 (PID, not on/off).
What is the difference between Omron's proportional band and a gain in PID(190)?
The PID(190) parameter C+1 is a proportional BAND, not a gain. Band of 100 means "100 engineering units of error produces 100% MV." Band of 9999 disables P-action. To convert a desired gain Kp to a band, use P-band = (full scale / Kp). For a 0–4000 scale and a gain of 2, P-band = 4000 / 2 = 2000 (50% of scale), which is a small P-action. Start with a P-band of 5–20% of full scale (200–800 on a 0–4000 scale) and tune from there.
How do I set up the PID(190) control word (D905) for reverse action with a 0–4000 binary input range?
Set D905 = 0x1000 for reverse action in auto mode, or D905 = 0x1001 for direct action in auto mode. The 0x1000 sets bit 12 (auto/manual = auto), and bit 0 selects reverse (0) or direct (1). The range selectors in bits 1–3, 4–7, and 8–11 default to 0 (0–4000 binary) when those bits are zero, so leave bits 1–11 cleared unless you need a different range.
Why does my MV jump between 0 and 4048 in an airflow control loop?
The pattern 0x0000 to 0x0FD0 (4048) is the textbook signature of two-position (on/off) control. Bit 14 of D905 is set, forcing the controller into hysteresis mode where the output snaps between the lower limit (0x0000) and the upper limit (0x0FD0 = 4048, close to the configured 4000 upper limit). Clear bit 14 of D905 to return to PID/PI control, then re-tune the P-band and I-time.
Should I use PID(190) or PIDAT(191) on a CP1H?
Use PID(190) for normal operation once the loop is wired and the parameter table is correct, and switch to PIDAT(191) only when you want autotuning. PIDAT(191) uses the same ten-word parameter table as PID(190) plus a 30-word work area starting at the operand immediately after the parameter table. Autotune perturbs the process to identify the process gain, dead time, and time constant, then writes new P, I, and D values back to the parameter table. Run autotune with the loop in a stable region of the operating envelope, not at a setpoint extreme.