arduino esp8266 sgp30 空气tvoc,eco2检测

功能介绍
1.eco2,tvoc,温湿度检测

大家可以根据实际情况减去外部环境影响的温度.

下面是代码:

#include <Wire.h>
#include "Adafruit_SGP30.h"
#include <ESP8266WiFi.h>
#include "Adafruit_SHT31.h"
#include <PubSubClient.h>

Adafruit_SGP30 sgp;

#define AP_SSID "abc" // 这里改成你的wifi名字
#define AP_PSW  "123456" // 这里改成你的wifi密码

#define MQTT_SERVER      "mqtt.com"
#define MQTT_SERVERPORT  1883
#define MQTT_USERNAME    "test"
#define MQTT_PASSWD      "test"
#define MQTT_CLIENT_ID "esp8266_sgp30"

bool enableHeater = false;
uint8_t loopCnt = 0;
Adafruit_SHT31 sht31 = Adafruit_SHT31();

/* return absolute humidity [mg/m^3] with approximation formula
  @param temperature [°C]
  @param humidity [%RH]
*/
uint32_t getAbsoluteHumidity(float temperature, float humidity) {
  // approximation formula from Sensirion SGP30 Driver Integration chapter 3.15
  const float absoluteHumidity = 216.7f * ((humidity / 100.0f) * 6.112f * exp((17.62f * temperature) / (243.12f + temperature)) / (273.15f + temperature)); // [g/m^3]
  const uint32_t absoluteHumidityScaled = static_cast<uint32_t>(1000.0f * absoluteHumidity); // [mg/m^3]
  return absoluteHumidityScaled;
}

WiFiClient espClient;
void callback(char* topic, byte* payload, unsigned int length) {
}
PubSubClient client(MQTT_SERVER, MQTT_SERVERPORT, callback, espClient);

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

  while (!Serial)
    delay(10); // 将暂停“零”,“莱昂纳多”等,直到打开串行控制台

  // 启动STA模式,并连接到wifi网络
  WiFi.begin(AP_SSID, AP_PSW);
  // 判断网络状态是否连接上,没连接上就延时500ms,并且打出一个点,模拟连接过程
  // 加入网络一直都连不上 是否可以做个判断,由你们自己实现
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.println(".");
  }
  // 输出station IP地址,这里的IP地址由DHCP分配
  Serial.println(WiFi.localIP());

  // sht31
  if (! sht31.begin(0x44)) {   // Set to 0x45 for alternate i2c addr
    Serial.println("Couldn't find SHT31");
    //    while (1) delay(1);
  }
  //  Serial.print("Heater Enabled State: ");
  //  if (sht31.isHeaterEnabled())
  //    Serial.println("ENABLED");
  //  else
  //    Serial.println("DISABLED");

  // Serial.println("SGP30 test");
  if (! sgp.begin()) {
    Serial.println("Sensor not found :(");
    //    while (1);
  }
  // Serial.print("Found SGP30 serial #");
  Serial.print(sgp.serialnumber[0], HEX);
  Serial.print(sgp.serialnumber[1], HEX);
  Serial.println(sgp.serialnumber[2], HEX);

  // If you have a baseline measurement from before you can assign it to start, to 'self-calibrate'
  // sgp.setIAQBaseline(0x8E68, 0x8F41);  // Will vary for each sensor!
}

int counter = 0;
void loop() {
  // sht31
  float t = sht31.readTemperature();
  float h = sht31.readHumidity();

  char temperature[32];
  float temperature_tmp;
  if (! isnan(t)) {  // check if 'is not a number'
    //    Serial.print("Temp *C = "); Serial.print(t); Serial.print("\t\t");
    temperature_tmp = float(t);
    Serial.print(temperature_tmp); Serial.print("*C\t");
    sprintf(temperature, "%f", temperature_tmp);
    Serial.print(temperature); Serial.print("\t");
  } else {
    Serial.println("Failed to read temperature");
  }
  
  char humidity[32];
  float humidity_tmp;
  if (! isnan(h)) {  // check if 'is not a number'
    //    Serial.print("Hum. % = "); Serial.pr intln(h);
    humidity_tmp = float(h);
    Serial.print(humidity_tmp); Serial.print("%\t");
    sprintf(humidity, "%f", humidity_tmp);
    Serial.print(humidity); Serial.print("\t");
  } else {
    Serial.println("Failed to read humidity");
  }
  
  delay(1000);
  // 每30秒切换一次加热器启用状态
  // 启用加热器后,温度会升高约3.0摄氏度
  if (++loopCnt == 30) {
    enableHeater = !enableHeater;
    sht31.heater(enableHeater);
    //    Serial.print("Heater Enabled State: ");
    //    if (sht31.isHeaterEnabled())
    //      Serial.println("ENABLED");
    //    else
    //      Serial.println("DISABLED");

    loopCnt = 0;
  }

  // sgp30
  // If you have a temperature / humidity sensor, you can set the absolute humidity to enable the humditiy compensation for the air quality signals
  // 温湿度补偿
  //  float temperature = 26.3; // [°C]
  //  float humidity = 74.8; // [%RH]
  Serial.print("\n计算:\n");
  Serial.print(temperature_tmp);
  Serial.print("\n");
  Serial.print( humidity_tmp);
  Serial.print("\n");
  sgp.setHumidity(getAbsoluteHumidity(temperature_tmp, humidity_tmp));

  if (! sgp.IAQmeasure()) {
    Serial.println("Measurement failed");
    return;
  }
  Serial.print("TVOC "); Serial.print(sgp.TVOC); Serial.print(" ppb\t");
  Serial.print("eCO2 "); Serial.print(sgp.eCO2); Serial.println(" ppm\t");
  char tvoc[8], eco2[8];
  sprintf(tvoc, "%d", sgp.TVOC);
  sprintf(eco2, "%d", sgp.eCO2);

  if (! sgp.IAQmeasureRaw()) {
    Serial.println("Raw Measurement failed");
    return;
  }
  //  Serial.print("Raw H2 "); Serial.print(sgp.rawH2); Serial.print(" \t"); // 原始h2
  //  Serial.print("Raw Ethanol "); Serial.print(sgp.rawEthanol); Serial.println(""); // 原始乙醇

  delay(5000);

  counter++;
  if (counter == 30) {
    counter = 0;

    uint16_t TVOC_base, eCO2_base;
    if (! sgp.getIAQBaseline(&eCO2_base, &TVOC_base)) {
      Serial.println("Failed to get baseline readings");
      return;
    }
    // Serial.print("****Baseline values: eCO2: 0x"); Serial.print(eCO2_base, HEX); // 基准值
    // Serial.print(" & TVOC: 0x"); Serial.println(TVOC_base, HEX);
  }

  delay(3000);
  if (client.connect(MQTT_CLIENT_ID, MQTT_USERNAME, MQTT_PASSWD)) {
    Serial.println("MQTT Connected!");
    // topic
    client.publish("/esp8266/sgp30/tvoc", tvoc);
    client.publish("/esp8266/sgp30/eco_two", eco2);
    client.publish("/esp8266/sgp30/temperature", temperature);
    client.publish("/esp8266/sgp30/humidity", humidity);
  }
}