BMP680 CO2-Ampel


#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);
    
}