Persistent machine counters on an ESP32 PLC using NVS (Preferences)
Machine totals are worthless if they vanish at every power cycle. With ESP32 NVS Preferences the PLC keeps its serial number, load/unload cycle counters, lifetime totals, oil volume and an activation flag in internal flash — no SD card, no battery. This pattern comes from a real mobile hydraulic machine deployment where the equipment is powered from a truck and gets switched off abruptly several times a day, yet warranty counters must never reset.
One namespace, typed keys
The Preferences library wraps the ESP32 NVS partition in a simple key-value API:
putInt, putFloat, putString and putBool under a single "nvdata" namespace, with matching getters that accept a default value. On boot the firmware reads everything back in one pass, so a freshly flashed PLC starts cleanly at zero while a unit returning from the field resumes exactly where it left off — same code, no special cases.Deferred writes protect the flash
NVS flash supports a finite number of write cycles, so writing on every event is a slow way to kill the chip. The example sets a dirty flag when a counter changes and commits at most once every few seconds. Power loss can cost you the last seconds of data at worst — an acceptable trade for years of flash life.
Counters the mobile app can read
In the full machine these values are reported over BLE as
[C1] and [C2] frames, so a technician's phone shows lifetime load and unload cycles without opening the electrical cabinet or plugging in a laptop. The same storage also backs the hardware watchdog's reboot counter and the activation flag used for commissioning, which effectively turns NVS into the machine's built-in, tamper-resistant logbook.A snippet from the implementation
Straight from the example as deployed on the ESP32 PLC 38R — copy it freely:
void setup() {
Serial.begin(115200);
pinMode(BTN_LOAD, INPUT);
pinMode(BTN_UNLOAD, INPUT);
loadNVS(); // the counters come back exactly as they were after every reboot
Serial.println("=== Persistent counters (NVS) ===");
Serial.println("Serial: " + serialNum);
Serial.println("Loads: " + String(counterLoad));
Serial.println("Unloads: " + String(counterUnload));
Serial.println("Lifetime: " + String(counterLife));
Serial.println("Oil: " + String(oilVolume, 1) + " L");
Serial.println("Activated: " + String(activated ? "yes" : "no"));
}The full example is a complete program — wiring header, setup and main loop — ready to adapt to your application.
Frequently asked questions
How many write cycles does ESP32 NVS flash survive?
The underlying flash endures around 100,000 erase cycles per sector, and NVS wear-levels across its partition. With deferred writes every few seconds you get many years of service in practice.
What happens to my counters when I upload new firmware?
Nothing. NVS lives in its own flash partition, so OTA updates and USB re-flashing of the application leave the stored values intact unless you explicitly erase the whole flash.
Is Preferences better than EEPROM emulation on ESP32?
Yes. The EEPROM library on ESP32 is a compatibility shim on top of a single NVS blob, while Preferences gives you typed keys, wear leveling and atomic commits natively.