├── ESP32_bme680_CC_demo_02.ino ├── ESP32_bme680_CC_demo_03.ino ├── Licence.txt ├── README.md └── Slide1.JPG /ESP32_bme680_CC_demo_02.ino: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | This is a library for the BME680 gas, humidity, temperature & pressure sensor 3 | 4 | Designed specifically to work with the Adafruit BME680 Breakout 5 | ----> http://www.adafruit.com/products/XXXX 6 | 7 | These sensors use I2C or SPI to communicate, 2 or 4 pins are required 8 | to interface. 9 | 10 | Adafruit invests time and resources providing this open source code, 11 | please support Adafruit andopen-source hardware by purchasing products 12 | from Adafruit! 13 | 14 | Written by Limor Fried & Kevin Townsend for Adafruit Industries. 15 | BSD license, all text above must be included in any redistribution 16 | ***************************************************************************/ 17 | 18 | #include 19 | #include 20 | #include 21 | #include "Adafruit_BME680.h" 22 | 23 | #define BME_SCK 13 24 | #define BME_MISO 12 25 | #define BME_MOSI 11 26 | #define BME_CS 10 27 | #define SEALEVELPRESSURE_HPA (1013.25) 28 | 29 | Adafruit_BME680 bme; // I2C 30 | //Adafruit_BME680 bme(BME_CS); // hardware SPI 31 | //Adafruit_BME680 bme(BME_CS, BME_MOSI, BME_MISO, BME_SCK); 32 | 33 | float hum_weighting = 0.25; // so hum effect is 25% of the total air quality score 34 | float gas_weighting = 0.75; // so gas effect is 75% of the total air quality score 35 | 36 | float hum_score, gas_score; 37 | float gas_reference = 250000; 38 | float hum_reference = 40; 39 | int getgasreference_count = 0; 40 | 41 | void setup() { 42 | Serial.begin(115200); 43 | while (!Serial); 44 | Serial.println(F("BME680 test")); 45 | 46 | 47 | Wire.begin(); 48 | if (!bme.begin()) { 49 | Serial.println("Could not find a valid BME680 sensor, check wiring!"); 50 | while (1); 51 | } else Serial.println("Found a sensor"); 52 | 53 | // Set up oversampling and filter initialization 54 | bme.setTemperatureOversampling(BME680_OS_2X); 55 | bme.setHumidityOversampling(BME680_OS_2X); 56 | bme.setPressureOversampling(BME680_OS_2X); 57 | bme.setIIRFilterSize(BME680_FILTER_SIZE_3); 58 | bme.setGasHeater(320, 150); // 320°C for 150 ms 59 | // 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. 60 | GetGasReference(); 61 | } 62 | 63 | void loop() { 64 | Serial.print("Temperature = "); 65 | 66 | Serial.print(bme.readTemperature()); 67 | Serial.println("°C"); 68 | 69 | Serial.print(" Pressure = "); 70 | 71 | Serial.print(bme.readPressure() / 100.0F); 72 | Serial.println(" hPa"); 73 | 74 | Serial.print(" Humidity = "); 75 | Serial.print(bme.readHumidity()); 76 | Serial.println("%"); 77 | 78 | Serial.print(" Gas = "); 79 | Serial.print(bme.readGas()); 80 | Serial.println("R\n"); 81 | /* 82 | This software, the ideas and concepts is Copyright (c) David Bird 2018. All rights to this software are reserved. 83 | 84 | Any redistribution or reproduction of any part or all of the contents in any form is prohibited other than the following: 85 | 1. You may print or download to a local hard disk extracts for your personal and non-commercial use only. 86 | 2. You may copy the content to individual third parties for their personal use, but only if you acknowledge the author David Bird as the source of the material. 87 | 3. You may not, except with my express written permission, distribute or commercially exploit the content. 88 | 4. You may not transmit it or store it in any other website or other form of electronic retrieval system for commercial purposes. 89 | 90 | The above copyright ('as annotated') notice and this permission notice shall be included in all copies or substantial portions of the Software and where the 91 | software use is visible to an end-user. 92 | 93 | THE SOFTWARE IS PROVIDED "AS IS" FOR PRIVATE USE ONLY, IT IS NOT FOR COMMERCIAL USE IN WHOLE OR PART OR CONCEPT. FOR PERSONAL USE IT IS SUPPLIED WITHOUT WARRANTY 94 | OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 95 | IN NO EVENT SHALL THE AUTHOR OR COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 96 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 97 | See more at http://www.dsbird.org.uk 98 | */ 99 | //Calculate humidity contribution to IAQ index 100 | float current_humidity = bme.readHumidity(); 101 | if (current_humidity >= 38 && current_humidity <= 42) 102 | hum_score = 0.25*100; // Humidity +/-5% around optimum 103 | else 104 | { //sub-optimal 105 | if (current_humidity < 38) 106 | hum_score = 0.25/hum_reference*current_humidity*100; 107 | else 108 | { 109 | hum_score = ((-0.25/(100-hum_reference)*current_humidity)+0.416666)*100; 110 | } 111 | } 112 | 113 | //Calculate gas contribution to IAQ index 114 | float gas_lower_limit = 5000; // Bad air quality limit 115 | float gas_upper_limit = 50000; // Good air quality limit 116 |   if (gas_reference > gas_upper_limit) gas_reference = gas_upper_limit;  117 | if (gas_reference < gas_lower_limit) gas_reference = gas_lower_limit; 118 | gas_score = (0.75/(gas_upper_limit-gas_lower_limit)*gas_reference -(gas_lower_limit*(0.75/(gas_upper_limit-gas_lower_limit))))*100; 119 | 120 | //Combine results for the final IAQ index value (0-100% where 100% is good quality air) 121 | float air_quality_score = hum_score + gas_score; 122 | 123 | Serial.println("Air Quality = "+String(air_quality_score,1)+"% derived from 25% of Humidity reading and 75% of Gas reading - 100% is good quality air"); 124 | Serial.println("Humidity element was : "+String(hum_score/100)+" of 0.25"); 125 | Serial.println(" Gas element was : "+String(gas_score/100)+" of 0.75"); 126 | if (bme.readGas() < 120000) Serial.println("***** Poor air quality *****"); 127 | Serial.println(); 128 | if ((getgasreference_count++)%10==0) GetGasReference(); 129 | Serial.println(CalculateIAQ(air_quality_score)); 130 | Serial.println("------------------------------------------------"); 131 | delay(2000); 132 | } 133 | 134 | void GetGasReference(){ 135 | // 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. 136 | Serial.println("Getting a new gas reference value"); 137 | int readings = 10; 138 | for (int i = 1; i <= readings; i++){ // read gas for 10 x 0.150mS = 1.5secs 139 | gas_reference += bme.readGas(); 140 | } 141 | gas_reference = gas_reference / readings; 142 | } 143 | 144 | String CalculateIAQ(float score){ 145 | String IAQ_text = "Air quality is "; 146 | score = (100-score)*5; 147 | if (score >= 301) IAQ_text += "Hazardous"; 148 | else if (score >= 201 && score <= 300 ) IAQ_text += "Very Unhealthy"; 149 | else if (score >= 176 && score <= 200 ) IAQ_text += "Unhealthy"; 150 | else if (score >= 151 && score <= 175 ) IAQ_text += "Unhealthy for Sensitive Groups"; 151 | else if (score >= 51 && score <= 150 ) IAQ_text += "Moderate"; 152 | else if (score >= 00 && score <= 50 ) IAQ_text += "Good"; 153 | return IAQ_text; 154 | } 155 | -------------------------------------------------------------------------------- /ESP32_bme680_CC_demo_03.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Calculate IAQ indices scaled 0-100% (100% is excellent) and 0-500 where 0 is excellent and 500 Hazardous 3 | The index is a hybrid of humidity and adverse gas content. See the Redme for further detaisl of the index. 4 | 5 | This software, the ideas and concepts is Copyright (c) David Bird 2019. All rights to this software are reserved. 6 | 7 | Any redistribution or reproduction of any part or all of the contents in any form is prohibited other than the following: 8 | 1. You may print or download to a local hard disk extracts for your personal and non-commercial use only. 9 | 2. You may copy the content to individual third parties for their personal use, but only if you acknowledge the author David Bird as the source of the material. 10 | 3. You may not, except with my express written permission, distribute or commercially exploit the content. 11 | 4. You may not transmit it or store it in any other website or other form of electronic retrieval system for commercial purposes. 12 | 13 | The above copyright ('as annotated') notice and this permission notice shall be included in all copies or substantial portions of the Software and where the 14 | software use is visible to an end-user. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS" FOR PRIVATE USE ONLY, IT IS NOT FOR COMMERCIAL USE IN WHOLE OR PART OR CONCEPT. FOR PERSONAL USE IT IS SUPPLIED WITHOUT WARRANTY 17 | OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 18 | IN NO EVENT SHALL THE AUTHOR OR COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 | See more at http://www.dsbird.org.uk 21 | */ 22 | /**************************************************************************** 23 | This is a library for the BME680 gas, humidity, temperature & pressure sensor 24 | Designed specifically to work with the Adafruit BME680 Breakout 25 | ----> http://www.adafruit.com/products/XXXX 26 | These sensors use I2C or SPI to communicate, 2 or 4 pins are required 27 | to interface. 28 | Adafruit invests time and resources providing this open source code, 29 | please support Adafruit andopen-source hardware by purchasing products 30 | from Adafruit! 31 | Written by Limor Fried & Kevin Townsend for Adafruit Industries. 32 | BSD license, all text above must be included in any redistribution 33 | ***************************************************************************/ 34 | #include 35 | #include 36 | #include "Adafruit_BME680.h" 37 | 38 | #define SEALEVELPRESSURE_HPA (1013.25) 39 | 40 | Adafruit_BME680 bme; // I2C 41 | 42 | float hum_weighting = 0.25; // so hum effect is 25% of the total air quality score 43 | float gas_weighting = 0.75; // so gas effect is 75% of the total air quality score 44 | 45 | int humidity_score, gas_score; 46 | float gas_reference = 2500; 47 | float hum_reference = 40; 48 | int getgasreference_count = 0; 49 | int gas_lower_limit = 10000; // Bad air quality limit 50 | int gas_upper_limit = 300000; // Good air quality limit 51 | 52 | void setup() { 53 | Serial.begin(115200); 54 | Serial.println(F("BME680 test")); 55 | Wire.begin(); 56 | if (!bme.begin()) { 57 | Serial.println("Could not find a valid BME680 sensor, check wiring!"); 58 | while (1); 59 | } else Serial.println("Found a sensor"); 60 | 61 | // Set up oversampling and filter initialization 62 | bme.setTemperatureOversampling(BME680_OS_8X); 63 | bme.setHumidityOversampling(BME680_OS_2X); 64 | bme.setPressureOversampling(BME680_OS_4X); 65 | bme.setIIRFilterSize(BME680_FILTER_SIZE_3); 66 | bme.setGasHeater(320, 150); // 320°C for 150 ms 67 | // 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. 68 | // The sensor takes ~30-mins to fully stabilise 69 | GetGasReference(); 70 | } 71 | 72 | void loop() { 73 | Serial.println("Sensor Readings:"); 74 | Serial.println(" Temperature = " + String(bme.readTemperature(), 2) + "°C"); 75 | Serial.println(" Pressure = " + String(bme.readPressure() / 100.0F) + " hPa"); 76 | Serial.println(" Humidity = " + String(bme.readHumidity(), 1) + "%"); 77 | Serial.println(" Gas = " + String(gas_reference) + " ohms\n"); 78 | Serial.print("Qualitative Air Quality Index "); 79 | 80 | humidity_score = GetHumidityScore(); 81 | gas_score = GetGasScore(); 82 | 83 | //Combine results for the final IAQ index value (0-100% where 100% is good quality air) 84 | float air_quality_score = humidity_score + gas_score; 85 | Serial.println(" comprised of " + String(humidity_score) + "% Humidity and " + String(gas_score) + "% Gas"); 86 | if ((getgasreference_count++) % 5 == 0) GetGasReference(); 87 | Serial.println(CalculateIAQ(air_quality_score)); 88 | Serial.println("--------------------------------------------------------------"); 89 | delay(2000); 90 | } 91 | 92 | void GetGasReference() { 93 | // 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. 94 | //Serial.println("Getting a new gas reference value"); 95 | int readings = 10; 96 | for (int i = 1; i <= readings; i++) { // read gas for 10 x 0.150mS = 1.5secs 97 | gas_reference += bme.readGas(); 98 | } 99 | gas_reference = gas_reference / readings; 100 | //Serial.println("Gas Reference = "+String(gas_reference,3)); 101 | } 102 | 103 | String CalculateIAQ(int score) { 104 | String IAQ_text = "air quality is "; 105 | score = (100 - score) * 5; 106 | if (score >= 301) IAQ_text += "Hazardous"; 107 | else if (score >= 201 && score <= 300 ) IAQ_text += "Very Unhealthy"; 108 | else if (score >= 176 && score <= 200 ) IAQ_text += "Unhealthy"; 109 | else if (score >= 151 && score <= 175 ) IAQ_text += "Unhealthy for Sensitive Groups"; 110 | else if (score >= 51 && score <= 150 ) IAQ_text += "Moderate"; 111 | else if (score >= 00 && score <= 50 ) IAQ_text += "Good"; 112 | Serial.print("IAQ Score = " + String(score) + ", "); 113 | return IAQ_text; 114 | } 115 | 116 | int GetHumidityScore() { //Calculate humidity contribution to IAQ index 117 | float current_humidity = bme.readHumidity(); 118 | if (current_humidity >= 38 && current_humidity <= 42) // Humidity +/-5% around optimum 119 | humidity_score = 0.25 * 100; 120 | else 121 | { // Humidity is sub-optimal 122 | if (current_humidity < 38) 123 | humidity_score = 0.25 / hum_reference * current_humidity * 100; 124 | else 125 | { 126 | humidity_score = ((-0.25 / (100 - hum_reference) * current_humidity) + 0.416666) * 100; 127 | } 128 | } 129 | return humidity_score; 130 | } 131 | 132 | int GetGasScore() { 133 | //Calculate gas contribution to IAQ index 134 | 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; 135 | if (gas_score > 75) gas_score = 75; // Sometimes gas readings can go outside of expected scale maximum 136 | if (gas_score < 0) gas_score = 0; // Sometimes gas readings can go outside of expected scale minimum 137 | return gas_score; 138 | } 139 | -------------------------------------------------------------------------------- /Licence.txt: -------------------------------------------------------------------------------- 1 | This software, the ideas and concepts is Copyright (c) David Bird 2014 and beyond. 2 | 3 | All rights to this software are reserved. 4 | 5 | It is prohibited to redistribute or reproduce of any part or all of the software contents in any form other than the following: 6 | 7 | 1. You may print or download to a local hard disk extracts for your personal and non-commercial use only. 8 | 9 | 2. You may copy the content to individual third parties for their personal use, but only if you acknowledge the author David Bird as the source of the material. 10 | 11 | 3. You may not, except with my express written permission, distribute or commercially exploit the content. 12 | 13 | 4. You may not transmit it or store it in any other website or other form of electronic retrieval system for commercial purposes. 14 | 15 | 5. You MUST include all of this copyright and permission notice ('as annotated') and this shall be included in all copies or substantial portions of the software and where the software use is visible to an end-user. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS" FOR PRIVATE USE ONLY, IT IS NOT FOR COMMERCIAL USE IN WHOLE OR PART OR CONCEPT. 18 | 19 | FOR PERSONAL USE IT IS SUPPLIED WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | 21 | IN NO EVENT SHALL THE AUTHOR OR COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | BME680 IAQ Example 5 | 6 | Using the BME680 to measure temperature, pressure, humidity and air quality. 7 | 8 | The sensor is used to obtain the so-called Gas Resistance and then calculate an Index of Air Quality (IAQ) from a combination of humidity and the gas content readings of the air, optionally temperature could be added too, but omittied in this example. 9 | 10 | The index is a function of humidity which contributes up to 25% and gas concentrations that contributes up to 75%. See slide1.jpg for details of the IAQ index formulation. 11 | 12 | In this current version only Humidity and Gas concentrations are used for the index, but adding temperature would be straightforward on the basis that temperatures for humans that are too high or low add to the overal Air Quality index along with Humidity and Gas concetrations. 13 | 14 | Humidity is measured between 0 - 100% and is universally accepted as being optimal when it is 40% and where in this index the contribution will be 0, but at a Humidity reading of 0%, the contribution increases to 25% and similarly when humidity reaches 100% it contributes 25% to the index. See Slide1 for details. 15 | 16 | Gas concentrations for normal breathable air with no pollutants (no adverse gases) corresponds to the sensors highest resitance output of 50,000 ohms or more. The sensor normally outputs a Gas resistance value ranging from a low of 50ohm to a high of 50,000ohm and beyond. A linear relationship is assumed and the output scaled accordingly between 0 and 75% for the range 50-50,000 ohms. 17 | 18 | The result of combining humidity and gas measurements into an in index is a qualitative and so-called IAQ - Indoor Air Quality index value scaled from 0-100% (where 100% is good). This is then scaled again from 0-500 where a 500 value is bad and descriptive values are applied in stages from good to hazardous air quality. 19 | 20 | There is no definitive (ISO Standard) method for calculating an IAQ. 21 | 22 | (c) d.l.bird 2018 all rights reserved and as per the Licence agreements listed in my software. 23 | 24 | This IAQ and the ideas and concepts is Copyright (c) David Bird 2018. All rights to this IAQ and software are reserved. 25 | Any redistribution or reproduction of any part or all of the contents in any form is prohibited other than the following: 26 | 1. You may print or download to a local hard disk extracts for your personal and non-commercial use only. 27 | 2. You may copy the content to individual third parties for their personal use, but only if you acknowledge the author David Bird as the source of the material. 28 | 3. You may not, except with my express written permission, distribute or commercially exploit the content. 29 | 4. You may not transmit it or store it in any other website or other form of electronic retrieval system for commercial purposes. 30 | 31 | The above copyright ('as annotated') notice and this permission notice shall be included in all copies or substantial portions of the IAQ index and Software and where the software use is visible to an end-user. 32 | 33 | ![alt text](Slide1.JPG) 34 | -------------------------------------------------------------------------------- /Slide1.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/G6EJD/BME680-Example/093ed551a12b05b80629d6b126c05d273a8223f3/Slide1.JPG --------------------------------------------------------------------------------