ESP32 Web Server with BME680 – Weather Station (Arduino IDE)

This tutorial shows how to build a web server weather station with the ESP32 to display sensor readings from the BME680 environmental sensor: gas (air quality), temperature, humidity and pressure. The readings are updated automatically on the web server using Server-Sent Events (SSE). The ESP32 will be programmed using Arduino IDE.

ESP32 BME680 Gas sensor humidity barometric pressure ambient temperature gas air quality Arduino IDE Web Server

To build the web server we’ll use the ESP Async Web Server library that provides an easy way to build an asynchronous web server.

BME680 Environmental Sensor

The BME680 is an environmental sensor that combines gas, temperature, humidity and pressure sensors. The gas sensor can detect a broad range of gases like volatile organic compounds (VOC). For this reason, the BME680 can be used in indoor air quality control.

BME680 Gas sensor humidity barometric pressure ambient temperature gas air quality front

The BME680 contains a MOX (Metal-oxide) sensor that detects VOCs in the air. This sensor gives you a qualitative idea of the sum of VOCs/contaminants in the surrounding air. As a raw signal, the BME680 outputs resistance values. These values change due to variations in VOC concentrations:

BME680 Gas Environmental Air Quality Sensor Resistance How It Works
  • Higher concentration of VOCs » Lower resistance
  • Lower concentration of VOCs » Higher resistance

For more information about the BME680, read our getting started guide: ESP32: BME680 Environmental Sensor using Arduino IDE (Gas, Pressure, Humidity, Temperature).

Parts Required

ESP32 Board BME680 Gas sensor circuit wiring diagram schematics

To complete this tutorial you need the following parts:

You can use the preceding links or go directly to MakerAdvisor.com/tools to find all the parts for your projects at the best price!

Schematic – ESP32 with BME680

The BME680 can communicate using I2C or SPI communication protocols. In this tutorial, we’ll use I2C communication protocol.

Follow the next schematic diagram to wire the BME680 to the ESP32 using the default I2C pins.

ESP32 BME680 Wiring Diagram I2C

Recommended reading: ESP32 Pinout Reference – Which GPIO pins should you use?

Preparing Arduino IDE

We’ll program the ESP32 board using Arduino IDE. So, make sure you have the ESP32 add-on installed. Follow the next tutorial:

You also need to install the following libraries.

Follow the next instructions to install them.

Installing the BME680 Library

To get readings from the BME680 sensor module we’ll use the Adafruit_BME680 library. Follow the next steps to install the library in your Arduino IDE:

Open your Arduino IDE and go to Sketch Include Library > Manage Libraries. The Library Manager should open.

Search for “adafruit bme680 ” on the Search box and install the library.

Install BM6280 Adafruit Library Arduino IDE Library Manager

Installing the Adafruit_Sensor Library

To use the BME680 library, you also need to install the Adafruit_Sensor library. Follow the next steps to install the library in your Arduino IDE:

Go to Sketch Include Library > Manage Libraries and type “Adafruit Unified Sensor” in the search box. Scroll all the way down to find the library and install it.

Installing Adafruit Unified Sensor Driver library

Installing the ESPAsyncWebServer library

The ESPAsyncWebServer library is not available to install in the Arduino IDE Library Manager. So, you need to install it manually.

Follow the next steps to install the ESPAsyncWebServer library:

  1. Click here to download the ESPAsyncWebServer library. You should have a .zip folder in your Downloads folder
  2. Unzip the .zip folder and you should get ESPAsyncWebServer-master folder
  3. Rename your folder from ESPAsyncWebServer-master to ESPAsyncWebServer
  4. Move the ESPAsyncWebServer folder to your Arduino IDE installation libraries folder

Alternatively, in your Arduino IDE, you can go to Sketch Include Library > Add .zip Library and select the library you’ve just downloaded.

Installing the ESPAsync TCP Library

The ESPAsyncWebServer library requires the ESPAsyncTCP library to work. Follow the next steps to install that library:

  1. Click here to download the ESPAsyncTCP library. You should have a .zip folder in your Downloads folder
  2. Unzip the .zip folder and you should get ESPAsyncTCP-master folder
  3. Rename your folder from ESPAsyncTCP-master to ESPAsyncTCP
  4. Move the ESPAsyncTCP folder to your Arduino IDE installation libraries folder
  5. Finally, re-open your Arduino IDE

Alternatively, in your Arduino IDE, you can go to Sketch Include Library > Add .zip Library and select the library you’ve just downloaded.

ESP32 BME680 Web Server Code

Open your Arduino IDE and copy the following code. To make it work, you need to insert your network credentials: SSID and password.

/*********
  Rui Santos
  Complete project details at https://RandomNerdTutorials.com/esp32-bme680-sensor-arduino/
  
  Permission is hereby granted, free of charge, to any person obtaining a copy
  of this software and associated documentation files.
  
  The above copyright notice and this permission notice shall be included in all
  copies or substantial portions of the Software.
*********/

#include <Wire.h>
#include <SPI.h>
#include <Adafruit_Sensor.h>
#include "Adafruit_BME680.h"
#include <WiFi.h>
#include "ESPAsyncWebServer.h"

// Replace with your network credentials
const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";

//Uncomment if using SPI
/*#define BME_SCK 18
#define BME_MISO 19
#define BME_MOSI 23
#define BME_CS 5*/

Adafruit_BME680 bme; // I2C
//Adafruit_BME680 bme(BME_CS); // hardware SPI
//Adafruit_BME680 bme(BME_CS, BME_MOSI, BME_MISO, BME_SCK);

float temperature;
float humidity;
float pressure;
float gasResistance;

AsyncWebServer server(80);
AsyncEventSource events("/events");

unsigned long lastTime = 0;  
unsigned long timerDelay = 30000;  // send readings timer

void getBME680Readings(){
  // Tell BME680 to begin measurement.
  unsigned long endTime = bme.beginReading();
  if (endTime == 0) {
    Serial.println(F("Failed to begin reading :("));
    return;
  }
  if (!bme.endReading()) {
    Serial.println(F("Failed to complete reading :("));
    return;
  }
  temperature = bme.temperature;
  pressure = bme.pressure / 100.0;
  humidity = bme.humidity;
  gasResistance = bme.gas_resistance / 1000.0;
}

String processor(const String& var){
  getBME680Readings();
  //Serial.println(var);
  if(var == "TEMPERATURE"){
    return String(temperature);
  }
  else if(var == "HUMIDITY"){
    return String(humidity);
  }
  else if(var == "PRESSURE"){
    return String(pressure);
  }
 else if(var == "GAS"){
    return String(gasResistance);
  }
}

const char index_html[] PROGMEM = R"rawliteral(
<!DOCTYPE HTML><html>
<head>
  <title>BME680 Web Server</title>
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.7.2/css/all.css" integrity="sha384-fnmOCqbTlWIlj8LyTjo7mOUStjsKC4pOpQbqyi7RrhN7udi9RwhKkMHpvLbHG9Sr" crossorigin="anonymous">
  <link rel="icon" href="data:,">
  <style>
    html {font-family: Arial; display: inline-block; text-align: center;}
    p {  font-size: 1.2rem;}
    body {  margin: 0;}
    .topnav { overflow: hidden; background-color: #4B1D3F; color: white; font-size: 1.7rem; }
    .content { padding: 20px; }
    .card { background-color: white; box-shadow: 2px 2px 12px 1px rgba(140,140,140,.5); }
    .cards { max-width: 700px; margin: 0 auto; display: grid; grid-gap: 2rem; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); }
    .reading { font-size: 2.8rem; }
    .card.temperature { color: #0e7c7b; }
    .card.humidity { color: #17bebb; }
    .card.pressure { color: #3fca6b; }
    .card.gas { color: #d62246; }
  </style>
</head>
<body>
  <div class="topnav">
    <h3>BME680 WEB SERVER</h3>
  </div>
  <div class="content">
    <div class="cards">
      <div class="card temperature">
        <h4><i class="fas fa-thermometer-half"></i> TEMPERATURE</h4><p><span class="reading"><span id="temp">%TEMPERATURE%</span> &deg;C</span></p>
      </div>
      <div class="card humidity">
        <h4><i class="fas fa-tint"></i> HUMIDITY</h4><p><span class="reading"><span id="hum">%HUMIDITY%</span> &percnt;</span></p>
      </div>
      <div class="card pressure">
        <h4><i class="fas fa-angle-double-down"></i> PRESSURE</h4><p><span class="reading"><span id="pres">%PRESSURE%</span> hPa</span></p>
      </div>
      <div class="card gas">
        <h4><i class="fas fa-wind"></i> GAS</h4><p><span class="reading"><span id="gas">%GAS%</span> K&ohm;</span></p>
      </div>
    </div>
  </div>
<script>
if (!!window.EventSource) {
 var source = new EventSource('/events');
 
 source.addEventListener('open', function(e) {
  console.log("Events Connected");
 }, false);
 source.addEventListener('error', function(e) {
  if (e.target.readyState != EventSource.OPEN) {
    console.log("Events Disconnected");
  }
 }, false);
 
 source.addEventListener('message', function(e) {
  console.log("message", e.data);
 }, false);
 
 source.addEventListener('temperature', function(e) {
  console.log("temperature", e.data);
  document.getElementById("temp").innerHTML = e.data;
 }, false);
 
 source.addEventListener('humidity', function(e) {
  console.log("humidity", e.data);
  document.getElementById("hum").innerHTML = e.data;
 }, false);
 
 source.addEventListener('pressure', function(e) {
  console.log("pressure", e.data);
  document.getElementById("pres").innerHTML = e.data;
 }, false);
 
 source.addEventListener('gas', function(e) {
  console.log("gas", e.data);
  document.getElementById("gas").innerHTML = e.data;
 }, false);
}
</script>
</body>
</html>)rawliteral";

void setup() {
  Serial.begin(115200);

  // Set the device as a Station and Soft Access Point simultaneously
  WiFi.mode(WIFI_AP_STA);
  
  // Set device as a Wi-Fi Station
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.println("Setting as a Wi-Fi Station..");
  }
  Serial.print("Station IP Address: ");
  Serial.println(WiFi.localIP());
  Serial.println();

  // Init BME680 sensor
  if (!bme.begin()) {
    Serial.println(F("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

  // Handle Web Server
  server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send_P(200, "text/html", index_html, processor);
  });

  // Handle Web Server Events
  events.onConnect([](AsyncEventSourceClient *client){
    if(client->lastId()){
      Serial.printf("Client reconnected! Last message ID that it got is: %u\n", client->lastId());
    }
    // send event with message "hello!", id current millis
    // and set reconnect delay to 1 second
    client->send("hello!", NULL, millis(), 10000);
  });
  server.addHandler(&events);
  server.begin();
}

void loop() {
  if ((millis() - lastTime) > timerDelay) {
    getBME680Readings();
    Serial.printf("Temperature = %.2f ºC \n", temperature);
    Serial.printf("Humidity = %.2f % \n", humidity);
    Serial.printf("Pressure = %.2f hPa \n", pressure);
    Serial.printf("Gas Resistance = %.2f KOhm \n", gasResistance);
    Serial.println();

    // Send Events to the Web Server with the Sensor Readings
    events.send("ping",NULL,millis());
    events.send(String(temperature).c_str(),"temperature",millis());
    events.send(String(humidity).c_str(),"humidity",millis());
    events.send(String(pressure).c_str(),"pressure",millis());
    events.send(String(gasResistance).c_str(),"gas",millis());
    
    lastTime = millis();
  }
}

View raw code

Insert your network credentials in the following variables and the code will work straight away.

const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";

How the Code Works

Read this section to learn how the code works, or skip to the next section.

Including Libraries

Start by including the necessary libraries. The Wire library is needed for I2C communication protocol. We also include the SPI library if you want to use SPI communication instead.

#include <Wire.h>
#include <SPI.h>

The Adafruit_Sensor and Adafruit_BME680 libraries are needed to interface with the BME680 sensor.

#include <Adafruit_Sensor.h>
#include "Adafruit_BME680.h"

The WiFi and ESPAsyncWebServer libraries are used to create the web server.

#include <WiFi.h>
#include "ESPAsyncWebServer.h"

Network Credentials

Insert your network credentials in the following variables, so that the ESP32 can connect to your local network using Wi-Fi.

const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";

I2C Communication

Create an Adafruit_BME680 object called bme on the default ESP32 I2C pins.

Adafruit_BME680 bme; // I2C

If you want to use SPI communication instead, you need to define the ESP32 SPI pins on the following lines (to uncomment remove the /* and */):

/*#define BME_SCK 18
#define BME_MISO 19
#define BME_MOSI 23
#define BME_CS 15*/

And then, create an Adafruit_BME680 object using those pins (to uncomment remove the //).

//Adafruit_BME680 bme(BME_CS, BME_MOSI, BME_MISO, BME_SCK);

Declaring Variables

The temperature, humidity, pressure and gasResistance float variables will be used to hold BME680 sensor readings.

float temperature;
float humidity;
float pressure;
float gasResistance;

The lastTime and the timerDelay variables will be used to update sensor readings every X number of seconds. As an example, we’ll get new sensor readings every 30 seconds (30000 milliseconds). You can change that delay time in the timerDelay variable.

unsigned long lastTime = 0;
unsigned long timerDelay = 30000;

Create an Async Web Server on port 80.

AsyncWebServer server(80);

Create Event Source

To automatically display the information on the web server when a new reading arrives, we’ll use Server-Sent Events (SSE).

The following line creates a new event source on /events.

AsyncEventSource events("/events");

Server-Sent Events allow a web page (client) to get updates from a server. We’ll use this to automatically display new readings on the web server page when new BME680 readings are available.

Important: Server-sent events are not supported on Internet Explorer.

Get BME680 Readings

The getBME680Reading() function gets gas, temperature, humidity and pressure readings from the BME680 sensor and saves them on the gasResistance, temperature, humidity and pressure variables.

void getBME680Readings(){
  // Tell BME680 to begin measurement.
  unsigned long endTime = bme.beginReading();
  if (endTime == 0) {
    Serial.println(F("Failed to begin reading :("));
    return;
  }
  if (!bme.endReading()) {
    Serial.println(F("Failed to complete reading :("));
    return;
  }
  temperature = bme.temperature;
  pressure = bme.pressure / 100.0;
  humidity = bme.humidity;
  gasResistance = bme.gas_resistance / 1000.0;
}

Processor

The processor() function replaces any placeholders on the HTML text used to build the web page with the current sensor readings.

String processor(const String& var){
  getBME680Readings();
  //Serial.println(var);
  if(var == "TEMPERATURE"){
    return String(temperature);
  }
  else if(var == "HUMIDITY"){
    return String(humidity);
  }
  else if(var == "PRESSURE"){
    return String(pressure);
  }
 else if(var == "GAS"){
    return String(gasResistance);
  }
}

This allows us to display the current sensor readings on the web page when you access it for the first time. Otherwise, you would see a blank space until new readings were available (which can take some time depending on the delay time you’ve defined on the code).

Building the Web Page

The index_html variable contains all the HTML, CSS and JavaScript to build the web page. We won’t go into detail on how the HTML and CSS works. We’ll just take a look at how to handle the events sent by the server.

Let’s take a quick look at the line that displays the temperature:

<h4><i class="fas fa-thermometer-half"></i> TEMPERATURE</h4><p><span class="reading"><span id="temp">%TEMPERATURE%</span> &deg;C</span></p>

You can see that the %TEMPERATURE% placeholder is surrounded by <span id=”temp”></span> tags. The HTML id attribute is used to specify a unique id for an HTML element.

It is used to point to a specific style or it can be used by JavaScript to access and manipulate the element with that specific id. That’s what we’re going to do.

For instance, when the web server receives a new event with the latest temperature reading, we’ll update the HTML element with the id “temp” with the new reading.

A similar process is done to update the other readings.

Handle Events

Create a new EventSource object and specify the URL of the page sending the updates. In our case, it’s /events.

if (!!window.EventSource) {
  var source = new EventSource('/events');

Once you’ve instantiated an event source, you can start listening for messages from the server with addEventListener().

These are the default event listeners, as shown here in the AsyncWebServer documentation.

source.addEventListener('open', function(e) {
  console.log("Events Connected");
}, false);
source.addEventListener('error', function(e) {
 if (e.target.readyState != EventSource.OPEN) {
   console.log("Events Disconnected");
 }
}, false);

source.addEventListener('message', function(e) {
 console.log("message", e.data);
}, false);

Then, add the event listener for “temperature”.

source.addEventListener('temperature', function(e) {

When a new temperature reading is available, the ESP32 sends an event (“temperature”) to the client. The following lines handle what happens when the browser receives that event.

console.log("temperature", e.data);
document.getElementById("temp").innerHTML = e.data;

Basically, print the new readings on the browser console, and put the received data into the element with the corresponding id (“temp“) on the web page.

A similar processor is done for humidity, pressure and gas resistance.

source.addEventListener('humidity', function(e) {
  console.log("humidity", e.data);
  document.getElementById("hum").innerHTML = e.data;
}, false);
 
source.addEventListener('pressure', function(e) {
  console.log("pressure", e.data);
  document.getElementById("pres").innerHTML = e.data;
}, false);
 
source.addEventListener('gas', function(e) {
  console.log("gas", e.data);
  document.getElementById("gas").innerHTML = e.data;
}, false);

setup()

In the setup(), initialize the Serial Monitor.

Serial.begin(115200);

Connect the ESP32 to your local network and print the ESP32 IP address.

// Set device as a Wi-Fi Station
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
  delay(1000);
  Serial.println("Setting as a Wi-Fi Station..");
}
Serial.print("Station IP Address: ");
Serial.println(WiFi.localIP());
Serial.println();

Initialize the BME680 sensor.

// Init BME680 sensor
if (!bme.begin()) {
  Serial.println(F("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

Handle Requests

When you access the ESP32 IP address on the root / URL, send the text that is stored on the index_html variable to build the web page and pass the processor as argument, so that all placeholders are replaced with the latest sensor readings.

server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
  request->send_P(200, "text/html", index_html, processor);
});

Server Event Source

Set up the event source on the server.

// Handle Web Server Events
events.onConnect([](AsyncEventSourceClient *client){
  if(client->lastId()){
    Serial.printf("Client reconnected! Last message ID that it got is: %u\n", client->lastId());
  }
  // send event with message "hello!", id current millis
  // and set reconnect delay to 1 second
  client->send("hello!", NULL, millis(), 10000);
});
server.addHandler(&events);

Finally, start the server.

server.begin();

loop()

In the loop(), get new sensor readings:

getBME680Readings();

Print the new readings in the Serial Monitor.

Serial.printf("Temperature = %.2f ºC \n", temperature);
Serial.printf("Humidity = %.2f % \n", humidity);
Serial.printf("Pressure = %.2f hPa \n", pressure);
Serial.printf("Gas Resistance = %.2f KOhm \n", gasResistance);
Serial.println();

Finally, send events to the browser with the newest sensor readings to update the web page.

// Send Events to the Web Server with the Sensor Readings
events.send("ping",NULL,millis());
events.send(String(temperature).c_str(),"temperature",millis());
events.send(String(humidity).c_str(),"humidity",millis());
events.send(String(pressure).c_str(),"pressure",millis());
events.send(String(gasResistance).c_str(),"gas",millis());

The following diagram summarizes how Server-Sent Events work to update the web page.

Update BME680 Web Server Readings ESP32 with Arduino IDE using Server Sent Events

Uploading the Code

Now, upload the code to your ESP32. Make sure you have the right board and COM port selected.

After uploading, open the Serial Monitor at a baud rate of 115200. Press the ESP32 on-board RST/EN button. The ESP32 IP address should be printed in the serial monitor.

ESP32 IP Address Serial Monitor Arduino IDE

Demonstration

Open a browser in your local network and type the ESP32 IP address. You should get access to the ESP32 web server with the latest BME680 readings.

ESP32 BME680 Gas sensor Web Server Demonstration

The readings are updated automatically using Server-Sent Events.

ESP32 or ESP8266 NodeMCU Board Web Server Demonstration with BME680 Gas sensor

Wrapping Up

In this tutorial you’ve learned how to build an asynchronous web server weather station with the ESP32 to display BME680 sensor readings – gas (air quality), temperature, humidity and pressure – and how to update the readings automatically on the web page using Server-Sent Events.

We have other web server tutorials that you may like:

We hope you’ve found this project interesting. Learn more about the ESP32 with our resources:

Thanks for reading.



Learn how to build a home automation system and we’ll cover the following main subjects: Node-RED, Node-RED Dashboard, Raspberry Pi, ESP32, ESP8266, MQTT, and InfluxDB database DOWNLOAD »
Learn how to build a home automation system and we’ll cover the following main subjects: Node-RED, Node-RED Dashboard, Raspberry Pi, ESP32, ESP8266, MQTT, and InfluxDB database DOWNLOAD »

Enjoyed this project? Stay updated by subscribing our newsletter!

34 thoughts on “ESP32 Web Server with BME680 – Weather Station (Arduino IDE)”

  1. In ESPAsysncWebServer.h there are the statements
    #ifdef ESP32
    #include <WiFi.h>
    #include <AsyncTCP.h>
    #elif defined(ESP8266)
    #include <ESP8266WiFi.h>
    #include <ESPAsyncTCP.h>
    i.e., for ESP 32 <AsyncTCP.h> is included instead of <ESPAsyncTCP.h>. When I install the latter as you say in the tutorial, <AsyncTCP.h> is not found and the project does not compile correctly. Should I include another library (where do I find the correct AsyncTCP library?) of should I edit ESPAsysncWebServer.h (replace #include <AsyncTCP.h> by <ESPAsyncTCP.h>)?

    Reply
    • Hi.
      If the library is not called, you don’t need to include it.
      But to prevent issues, if you’re using an ESP32, you can delete the lines that refer to the ESP8266:
      #elif defined(ESP8266)
      #include <ESP8266WiFi.h>
      #include <ESPAsyncTCP.h>
      What code are you following?
      Regards,
      Sara

      Reply
  2. Forcing the web page to update by re-entering the IP address or on first reading, I get ‘Failed to complete reading :(‘ in the terminal. Is this normal? Can it be avoided?

    Reply
    • Hi William.
      In this project, the web page is updated automatically when new readings are available.
      There’s no need to force an update because it won’t have new readings.
      Regards,
      Sara

      Reply
  3. I try to fix this tutorial. I use a ESP32 with 30-pin. Board: “ESP32 DEV Module”.
    No changes in Boardmanager.
    Sensor sketch-line: Adafruit_BME680 bme; // I2C
    Compiling and Uploading works without errors.

    But after reset/start I get the serial monitor message:

    rst:0x3 (SW_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
    configsip: 0, SPIWP:0xee
    clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
    mode:DIO, clock div:1
    load:0x3fff0018,len:4
    load:0x3fff001c,len:1216
    ho 0 tail 12 room 4
    load:0x40078000,len:9720
    ho 0 tail 12 room 4
    load:0x40080400,len:6352
    entry 0x400806b8

    Can you please help me fixing this problem?

    Reply
  4. Great tutorial, as always!
    About BME680 I read that the Gas Resistance is only half way to determin Air Qualität as the Signal needs further processing. There is a Bosch BSEC library having all maths included, but I struggle to get this precompiled code library to work with the ESP32 🙁
    Maybe you could do a Follow Up on this in near future 😉

    Reply
  5. The two decimal points of precision displayed on the web page probably represent more precision than the capability of the device. rather than displaying 80.45 is would be better to display 80.5 . Rounding to one decimal is easy but the trailing zero is still displayed. Can the rounding function be accomplished the a trailing zero is not displayed? Perhapse in the Java script?

    Reply
  6. Can you explain to me, how I can convert the gas-data from kOhm to PPM.
    I know that the air is bad, when CO² is bigger then 1.000 PPM.

    400 PPM is fresh air
    1.000 PPM is bad air
    2.000 PPM means death

    Reply
  7. what changes require if I use a different board as I have adafruit huzzah feather.
    I try this code on my board and it gives this message.
    Setting as a Wi-Fi Station..
    continuously.

    Reply
  8. Hello
    I am using ESP32 board with BME 680 i have successfully made it work with Micro Python script from your project.
    Was trying the Arduino IDE Webserver script for the same (ESP32 with BME680) and have the following error:

    Arduino: 1.8.13 (Windows 10), Board: “ESP32 FM DevKit, 921600, None”

    Multiple libraries were found for “WiFi.h”

    Used: C:\Users\RanjitPrabhu\AppData\Local\Arduino15\packages\esp32\hardware\esp32\1.0.4\libraries\WiFi

    In file included from E:\Users\RanjitPrabhu\Documents\Arduino\sketch_dec21b\sketch_dec21b.ino:17:0:

    Not used: C:\Program Files (x86)\Arduino\libraries\WiFi

    E:\Users\RanjitPrabhu\Documents\Arduino\libraries\ESPAsyncWebServer\src/ESPAsyncWebServer.h:33:22: fatal error: AsyncTCP.h: No such file or directory

    compilation terminated.

    exit status 1

    Error compiling for board ESP32 FM DevKit.

    This report would have more information with
    “Show verbose output during compilation”
    option enabled in File -> Preferences.

    Reply
    • Hi.
      This error: “fatal error: AsyncTCP.h: No such file” means that you need to install the AsyncTCP library.
      Regards,
      Sara

      Reply
      • Hello, i am getting the same error but I have the library downloaded and within my Arduino Libraries? Any other insight on what to do to make it work?

        Reply
        • That error means that it can’t find the library.
          You may have several Arduino IDE installations and you may be putting the library in the wrong folder.
          Regards,
          Sara

          Reply
  9. Hi

    I had problems compiling the code and after some searching found out that at least in my case solution was to include following libraries:
    ESPAsyncWebServer
    AsyncTCP-master (https://github.com/me-no-dev/AsyncTCP)
    not to install ESPAsyncTCP-master

    Hope this helps someone struggling with the same problems.

    Reply
  10. Hey, just wanted to let you know that your code seems to have been plagiarized here, without the copyright comment included:XXXXX

    Reply
    • Hi Caleb.
      Thanks for letting us know.
      In fact, that website plagiarizes almost all our content, not just the code, but complete tutorials.
      It’s very annoying, but unfortunately, there’s nothing we can do.
      I can hope that people understand that ours is the original content.
      Thanks once again.
      Regards,
      Sara

      Reply
  11. Good afternoon.
    After sewing ESP32 data:
    15:42:45.579 -> Setting as a Wi-Fi Station..
    15:42:45.579 -> Station IP Address: 192.168.1.100
    But the site page does not open…!!
    In the process it gives an error:
    C:\Users.…\Documents\Arduino\Monin\Monin.ino: In function ‘String processor(const String&)’:
    C:\Users.…\Documents\Arduino\Monin\Monin.ino:76:1: warning: control reaches end of non-void function [-Wreturn-type]
    What to do?

    Reply
    • Hi.
      Modify the processor() function as follows:
      String processor(const String& var){
      getBME680Readings();
      //Serial.println(var);
      if(var == “TEMPERATURE”){
      return String(temperature);
      }
      else if(var == “HUMIDITY”){
      return String(humidity);
      }
      else if(var == “PRESSURE”){
      return String(pressure);
      }
      else if(var == “GAS”){
      return String(gasResistance);
      }
      return String();
      }

      Let me know if this solves the issue.
      Regards.
      Sara

      Reply
  12. Thanks for putting this up. I used a freenove wrover board I got as part of a kit off of amazon. My sensor is a BME680 from Pimoroni LTD. I eventually realized that the default address for this is different from the Adafruit version so I cut the trace to change the address.

    I tried to install the libraries via your instructions but I got a message about multiple wifi.h’s found. Went into library manager and downloaded ESPAsyncWebSrv and made the change to the header file.
    It is working, I have an Adafruit sensor on order along with other items to help her make a living.

    How do you change the sensor address in the program. I’m pretty new at this.

    I sent you some coffee money via paypal. Thanks!

    Reply
  13. When compiling the program, the following two errors occur:
    C:\Users\rogga\Documents\Arduino\sketch_jun17a_ESP32_BME680_Web-Server\sketch_jun17a_ESP32_BME680_Web-Server.ino: In function ‘void loop()’:
    C:\Users\rogga\Documents\Arduino\sketch_jun17a_ESP32_BME680_Web-Server\sketch_jun17a_ESP32_BME680_Web-Server.ino:212:19: error: unknown conversion type character ‘\x0a’ in format [-Werror=format=]
    Serial.printf(“Humidity = %.2f % \n”, humidity);
    ^~~~~~~~~~~~~~~~~~~~~~
    C:\Users\rogga\Documents\Arduino\sketch_jun17a_ESP32_BME680_Web-Server\sketch_jun17a_ESP32_BME680_Web-Server.ino: In function ‘String processor(const String&)’:
    C:\Users\rogga\Documents\Arduino\sketch_jun17a_ESP32_BME680_Web-Server\sketch_jun17a_ESP32_BME680_Web-Server.ino:77:1: error: control reaches end of non-void function [-Werror=return-type]
    }

    Reply
  14. I wonder if I can use adafruit bme680 libraries since my chip is generic bme680 and the program has no adafruit bme680 identified. in this case, is there any other libraries for bme680 that I can use?

    Reply
  15. Goodnight! Is it possible to create an alarm with the cards? For example: I want the gas sensor card to change the background color (red) and font color (white) when it is greater than a certain value and blink while the sensor value is above this value. Can you show me how I can do this?

    Reply
  16. Hi, If we want to change the color of the temperature box depending on a certain condition, for example if the temperature is higher than 30°C, the color changes to RED. Do we have to to this is the script file ? And can you give a hint on the code ? Thanks !

    Reply
  17. Hello… good afternoon
    This tutorials is OK: the sketch compiled ok but i have this problem:
    i use windows 11 with Firefox but the html page is “NOT VISIBLE” with the message: “Il server 192.168.0.6 sta impiegando troppo tempo a rispondere.” But the sketch is running: the value BME680 are writted on serial monitor.
    With cellular RED_MI_NOTE_11 identical message.
    Microsoft Edge: 192.168.0.6 ha richiesto troppo tempo per rispondere
    With cellular TCL_20 is “OK !!!! and the HTML page is OK.
    With cellular LG K9 is “OK” !!! and the HTML page is ok.
    WHY ??? Sketch compiled with arduino 1.8.19 is ok.
    Pardon my little english.
    Best regards: wait for respons. Thank you
    G.Valenti Trento (Italy)

    Reply
  18. Hi,
    There is a new Drop-In Replacement BME688, could you update this tutorial?

    and can you combine this tutorial with the Weather Station PCB, or simply add a display (CYD?) so that you can see the data both on Browser and on device itself as stand alone weather station.

    Reply
  19. Hello
    I followed your logic wrote a dimple code to test my BME680. It’s very odd that nothing showing up in the serial monitor. I have tested many things, including different BME680, different ESP32, I2C scanner, rsisters (5.1k and 10k). Nothing worked. With the I2C scanner, it can identify device at 76. What could be wrong? Thanks a lot.
    #include <Wire.h>
    #include <Adafruit_Sensor.h>
    #include <Adafruit_BME680.h>

    Adafruit_BME680 bme; // I2C

    void setup() {
    Serial.begin(115200);
    delay(2000); // Small delay to ensure stable serial communication
    Serial.println(“Starting BME680 test…”);

    // Initialize the BME680 sensor
    if (!bme.begin(0x76)) { // Try 0x76 address first
    Serial.println(“Could not find a valid BME680 sensor, check wiring!”);
    while (1);
    }

    Serial.println(“BME680 initialization successful!”);
    }

    void loop() {
    // Perform a sensor reading
    if (!bme.performReading()) {
    Serial.println(“Failed to perform reading :(“);
    return;
    }

    // Display sensor readings
    Serial.print(“Temperature = “);
    Serial.print(bme.temperature);
    Serial.println(” *C”);

    Serial.print(“Pressure = “);
    Serial.print(bme.pressure / 100.0);
    Serial.println(” hPa”);

    Serial.print(“Humidity = “);
    Serial.print(bme.humidity);
    Serial.println(” %”);

    Serial.print(“Gas = “);
    Serial.print(bme.gas_resistance / 1000.0);
    Serial.println(” KOhms”);

    delay(2000); // Delay between readings
    }

    Reply

Leave a Comment

Download Our Free eBooks and Resources

Get instant access to our FREE eBooks, Resources, and Exclusive Electronics Projects by entering your email address below.