ESP32 Bench
Boards: ESP32, S2, S3, C3, C6
Flash and monitor: Web Serial
← All projects

BME280 web dashboard

The board serves its own web page with live temperature, humidity and pressure and a chart that grows every two seconds.

Intermediate25 min115200 baud
Board
Fig. 1. Pins this project uses on the ESP32-DevKitC V4, 38 pin. USB connector at the bottom.

Wiring

FromTo boardNote
BME280 VIN or VCC3V3
BME280 GNDGND
BME280 SDA or SDIGPIO 21
BME280 SCL or SCKGPIO 22

Tested on this board

Not run on this board yet. Treat the wiring and code as a first draft.

Firmware, Arduino sketch for ESP32 Dev Module

#include <WiFi.h>
#include <WebServer.h>
#include <Wire.h>
#include <Adafruit_BME280.h>

const char* WIFI_NAME = "your-network";
const char* WIFI_PASS = "your-password";

Adafruit_BME280 bme;
WebServer server(80);
unsigned long lastLog = 0;

const char PAGE[] = R"html(<!doctype html>
<html><head><meta name="viewport" content="width=device-width,initial-scale=1"><title>BME280</title>
<style>body{font-family:sans-serif;margin:16px;background:#f2f5f1;color:#14231f}b{font-size:2em}
canvas{width:100%;height:160px;background:#fff;border:1px solid #c8d1cb}</style></head>
<body><h1>BME280</h1>
<p><b id="t">--</b> &deg;C &nbsp; <b id="h">--</b> %RH &nbsp; <b id="p">--</b> hPa</p>
<canvas id="c" width="600" height="160"></canvas><p id="s">connecting</p>
<script>
var pts = [], c = document.getElementById('c'), g = c.getContext('2d');
function draw() {
  g.clearRect(0, 0, 600, 160);
  if (pts.length < 2) return;
  var lo = Math.min.apply(null, pts) - 0.5, hi = Math.max.apply(null, pts) + 0.5;
  g.beginPath();
  pts.forEach(function (v, i) {
    var x = i * 600 / (pts.length - 1), y = 160 - (v - lo) * 160 / (hi - lo);
    if (i) g.lineTo(x, y); else g.moveTo(x, y);
  });
  g.strokeStyle = '#c0341a'; g.lineWidth = 2; g.stroke();
}
function tick() {
  fetch('/data.json').then(function (r) { return r.json(); }).then(function (d) {
    document.getElementById('t').textContent = d.t.toFixed(1);
    document.getElementById('h').textContent = d.h.toFixed(0);
    document.getElementById('p').textContent = d.p.toFixed(1);
    pts.push(d.t); if (pts.length > 150) pts.shift(); draw();
    document.getElementById('s').textContent = 'updated ' + new Date().toLocaleTimeString();
  }).catch(function () { document.getElementById('s').textContent = 'board not answering'; });
}
tick(); setInterval(tick, 2000);
</script></body></html>)html";

void sendData() {
  char json[96];
  snprintf(json, sizeof json, "{\"t\":%.2f,\"h\":%.1f,\"p\":%.1f}",
           bme.readTemperature(), bme.readHumidity(), bme.readPressure() / 100.0f);
  server.send(200, "application/json", json);
}

void setup() {
  Serial.begin(115200);
  Wire.begin(21, 22);
  if (!bme.begin(0x76, &Wire) && !bme.begin(0x77, &Wire)) {
    Serial.println("BME280 not found at 0x76 or 0x77: check wiring, or it may be a BMP280");
    for (;;) delay(1000);
  }

  WiFi.mode(WIFI_STA);
  WiFi.begin(WIFI_NAME, WIFI_PASS);
  Serial.printf("wifi joining %s\n", WIFI_NAME);
  while (WiFi.status() != WL_CONNECTED) delay(300);

  server.on("/", []() { server.send(200, "text/html", PAGE); });
  server.on("/data.json", sendData);
  server.begin();
  Serial.printf("dashboard at http://%s/\n", WiFi.localIP().toString().c_str());
}

void loop() {
  server.handleClient();
  if (millis() - lastLog > 10000) {
    lastLog = millis();
    Serial.printf("t %.2f C  h %.1f %%  p %.1f hPa\n", bme.readTemperature(), bme.readHumidity(), bme.readPressure() / 100.0f);
  }
}

Parts

QuantityPartWhere to buy
1×ESP32 dev boardBuy at Amazon
1×BME280 breakout, I2CBuy at Adafruit
4×Jumper wires

Amazon buy links may include an Associates tag, and this site may earn a commission from qualifying Amazon purchases at no extra cost to you. Adafruit links are direct.

Libraries

Adafruit BME280 Library, Adafruit Unified Sensor, WiFi (built in), WebServer (built in)

Load it

  1. In the Arduino IDE, install the esp32 board package and pick the board named above the sketch.
  2. Install the libraries listed above from the Library Manager.
  3. Paste the sketch, choose the board's port and upload. Hold BOOT if the upload stalls at Connecting.
  4. Close the IDE's serial monitor, then open the bench here to watch the output.

Field notes

  • Open the address the bench prints, such as http://192.168.1.80/, from any phone or computer on the same network. The chart keeps the last five minutes in the browser.
  • Many cheap purple breakouts sold as BME280 carry a BMP280, which has no humidity sensor. The library refuses it, and the sketch says so. The chip markings tell them apart.
  • Address 0x76 or 0x77 depends on the board's SDO pin; the sketch tries both. Run the I2C scanner project if neither answers.
  • The BME280 warms itself a little when read constantly. Readings every two seconds are fine; for accurate room temperature, keep the sensor away from the ESP32's own heat.
  • /data.json is plain JSON, so Home Assistant's REST sensor or a script can read it too.

Not tested yet

  • Not tested on hardware yet. Compiles for every board listed with Arduino-ESP32 core 3.3.12.

Built it? Send a build report with your board and what the serial port printed. Working reports become the "Tested on this board" entries above.