เก็บค่าการตั้งค่า ESP32 แบบถาวรด้วย Preferences
บทนำ:
Preferences คืออะไร?
Preferences เป็นคลาสที่อยู่ใน Arduino Core for ESP32 ใช้สำหรับ จัดเก็บข้อมูลถาวร (non-volatile storage) ลงในหน่วยความจำแฟลชของบอร์ด โดยข้อมูลจะ ไม่หายแม้ปิดไฟ เหมาะกับการเก็บค่าการตั้งค่าต่าง ๆ เช่น:
ค่าคอนฟิกอุปกรณ์ (เช่น ตั้งเวลาเปิด/ปิดอัตโนมัติ)
ค่าเซตพ้อยต์อุณหภูมิ
ค่ารหัส Wi-Fi
สถานะอุปกรณ์ล่าสุด
แล้วมันต่างจาก EEPROM ยังไง?
แม้ Preferences และ EEPROM จะใช้เก็บข้อมูลถาวรเหมือนกัน แต่มีความแตกต่างหลัก ๆ ดังนี้:
| จุดเปรียบเทียบ | Preferences | EEPROM |
|---|---|---|
| รองรับหลาย key | ✅ ใช้ key เป็นชื่อแยกแต่ละค่า | ❌ ใช้เป็น byte address |
| ใช้งานง่ายกว่า | ✅ ใช้ฟังก์ชัน putString(), getInt() ฯลฯ | ❌ ต้องกำหนด byte address เอง |
| มีระบบ namespace | ✅ จัดกลุ่มข้อมูลได้ | ❌ ไม่มีระบบจัดกลุ่ม |
| ความปลอดภัยข้อมูล | ✅ มีระบบ commit อัตโนมัติ | ❌ ต้องระวังเขียนทับ address |
ดังนั้นหากคุณใช้ ESP32 ไม่จำเป็นต้องย้อนกลับไปใช้ EEPROM เลย เพราะ Preferences ถูกออกแบบมาให้ใช้งานได้สะดวกและปลอดภัยกว่าโดยตรง
ทำไมต้องใช้ Preferences กับ ESP32?
เหตุผลที่ควรใช้ Preferences มีหลายข้อ โดยเฉพาะในการสร้างระบบ Smart Farm หรือ IoT เช่นระบบ PoPo ที่ต้อง:
✅ จำค่าตั้งเวลาอุปกรณ์ (เช่น เปิดพัดลมเวลา 10:00 น.)
✅ จำค่า Wi-Fi ที่ผู้ใช้ป้อน (เพื่อเชื่อมต่ออัตโนมัติเมื่อรีสตาร์ท)
✅ เก็บสถานะ “เปิด/ปิดอัตโนมัติ” หรือโหมดต่าง ๆ
✅ ทำให้ระบบ รีสตาร์ทแล้วทำงานต่อได้ทันที โดยไม่ต้องตั้งค่าใหม่ทุกครั้ง
โดยรวมแล้ว Preferences คือเครื่องมือสำคัญที่ช่วยให้ ESP32 กลายเป็นอุปกรณ์อัจฉริยะที่ “จำได้” และ “ทำต่อ” ได้แม้ไฟดับหรือบอร์ดรีสตาร์ท
รายละเอียดพื้นฐานของ — ESP32 คืออะไร พร้อมจุดเด่นและวิธีเริ่มต้นใช้งาน
เริ่มต้นใช้งาน Preferences บน ESP32
หลังจากรู้แล้วว่า Preferences คืออะไรและทำไมถึงควรใช้ มาดูวิธีเริ่มต้นใช้งานกันเลยครับ ง่าย ๆ ไม่กี่บรรทัดก็ใช้ได้แล้ว
1. การ import ไลบรารี Preferences.h
ก่อนอื่นต้อง include ไลบรารีนี้เข้าไปในโค้ดของเราก่อนครับ#include
2. การประกาศตัวแปร Preferences และเริ่มต้นใช้งาน
Preferences prefs; // ประกาศตัวแปร prefs สำหรับเรียกใช้งานในการเริ่มใช้งาน ต้องเรียก prefs.begin() ก่อน โดยมีรูปแบบดังนี้:
prefs.begin("my-app", false);| พารามิเตอร์ | อธิบาย |
|---|---|
"my-app" | ชื่อ namespace ใช้แยกกลุ่มข้อมูล |
false | ถ้า false = อ่าน/เขียน, ถ้า true = อ่านอย่างเดียว |
3. การเก็บค่า (put) และเรียกคืนค่า (get)
Preferences รองรับหลายประเภทข้อมูล เช่น int, float, String
ตัวอย่างเช่น เราอยากเก็บค่าอุณหภูมิตั้งต้นไว้:// บันทึกค่า
prefs.putFloat("tempSet", 25.5);
// อ่านค่า
float temp = prefs.getFloat("tempSet", 0.0); // ถ้าไม่มีค่าให้ใช้ 0.0 แทน
หรือถ้าเป็นข้อความ:prefs.putString("wifiPass", "12345678");
String pass = prefs.getString("wifiPass", "defaultpass");
✅ Tip: อย่าลืมปิดเมื่อใช้เสร็จ เพื่อเคลียร์หน่วยความจำprefs.end();
สรุปโครงสร้างแบบสั้น ๆ
#include <Preferences.h>
Preferences prefs;
void setup() {
Serial.begin(115200);
prefs.begin("my-app", false); // เริ่มใช้งาน Preferences
prefs.putInt("count", 10); // บันทึกค่า
int value = prefs.getInt("count", 0); // ดึงค่ากลับมา
Serial.println(value);
prefs.end(); // ปิดการใช้งาน
}
ตัวอย่างการใช้งาน Preferences บน ESP32
การใช้ Preferences ช่วยให้บอร์ด ESP32 “จำค่าเดิมได้” แม้จะปิดไฟหรือรีเซ็ตไปแล้ว โดยเฉพาะในระบบ Smart Farm ที่ต้องเก็บค่า config ต่าง ๆ ของผู้ใช้ไว้ให้พร้อมใช้งานทุกครั้งที่เปิดเครื่อง
#include <Preferences.h>
Preferences prefs;
void saveDeviceName(String name) {
prefs.begin("config", false);
prefs.putString("deviceName", name);
prefs.end();
}
String loadDeviceName() {
prefs.begin("config", true);
String name = prefs.getString("deviceName", "MyESP32");
prefs.end();
return name;
}
🔧 ใช้ในระบบ PoPo เพื่อแสดงชื่ออุปกรณ์ในหน้าแอป เช่น “พัดลมโรงเรือน”, “แสงสว่างโซน A”
void saveHumiditySetpoint(float humidity) {
prefs.begin("config", false);
prefs.putFloat("humSet", humidity);
prefs.end();
}
float loadHumiditySetpoint() {
prefs.begin("config", true);
float humidity = prefs.getFloat("humSet", 50.0); // ค่า default = 50%
prefs.end();
return humidity;
}
📌 นำไปใช้เปรียบเทียบกับค่าความชื้นจริง ถ้าต่ำกว่าก็เปิดปั๊มน้ำอัตโนมัติ
void saveWiFiConfig(String ssid, String password) {
prefs.begin("wifi", false);
prefs.putString("ssid", ssid);
prefs.putString("pass", password);
prefs.end();
}
void loadWiFiConfig(String &ssid, String &password) {
prefs.begin("wifi", true);
ssid = prefs.getString("ssid", "");
password = prefs.getString("pass", "");
prefs.end();
}
🔐 ข้อมูล SSID และรหัสผ่านจะถูกเก็บในหน่วยความจำแฟลช ไม่หลุดหายเมื่อรีสตาร์ท และไม่ต้องใส่ใหม่ทุกครั้ง| การใช้งาน | Key | Namespace | ประเภทข้อมูล |
|---|---|---|---|
| ชื่ออุปกรณ์ | "deviceName" | "config" | String |
| Setpoint ความชื้น | "humSet" | "config" | float |
| WiFi SSID/Pass | "ssid", "pass" | "wifi" | String |
ข้อควรระวังและแนวทางที่ดีเมื่อใช้ Preferences กับ ESP32
แม้ว่า Preferences จะใช้ง่ายและสะดวกมาก แต่ก็มีข้อควรระวังที่สำคัญ และแนวทางดี ๆ ที่ช่วยให้ระบบของคุณทำงานได้ยาวนานและมีระเบียบมากขึ้น
⚠️ 1. อย่าเขียนข้อมูลถี่เกินไป (Flash Wear)
หน่วยความจำ Flash ของ ESP32 มี อายุจำกัด ประมาณ 10,000 – 100,000 ครั้งในการเขียนต่อ 1 บล็อก
🔥 ถ้าคุณ
prefs.putXXX()บ่อย ๆ เช่น ทุกวินาที หรือทุกครั้งที่มีเซนเซอร์เปลี่ยนค่า = Flash เสื่อมไวแน่นอน
แนวทางที่ดี:
เขียนเมื่อจำเป็น เช่น เมื่อผู้ใช้กด “บันทึก” ในแอป
หลีกเลี่ยงเขียนใน loop()
ตั้ง flag ว่า “ข้อมูลเปลี่ยนแล้ว” ค่อยเขียน
bool needToSave = false;
if (humiditySetpointChanged) {
needToSave = true;
}
if (needToSave) {
prefs.begin("config", false);
prefs.putFloat("humSet", newHumidity);
prefs.end();
needToSave = false;
}
2. แยก namespace ตามหมวดหมู่ (เพื่อความเป็นระเบียบ)
Preferences รองรับ namespace ให้คุณจัดกลุ่มข้อมูลได้ เช่น:
prefs.begin("config", false); // สำหรับค่าเซ็ตพอยต์
prefs.begin("wifi", false); // สำหรับ WiFi SSID/Password
prefs.begin("user", false); // สำหรับชื่ออุปกรณ์
3. เคล็ดลับการ Debug ค่าที่เก็บไว้
วิธีดูค่าทั้งหมดที่เก็บไว้ใน namespace:
Preferences prefs;
prefs.begin("config", true);
Serial.println(prefs.getFloat("humSet", 0));
Serial.println(prefs.getInt("timerHour", 0));
Serial.println(prefs.getBool("autoMode", false));
prefs.end();
prefs.begin("config", false);
prefs.clear(); // ลบทุก key ใน namespace นี้
prefs.end();
🎯 สรุปแนวทางที่ดี:
| แนวทาง | อธิบาย |
|---|---|
| เขียนข้อมูลเฉพาะเมื่อจำเป็น | ลดการสึกหรอของ Flash |
| แยก namespace ชัดเจน | ทำให้โค้ดดูแลง่าย |
| ใส่ default value เสมอ | กันโค้ดพังเมื่อยังไม่มีข้อมูล |
ใช้ clear() สำหรับ debug | ล้างค่าเพื่อลองใหม่ได้เร็ว |
“หากยังไม่รู้จัก ESPAsyncWebServer มาก่อน แนะนำให้อ่านคู่มือฉบับเต็มก่อนใช้งานจริง”
🔗 ESPAsyncWebServer Guide
ตัวอย่างโค้ดเต็ม: การใช้งาน Preferences เก็บค่าและเรียกคืนค่า
🎯 เป้าหมายของโค้ด
บันทึกชื่ออุปกรณ์
บันทึกค่า Setpoint ความชื้น
โหลดค่าทั้งสองจาก Flash เมื่อบอร์ดเปิดใหม่
#include <Preferences.h> // โหลดไลบรารี Preferences
Preferences prefs; // สร้างตัวแปร prefs เพื่อใช้งาน
String deviceName; // ตัวแปรเก็บชื่ออุปกรณ์
float humiditySetpoint; // ตัวแปรเก็บค่าเซ็ตพอยต์ความชื้น
void setup() {
Serial.begin(115200); // เปิด Serial Monitor สำหรับดูผล
// เริ่มต้นใช้งาน Preferences ใน namespace "config"
prefs.begin("config", false); // false = อนุญาตให้อ่าน/เขียน
// ดึงค่าจาก Flash หากเคยบันทึกไว้, ถ้าไม่เคย จะใช้ค่าตั้งต้น
deviceName = prefs.getString("devName", "MyDevice"); // default: MyDevice
humiditySetpoint = prefs.getFloat("humSet", 50.0); // default: 50%
// แสดงค่าที่โหลดมา
Serial.println("ชื่ออุปกรณ์: " + deviceName);
Serial.print("เซ็ตพอยต์ความชื้น: ");
Serial.println(humiditySetpoint);
prefs.end(); // ปิด Preferences เมื่อใช้งานเสร็จ
}
void loop() {
// ตัวอย่าง: ถ้าผู้ใช้ส่งค่ามา (เช่นจาก Serial หรือแอป)
// เราจะจำลองการบันทึกค่าใหม่
delay(10000); // รอ 10 วินาที (จำลองว่าเกิด event)
// บันทึกค่าชื่อใหม่และค่าเซ็ตพอยต์ใหม่
deviceName = "FAN_ZONE_A";
humiditySetpoint = 60.5;
prefs.begin("config", false);
prefs.putString("devName", deviceName);
prefs.putFloat("humSet", humiditySetpoint);
prefs.end();
Serial.println("บันทึกค่าลง Flash แล้ว");
Serial.println("ชื่ออุปกรณ์ใหม่: " + deviceName);
Serial.print("เซ็ตพอยต์ใหม่: ");
Serial.println(humiditySetpoint);
while (true); // จบ loop เพื่อไม่ให้เขียนซ้ำอีก
}
🔍 คำอธิบายสั้น ๆ:
| คำสั่ง | ความหมาย |
|---|---|
prefs.begin("config", false); | เริ่มใช้งาน namespace ชื่อ “config” (false = เขียนได้) |
prefs.getString("devName", "MyDevice") | ดึงค่าชื่ออุปกรณ์ ถ้าไม่มีใช้ "MyDevice" |
prefs.putFloat("humSet", humiditySetpoint) | บันทึกค่า setpoint แบบ float ลง Flash |
prefs.end(); | ปิดการใช้งาน Preferences เพื่อคืนหน่วยความจำ |
✅ สรุป:
ใช้งานง่ายมาก แค่ 3 ขั้นตอน:
begin → put/get → endใช้กับทุกโปรเจกต์ที่ต้อง “จำค่า” ได้เลย
ปลอดภัยกว่า EEPROM และอ่านง่ายกว่ามาก
หากคุณต้องการสร้างระบบเชื่อมต่อ WiFi แบบไม่ต้องแก้โค้ดทุกครั้ง พร้อมกับบันทึก SSID และรหัสผ่านแบบถาวรด้วย `Preferences` ✅ แนะนำเรียนรู้จากคอร์สเต็ม: 🔗 WiFiManager กับ ESP32 พร้อมใช้ Preferences
✅ FAQ (คำถามที่พบบ่อย)
Q: Preferences ต่างจาก EEPROM ยังไง?
A: Preferences ใช้ NVS (Non-volatile storage) ซึ่งปลอดภัยกว่า จัดการข้อมูลเป็น key-value ใช้ง่ายกว่า EEPROM
Q: เขียนข้อมูลบ่อย ๆ จะทำให้ flash เสื่อมหรือเปล่า?
A: ใช่ครับ แนะนำให้เขียนเฉพาะตอนที่มีการเปลี่ยนค่า ไม่ควรเขียนใน loop บ่อย ๆ
Q: เก็บ password WiFi ด้วย Preferences ปลอดภัยไหม?
A: ปลอดภัยระดับหนึ่งสำหรับงานทั่วไป แต่ไม่ควรใช้กับงานที่ต้องการความปลอดภัยสูงแบบ IoT Cloud
Q: จะลบค่าใน Preferences ต้องทำยังไง?
A: ใช้ preferences.remove("key_name") หรือลบทั้งหมดด้วย preferences.clear()






