I wanted to add a second BME 680 sensor to a working project to measure the environmental data (including timestamp) and safe it on a SD card/ print it on the Serial Monitor. The SD card is connected SPI, the BME680 sensor and the RTC module were connected via I2C. When I added the second sensor I changed the I2C adress for one on 0x76, the default one for the first sensor is 0x77. To ensure that both sensors have different adresses, the code reads them in the beginning. But since I installed the second sensor and have them as bme_1 and bme_2 in the code, it does only deliver 0 values for all the measurement attributes. The working code for only 1 sensor delivers valid values. Does anyone know if I need to set something differently to have both sensors working?
It is my first project with Arduino and programming, so I assume there could also be some more improvements in the code.
Code: Select all
#include <Wire.h>
#include <SD.h>
#include <Adafruit_Sensor.h>
#include "Adafruit_BME680.h"
#include <Adafruit_I2CDevice.h>
#include "RTClib.h"
#define SEALEVELPRESSURE_HPA (1022)
#define LED_RED 4
#define LED_GREEN 2
Adafruit_BME680 bme_1; // I2C
Adafruit_BME680 bme_2; // I2C
RTC_DS1307 rtc; //I2C
File dataFile; //MISO at 12 in purple, MOSI at 13 in white
DateTime now;
int measurement_frequency = 5000;
//Air Quality Index calculation https://github.com/G6EJD/680-Example/blob/master/ESP32_bme680_CC_demo_02.ino
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
float hum_score_1, gas_score_1,hum_score_2, gas_score_2;
float gas_reference_1 = 250000;
float hum_reference_1 = 40;
float gas_reference_2 = 250000;
float hum_reference_2 = 40;
int getgasreference_count = 0;
void setup() {
// put your setup code here, to run once:
pinMode(LED_RED, OUTPUT);
pinMode(LED_GREEN, OUTPUT);
//digitalWrite(LED_RED, HIGH)
//digitalWrite(LED_GREEN, HIGH)
Serial.begin(9600);
Serial.print("test");
digitalWrite(LED_GREEN, HIGH); //blink green that program is working
delay(50);
digitalWrite(LED_GREEN, LOW);
//RTC module initialization
if (! rtc.begin()) {
Serial.println("Couldn't find RTC");
digitalWrite(LED_RED, HIGH);
while (1);
}
else {
Serial.println("Couldn't find RTC");
}
digitalWrite(LED_RED, LOW);
//SC card module initialization
Serial.print("Initializing SD card...");
if (!SD.begin(10)) {
Serial.println("initialization failed!");
digitalWrite(LED_RED, HIGH);
while (1);
digitalWrite(LED_RED, LOW);
}
Serial.println("initialization done.");
//BME680 module initialization
if (!bme_1.begin(0x77)) {
Serial.println(F("Could not find a valid BME680_1 sensor, check wiring!"));
digitalWrite(LED_RED, HIGH);
// while (1);
}
else {
Serial.println("Found BME_1");
digitalWrite(LED_GREEN, HIGH);
delay(100);
digitalWrite(LED_GREEN, LOW);
}
if (!bme_2.begin(0x76)) {
Serial.println(F("Could not find a valid BME680_2 sensor, check wiring!"));
digitalWrite(LED_RED, HIGH);
// while (1);
}
else {
Serial.println("Found BME_2");
digitalWrite(LED_GREEN, HIGH);
delay(100);
digitalWrite(LED_GREEN, LOW);
}
//test 2
//bme settings
bme_1.setTemperatureOversampling(BME680_OS_8X);
bme_1.setHumidityOversampling(BME680_OS_2X);
bme_1.setPressureOversampling(BME680_OS_4X);
bme_1.setIIRFilterSize(BME680_FILTER_SIZE_3);
bme_1.setGasHeater(320, 150); // 320*C for 150 ms
bme_2.setTemperatureOversampling(BME680_OS_8X);
bme_2.setHumidityOversampling(BME680_OS_2X);
bme_2.setPressureOversampling(BME680_OS_4X);
bme_2.setIIRFilterSize(BME680_FILTER_SIZE_3);
bme_2.setGasHeater(320, 150); // 320*C for 150 ms
GetGasReference();
Serial.println("Got Gas Reference");
dataFile = SD.open("data.txt", FILE_WRITE);
digitalWrite(LED_GREEN, HIGH);
dataFile.close();
digitalWrite(LED_GREEN, LOW);
Serial.println(F("new measurement started"));
}
void loop() {
// Tell BME680 to begin measurement.
unsigned long endTime_1 = bme_1.beginReading();
unsigned long endTime_2 = bme_2.beginReading();
if (endTime_1 == 0) {
Serial.println(F("Failed to begin reading BME_1:("));
return;
}
if (endTime_2 == 0) {
Serial.println(F("Failed to begin reading BME_2:("));
return;
} //BME_1
float current_humidity_1 = bme_1.readHumidity();
if (current_humidity_1 >= 38 && current_humidity_1 <= 42) {
hum_score_1 = 0.25 * 100; // Humidity +/-5% around optimum
}
else
{ //sub-optimal
if (current_humidity_1 < 38)
hum_score_1 = 0.25 / hum_reference_1 * current_humidity_1 * 100;
else {
hum_score_1 = ((-0.25 / (100 - hum_reference_1) * current_humidity_1) + 0.416666) * 100;
}
}
//Calculate gas contribution to IAQ index
float gas_lower_limit = 5000; // Bad air quality limit
float gas_upper_limit = 50000; // Good air quality limit
if (gas_reference_1 > gas_upper_limit) gas_reference_1 = gas_upper_limit;
if (gas_reference_1 < gas_lower_limit) gas_reference_1 = gas_lower_limit;
gas_score_1 = (0.75 / (gas_upper_limit - gas_lower_limit) * gas_reference_1 - (gas_lower_limit * (0.75 / (gas_upper_limit - gas_lower_limit)))) * 100;
//Combine results for the final IAQ index value (0-100% where 100% is good quality air)
float air_quality_score_1 = hum_score_1 + gas_score_1;
//BME_2
float current_humidity_2 = bme_2.readHumidity();
if (current_humidity_2 >= 38 && current_humidity_2 <= 42) {
hum_score_2 = 0.25 * 100; // Humidity +/-5% around optimum
}
else
{ //sub-optimal
if (current_humidity_2 < 38)
hum_score_2 = 0.25 / hum_reference_2 * current_humidity_2 * 100;
else {
hum_score_2 = ((-0.25 / (100 - hum_reference_2) * current_humidity_2) + 0.416666) * 100;
}
}
//Calculate gas contribution to IAQ index
if (gas_reference_2 > gas_upper_limit) gas_reference_2 = gas_upper_limit;
if (gas_reference_2 < gas_lower_limit) gas_reference_2 = gas_lower_limit;
gas_score_2 = (0.75 / (gas_upper_limit - gas_lower_limit) * gas_reference_2 - (gas_lower_limit * (0.75 / (gas_upper_limit - gas_lower_limit)))) * 100;
//Combine results for the final IAQ index value (0-100% where 100% is good quality air)
float air_quality_score_2 = hum_score_2 + gas_score_2;
//create timestamp value
now = rtc.now();
//print on SD
dataFile = SD.open("data.txt", FILE_WRITE);
digitalWrite(LED_GREEN, HIGH);
dataFile.print(now.year(), DEC); dataFile.print('/');
dataFile.print(now.month(), DEC); dataFile.print('/');
dataFile.print(now.day(), DEC); dataFile.print(F(","));
dataFile.print(now.year(), DEC); dataFile.print('/');
dataFile.print(now.month(), DEC); dataFile.print('/');
dataFile.print(now.day(), DEC); dataFile.print(F(" "));
dataFile.print(now.hour(), DEC); dataFile.print(':');
dataFile.print(now.minute(), DEC); dataFile.print(':');
dataFile.print(now.second(), DEC); dataFile.print(F(","));
dataFile.print(bme_1.temperature); dataFile.print(F(","));
dataFile.print(bme_1.pressure / 100.0); dataFile.print(F(","));
dataFile.print(bme_1.humidity); dataFile.print(F(","));
dataFile.print(bme_1.gas_resistance / 1000.0); dataFile.print(F(","));
dataFile.print(String(air_quality_score_1)); dataFile.print(F(","));
dataFile.print(CalculateAQI(air_quality_score_1)); dataFile.print(F(","));
dataFile.println(bme_1.readAltitude(SEALEVELPRESSURE_HPA));
dataFile.print(bme_2.temperature); dataFile.print(F(","));
dataFile.print(bme_2.pressure / 100.0); dataFile.print(F(","));
dataFile.print(bme_2.humidity); dataFile.print(F(","));
dataFile.print(bme_2.gas_resistance / 1000.0); dataFile.print(F(","));
dataFile.print(String(air_quality_score_2)); dataFile.print(F(","));
dataFile.print(CalculateAQI(air_quality_score_2)); dataFile.print(F(","));
dataFile.println(bme_2.readAltitude(SEALEVELPRESSURE_HPA));
dataFile.close();
digitalWrite(LED_GREEN, LOW);
//print on Serial Monitor
digitalWrite(LED_RED, HIGH);
Serial.print(now.year(), DEC);
Serial.print('/');
Serial.print(now.month(), DEC);
Serial.print('/');
Serial.print(now.day(), DEC);
Serial.print(F(","));
Serial.print(now.hour(), DEC);
Serial.print(':');
Serial.print(now.minute(), DEC);
Serial.print(':');
Serial.print(now.second(), DEC);
Serial.println(F(";"));
Serial.println(F("***BME_1***"));
Serial.print(F("Temperature = "));
Serial.print(bme_1.temperature);
Serial.println(F(" *C"));
Serial.print(F("Pressure = "));
Serial.print(bme_1.pressure / 100.0);
Serial.println(F(" hPa"));
Serial.print(F("Humidity = "));
Serial.print(bme_1.humidity);
Serial.println(F(" %"));
Serial.print(F("Gas = "));
Serial.print(bme_1.gas_resistance / 1000.0);
Serial.println(F(" KOhms"));
Serial.print(F("Air Quality = "));
Serial.print(String(air_quality_score_1));
Serial.print(F(" % - "));
Serial.println(CalculateAQI(air_quality_score_1));
Serial.print("Humidity element was : ");
Serial.print((hum_score_1 / 100));
Serial.println( " of 0.25");
Serial.print("Gas element was : ");
Serial.print((gas_score_1 / 100));
Serial.println(" of 0.75");
Serial.print(F("Approx. Altitude = "));
Serial.print(bme_1.readAltitude(SEALEVELPRESSURE_HPA));
Serial.println(F(" m"));
Serial.println(F("***BME_2***"));
Serial.print(F("Temperature = "));
Serial.print(bme_2.temperature);
Serial.println(F(" *C"));
Serial.print(F("Pressure = "));
Serial.print(bme_2.pressure / 100.0);
Serial.println(F(" hPa"));
Serial.print(F("Humidity = "));
Serial.print(bme_2.humidity);
Serial.println(F(" %"));
Serial.print(F("Gas = "));
Serial.print(bme_2.gas_resistance / 1000.0);
Serial.println(F(" KOhms"));
Serial.print(F("Air Quality = "));
Serial.print(String(air_quality_score_2));
Serial.print(F(" % - "));
Serial.println(CalculateAQI(air_quality_score_2));
Serial.print("Humidity element was : ");
Serial.print((hum_score_2 / 100));
Serial.println( " of 0.25");
Serial.print("Gas element was : ");
Serial.print((gas_score_2 / 100));
Serial.println(" of 0.75");
Serial.print(F("Approx. Altitude = "));
Serial.print(bme_2.readAltitude(SEALEVELPRESSURE_HPA));
Serial.println(F(" m"));
Serial.println();
digitalWrite(LED_RED, LOW);
delay(measurement_frequency);
}
float 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.
int readings = 10;
//BME_1
for (int i = 1; i <= readings; i++) { // read gas for 10 x 0.150mS = 1.5secs
gas_reference_1 += bme_1.readGas();
}
float gas_reference_1 = gas_reference_1 / readings;
//BME_2
for (int i = 1; i <= readings; i++) { // read gas for 10 x 0.150mS = 1.5secs
gas_reference_2 += bme_2.readGas();
}
float gas_reference_2 = gas_reference_2 / readings;
}
String CalculateAQI(float score) { //calculates score of AQI into text to describe AQ
String AQI_text;
score = (100 - score) * 5;
if (score >= 301) AQI_text = "Hazardous";
else if (score >= 201 && score <= 300 ) AQI_text = "Very Unhealthy";
else if (score >= 176 && score <= 200 ) AQI_text = "Unhealthy";
else if (score >= 151 && score <= 175 ) AQI_text = "Unhealthy for Sensitive Groups";
else if (score >= 51 && score <= 150 ) AQI_text = "Moderate";
else if (score >= 00 && score <= 50 ) AQI_text = "Good";
return AQI_text;
}