Skip to Content

Scaling a 4-20 mA signal in the PLC: formula, constants and code

Short answer: a 4-20 mA transmitter sends 4 mA at the bottom of its range, not 0 mA. Subtract 4 mA, divide by the 16 mA span and multiply by the range. If the program scales from zero, an empty tank reads 20 %.

This works for any PLC with analog inputs. Below you will find the constants for each Industrial Shields PLC range and a link to tested code.

The formula

PV = PVmin + (I − 4 mA) / 16 mA × (PVmax − PVmin)

Example: a 0-10 bar transmitter at 12 mA gives 0 + (12 − 4) / 16 × 10 = 5 bar.

On a 0-10 V input with a 500 Ω resistor

A 500 Ω resistor between the input and 0 V turns 4-20 mA into 2-10 V: scale from 2 V, not from 0 V. The input impedance is in parallel with the resistor and lowers the reading a little. For accuracy, calibrate with a loop calibrator at 4 mA and at 20 mA, and use those two readings as the ends of the scale.

Constants for your PLC range

PLC rangeAnalog inputanalogRead() at full scale
M-Duino and Ardbox0-10 V, 10 bit, input impedance 39 kΩ1023
ESP32 PLC0-10 V, 11 bit2047
ESP32 PLC 14AI0.0 and AI0.1: 0-10 V or 4-20 mA mode, selected in softwareSee the ESP32 PLC 14 datasheet
Raspberry PLC V4 and V60-10 V, 12 bit4095
Raspberry PLC V30-10 V2047

Sources: family datasheets and the official rpiplc library for the Raspberry PLC. On a 0-10 V input, 4 mA with 500 Ω reads about 20 % of full scale: 205 counts of 1023, before the input impedance correction.

Scaling function

// counts: analogRead() value, adcMax: value at 10 V for your range
// rEq: 500 ohm in parallel with the input impedance (493.7 ohm on M-Duino)
float countsToMilliamps(float counts, float adcMax, float rEq) {
  return counts * 10.0 / adcMax / rEq * 1000.0;
}

float scale420(float mA, float pvMin, float pvMax) {
  return pvMin + (mA - 4.0) * (pvMax - pvMin) / 16.0;
}

// Below 3.6 mA: broken loop or a transmitter fault (NAMUR NE 43). Alarm, do not scale.

The full sketch, tested on an M-Duino, with averaging, loop fault detection and full-scale check, is in the guide how to convert a 4-20 mA signal to 0-10 V in an Arduino PLC.

Near 0 mA is a fault, not a value

  • 0 mA or close: broken wire, no loop power or reversed polarity. Raise an alarm and go to a safe state.
  • Below 3.6 mA or above 21 mA: transmitters that follow NAMUR NE 43 use these values to signal a fault.
  • Reading stuck at full scale: the real current can be higher than the input can show. Check the resistor value and the input range.

Commenting is not enabled on this course.