The short answer
How to Scale a 4-20 mA Input in a PLC
To scale a 4-20 mA input, find the raw counts your analog card reports at 4 mA and 20 mA, get the transmitter calibrated range, then apply EU = (Raw − Raw_min) ÷ (Raw_max − Raw_min) × (EU_max − EU_min) + EU_min. Verify by injecting 4, 12, and 20 mA and confirming the scaled value reads the bottom, middle, and top of the calibrated range.
Key points
- You need three facts: card counts at 4 and 20 mA, and the transmitter calibrated range.
- Verify at 50%, not just at zero. A span error is invisible at the bottom of the range.
- Clamp the result and flag out-of-range values instead of scaling a fault into a plausible number.
- Record the calibrated range on the loop sheet so the next person can find it.
What you need
- Loop calibrator or a milliamp source
- The analog module manual, for the raw count range
- The transmitter configuration or its calibration record
- Programming software with online monitoring
- The loop sheet or instrument list for this point
Procedure
- 1
Confirm the analog card range configuration
Check whether the channel is configured for 4-20 mA or 0-20 mA. A channel set for 0-20 mA reading a 4-20 mA transmitter reads 25% high at zero, and the error shrinks toward full scale, which looks exactly like calibration drift. Fix this before doing anything else.
- 2
Find the raw counts at 4 mA and 20 mA
Read the module manual, then verify it. Inject 4.00 mA and record the raw value online. Inject 20.00 mA and record it. Do not assume 0 and 32767; modules vary widely and some report offset ranges.
- 3
Get the transmitter calibrated range
Read it from the transmitter display, a HART communicator, or the calibration record. Do not take it from the drawing, because re-ranging in the field is common and drawings are rarely updated.
- 4
Write the scaling
Apply the linear formula. Use a floating point result. If your platform has a scaling instruction, use it, but confirm what its parameters mean because vendors differ in whether they take input range or a slope and offset.
- 5
Verify at three points
Inject 4 mA and confirm the bottom of the range. Inject 12 mA and confirm exactly the midpoint. Inject 20 mA and confirm the top. The midpoint check is the one that catches span errors, and it is the one people skip.
- 6
Add validity checking
Test the raw value against the NAMUR fault thresholds and set a separate fault bit. Clamp the scaled result to the calibrated range. Hold the last good value when faulted, and make the held state visible.
- 7
Restore and document
Remove the calibrator, confirm the live reading is sensible, return the loop to automatic, and record the calibrated range and the raw endpoints on the loop sheet.
The arithmetic
EU = (Raw − Raw_min) ÷ (Raw_max − Raw_min) × (EU_max − EU_min) + EU_min
(* Constants for this point *)
RAW_MIN := 0.0; (* counts at 4 mA *)
RAW_MAX := 32767.0; (* counts at 20 mA *)
EU_MIN := 0.0; (* ft at 4 mA *)
EU_MAX := 25.0; (* ft at 20 mA *)
RAW_FAULT_LO := -1638.0; (* about 3.2 mA *)
RAW_FAULT_HI := 34406.0; (* about 21 mA *)
Level_Fault := (Raw < RAW_FAULT_LO) OR (Raw > RAW_FAULT_HI);
IF NOT Level_Fault THEN
Level := (Raw - RAW_MIN) / (RAW_MAX - RAW_MIN)
* (EU_MAX - EU_MIN) + EU_MIN;
(* clamp so downstream logic never sees the impossible *)
IF Level < EU_MIN THEN Level := EU_MIN; END_IF;
IF Level > EU_MAX THEN Level := EU_MAX; END_IF;
Level_Good := Level; (* remember the last trustworthy value *)
ELSE
Level := Level_Good; (* hold, and flag it as held on the HMI *)
END_IF;Verification table
| Inject | Expected raw | Expected engineering value | Percent |
|---|---|---|---|
| 4.00 mA | 0 | 0.0 ft | 0% |
| 8.00 mA | 8192 | 6.25 ft | 25% |
| 12.00 mA | 16384 | 12.5 ft | 50% |
| 16.00 mA | 24575 | 18.75 ft | 75% |
| 20.00 mA | 32767 | 25.0 ft | 100% |
If the numbers do not match
| What you see | Cause | Fix |
|---|---|---|
| Reads 25% high at 4 mA, correct at 20 mA | Card configured for 0-20 mA | Change the channel range configuration |
| Correct at 4 mA, wrong at 20 mA | Span mismatch between transmitter and program | Compare the transmitter upper range value to EU_MAX |
| Constant offset across the whole range | EU_MIN wrong, often a suppressed zero | Set EU_MIN to the actual lower range value |
| Result is an integer that jumps | Integer math truncating the division | Do the arithmetic in floating point |
| Value negative at true zero | Transmitter slightly below 4 mA | Clamp, and check the transmitter zero |
Frequently asked questions
- Should I use the built-in scaling instruction or write the math?
- Either works. The built-in instruction is fine if you understand its parameters, which differ between platforms. Writing the arithmetic explicitly makes the constants visible to whoever opens the program next, which has real maintenance value.
- What raw value corresponds to 4 mA on my card?
- Read the module manual and then verify by injection. There is no universal answer, and assuming one is the most common cause of a scaling error.
- Do I need to clamp the output?
- Yes. Without clamping, a transmitter at 3.9 mA produces a slightly negative level and a fault at 21.5 mA produces a level above the top of the well. Downstream logic will act on both.
Related topics
- Analog Scaling: Raw Counts to Engineering UnitsThe arithmetic that turns an analog card reading into feet, psi, or gallons per minute — plus the range mismatches that silently corrupt it.
- 4-20 mA Current LoopsWhy the industry standardized on current instead of voltage, how a two-wire loop is powered, what the live zero buys you, and how to read a loop with a meter.
- How to Test a 4-20 mA LoopProve a current loop end to end with a meter and a calibrator, without interrupting a process you were not authorized to interrupt.
- Signal ValidationCatching a failed analog input in logic before it runs a pump on a dead transmitter: range checks, module status bits, frozen-value detection, rate checks, and what the program does with a bad value.
- How to Program Lead/Lag Pump ControlBuild duplex pump control with alternation, failure detection, minimum run and off timers, and an operator override that survives a restart.
- How to Build a SequencerBuild a step sequencer in a controller that will not stick, restart into the wrong step, or leave equipment half way: define the steps from the narrative, choose a step register, and test every path before the plant depends on it.
Direct contact
Have a controls question?
Reach Eric Sullivan directly about anything on this site, a controls or automation topic, or one of his personal projects.