Thư viện Preferences.h: thay EEPROM trên ESP32
ESP32 không có EEPROM thực sự — chỉ giả lập trên flash với API giống Arduino. Espressif khuyến nghị không dùng EEPROM.h, mà chuyển sang Preferences.h: API key-value đơn giản, wear-leveling tốt, kiểu dữ liệu rõ ràng. Bài này hướng dẫn đầy đủ.
1. Preferences là gì?
Wrapper xung quanh NVS (Non-Volatile Storage) — phân vùng flash dành riêng. Lưu cặp key-value trong các "namespace":
- Mỗi namespace như một "thư mục" (≤ 15 ký tự).
- Mỗi key như tên biến (≤ 15 ký tự).
- Value: kiểu cụ thể (uint8/16/32/64, string, blob).
Không phải dùng địa chỉ byte như EEPROM — dễ đọc hơn nhiều.
2. Cài đặt
Preferences.h đi kèm Arduino-ESP32 core — KHÔNG cần cài thêm.
#include
Preferences prefs;
3. Mở namespace
prefs.begin("my-app", false); // false = read/write
prefs.begin("my-app", true); // true = read-only
Namespace tự tạo lần đầu. Tối đa ~250 namespace trên partition NVS mặc định.
4. Ghi giá trị
prefs.putUChar("led-mode", 2);
prefs.putUShort("port", 1883);
prefs.putUInt("baud", 115200);
prefs.putULong64("timestamp", 1716000000ULL);
prefs.putFloat("temp-offset", -1.5);
prefs.putDouble("pi", 3.14159265358979);
prefs.putString("ssid", "MyWiFi");
prefs.putString("pass", "secret");
prefs.putBool("enabled", true);
prefs.putBytes("raw", buf, len);
Có overload cho mọi kiểu dữ liệu cơ bản. Mỗi putXxx trả số byte đã ghi.
5. Đọc giá trị (với default fallback)
uint8_t mode = prefs.getUChar("led-mode", 0); // default 0 nếu thiếu
uint16_t port = prefs.getUShort("port", 1883);
String ssid = prefs.getString("ssid", "");
bool en = prefs.getBool("enabled", false);
float off = prefs.getFloat("temp-offset", 0.0);
size_t n = prefs.getBytes("raw", buf, 256);
Luôn có default — tránh giá trị rác khi key chưa tồn tại.
6. Đóng namespace
prefs.end();
Có thể không gọi end() nếu chỉ dùng 1 namespace trong app — tài nguyên tự free khi reboot. Nhưng nên gọi để giải phóng heap.
7. Xoá
prefs.remove("led-mode"); // xoá 1 key
prefs.clear(); // xoá toàn namespace
8. Kiểm tra tồn tại
if (prefs.isKey("ssid")) {
// có
}
9. Pattern thực tế — load/save config
struct Config {
char ssid[33];
char pass[33];
uint16_t port;
bool deepSleep;
};
void loadConfig(Config& c) {
Preferences p;
p.begin("cfg", true);
String s = p.getString("ssid", "");
strncpy(c.ssid, s.c_str(), sizeof(c.ssid));
s = p.getString("pass", "");
strncpy(c.pass, s.c_str(), sizeof(c.pass));
c.port = p.getUShort("port", 1883);
c.deepSleep = p.getBool("ds", false);
p.end();
}
void saveConfig(const Config& c) {
Preferences p;
p.begin("cfg", false);
p.putString("ssid", c.ssid);
p.putString("pass", c.pass);
p.putUShort("port", c.port);
p.putBool("ds", c.deepSleep);
p.end();
}
10. Lưu mảng / struct dài
uint8_t buf[128];
prefs.putBytes("data", buf, sizeof(buf));
prefs.getBytes("data", buf, sizeof(buf));
size_t actualSize = prefs.getBytesLength("data");
Tốt cho lưu calibration data, lookup table.
11. Wear-leveling và tuổi thọ
NVS tự rotate vị trí ghi để san bằng wear. ESP32 flash chịu ~100.000 chu kỳ ghi mỗi sector. Với NVS, bạn có thể ghi key giá trị mới hàng triệu lần tổng cộng — đủ cho mọi use case thực tế.
Nhưng vẫn nên: chỉ ghi khi giá trị thay đổi, không ghi mỗi loop.
12. Reset NVS — recovery
Khi code crash do data hỏng, có thể wipe NVS từ menu Arduino IDE → Tools → Erase All Flash Before Sketch Upload: Enabled. Hoặc:
nvs_flash_erase(); // xoá toàn NVS
nvs_flash_init(); // init lại
13. So sánh với EEPROM.h
| Tính năng | EEPROM.h (ESP32) | Preferences.h |
|---|---|---|
| API | Địa chỉ byte | Key-value |
| Kiểu dữ liệu | Byte/struct (put/get) | Tất cả kiểu sẵn |
| Wear-leveling | Không | Có |
| Phải commit | Có | Tự lưu sau put |
| Đa namespace | Không | Có |
Không có lý do gì để dùng EEPROM.h trên ESP32. Preferences thắng về mọi mặt.
14. Lỗi thường gặp
- begin() returns false: partition NVS không tồn tại → đổi partition scheme.
- String dài bị truncate: NVS giới hạn ~1984 byte mỗi key. Chia ra nhiều key.
- Namespace name quá dài: tối đa 15 ký tự. Đặt ngắn.
- Get sai kiểu: lưu bằng
putUInt, đọc bằnggetUShort→ giá trị sai. Phải khớp kiểu.
Liên quan
So sánh với EEPROM.h: lưu cấu hình vào flash Arduino. Áp dụng để lưu cấu hình WiFi trong dự án ESP32 web server bật/tắt relay.