Skip to main content
Call Eric:863-698-8266
CURRYCONTROLS.COMControls & Automation Knowledge Hub
How-ToPLCAnalogHow-To

How to Scale a 4-20 mA Input in a PLC

Turn raw analog counts into engineering units, verify at three points, and add the validity checks that stop a failed transmitter from producing a believable number.

7 min readUpdated Aug 12, 2026Published Feb 14, 2026By Eric Sullivan

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. 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. 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. 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. 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. 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. 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. 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

Structured text implementation with validity handling
(* 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

InjectExpected rawExpected engineering valuePercent
4.00 mA00.0 ft0%
8.00 mA81926.25 ft25%
12.00 mA1638412.5 ft50%
16.00 mA2457518.75 ft75%
20.00 mA3276725.0 ft100%
Expected values for a 0-25 ft range on a 0-32767 count card

If the numbers do not match

What you seeCauseFix
Reads 25% high at 4 mA, correct at 20 mACard configured for 0-20 mAChange the channel range configuration
Correct at 4 mA, wrong at 20 mASpan mismatch between transmitter and programCompare the transmitter upper range value to EU_MAX
Constant offset across the whole rangeEU_MIN wrong, often a suppressed zeroSet EU_MIN to the actual lower range value
Result is an integer that jumpsInteger math truncating the divisionDo the arithmetic in floating point
Value negative at true zeroTransmitter slightly below 4 mAClamp, 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.

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.