Skip to content

Instantly share code, notes, and snippets.

@JavanXD
Last active June 1, 2021 15:04
Show Gist options
  • Save JavanXD/e18d510216599d678d1f380f82a6841e to your computer and use it in GitHub Desktop.
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)
#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("&deg;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