Skip to Content

How to convert a 4-20mA to 0-10V signal in an Arduino PLC

500 Ω resistor wiring, mA to volts table, scaling formula, loop fault detection and Arduino code for 0-10 V PLC inputs
January 9, 2019 by
How to convert a 4-20mA to 0-10V signal in an Arduino PLC
Boot & Work Corp. S.L, Support Team

To convert a 4-20 mA signal to 0-10 V, connect a 500 Ω resistor between the analog input and 0 V (GND) and let the loop current flow through it. By Ohm's law (V = I × R), 4 mA gives 2 V and 20 mA gives 10 V, so a 0-10 V input of a PLC reads the sensor as a 2-10 V signal.

This guide shows the wiring of a 2-wire transmitter, a table from mA to volts and ADC counts, the scaling formula to engineering units, how to detect a broken loop and tested Arduino code for an Arduino PLC. It also explains the errors that the resistor and the input impedance add, and when you need an isolated converter instead of a resistor.

 
 

What is a 4-20 mA signal?

A 4-20 mA signal is an analog current signal. A transmitter (pressure, level, flow, temperature) sets the current in the loop: 4 mA is the lowest value of its measuring range and 20 mA is the highest. For example, a 0-10 bar pressure transmitter gives 4 mA at 0 bar, 12 mA at 5 bar and 20 mA at 10 bar.

4-20 mA is the standard analog signal for industrial transmitters because the current is the same at every point of a series loop. The resistance of a long cable does not change the value, and the 4 mA "live zero" lets the PLC tell a real zero from a broken wire.

Two properties make 4-20 mA the default choice for field sensors:

  • Long cables. A voltage signal loses part of its value in the cable resistance and picks up noise from motors, contactors and drives. In a current loop, the transmitter keeps the current constant as long as the supply has enough voltage, so the cable resistance does not change the reading.
  • Live zero. The signal never goes below 4 mA in normal operation. A current near 0 mA can only mean a cut cable, a loose terminal or a transmitter without power.

Most 4-20 mA transmitters are 2-wire devices: the same two wires carry the power and the signal. The loop needs a DC supply, usually 24 Vdc.

A PLC analog input usually measures voltage. On the Arduino PLC (M-Duino and Ardbox), the ESP32 PLC and the Raspberry PLC the analog inputs measure 0 to 10 Vdc (family datasheets). To read a 4-20 mA transmitter on these inputs, you turn the current into a voltage with a resistor.

500 Ω resistor: Ohm's law turns 4-20 mA into 2-10 V

The resistor is a current-to-voltage converter. The voltage across it is the loop current multiplied by its resistance.

V = I × R = 0.020 A × 500 Ω = 10 V4 mA × 500 Ω = 2 V · 12 mA × 500 Ω = 6 V · 20 mA × 500 Ω = 10 V

500 Ω is the value that puts 20 mA exactly at the top of a 0-10 V input. For a 0-5 V input, use 250 Ω: 4-20 mA becomes 1-5 V. This is the case of an Arduino Uno, Mega or Leonardo board, whose analog pins read 0 to 5 V.

The table shows what a 10-bit, 0-10 V input reads (0 to 1023 counts), as on the M-Duino and the Ardbox. The column "ideal" uses 500 Ω only. The last two columns include the 39 kΩ input impedance of the M-Duino analog input (see the next section).

Loop currentVoltage, 500 Ω idealCounts, idealVoltage with 39 kΩ inputCounts with 39 kΩ inputMeaning
0 mA0 V00 V0Broken wire or no power
3.6 mA1.80 V1841.78 V182Fault limit (NAMUR NE 43)
4 mA2.00 V2051.98 V2020 % of the range
8 mA4.00 V4093.95 V40425 %
12 mA6.00 V6145.92 V60650 %
16 mA8.00 V8187.90 V80875 %
20 mA10.00 V10239.87 V1010100 % of the range
21 mA10.50 V1023 (full scale)10.37 V1023 (full scale)High fault (NAMUR NE 43)

Counts = V / 10 V × 1023, rounded. 4 mA gives 204.6 counts, which the ADC reads as 204 or 205. The graph shows the same straight line from 2 V to 10 V.

Result of 4mA (2Vdc)-Linear graph

Two practical points on the resistor:

  • Power. At 20 mA a 500 Ω resistor dissipates P = I² × R = 0.2 W. Use a resistor rated well above this, for example 0.5 W.
  • Tolerance. The reading error follows the resistor tolerance one to one: a 5 % resistor gives up to 5 % error. Use a precision resistor (1 % or better) or calibrate the input.

Wiring a 2-wire 4-20 mA transmitter to an Arduino PLC analog input

The resistor goes in parallel with the analog input, between the input terminal and the 0 V of the PLC. The transmitter goes in series in the loop, between the +24 Vdc supply and the input.

  1. Step 1+24 Vdc to the transmitterConnect the + of the 24 Vdc supply to the + terminal of the transmitter.
  2. Step 2Transmitter to the inputConnect the - terminal of the transmitter to an analog input, for example I0.7 on an M-Duino.
  3. Step 3500 Ω to 0 VConnect the resistor between the same input terminal and GND (0 V) of the PLC.
  4. Step 4Common 0 VThe 0 V of the 24 Vdc supply and the GND of the PLC must be the same reference.
Converter circuit diagram Arduino Industrial application for Analog Signals Diagram
Converter circuit: the 500 Ω resistor between the analog input and GND turns the loop current into a voltage.
2-wire sensor connection: the transmitter is in series between the 24 Vdc supply and the analog input.

For a 3-wire or 4-wire transmitter, the sensor has its own supply terminals. Connect its current output to the analog input and its signal return to the 0 V of the PLC. The resistor stays between the input and 0 V.

Check the loop voltage. At 20 mA the resistor takes 10 V of the 24 V supply. The transmitter and the cable get the remaining 14 V. The transmitter datasheet gives the minimum supply voltage at its terminals: it must be lower than 14 V minus the voltage drop in the cable (cable resistance × 0.02 A). If it is not, the current stops rising before 20 mA and the top of the range reads low.

On the M-Duino and the Ardbox, the analog inputs are "Analog/Digital" inputs (datasheets): the same terminal reads 0-10 V with analogRead() or a digital level with digitalRead(). For a 4-20 mA loop, read it with analogRead(). Use one resistor for each loop: two transmitters must not share the same resistor or the same input.

Input impedance and ADC resolution change the real reading

The PLC input is not an open circuit. Its input impedance is in parallel with the 500 Ω resistor, so part of the loop current goes into the input and the voltage is a little lower.

You have two ways to correct the error. Use the equivalent resistance (493.7 Ω on an M-Duino) in the conversion, as the code below does. Or do a two-point calibration: inject 4.00 mA and 20.00 mA with a loop calibrator, write down the counts and use them as the ends of the scale. Calibration also removes the resistor tolerance, so it is the better option when accuracy matters.

Resolution: on a 10-bit, 0-10 V input one count is 9.8 mV. With 493.7 Ω this is about 0.02 mA, or 0.12 % of the 16 mA span. The 4-20 mA range uses about 808 of the 1024 counts, because the bottom 2 V are the live zero.

Scaling formula from 4-20 mA to engineering units

A 4-20 mA transmitter is linear. To get the process value, remove the 4 mA offset and divide by the 16 mA span:

PV = PVmin + (I - 4 mA) / 16 mA × (PVmax - PVmin)Example, 0-10 bar transmitter at 12 mA: 0 + (12 - 4) / 16 × 10 = 5 bar

The same formula works with a level probe (for example 0-250 cm), a temperature transmitter (for example -50 to 150 °C) or a flow meter. Only PVmin and PVmax change. Keep them as constants in the program: if you change the transmitter, you change two numbers.

If you prefer to work directly with counts, use the counts at 4 mA and at 20 mA from the table or from your calibration: PV = PVmin + (counts - counts4mA) / (counts20mA - counts4mA) × (PVmax - PVmin).

Loop fault detection: a broken wire reads below 3.6 mA

The live zero is the diagnostic. The NAMUR NE 43 recommendation defines how a transmitter reports its state with the loop current:

Loop currentNAMUR NE 43 meaningWhat the PLC program should do
3.6 mA or lessFault (low)Alarm. Do not use the value. Broken wire and no power also read here (0 mA).
3.6 to 3.8 mAOut of the measuring rangeShow the minimum of the range and warn.
3.8 to 20.5 mAMeasurementScale with the formula.
20.5 to 21 mAOut of the measuring rangeShow the maximum of the range and warn.
21 mA or moreFault (high)Alarm. Do not use the value.

Limit of a 500 Ω resistor on a 0-10 V input: 20 mA already gives the full 10 V. With the 39 kΩ input of the M-Duino, the input reaches full scale at about 20.3 mA. Above that value the reading stays at 1023 counts, so the PLC cannot tell 20.5 mA from a high fault at 21 mA. Two solutions:

  • Set the transmitter to report faults with the low current (3.6 mA or less), if it has this option. The PLC then detects every fault at the bottom of the scale.
  • Use a lower resistor, for example 470 Ω. With the 39 kΩ input, 21 mA gives 9.75 V and stays readable. You lose about 6 % of the resolution, and you must use 470 Ω in the conversion.

Never treat a reading below 4 mA as "zero level" or "zero pressure". A pump controlled by a level probe with a cut cable would run dry. The program must go to a safe state and keep a hard-wired protection (a float switch, a pressure switch) that does not depend on the analog signal.

Arduino code: read 4-20 mA, scale it and detect a broken loop

This sketch reads a 0-10 bar transmitter on input I0.7 of an M-Duino with a 500 Ω resistor. It averages 16 samples, converts the counts to mA with the equivalent resistance, checks the loop and scales the value. It compiles for the ATmega2560 of the M-Duino (7.3 KB of flash) and the conversion was tested on a PC with simulated readings from 0 to 21 mA. To compile it, install the Industrial Shields boards in the Arduino IDE: they define the pin names such as I0_7.

// 4-20 mA transmitter on an M-Duino analog input (0-10 Vdc, 10 bit)
// A 500 ohm resistor between the input and GND turns 4-20 mA into 2-10 V.

const uint8_t AI_PIN = I0_7;        // analog input used for the loop

const float ADC_MAX  = 1023.0;      // 10 bit: M-Duino and Ardbox
const float AI_RANGE = 10.0;        // input range in volts
const float R_SHUNT  = 500.0;       // resistor in ohm
const float R_INPUT  = 39000.0;     // input impedance from the datasheet
const float R_EQ = R_SHUNT * R_INPUT / (R_SHUNT + R_INPUT);  // 493.7 ohm

const float PV_MIN = 0.0;           // value at 4 mA (example: 0 bar)
const float PV_MAX = 10.0;          // value at 20 mA (example: 10 bar)

const float MA_FAULT_LOW = 3.6;     // NAMUR NE 43: 3.6 mA or less is a fault
const uint8_t N_SAMPLES = 16;

float readCounts() {
  uint32_t sum = 0;
  for (uint8_t i = 0; i < N_SAMPLES; i++) {
    sum += analogRead(AI_PIN);
  }
  return (float)sum / N_SAMPLES;
}

float countsToMilliamps(float counts) {
  float volts = counts * AI_RANGE / ADC_MAX;
  return volts / R_EQ * 1000.0;
}

void setup() {
  Serial.begin(115200);
  pinMode(AI_PIN, INPUT);
}

void loop() {
  float counts = readCounts();
  float mA = countsToMilliamps(counts);

  Serial.print(mA, 2);
  Serial.print(" mA  ");

  if (mA <= MA_FAULT_LOW) {
    // Broken wire, transmitter without power or a low fault signal
    Serial.println("LOOP FAULT");
  } else if (counts >= ADC_MAX - 1) {
    // The input is at full scale: the real current can be higher
    Serial.println("INPUT AT FULL SCALE");
  } else {
    float pv = PV_MIN + (mA - 4.0) * (PV_MAX - PV_MIN) / 16.0;
    if (pv < PV_MIN) pv = PV_MIN;   // 3.6 to 4 mA: under range
    Serial.print(pv, 2);
    Serial.println(" bar");
  }

  delay(500);
}

To use it on another PLC, change three constants: ADC_MAX (2047 on an ESP32 PLC, 4095 on a Raspberry PLC), R_INPUT (the input impedance of your PLC, or remove the parallel correction and calibrate) and AI_PIN. For more ways to get a stable reading, see how to improve analog reading.

Expected output with a healthy loop at mid scale: 12.00 mA 5.00 bar. With the cable disconnected: 0.00 mA LOOP FAULT.

Resistor or isolated 4-20 mA to 0-10 V converter

A resistor is enough when the PLC, the transmitter supply and the resistor share the same 0 V, inside one cabinet. An active, isolated signal converter is the right choice in other cases.

Criterion500 Ω resistorIsolated signal converter
How it worksOhm's law, passiveMeasures the current and generates a new 0-10 V output
Galvanic isolationNo: the loop and the PLC share 0 VYes: input, output and supply are separated
Loop already used by another deviceOnly if the 0 V references are compatible and the loop voltage is enoughYes, a typical use
Ground loops, long cables between buildingsRisk of offset and noiseBreaks the ground loop
SupplyNoneNeeds its own supply
AccuracyResistor tolerance plus the input impedance errorGiven by the converter datasheet

For a DIN-rail installation, Industrial Shields has the IS.ACANTO10-0.5k: a 500 Ω resistor with ±1 % tolerance inside a feed-through terminal block, so the conversion sits on the rail next to the PLC.

Hardware and software for the 4-20 mA to 0-10 V example

Arduino based PLC

Arduino PLC

M-Duino (Ethernet family) or Ardbox (20 I/Os family). Both have 0-10 V analog/digital inputs with 10-bit resolution.

4-20ma to 0-10V converter module

500 Ω resistor

One per loop. A DIN-rail terminal block with a ±1 % resistor, or any 1 % resistor rated for 0.5 W or more.

Arduino IDE

Arduino IDE

The Arduino IDE with the Industrial Shields boards installed. The "AnalogInput" example of the IDE is a quick first test.

4-20 mA transmitters in PLC projects

For the basics of analog inputs (resolution, ranges, voltage and current signals), see the basics about analog inputs of an industrial PLC.

Next steps with 4-20 mA signals on a PLC

See the Arduino PLC familyAsk an engineer about your sensors

FAQ about 4-20 mA to 0-10 V conversion

How do I convert 4-20 mA to 0-10 V?

Connect a 500 Ω resistor between the analog input and 0 V and put the input in the loop. The current through the resistor gives 2 V at 4 mA and 10 V at 20 mA. For galvanic isolation, use an isolated signal converter instead.

What voltage does 4 mA give with a 500 Ω resistor?

2 V (0.004 A × 500 Ω). On a 10-bit, 0-10 V input this is about 205 counts, or 202 counts on an M-Duino because of its 39 kΩ input impedance.

Which resistor converts 4-20 mA to 0-5 V?

250 Ω. 4 mA gives 1 V and 20 mA gives 5 V. Use it with inputs that read 0 to 5 V, such as the analog pins of an Arduino Uno, Mega or Leonardo board.

Can I connect a 4-20 mA sensor directly to an Arduino analog pin?

No. The analog pin measures voltage, not current. You need the 250 Ω resistor and a 24 Vdc loop supply, and the pin must never see more than its maximum voltage. An industrial PLC with 0-10 V inputs and a 500 Ω resistor gives more margin.

Why does 4-20 mA start at 4 mA and not at 0 mA?

The 4 mA live zero powers 2-wire transmitters at the bottom of the range and lets the PLC detect faults. A healthy loop never reads below about 3.8 mA, so a reading near 0 mA means a broken wire or a transmitter without power.

How long can a 4-20 mA cable be?

It depends on the loop voltage. The supply voltage minus the 10 V on the resistor and the minimum voltage of the transmitter gives the voltage left for the cable. Divide it by 0.02 A to get the maximum cable resistance (both wires), then use the resistance per metre of your cable.

​Search in our Blog

How to convert a 4-20mA to 0-10V signal in an Arduino PLC
Boot & Work Corp. S.L, Support Team January 9, 2019
Share this post

Looking for your ideal Programmable Logic Controller?

Take a look at this product comparison with other industrial controllers Arduino-based. 

We are comparing inputs, outputs, communications and other features with the ones of the relevant brands.

PLC Comparison