Skip to Content

← All functionalities

Water pumping (sanitation)ESP32 PLC 38ARGPIOAcquisition

Reading a 4-20 mA level probe on an ESP32 PLC, the right way

A 4-20 mA level sensor is the industrial standard for tank and well measurement, and reading it well takes more than one analogRead. This example, taken from a real water pumping station deployment, reads a hydrostatic probe on input I0_11 of an ESP32 PLC 38AR through a 500 Ω shunt resistor (4-20 mA becomes 2-10 V on the 0-10 V input), filters the raw reading, converts it to centimetres, detects a broken loop and drives the pump with proper hysteresis.

Why 4-20 mA starts at 4, not 0

The live-zero is the diagnostic. A healthy loop never drops below 4 mA, so a reading near 0 mA can only mean a cut cable or a dead transmitter. The example flags anything below ~3.5 mA as broken wire, lights the alarm pilot and falls back to a hard-wired overflow float. The measurement fails, but the station stays safe.

Filtering and scaling to engineering units

Current loops pick up ripple from contactors and VFDs. An 8-sample moving average smooths the 0-1023 reading before scaling: subtract the 4 mA offset (~205 counts) and map the remaining span to the probe range, 0-250 cm in this case. Print raw counts and centimetres side by side: that trace is how you calibrate the scale on site.

Hysteresis instead of a single threshold

With one threshold the pump would chatter every time waves cross it. Two setpoints, start above 180 cm and stop below 60 cm, give each cycle a defined volume, fewer motor starts and longer contactor life. The filtered value is also ready to be bit-packed into a LoRaWAN frame for remote monitoring.

A snippet from the implementation

Straight from the example as deployed on the ESP32 PLC 38AR. Copy it freely:

void setup() {
  Serial.begin(115200);

  pinMode(I_LEVEL_SENSOR, INPUT);
  pinMode(I_OVERLEVEL, INPUT);
  pinMode(Q_PUMP, OUTPUT);
  pinMode(Q_PILOT, OUTPUT);
  digitalWrite(Q_PUMP, LOW);
  digitalWrite(Q_PILOT, LOW);

  // Preload the filter so it does not start with a zero average
  uint16_t first = analogRead(I_LEVEL_SENSOR);
  for (uint8_t i = 0; i < N_SAMPLES; i++) samples[i] = first;
}

The full example is a complete program, with the wiring header, setup and main loop, ready to adapt to your application.

Frequently asked questions

How do I connect a 2-wire 4-20 mA sensor to the PLC?

Connect +24 Vdc to the + of the transmitter and its - to the analog input, and put a 500 Ω resistor between that input and GND. The analog inputs of the ESP32 PLC 38AR measure 0 to 10 V, so the resistor turns 4-20 mA into 2-10 V. The 0 V of the supply and the GND of the PLC must be the same reference.

What does a reading below 4 mA mean?

Loop failure: a broken cable, a disconnected probe or a dead transmitter. Treat it as a fault, never as "level zero", and switch to a safe fallback like a hard-wired float switch.

Can I use this on an ESP32 PLC 14?

Yes, and without the resistor. The ESP32 PLC 14 has two analog inputs, AI0.0 and AI0.1, with a 4-20 mA mode that you select in software (ESP32 PLC 14 datasheet). Use one of them in that mode, adapt the pin and the conversion to mA, and keep the same filtering, scaling and broken-wire logic.

Related functionalities