공기정화 식물-인공지능-IOT

ESP32보드 SPS30 I2C + SparkFun CCS811+BME280 인터페이스 미세먼지 및 유해가스 농도 측정

coding art 2021. 3. 23. 16:56
728x90

SPS30 미세먼지 센서와 총량유해가스 센서 CCS811 BME280을 사진에서처럼 함께 설치해 보자. 두 종류의 센서 모두 I2C 인터페이스를 사용함으로 빵판 배선이 반드시 필요하다. PCB를 사용하지 않음으로 인해서 다소 복잡할 수도 있으므로 점퍼선 다발 배선 교통정리가 반드시 필요하다.

아두이노 IDE의 스케치->라이브러리 포함하기->라이브러리 관리를 클릭하며 라이브러리 매니저 팝업 창을 뛰운 후 아래와 같이 SparkFun_CCS811 라이브러리를 검색하여 BME280 CCS811 라이브러리를 각각 설치하자. 아울러 sps30 도 검색하여 sensirion-sps 라이브러리를 설치하자. 그밖에 Thingspeak.h 라이브러리도 IOT 작업을 위해서 설치하도록 하자.

 

한편 빌드 작업에서 다소 시간이 많이 걸리므로 빌드타임 시간 초과 에러가 발생할 수 있다. 이때에는 esp32 보드의 오른쪽 BOOT 버튼을 누른 상태에서 빌드 업로딩 하도록 하자. 완료 후 반드시 리세트 버튼을 눌러야 시작이 된다.

 

//Thingspeak_sps30_tvoc

#include "ThingSpeak.h"

#include <WiFi.h>

#include <sps30.h>

//----------------------------------------------

#include <Wire.h>

#include "SparkFunCCS811.h"

#include "SparkFunBME280.h"

#define CCS811_ADDR 0x5B //Default I2C Address

 

char ssid[] = "droidan1234"; // your network SSID (name)

char pass[] = "dddddddddd"; // your network password

 

unsigned long myChannelNumber = 899023;

const char * myWriteAPIKey = "Y7RAJNWH7QRXV2UD";

unsigned long sampling_time =30000;

WiFiClient client;

//-------------------------------------------------------

CCS811 mySensor(CCS811_ADDR);

BME280 myBME280;

 

void setup() {

int16_t ret;

uint8_t auto_clean_days = 4;

uint32_t auto_clean;

 

Serial.begin(9600);

delay(2000);

WiFi.mode(WIFI_STA);

ThingSpeak.begin(client); // Initialize ThingSpeak

 

sensirion_i2c_init();

 

while (sps30_probe() != 0) {

Serial.print("SPS sensor probing failed\n");

delay(500);

}

 

ret = sps30_set_fan_auto_cleaning_interval_days(auto_clean_days);

if (ret) {

Serial.print("error setting the auto-clean interval: ");

Serial.println(ret);

}

 

ret = sps30_start_measurement();

if (ret < 0) {

Serial.print("error starting measurement\n");

}

 

#ifndef PLOTTER_FORMAT

Serial.print(" PM measurements started\n");

#endif /* PLOTTER_FORMAT */

 

#ifdef SPS30_LIMITED_I2C_BUFFER_SIZE

Serial.print("Your Arduino hardware has a limitation that only\n");

Serial.print(" allows reading the mass concentrations. For more\n");

Serial.print(" information, please check\n");

Serial.print(" https://github.com/Sensirion/arduino-sps#esp8266-partial-legacy-support\n");

Serial.print("\n");

delay(2000);

#endif

delay(1000);

 

Serial.println("CCS811 Basic Example");

Wire.begin(); //Inialize I2C Hardware

if (mySensor.begin() == false) {

Serial.print("CCS811 error. Please check wiring. Freezing...");

while (1)

;

}

 

//For I2C, enable the following and disable the SPI section

myBME280.settings.commInterface = I2C_MODE;

myBME280.settings.I2CAddress = 0x77;

 

//Initialize BME280

//For I2C, enable the following and disable the SPI section

myBME280.settings.commInterface = I2C_MODE;

myBME280.settings.I2CAddress = 0x77;

myBME280.settings.runMode = 3; //Normal mode

myBME280.settings.tStandby = 0;

myBME280.settings.filter = 4;

myBME280.settings.tempOverSample = 5;

myBME280.settings.pressOverSample = 5;

myBME280.settings.humidOverSample = 5;

myBME280.begin();

 

}

 

void loop() {

 

// Connect or reconnect to WiFi

if(WiFi.status() != WL_CONNECTED) {

Serial.print("Attempting to connect to SSID: ");

while(WiFi.status() != WL_CONNECTED){

WiFi.begin(ssid,pass);

Serial.print(".");

delay(5000);

}

Serial.println("\nConnected.");

}

 

struct sps30_measurement m;

char serial[SPS30_MAX_SERIAL_LEN];

uint16_t data_ready;

int16_t ret;

 

do {

ret = sps30_read_data_ready(&data_ready);

if (ret < 0) {

Serial.print("error reading data-ready flag: ");

Serial.println(ret);

} else if (!data_ready)

Serial.print("data not ready, no new measurement available\n");

else

break;

delay(100); /* retry in 100ms */

} while (1);

 

ret = sps30_read_measurement(&m);

if (ret < 0) {

Serial.print("error reading measurement\n");

} else {

 

//Serial.print("PM 1.0: ");

Serial.print(m.mc_1p0);

Serial.print(" ");

//Serial.print("PM 2.5: ");

Serial.print(m.mc_2p5);

Serial.print(" ");

//Serial.print("PM 10.0: ");

Serial.print(m.mc_10p0);

Serial.print(" ");

Serial.println();

}

ThingSpeak.setField(1, m.mc_1p0);

ThingSpeak.setField(2, m.mc_2p5);

ThingSpeak.setField(3, m.mc_10p0);

 

int tvoc, co2, temp, pressure, humidity;

//Check to see if data is ready with .dataAvailable()

if (mySensor.dataAvailable()) {

mySensor.readAlgorithmResults();

co2 = mySensor.getCO2();

Serial.print(co2);

tvoc = mySensor.getTVOC();

Serial.print(tvoc);

temp = myBME280.readTempC();

Serial.print(temp);

pressure = myBME280.readFloatPressure()/100.0;

Serial.print(pressure);

humidity = myBME280.readFloatHumidity();

Serial.print(humidity);

Serial.println();

}

ThingSpeak.setField(4, tvoc);

ThingSpeak.setField(5, co2);

ThingSpeak.setField(6, temp);

ThingSpeak.setField(7, pressure);

ThingSpeak.setField(8, humidity);

 

int x = ThingSpeak.writeFields(myChannelNumber, myWriteAPIKey);

delay(sampling_time);

}