#include <Wire.h>
#include <Adafruit_Sensor.h>
#include "Adafruit_BME680.h"
#include <LiquidCrystal_I2C.h>
#define SEALEVELPRESSURE_HPA (1013.25)
Adafruit_BME680 bme; // I2C
LiquidCrystal_I2C lcd(0x27,16,2);
float hum_weighting = 0.25; // so hum effect is 25% of the total air quality score
float gas_weighting = 0.75; // so gas effect is 75% of the total air quality score
int humidity_score, gas_score;
float gas_reference = 2500;
float hum_reference = 40;
int getgasreference_count = 0;
int gas_lower_limit = 10000; // Bad air quality limit
int gas_upper_limit = 300000; // Good air quality limit
int gruen = 12;
int gelb = 13;
int rot = 14;
int durchlauf=1;
void setup() {
Serial.begin(115200);
Serial.println(F("BME680 test"));
Wire.begin();
if (!bme.begin()) {
Serial.println("Could not find a valid BME680 sensor, check wiring!");
while (1);
} else Serial.println("Found a sensor");
// Set up oversampling and filter initialization
bme.setTemperatureOversampling(BME680_OS_8X);
bme.setHumidityOversampling(BME680_OS_2X);
bme.setPressureOversampling(BME680_OS_4X);
bme.setIIRFilterSize(BME680_FILTER_SIZE_3);
bme.setGasHeater(320, 150); // 320°C for 150 ms
// Now run the sensor to normalise the readings, then use combination of relative humidity and gas resistance to estimate indoor air quality as a percentage.
// The sensor takes ~30-mins to fully stabilise
GetGasReference();
lcd.init();
lcd.backlight();
pinMode(gruen,OUTPUT);
pinMode(gelb,OUTPUT);
pinMode(rot,OUTPUT);
start();
}
void loop() {
Serial.println("Sensor Readings:");
Serial.println(" Temperature = " + String(bme.readTemperature(), 2) + "°C");
Serial.println(" Pressure = " + String(bme.readPressure() / 100.0F) + " hPa");
Serial.println(" Humidity = " + String(bme.readHumidity(), 1) + "%");
Serial.println(" Gas = " + String(gas_reference) + " ohms\n");
Serial.print("Qualitative Air Quality Index ");
humidity_score = GetHumidityScore();
gas_score = GetGasScore();
//Combine results for the final IAQ index value (0-100% where 100% is good quality air)
float air_quality_score = humidity_score + gas_score;
Serial.println(" comprised of " + String(humidity_score) + "% Humidity and " + String(gas_score) + "% Gas");
if ((getgasreference_count++) % 5 == 0) GetGasReference();
setAmpel(air_quality_score);
lcd.clear();
if(durchlauf ==1){
lcd.setCursor(0,0);
lcd.print("Luftqualitaet");
lcd.setCursor(0,1);
lcd.print("ist: ");
lcd.print(CalculateIAQ(air_quality_score));
durchlauf = 2;
delay(4000);
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Airqualityscore:");
lcd.setCursor(0,1);
lcd.print((100-air_quality_score)*5);
delay(2000);
}else{
lcd.setCursor(0,0);
lcd.print("Tp: ");
lcd.print(String(bme.readTemperature(), 1));
lcd.print(" Feucht");
lcd.setCursor(0,1);
lcd.print(String(bme.readHumidity(), 0));
lcd.print("% Druck: ");
lcd.print(String(bme.readPressure() / 100.0F,0));
durchlauf = 1;
}
Serial.println(CalculateIAQ(air_quality_score));
Serial.println("--------------------------------------------------------------");
delay(2000);
}
void GetGasReference() {
// Now run the sensor for a burn-in period, then use combination of relative humidity and gas resistance to estimate indoor air quality as a percentage.
//Serial.println("Getting a new gas reference value");
int readings = 10;
for (int i = 1; i <= readings; i++) { // read gas for 10 x 0.150mS = 1.5secs
gas_reference += bme.readGas();
}
gas_reference = gas_reference / readings;
//Serial.println("Gas Reference = "+String(gas_reference,3));
}
void setAmpel(int score){
score = (100 - score) * 5;
if(score<150){
digitalWrite(gruen,HIGH);
digitalWrite(gelb,LOW);
digitalWrite(rot,LOW);
}else{
if(score<175){
digitalWrite(gruen,LOW);
digitalWrite(gelb,HIGH);
digitalWrite(rot,LOW);
}else{
digitalWrite(gruen,LOW);
digitalWrite(gelb,LOW);
digitalWrite(rot,HIGH);
}
}
}
String CalculateIAQ(int score) {
String IAQ_text = "";
score = (100 - score) * 5;
if (score >= 301) IAQ_text += "megamies";
else if (score >= 201 && score <= 300 ) IAQ_text += "mies";
else if (score >= 176 && score <= 200 ) IAQ_text += "ungesund";
else if (score >= 151 && score <= 175 ) IAQ_text += "nicht gut";
else if (score >= 51 && score <= 150 ) IAQ_text += "in Ordnung";
else if (score >= 00 && score <= 50 ) IAQ_text += "sehr gut";
Serial.print("IAQ Score = " + String(score) + ", ");
return IAQ_text;
}
int GetHumidityScore() { //Calculate humidity contribution to IAQ index
float current_humidity = bme.readHumidity();
if (current_humidity >= 38 && current_humidity <= 42) // Humidity +/-5% around optimum
humidity_score = 0.25 * 100;
else
{ // Humidity is sub-optimal
if (current_humidity < 38)
humidity_score = 0.25 / hum_reference * current_humidity * 100;
else
{
humidity_score = ((-0.25 / (100 - hum_reference) * current_humidity) + 0.416666) * 100;
}
}
return humidity_score;
}
int GetGasScore() {
//Calculate gas contribution to IAQ index
gas_score = (0.75 / (gas_upper_limit - gas_lower_limit) * gas_reference - (gas_lower_limit * (0.75 / (gas_upper_limit - gas_lower_limit)))) * 100.00;
if (gas_score > 75) gas_score = 75; // Sometimes gas readings can go outside of expected scale maximum
if (gas_score < 0) gas_score = 0; // Sometimes gas readings can go outside of expected scale minimum
return gas_score;
}
void start(){
lcd.clear();
lcd.setCursor(0,0);
lcd.print(" CO2-Ampel");
lcd.setCursor(0,1);
lcd.print("NaBi Herten");
lcd.backlight();
delay(1000);
lcd.noBacklight();
digitalWrite(gruen,HIGH);
digitalWrite(gelb,HIGH);
digitalWrite(rot,HIGH);
delay(1000);
lcd.backlight();
digitalWrite(gruen,LOW);
digitalWrite(gelb,LOW);
digitalWrite(rot,LOW);
delay(1000);
lcd.noBacklight();
digitalWrite(gruen,HIGH);
digitalWrite(gelb,HIGH);
digitalWrite(rot,HIGH);
delay(1000);
lcd.backlight();
digitalWrite(gruen,LOW);
digitalWrite(gelb,LOW);
digitalWrite(rot,LOW);
delay(1000);
lcd.noBacklight();
digitalWrite(gruen,HIGH);
digitalWrite(gelb,HIGH);
digitalWrite(rot,HIGH);
delay(1000);
lcd.backlight();
digitalWrite(gruen,LOW);
digitalWrite(gelb,LOW);
digitalWrite(rot,LOW);
delay(1000);
}