/* 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); }