You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将网页数据推送存储到CSV文件?基于ESP32+BME680传感器场景

ESP32 WebServer对接BME680数据存储CSV实现方案

核心逻辑说明

不建议从HTML前端主动推送数据存储,最优方案是ESP32采集完BME680传感器数据后,同步做两个操作:

  1. 把数据返回给前端网页做实时展示
  2. 直接在ESP32本地写入CSV文件,后续绘图时直接读取本地CSV内容返回前端即可
    该方案不需要额外的前端交互逻辑,稳定性更高,资源占用更低。

具体实现步骤

1. 前置准备

首先在Arduino IDE中安装ESP32 LittleFS文件系统上传插件,使用LittleFS存储CSV文件,相比SPIFFS读写效率更高、容错性更好。

2. 文件系统与CSV初始化

启动WebServer前先挂载LittleFS,若CSV文件不存在则自动创建并写入表头:

#include <WebServer.h>
#include <LittleFS.h>
#include <Adafruit_BME680.h> // 按需替换为你使用的BME680库

WebServer server(80);
Adafruit_BME680 bme1;
Adafruit_BME680 bme2;

void setup() {
  Serial.begin(115200);
  // 初始化BME680传感器代码省略
  // 初始化WiFi连接代码省略

  // 挂载LittleFS
  if(!LittleFS.begin(true)){
    Serial.println("LittleFS挂载失败");
    return;
  }
  // 初始化CSV文件
  if(!LittleFS.exists("/sensor_data.csv")){
    File csvFile = LittleFS.open("/sensor_data.csv", "w");
    if(csvFile){
      // 写入表头,按需调整字段
      csvFile.println("timestamp,s1_temp,s1_hum,s1_press,s1_voc,s2_temp,s2_hum,s2_press,s2_voc");
      csvFile.close();
    }
  }

  // 注册Web接口代码省略
  server.begin();
}

3. 传感器数据写入CSV逻辑

每次完成传感器读数后调用追加写入函数,把数据存入CSV:

void appendCsv(long ts, float s1t, float s1h, float s1p, float s1v, float s2t, float s2h, float s2p, float s2v){
  File csvFile = LittleFS.open("/sensor_data.csv", "a");
  if(csvFile){
    csvFile.printf("%ld,%.2f,%.2f,%.2f,%.0f,%.2f,%.2f,%.2f,%.0f\n", ts, s1t, s1h, s1p, s1v, s2t, s2h, s2p, s2v);
    csvFile.close();
  }
}

// 传感器读数示例调用
void readSensorAndSave(){
  bme1.performReading();
  bme2.performReading();
  long timestamp = millis(); // 可替换为NTP同步的UTC时间戳
  appendCsv(
    timestamp,
    bme1.temperature, bme1.humidity, bme1.pressure/100, bme1.gas_resistance/1000,
    bme2.temperature, bme2.humidity, bme2.pressure/100, bme2.gas_resistance/1000
  );
}

4. 可选:前端主动推送存储方案

如果业务需要前端触发存储,可在ESP32新增POST接收接口,前端通过fetch请求推送数据:

ESP32接口代码

server.on("/save-data", HTTP_POST, [](){
  if(!server.hasArg("s1_temp") || !server.hasArg("s2_temp")){
    server.send(400, "text/plain", "参数缺失");
    return;
  }
  long ts = millis();
  appendCsv(
    ts,
    server.arg("s1_temp").toFloat(), server.arg("s1_hum").toFloat(), server.arg("s1_press").toFloat(), server.arg("s1_voc").toFloat(),
    server.arg("s2_temp").toFloat(), server.arg("s2_hum").toFloat(), server.arg("s2_press").toFloat(), server.arg("s2_voc").toFloat()
  );
  server.send(200, "text/plain", "保存成功");
});

前端JS调用代码

// 拿到页面上展示的传感器数值后调用
function pushDataToSave(s1Data, s2Data){
  fetch('/save-data', {
    method: 'POST',
    headers: {'Content-Type': 'application/x-www-form-urlencoded'},
    body: `s1_temp=${s1Data.temp}&s1_hum=${s1Data.hum}&s1_press=${s1Data.press}&s1_voc=${s1Data.voc}&s2_temp=${s2Data.temp}&s2_hum=${s2Data.hum}&s2_press=${s2Data.press}&s2_voc=${s2Data.voc}`
  })
}

5. 绘图用CSV读取接口

新增接口返回CSV全量内容,前端拿到后即可解析为数组传入图表库绘图:

server.on("/get-csv", [](){
  if(!LittleFS.exists("/sensor_data.csv")){
    server.send(404, "text/plain", "文件不存在");
    return;
  }
  File csvFile = LittleFS.open("/sensor_data.csv", "r");
  server.send(200, "text/csv", csvFile.readString());
  csvFile.close();
});

注意事项

  • LittleFS默认分配的存储空间有限,建议采样间隔不小于1分钟,避免快速占满Flash空间
  • 写入前可调用LittleFS.totalBytes() - LittleFS.usedBytes()判断剩余空间,避免写入失败
  • 如需长期大量存储,可外接SD卡模块,替换LittleFS为ESP32 SD库即可,读写逻辑基本一致
  • 存储在Flash中的CSV文件掉电不会丢失,重启设备后可正常读取

内容的提问来源于stack exchange,提问作者Cezar Constantin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.06 07:36:04