Last active
June 1, 2021 15:04
-
-
Save JavanXD/e18d510216599d678d1f380f82a6841e to your computer and use it in GitHub Desktop.
ESP32: Create Accesspoint and visualize measurement data from BME680 sensor. Read my write-up: https://javan.de/esp32-bme680-sensor-in-webinterface-visualisieren/ (German language)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <WiFi.h> | |
#include <Wire.h> | |
#include <SPI.h> | |
#include <Adafruit_Sensor.h> | |
#include "Adafruit_BME680.h" | |
// Only needed for software SPI | |
//#define BME_SCK 13 | |
//#define BME_MISO 12 | |
//#define BME_MOSI 11 | |
//#define BME_CS 10 | |
#define SEALEVELPRESSURE_HPA (1013.25) | |
Adafruit_BME680 bme; // I2C | |
//Adafruit_BME680 bme(BME_CS); // Hardware SPI | |
//Adafruit_BME680 bme(BME_CS, BME_MOSI, BME_MISO, BME_SCK); // Software SPI | |
// Set the humidity baseline to 40%, an optimal indoor humidity. | |
float humidityBaseline = 40.0; | |
// This sets the balance between humidity and gas reading in the calculation of airQualityScore (25:75, humidity:gas). | |
float humidityWeighting = 0.25; | |
int gasBaseline = 0; | |
boolean burnedIn = false; | |
// Replace with your network credentials. | |
const char* ssid = "Sensoright"; | |
const char* password = "123456789"; | |
// Set web server port number to 80. | |
WiFiServer server(80); | |
// Variable to store the HTTP request. | |
String header; | |
void setup() { | |
Serial.begin(115200); | |
while (!Serial) { | |
; // Wait for serial port to connect. Needed for native USB port only. | |
} | |
Serial.println("Sensoright - BME680 ESP32"); | |
if (!bme.begin()) { | |
Serial.println("Could not find a valid BME680 sensor, check wiring!"); | |
while (1); | |
} | |
// 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 | |
// Connect to Wi-Fi network with SSID and password. | |
Serial.println("Setting AP (Access Point)…"); | |
// Remove the password parameter, if you want the AP (Access Point) to be open. | |
WiFi.softAP(ssid, password); | |
IPAddress IP = WiFi.softAPIP(); | |
Serial.print("Access point IP address: "); | |
Serial.println(IP); | |
server.begin(); | |
} | |
void loop() { | |
WiFiClient client = server.available(); // Listen for incoming clients | |
if (client) { // If a new client connects, | |
Serial.println("New Client."); // print a message out in the serial port | |
String currentLine = ""; // make a String to hold incoming data from the client | |
while (client.connected()) { // loop while the client's connected | |
if (client.available()) { // if there's bytes to read from the client, | |
char c = client.read(); // read a byte, then | |
Serial.write(c); // print it out the serial monitor | |
header += c; | |
if (c == '\n') { // if the byte is a newline character | |
// if the current line is blank, you got two newline characters in a row. | |
// that's the end of the client HTTP request, so send a response: | |
if (currentLine.length() == 0) { | |
// HTTP headers always start with a response code (e.g. HTTP/1.1 200 OK) | |
// and a content-type so the client knows what's coming, then a blank line: | |
client.println("HTTP/1.1 200 OK"); | |
client.println("Content-type:text/html"); | |
client.println("Connection: close"); | |
client.println(); | |
// Display the HTML web page | |
client.println("<!DOCTYPE html><html>"); | |
client.println("<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">"); | |
client.println("<meta charset=\"utf-8\">"); | |
client.println("<meta http-equiv=\"refresh\" content=\"30\"></head>"); | |
// Web page heading | |
client.println("<body><h1>Sensoright</h1>"); | |
if (!bme.performReading()) { | |
Serial.println("Auslesen des BME680-Sensors fehlgeschlagen!"); | |
client.println("<div><p>Auslesen des BME680-Sensors fehlgeschlagen!"); | |
client.println("</p></div>"); | |
client.println("</body></html>"); | |
// The HTTP response ends with another blank line | |
client.println(); | |
// Break out of the while loop | |
break; | |
} | |
if (!burnedIn) { | |
client.println("<div><p>Der BME680-Sensor muss zuerst 2 Minuten eingebrannt werden, damit die Messwerte so genau wie möglich werden. Bitte warten…"); | |
client.println("</p></div>"); | |
client.println("</body></html>"); | |
// The HTTP response ends with another blank line | |
client.println(); | |
// Burning-in BME680 sensor for calculating the air quality score (IAQ). | |
Serial.println("Burning-in BME680 sensor and calculating gas baseline…"); | |
gasBaseline = calculateGasBaseline(); | |
// Break out of the while loop | |
break; | |
} | |
float temperature = bme.temperature; | |
Serial.print("Temperature = "); | |
Serial.print(temperature); | |
Serial.println(" °C"); | |
float humidity = bme.humidity; | |
Serial.print("Humidity = "); | |
Serial.print(humidity); | |
Serial.println(" %"); | |
float pressure = bme.pressure / 100.0; | |
Serial.print("Pressure = "); | |
Serial.print(pressure); | |
Serial.println(" hPa"); | |
float gas = bme.gas_resistance / 1000.0; | |
Serial.print("Gas = "); | |
Serial.print(gas); | |
Serial.println(" KOhms"); | |
int iaq = getIaq(); | |
Serial.print("Air quality score = "); | |
Serial.print(iaq); | |
Serial.println(" IAQ"); | |
float altitude = bme.readAltitude(SEALEVELPRESSURE_HPA); | |
Serial.print("Approx. altitude = "); | |
Serial.print(altitude); | |
Serial.println(" m"); | |
client.println("<div><p>Temperatur: "); | |
client.println(temperature); | |
client.println("°C</p><p>Luftfeuchtigkeit: "); | |
client.println(humidity); | |
client.println("%</p><p>Luftdruck: "); | |
client.println(pressure); | |
client.println("hPa</p><p>Gaswiderstand: "); | |
client.println(gas); | |
client.println("KOhms</p><p>Luftqualität: "); | |
client.println(iaq); | |
client.println("IAQ</p><p>Meeresspiegel: "); | |
client.println(altitude); | |
client.println("m</p></div>"); | |
client.println("</body></html>"); | |
// The HTTP response ends with another blank line | |
client.println(); | |
// Break out of the while loop | |
break; | |
} else { // if you got a newline, then clear currentLine | |
currentLine = ""; | |
} | |
} else if (c != '\r') { // If you got anything else but a carriage return character, | |
currentLine += c; // add it to the end of the currentLine. | |
} | |
} | |
} | |
// Give the web browser time to receive the data. | |
delay(1); | |
// Clear the header variable. | |
header = ""; | |
// Close the connection. | |
client.stop(); | |
Serial.println("Client disconnected."); | |
Serial.println(""); | |
} | |
} | |
int calculateGasBaseline() { | |
// Collect gas resistance burn-in values for 2 minutes, | |
// then use the average of the values to set the upper | |
// limit for calculating gasBaseline. | |
Serial.println("Collecting gas resistance burn-in data for 2 minutes"); | |
float burnInData[140]; | |
for (int i = 0; i < 140; i++) { | |
Serial.print("Read "); | |
Serial.print(i); | |
Serial.println(" of 140…"); | |
Serial.print("Temperatur = "); | |
Serial.println(bme.temperature); | |
Serial.print("Luftfeuchtigkeit = "); | |
Serial.println(bme.humidity); | |
Serial.print("Luftdruck = "); | |
Serial.println(bme.humidity); | |
Serial.print("Meerespiegel = "); | |
Serial.println(bme.readAltitude(SEALEVELPRESSURE_HPA)); | |
burnInData[i] = bme.gas_resistance; | |
Serial.print("Gas = "); | |
Serial.print(burnInData[i]); | |
Serial.println(" Ohms"); | |
Serial.println(); | |
delay(500); | |
} | |
// Calculate the gas baseline (average of the gas data). | |
float sum = 0; | |
for (int i = 0; i < 140; i++) { | |
sum = sum + burnInData[i]; | |
} | |
float gasBaseline = sum / 140; | |
Serial.print("Gas baseline = "); | |
Serial.println(gasBaseline); | |
burnedIn = true; | |
return gasBaseline; | |
} | |
int getIaq() { | |
float gas = bme.gas_resistance; | |
Serial.print("Gas = "); | |
Serial.println(gas); | |
float gasOffset = gasBaseline - gas; | |
Serial.print("Gas offset = "); | |
Serial.println(gasOffset); | |
float humidity = bme.humidity; | |
Serial.print("Humidity = "); | |
Serial.println(humidity); | |
float humidityOffset = humidity - humidityBaseline; | |
Serial.print("Humidity offset = "); | |
Serial.println(humidityOffset); | |
// Calculate humidityScore as the distance from the humidityBaseline. | |
float humidityScore = 0.0; | |
if (humidityOffset > 0) { | |
humidityScore = (100 - humidityBaseline - humidityOffset); | |
humidityScore /= (100 - humidityBaseline); | |
humidityScore *= (humidityWeighting * 100); | |
} else { | |
humidityScore = (humidityBaseline + humidityOffset); | |
humidityScore /= humidityBaseline; | |
humidityScore *= (humidityWeighting * 100); | |
} | |
Serial.print("Humidity score = "); | |
Serial.println(humidityScore); | |
// Calculate gasScore as the distance from the gasBaseline. | |
float gasScore = 0.0; | |
if (gasOffset > 0) { | |
gasScore = (gas / gasBaseline); | |
gasScore *= (100 - (humidityWeighting * 100)); | |
} else { | |
gasScore = 100 - (humidityWeighting * 100); | |
} | |
Serial.print("Gas score = "); | |
Serial.println(gasScore); | |
// Calcualte airQualityScore. | |
return (int)(humidityScore + gasScore); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment