Arduino ESP32 参数持久化实战:基于文件系统的配置存储方案

1次阅读
没有评论

共计 2335 个字符,预计需要花费 6 分钟才能阅读完成。

image.webp

背景痛点

在嵌入式开发中,参数持久化存储是一个基础但关键的需求。传统方案通常使用 EEPROM,但在 ESP32 开发中,这种方案存在明显不足:

Arduino ESP32 参数持久化实战:基于文件系统的配置存储方案

  • 有限的擦写次数 :典型 EEPROM 仅有 10 万次擦写寿命,频繁更新的参数会快速耗尽寿命
  • 小容量限制 :ESP32 模拟 EEPROM 通常只有几百字节空间,难以存储复杂配置
  • 管理不便 :需要手动处理地址分配,增加维护成本
  • 缺乏结构 :只能存储原始字节,缺乏数据组织形式

技术选型

ESP32 支持两种主流文件系统解决方案:

SPIFFS 特点

  • 专为 SPI NOR Flash 优化的轻量级文件系统
  • 静态磨损均衡机制
  • 最大支持 4MB 分区
  • 已被证明的稳定性

LittleFS 优势

  • 更现代的设计
  • 动态磨损均衡
  • 更好的目录支持
  • 更快的挂载速度

推荐选择 :对于大多数参数存储场景,SPIFFS 已经足够。如果需要频繁写入或更大容量,建议使用 LittleFS。

核心实现

1. 文件系统初始化

#include "SPIFFS.h"

void setup() {Serial.begin(115200);

  if(!SPIFFS.begin(true)) {Serial.println("SPIFFS 挂载失败");
    return;
  }

  // 检查配置文件是否存在
  if(!SPIFFS.exists("/config.json")) {createDefaultConfig();
  }
}

2. 参数序列化设计

推荐使用 JSON 格式存储结构化参数:

{
  "wifi_ssid": "MyNetwork",
  "wifi_pwd": "password123",
  "sensor_interval": 60,
  "threshold": 25.5
}

3. 原子写入实现

为防止写入过程中断电导致数据损坏,采用临时文件 + 重命名策略:

void saveConfig(const char *jsonStr) {File tempFile = SPIFFS.open("/config.tmp", "w");
  if(!tempFile) {Serial.println("临时文件创建失败");
    return;
  }

  tempFile.print(jsonStr);
  tempFile.close();

  // 原子操作:重命名替换
  if(SPIFFS.rename("/config.tmp", "/config.json")) {Serial.println("配置保存成功");
  } else {Serial.println("重命名失败");
    SPIFFS.remove("/config.tmp");
  }
}

完整代码示例

#include <ArduinoJson.h>
#include "SPIFFS.h"

struct Config {char wifiSSID[32];
  char wifiPWD[64];
  int sensorInterval;
  float threshold;
} config;

bool loadConfig() {File file = SPIFFS.open("/config.json", "r");
  if(!file) return false;

  DynamicJsonDocument doc(1024);
  DeserializationError error = deserializeJson(doc, file);
  file.close();

  if(error) {Serial.print("JSON 解析错误:");
    Serial.println(error.c_str());
    return false;
  }

  strlcpy(config.wifiSSID, doc["wifi_ssid"], sizeof(config.wifiSSID));
  strlcpy(config.wifiPWD, doc["wifi_pwd"], sizeof(config.wifiPWD));
  config.sensorInterval = doc["sensor_interval"];
  config.threshold = doc["threshold"];

  return true;
}

bool saveConfig() {DynamicJsonDocument doc(1024);
  doc["wifi_ssid"] = config.wifiSSID;
  doc["wifi_pwd"] = config.wifiPWD;
  doc["sensor_interval"] = config.sensorInterval;
  doc["threshold"] = config.threshold;

  File tempFile = SPIFFS.open("/config.tmp", "w");
  if(!tempFile) return false;

  serializeJson(doc, tempFile);
  tempFile.close();

  if(!SPIFFS.rename("/config.tmp", "/config.json")) {SPIFFS.remove("/config.tmp");
    return false;
  }

  return true;
}

性能优化

  1. 碎片化预防
  2. 避免频繁创建 / 删除文件
  3. 保持文件大小相对固定

  4. 内存管理

  5. 使用适当大小的 JSON 缓冲区
  6. 及时关闭文件句柄

  7. 读写速度

  8. 典型 4MB SPIFFS 写入速度约 100KB/s
  9. 读取速度可达 500KB/s

常见问题解决

文件系统挂载失败

  1. 检查分区表配置
  2. 尝试格式化:SPIFFS.format()
  3. 确认 Flash 模式设置正确

电源波动防护

  1. 使用 UPS 电容保证干净关机
  2. 实现写操作超时检测
  3. 添加校验和机制

线程安全

  1. 使用互斥锁保护文件操作
  2. 避免多任务同时写入

进阶扩展

考虑将本方案与 OTA 升级结合:

  1. 在 OTA 前备份配置
  2. 升级后自动恢复
  3. 实现配置版本兼容

通过文件系统存储参数,不仅解决了 EEPROM 的限制,还为未来功能扩展提供了坚实基础。

正文完
 0
评论(没有评论)