← Non-Blocking WiFi Reconnection on an ESP32 PLC
Non-Blocking WiFi Reconnection on an ESP32 PLC — full example
Non-blocking WiFi reconnection for ESP32 PLC firmware: rate-limited retries, drop counters and a loop that keeps monitoring machines with no network.
Complete, runnable program for the ESP32 PLC (nonblocking-wifi-reconnection.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 — Non-blocking WiFi reconnection
*
* Hardware: ESP32 PLC (Industrial Shields, any model with WiFi)
* Based on: textile monitoring project, modul_WIFI.h
*
* Network:
* Industrial plant WiFi (it can drop: saturated APs, interference
* from VFDs, maintenance outages...)
*
* Architecture:
* 1. checkWiFiConnection() is called on EVERY loop iteration and never
* blocks: if there is a connection it returns immediately
* 2. Without a connection, it retries at most once every 10 s
* (WiFi.begin() is asynchronous: the result is not awaited)
* 3. Meanwhile the PLC keeps working: in this example, counting
* machine pulses via interrupt and logging the status
* 4. Global status flag + drop counter for diagnostics
*
* Works together with other catalog examples:
* - production-pulse-counter.ino (keeps counting without network)
* - sd-daily-file-datalogging.ino (no data is lost)
* - webserver-ota-firmware.ino (exposes wifi_drops as a health metric)
*/
#include
const char *WIFI_SSID = "WIFI_SSID";
const char *WIFI_PASS = "WIFI_PASS";
const uint32_t RETRY_INTERVAL_MS = 10000; // 1 retry every 10 s
bool wifiConnected = false; // global flag other modules consult
uint32_t wifiDrops = 0; // number of connected->down transitions
uint32_t lastConnectionAttempt = 0;
uint32_t tStatus = 0;
volatile uint32_t pulses = 0; // real work that must NOT stop
// ------------------------------------------------- Core of the pattern
void checkWiFiConnection() {
if (WiFi.status() == WL_CONNECTED) {
if (!wifiConnected) {
wifiConnected = true;
Serial.println("WiFi connected. IP: " + WiFi.localIP().toString());
}
return; // fast path: zero cost
}
if (wifiConnected) { // it just went down
wifiConnected = false;
wifiDrops++;
Serial.println("WiFi down (drop no. " + String(wifiDrops) + ")");
}
// Spaced retry WITHOUT waiting for the result: begin() is asynchronous
if (millis() - lastConnectionAttempt >= RETRY_INTERVAL_MS) {
lastConnectionAttempt = millis();
Serial.println("Retrying WiFi...");
WiFi.mode(WIFI_STA);
WiFi.disconnect();
WiFi.begin(WIFI_SSID, WIFI_PASS);
}
}
void setup() {
Serial.begin(115200);
// Plant work: production counter via interrupt
pinMode(I0_0, INPUT);
attachInterrupt(I0_0, [] { pulses++; }, FALLING);
// First connection attempt, also without blocking startup
WiFi.mode(WIFI_STA);
WiFi.begin(WIFI_SSID, WIFI_PASS);
lastConnectionAttempt = millis();
}
void loop() {
checkWiFiConnection(); // never blocks
// The rest of the firmware ALWAYS runs, with or without network:
if (millis() - tStatus >= 5000) {
tStatus = millis();
String line = "pulses=" + String(pulses) +
" wifi=" + String(wifiConnected ? "OK" : "DOWN") +
" drops=" + String(wifiDrops);
Serial.println(line);
// In production: saveToSD(line) and, if wifiConnected,
// publish over MQTT. The SD covers the gaps without network.
}
delay(20);
}
Download the full project pack — freeThis example + the related ones + bill of materials