Skip to Content

← Non-Blocking WiFi Reconnection on an ESP32 PLC

Textile monitoring (weaving)ESP32 PLCWiFiResilience / OTA

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