/*
CO2 and breath volatile organic compounds monitor and visual alarm
Copyright (C) 2021 Jaanus Toomsalu
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
===
Arduino MKR WIFI 1010
LiPo battery (not necessary)
BME680 I2C
SSD1306 I2C 128x32 OLED
HTTP Server for RRDTOOL data.
co2>1000 RED LED
bvoc>1.5 BLUE LED
*/
#include
#include "bsec.h"
#include
#include
#include
#include
Adafruit_SSD1306 display = Adafruit_SSD1306();
void checkIaqSensorStatus(void);
void errLeds(void);
Bsec iaqSensor;
String output,output2;
char ssid[] = "essid";
char pass[] = "password";
IPAddress ip(10, 10, 10, 19);
WiFiServer server(80);
int co2eq,bvoc;
void setup(void)
{
Serial.begin(115200);
Wire.begin();
int countdownMS = Watchdog.enable(8000);
WiFiDrv::pinMode(25, OUTPUT); //GREEN
WiFiDrv::pinMode(26, OUTPUT); //RED
WiFiDrv::pinMode(27, OUTPUT); //BLUE
display.begin(SSD1306_SWITCHCAPVCC, 0x3C); // initialize with the I2C addr 0x3C (for the 128x32)
display.clearDisplay();
display.display();
display.setTextSize(0);
display.setTextColor(WHITE);
WiFi.config(ip);
while (WiFi.begin(ssid, pass) != WL_CONNECTED) {
delay(4000);
}
server.begin();
iaqSensor.begin(BME680_I2C_ADDR_PRIMARY, Wire);
checkIaqSensorStatus();
bsec_virtual_sensor_t sensorList[10] = {
BSEC_OUTPUT_RAW_TEMPERATURE,
BSEC_OUTPUT_RAW_PRESSURE,
BSEC_OUTPUT_RAW_HUMIDITY,
BSEC_OUTPUT_RAW_GAS,
BSEC_OUTPUT_IAQ,
BSEC_OUTPUT_STATIC_IAQ,
BSEC_OUTPUT_CO2_EQUIVALENT,
BSEC_OUTPUT_BREATH_VOC_EQUIVALENT,
BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_TEMPERATURE,
BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_HUMIDITY,
};
iaqSensor.updateSubscription(sensorList, 10, BSEC_SAMPLE_RATE_LP);
checkIaqSensorStatus();
pinMode(LED_BUILTIN, OUTPUT);
}
void loop(void)
{
Watchdog.reset();
if ( WiFi.status() != WL_CONNECTED) {
while (WiFi.begin(ssid, pass) != WL_CONNECTED) {
delay(4000);
}
}
if (iaqSensor.run()) {
output = "N:" + String(iaqSensor.temperature);
output += ":" + String(iaqSensor.pressure/100);
output += ":" + String(iaqSensor.humidity) ;
output += ":" + String(iaqSensor.gasResistance/1000);
output += ":" + String(iaqSensor.co2Equivalent);
output += ":" + String(iaqSensor.breathVocEquivalent);
output += ":" + String(analogRead(ADC_BATTERY)*(4.3/1023.0)) + ":U";
output2 = "c:" + String(iaqSensor.co2Equivalent);
output2 += " v:" + String(iaqSensor.gasResistance/1000);
output2 += " b:" + String(iaqSensor.breathVocEquivalent);
output2 += " t:" + String(iaqSensor.temperature);
output2 += " h:" + String(iaqSensor.humidity);
output2 += " p:" + String(iaqSensor.pressure/100);
output2 += " B:" + String(analogRead(ADC_BATTERY)*(4.3/1023.0));
co2eq=iaqSensor.co2Equivalent;
bvoc=iaqSensor.breathVocEquivalent;
} else {
checkIaqSensorStatus();
}
display.setCursor(0,0);
display.clearDisplay();
display.print(output2);
display.display();
if ( co2eq > 1000 ) { WiFiDrv::digitalWrite(26, HIGH); } else { WiFiDrv::digitalWrite(26, LOW); }
if ( bvoc > 1.5) { WiFiDrv::digitalWrite(27, HIGH); } else { WiFiDrv::digitalWrite(27, LOW); }
WiFiClient client = server.available();
if (client) {
digitalWrite(LED_BUILTIN, HIGH);
bool currentLineIsBlank = true;
while (client.connected()) {
if (client.available()) {
char c = client.read();
if (c == '\n' && currentLineIsBlank) {
client.println("HTTP/1.1 200 OK");
client.println("Content-Type: text/plain");
client.println("Connection: close");
client.println();
client.println(output);
break;
}
if (c == '\n') {
currentLineIsBlank = true;
}
else if (c != '\r') {
currentLineIsBlank = false;
}
}
}
delay (1);
client.stop();
digitalWrite(LED_BUILTIN, LOW);
}
}
void checkIaqSensorStatus(void)
{
if (iaqSensor.status != BSEC_OK) {
if (iaqSensor.status < BSEC_OK) {
output = "BSEC error code : " + String(iaqSensor.status);
Serial.println(output);
for (;;)
errLeds();
} else {
output = "BSEC warning code : " + String(iaqSensor.status);
Serial.println(output);
}
}
if (iaqSensor.bme680Status != BME680_OK) {
if (iaqSensor.bme680Status < BME680_OK) {
output = "BME680 error code : " + String(iaqSensor.bme680Status);
Serial.println(output);
for (;;)
errLeds();
} else {
output = "BME680 warning code : " + String(iaqSensor.bme680Status);
Serial.println(output);
}
}
}
void errLeds(void)
{
digitalWrite(LED_BUILTIN, HIGH);
delay(100);
digitalWrite(LED_BUILTIN, LOW);
delay(100);
}