这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 活动中心 » 板卡试用 » [ESP32‑S3ReverseTFTFeather评测]完成桌面环境监测仪

共2条 1/1 1 跳转至

[ESP32‑S3ReverseTFTFeather评测]完成桌面环境监测仪

专家
2026-08-20 14:02:51     打赏


DIY 桌面环境监测仪|ESP32‑S3 Reverse TFT Feather + SGP30 搭建全过程
接开箱贴,进行软件环境准备打开 Arduino IDE,选择开发板型号:Adafruit Feather ESP32‑S3 Reverse TFT。

通过库管理器安装 4 个必需库:Adafruit SGP30 Sensor Library、Adafruit ST77XX and ST7789 Library、Adafruit GFX Library、Adafruit MAX1704X Library。WiFi、time.h 属于 ESP32 系统自带库,不用额外安装。

kuguanli.JPG


先上传 I2C 扫描代码做硬件校验,正常可以扫描出 I2C 地址0x58(SGP30),同时会识别板载电量计。这里踩过坑:只做 I2C 扫描不写屏幕初始化代码会出现黑屏,必须开启TFT_I2C_POWER和TFT_BACKLITE引脚才能点亮背光。确认硬件通信没问题,再刷入完整工程代码。

功能实现说明:

SGP30 是室内空气质量 MOX 金属氧化物气体传感器,不能做实验室级精确检测,主要看变化趋势,不是绝对高精度仪器。
上电刚启动 10‑20 个读数:eCO₂=400 ppm,TVOC=0 ppb,属于传感器预热,不是故障,需要通电几十秒后数据才会正常变化。1、eCO₂ (等效二氧化碳,单位:ppm)
  • 全称:Equivalent CO₂,等效二氧化碳

  • 单位:ppm(百万分之一)

  • 范围:400 ~ 60000 ppm

重点:这不是真正二氧化碳浓度!SGP30 没有 CO₂检测元件,它通过空气中氢气、VOC 气体的含量估算出来等效 CO₂值
  • 400ppm:代表室外新鲜空气基准值;

  • 室内密闭人多、挥发物多,数值上升;

  • 仅作为空气质量参考,不能替代真实 CO₂传感器。

2、TVOC(总挥发性有机物,单位:ppb)

  • 全称:Total Volatile Organic Compounds,总挥发性有机物

  • 单位:ppb(十亿分之一)

  • 范围:0 ~ 60000 ppb

  • 含义:综合反映室内挥发性有害气体,例如油漆、酒精、香水、家具挥发、油烟等。

  • 参考经验:

    • TVOC <220 ppb:空气质量良好;

    • 220‑600 ppb:一般,注意通风;

    • >600 ppb:污染物偏高,建议开窗通风。

    3、rawH2(原始氢气信号)

  • 原始传感器读数,无单位,SGP 芯片内部检测到的氢气原始电阻信号

  • 氢气来自人呼吸、材料分解;

  • 主要用于芯片内部算法计算 eCO₂,一般不用直接看这个数值

  • 数值变大代表环境里氢气成分变多。

4、rawEthanol(原始乙醇信号)

  • 乙醇(酒精类挥发物)原始传感器读数,无单位。

  • 喷酒精、消毒水、白酒靠近传感器,这个数值会瞬间飙升;

  • 芯片内部用来计算 TVOC,属于底层原始数据

5、电池参数(来自板载 MAX17048 电量计)

  1.     batPercent:电池剩余百分比(%)

  2.         代码中设置:低于 20% 屏幕字体变红告警,提醒充电;

  3.     batVolt:锂电池电压(V)

  4.       3.7V 锂电池:满电约 4.2V,放空约 3.0V;USB 供电时读出电压,用来判断电池状态。

  5.  6、NTP 时间(屏幕上 Time)

  • 从阿里云 NTP 服务器获取东八区北京时间,格式HH:MM:SS;

  • WiFi 断开,屏幕显示Time: WiFi Disconnect。


完整固件实现这些功能:
  1. SGP30 采集 eCO₂等效 CO₂、TVOC 总挥发性有机物、原始氢气、乙醇信号;

  2. MAX17048 读取锂电池电压、剩余电量,电量低于 20% 屏幕红字告警;

  3. WiFi 联网,通过 SNTP 获取阿里云 NTP 北京时间,屏幕实时显示时分秒;

  4. 屏幕彩色 UI 展示全部数据,串口同步输出调试信息;

  5. WiFi 断开自动重连,断网时提示时间不可用。

重要提示:SGP30 上电初期十几秒固定输出eCO₂=400ppm,TVOC=0ppb,属于传感器预热,不是故障;需要连续通电 12 小时完成基线学习,读数才更加稳定,传感器适合看变化趋势,不作为实验室精密仪器。
#include <Wire.h>
#include <WiFi.h>
#include <WiFiUdp.h>
#include <NTPClient.h>
#include <Adafruit_GFX.h>
#include <Adafruit_ST7789.h>
#include <Fonts/FreeMono9pt7b.h>
#include <Adafruit_SGP30.h>
#include <Adafruit_MAX1704X.h>

//==================== 请修改为你的WiFi信息 ====================
const char* ssid     = "xbz123";
const char* password = "87654321";
//=============================================================

#define I2C_SDA 3
#define I2C_SCL 4

Adafruit_ST7789 tft = Adafruit_ST7789(TFT_CS, TFT_DC, TFT_RST);
Adafruit_SGP30 sgp;
Adafruit_MAX17048 batMon;

WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP, "pool.ntp.org", 8 * 3600, 60000); //东八区,60s更新一次NTP

unsigned long screenTimer = 0;
const unsigned long interval = 1000;

uint16_t eco2, tvoc;
uint16_t rawH2, rawEth;
float batVolt, batPercent;

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

  // 屏幕电源、背光
  pinMode(TFT_I2C_POWER, OUTPUT);
  digitalWrite(TFT_I2C_POWER, HIGH);
  delay(20);
  pinMode(TFT_BACKLITE, OUTPUT);
  digitalWrite(TFT_BACKLITE, HIGH);
  delay(20);

  tft.init(135, 240);
  tft.setRotation(3);
  tft.fillScreen(ST77XX_BLACK);
  tft.setFont(&FreeMono9pt7b);
  tft.setTextColor(ST77XX_WHITE);
  tft.setTextSize(1);

  tft.setCursor(10, 25);
  tft.println("Init Hardware...");

  Wire.begin(I2C_SDA, I2C_SCL);

  //电量计
  if (!batMon.begin()) {
    Serial.println("MAX17048 init fail");
    tft.println("BAT ERROR");
  }

  //SGP30
  if (!sgp.begin()) {
    Serial.println("SGP30 NOT FOUND! Check wiring!");
    tft.fillScreen(ST77XX_BLACK);
    tft.setCursor(10,40);
    tft.setTextColor(ST77XX_RED);
    tft.println("SGP30 ERROR!");
    while (1) delay(100);
  }
  sgp.IAQinit();
  delay(1000);

  //WiFi连接
  tft.setCursor(10,50);
  tft.print("WiFi:"); tft.print(ssid);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(300);
    Serial.print(".");
  }
  Serial.println("\nWiFi connected!");
  timeClient.begin();

  tft.fillScreen(ST77XX_BLACK);
  Serial.println("===== SGP30 Monitor Ready =====");
}

void loop() {
  //WiFi断连自动重连
  if(WiFi.status() != WL_CONNECTED){
    WiFi.reconnect();
  }
  timeClient.update();

  if (millis() - screenTimer >= interval) {
    screenTimer = millis();

    //读取空气质量
    if(sgp.IAQmeasure()){
      eco2 = sgp.eCO2;
      tvoc = sgp.TVOC;
    }
    if(sgp.IAQmeasureRaw()){
      rawH2 = sgp.rawH2;
      rawEth = sgp.rawEthanol;
    }

    //读取电池
    batVolt = batMon.cellVoltage();
    batPercent = batMon.cellPercent();

    //串口打印
    Serial.print("Time:"); Serial.print(timeClient.getFormattedTime()); Serial.print(" | ");
    Serial.print("eCO2:"); Serial.print(eco2); Serial.print(" ppm | ");
    Serial.print("TVOC:"); Serial.print(tvoc); Serial.print(" ppb | ");
    Serial.print("H2:"); Serial.print(rawH2); Serial.print(" ETH:"); Serial.print(rawEth);
    Serial.print(" | BAT:"); Serial.print(batPercent,1); Serial.print("% "); Serial.print(batVolt,2); Serial.println("V");

    //屏幕刷新
    tft.fillScreen(ST77XX_BLACK);

    //时间行 青色
    tft.setTextColor(ST77XX_CYAN);
    tft.setCursor(8,22);
    if(WiFi.status() == WL_CONNECTED){
      tft.print("Time:");
      tft.print(timeClient.getFormattedTime());
    }else{
      tft.print("Time: WiFi Disconnect");
    }

    //空气数据绿色
    tft.setTextColor(ST77XX_GREEN);
    tft.setCursor(8,48);
    tft.print("eCO2: "); tft.print(eco2); tft.print(" ppm");

    tft.setCursor(8,72);
    tft.print("TVOC: "); tft.print(tvoc); tft.print(" ppb");

    tft.setCursor(8,96);
    tft.print("H2:"); tft.print(rawH2); tft.print(" ETH:"); tft.print(rawEth);

    //电池状态
    if(batPercent < 20){
      tft.setTextColor(ST77XX_RED);
    }else{
      tft.setTextColor(ST77XX_YELLOW);
    }
    tft.setCursor(8,120);
    tft.print("BAT: "); tft.print(batPercent,1); tft.print("%  "); tft.print(batVolt,2); tft.print("V");
  }
}
在Arduino  IDE中运行代码

时间同步.JPG

编译上传后,ESP32‑S3 Reverse TFT Feather显示采集的数据。

微信图片_20260820133344_98_33.jpg

为了测试运行是否正常,将传感器靠近一个电动喷香机,可以看到参数直线上升,系统工作正常。

微信图片_20260820133514_101_33.jpg

开发中的注意事项
1、屏幕黑屏:忘记开启屏幕电源与背光引脚,补上引脚输出高电平解决;

2、编译报错 API 找不到:Arduino 版 SGP30 库和 CircuitPython 函数不一样,更换 Arduino 对应的接口函数;

3、第三方库头文件找不到:安装库之后必须完全关闭 IDE 再重启;

4、NTP 库安装失败:改用 ESP32 原生time.h,避开第三方 NTPClient 库。

后续还可以继续扩展,增加温湿度传感器和 3D 打印外壳。





关键词: ESP32     评测     环境    

院士
2026-08-24 14:11:03     打赏
2楼

EPS32-S3还是强大。

我觉得NTP服务挺难实现的。


共2条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]