Salvare il valore di un contatore o le credenziali WiFi in modo persistente non richiede piu' scrivere in EEPROM emulata. Da anni ESP32 offre NVS (Non-Volatile Storage) esposto via la libreria Preferences — 3 righe per leggere, 3 righe per scrivere, garanzia di wear leveling automatico.
1. Namespace: raggruppa i tuoi dati
Ogni set di variabili sta dentro un namespace (max 15 caratteri) per non collidere con librerie di terze parti.
#include <Preferences.h>
Preferences prefs;
void setup() {
prefs.begin("mia_app", /*readOnly=*/false); // apre il namespace
}
2. Scrittura
prefs.putUInt("boot_count", 42);
prefs.putFloat("k_calib", 1.023f);
prefs.putBool("dark_mode", true);
prefs.putString("wifi_ssid", "TuaRete");
prefs.putString("wifi_pass", "PasswordSegreta");
prefs.putBytes("cert", cert_data, cert_len); // fino a ~500 KB
3. Lettura con default
uint32_t n = prefs.getUInt ("boot_count", 0); // 0 se non presente
float k = prefs.getFloat ("k_calib", 1.0f);
bool dark = prefs.getBool ("dark_mode", false);
String ssid = prefs.getString ("wifi_ssid", "");
// bytes: passi un buffer, ritorna la lunghezza effettiva
uint8_t buf[512];
size_t n_read = prefs.getBytes("cert", buf, sizeof(buf));
4. Contatore di boot: esempio classico
void setup() {
prefs.begin("stats", false);
uint32_t boots = prefs.getUInt("count", 0) + 1;
prefs.putUInt("count", boots);
prefs.end();
Serial.printf("Boot n. %u
", boots);
}
5. Cancellare tutto (factory reset)
prefs.begin("mia_app", false);
prefs.clear(); // svuota solo questo namespace
prefs.end();
#include <nvs_flash.h>
nvs_flash_erase(); // wipe TOTALE (radicale, richiede reboot dopo)
nvs_flash_init();
6. Limiti da conoscere
- Chiavi max 15 caratteri.
"boot_count"OK,"contatore_boots"NO - Stringhe fino a ~4000 bytes; oltre usa
putByteso SPIFFS/LittleFS - Il write ha un limite di ~100.000 cicli per cella. Evita loop tipo "scrivi ogni sample" — accumula e scrivi periodicamente
- Se il namespace non esiste al primo begin ottieni un errore
nvs_open failed: NOT_FOUNDma viene creato: nessun impatto
7. Namespace di stato vs configurazione
Best practice: separa i namespace per proposito.
Preferences cfg, stats;
cfg.begin("config", false); // credenziali, URL server, calibrazione
stats.begin("stats", false); // boot count, error count, uptime medio
8. Esempio completo: credenziali WiFi con fallback AP
void connectWiFi() {
prefs.begin("wifi", true); // read-only
String ssid = prefs.getString("ssid", "");
String pass = prefs.getString("pass", "");
prefs.end();
if (ssid.length() == 0) {
WiFi.softAP("ESP32-Setup"); // modalita' AP per config web
return;
}
WiFi.begin(ssid.c_str(), pass.c_str());
}
Attenzione: non salvare password in chiaro in NVS se il dispositivo puo' cadere in mani sbagliate. NVS non e' cifrato di default. Per dati sensibili abilita NVS Encryption (usa e-fuse per la chiave, non modificabile dopo).