← Water Pump Control with an ESP32 PLC and Float Switches
Water pumping (sanitation)ESP32 PLC 14GPIOControl
Water Pump Control with an ESP32 PLC and Float Switches — full example
Complete Arduino example: automatic water pump control with float level switches, fault detection and a state machine on an industrial ESP32 PLC.
Complete, runnable program for the ESP32 PLC 14 (pump-state-machine-float-switches.ino): wiring header, requirements and integration notes included.
Download the full project pack — freeThis example + the related ones + bill of materials
Read-only preview.
/*
* COMPLETE EXAMPLE — Pump control with level float switches (state machine)
*
* Hardware: ESP32 PLC 14 (Industrial Shields)
* Based on: water pumping project (sanitation), bombament-1b-14.ino
*
* Wiring:
* I0_0 Minimum-level float switch (NO, closed = water above minimum)
* I0_1 Maximum-level float switch (NO, closed = water above maximum)
* I0_2 Overlevel / alarm float switch (NO)
* I0_3 Pump contactor auxiliary contact (running feedback)
* I0_4 Thermal relay contact (closed = fault)
* I0_5 Error reset push button
* Q0_0 Pump contactor command
* Q0_1 Alarm pilot light
*
* Logic:
* OFF -> ON when minimum AND maximum are active (tank full to the top)
* ON -> OFF when minimum is lost (tank emptied)
* While running, contactor feedback and thermal relay are monitored:
* any failure latches ERROR (pump stopped + pilot light) until manual reset.
*
* Integration: the `data[]` array is ready to be sent over whichever protocol
* applies — see the MQTT / LoRaWAN / Modbus templates in the catalog.
*/
// --- I/O map (ESP32 PLC 14 pins, industrialshields-arduino library)
#define I_FLOAT_MIN I0_0
#define I_FLOAT_MAX I0_1
#define I_FLOAT_OVERFLOW I0_2
#define I_CONFIRMATION I0_3
#define I_THERMAL I0_4
#define I_RESET I0_5
#define Q_PUMP Q0_0
#define Q_PILOT Q0_1
// --- Machine states
enum State { OFF_S, ON_S, ERROR_S };
State state = OFF_S;
// --- Telemetry variables (same order as the frame in the original project)
enum { MIN_LEVEL, MAX_LEVEL, OVERFLOW_LEVEL, RUNNING, FAULT, CONF_FAULT, ERROR_F, DATA_MAX };
bool data[DATA_MAX];
// Contactor feedback takes a while to arrive: allow a margin before declaring failure
const uint32_t T_CONFIRMATION_MS = 2000;
uint32_t t_start = 0;
void setup() {
Serial.begin(115200);
pinMode(I_FLOAT_MIN, INPUT);
pinMode(I_FLOAT_MAX, INPUT);
pinMode(I_FLOAT_OVERFLOW, INPUT);
pinMode(I_CONFIRMATION, INPUT);
pinMode(I_THERMAL, INPUT);
pinMode(I_RESET, INPUT);
pinMode(Q_PUMP, OUTPUT);
pinMode(Q_PILOT, OUTPUT);
digitalWrite(Q_PUMP, LOW);
digitalWrite(Q_PILOT, LOW);
}
void loop() {
// 1. Read inputs
bool minLvl = digitalRead(I_FLOAT_MIN);
bool maxLvl = digitalRead(I_FLOAT_MAX);
bool ovf = digitalRead(I_FLOAT_OVERFLOW);
bool confirm = digitalRead(I_CONFIRMATION);
bool thermal = digitalRead(I_THERMAL);
bool reset = digitalRead(I_RESET);
// 2. State machine
switch (state) {
case OFF_S:
if (minLvl && maxLvl) { // tank full: start
digitalWrite(Q_PUMP, HIGH);
t_start = millis();
state = ON_S;
}
break;
case ON_S:
if (!minLvl) { // tank emptied: stop
digitalWrite(Q_PUMP, LOW);
state = OFF_S;
break;
}
if (thermal) { // thermal relay tripped
data[FAULT] = true;
enterError();
break;
}
// no contactor feedback once the start-up margin has elapsed
if (!confirm && millis() - t_start > T_CONFIRMATION_MS) {
data[CONF_FAULT] = true;
enterError();
}
break;
case ERROR_S:
if (reset) { // manual reset
data[FAULT] = data[CONF_FAULT] = data[ERROR_F] = false;
digitalWrite(Q_PILOT, LOW);
state = OFF_S;
}
break;
}
// 3. Update telemetry
data[MIN_LEVEL] = minLvl;
data[MAX_LEVEL] = maxLvl;
data[OVERFLOW_LEVEL] = ovf;
data[RUNNING] = (state == ON_S);
// 4. Periodic serial dump (replace with MQTT/LoRaWAN/Modbus sending)
static uint32_t t_log = 0;
if (millis() - t_log > 5000) {
t_log = millis();
Serial.printf("state=%d min=%d max=%d ovf=%d run=%d fault=%d conf=%d err=%d\n",
state, minLvl, maxLvl, ovf,
data[RUNNING], data[FAULT], data[CONF_FAULT], data[ERROR_F]);
}
delay(100); // 100 ms control cycle, same as the original project
}
void enterError() {
digitalWrite(Q_PUMP, LOW);
digitalWrite(Q_PILOT, HIGH);
data[ERROR_F] = true;
state = ERROR_S;
}
Download the full project pack — freeThis example + the related ones + bill of materials