A weather station is the project that makes a maker check a dashboard every morning. This one measures the weather where you actually are — temperature, humidity, and the barometric pressure that warns of an incoming storm — with a single BME280, and streams it to a live dashboard you open from your phone anywhere. No regional-forecast API guessing at your microclimate; the pressure on your own balcony, charted.
Most ESP32 weather-station tutorials stop one step short: they read the sensor and print it to the Serial Monitor or a tiny OLED, then wave at “connect it to the cloud” as a next step. This one is the cloud step, done properly — over plain HTTPS to your own Cloudflare account, no MQTT broker and no legacy freemium platform holding your history.
Why the BME280
The default two-in-one sensor, the DHT22, measures temperature and humidity and nothing else. The BME280 measures those plus barometric pressure, from the same small I2C part — and pressure is what earns the name “weather station.” A steadily falling barometer is the oldest reliable storm signal there is, hours ahead of the clouds. The BME280 is also more accurate than a DHT22 and speaks clean I2C instead of the DHT’s slow, occasionally-flaky one-wire timing. For a few cents more, it’s the sensor every serious build uses.
(One caution when buying: the BMP280 is the cheaper sibling with no humidity. For a weather station you want the BME — the E has humidity.)
What you’ll need
- An ESP32 dev board (any common DevKit variant).
- A BME280 breakout (I2C version — most are).
- Four jumper wires.
- The Arduino IDE with the ESP32 board package, the Nodrix library, and Adafruit’s BME280 library (it pulls in the Adafruit Unified Sensor library), from the Library Manager.
- A nodrix instance with a project and a project token.
Wiring
I2C, four wires, no analog:
| From | To | Wire |
|---|---|---|
| BME280 VCC | ESP32 3V3 | Power |
| BME280 GND | ESP32 GND | Ground |
| BME280 SDA | ESP32 GPIO21 | I2C data |
| BME280 SCL | ESP32 GPIO22 | I2C clock |
Mount the BME280 away from the ESP32 on a short lead. The board’s own heat will bias the temperature reading if the sensor sits right against it — a couple of centimetres and some airflow fixes it.
The firmware
Read three values, send three variables, on a gentle cadence — weather moves slowly. The nodrix Arduino library handles the connection.
#include <Nodrix.h>
#include <Adafruit_BME280.h>
const char* WIFI_SSID = "your-ssid";
const char* WIFI_PASS = "your-password";
const char* HOST = "nodrix.you.workers.dev";
const char* TOKEN = "tok_your_project_token";
Adafruit_BME280 bme;
void setup() {
bme.begin(0x76); // some breakouts are at 0x77
Nodrix.begin(WIFI_SSID, WIFI_PASS, HOST, TOKEN);
}
void loop() {
Nodrix.run();
static unsigned long lastReading = 0;
if (millis() - lastReading >= 60000) {
lastReading = millis();
Nodrix.send("temperature", bme.readTemperature());
Nodrix.send("humidity", bme.readHumidity());
Nodrix.send("pressure", bme.readPressure() / 100.0F); // Pa → hPa
}
}
Worth understanding rather than copying:
- Pressure in hPa. The BME280 reports pascals; dividing by 100 gives hectopascals (millibars), the unit weather reports use — sea-level pressure sits around 1013 hPa, so your readings should land near there once you account for altitude.
- A minute between readings is generous. Weather doesn’t change in seconds. On mains power a minute is fine; on a battery you’d stretch it to 5–15 minutes and deep-sleep between.
- Check the I2C address. BME280 breakouts are at 0x76 or 0x77 depending on the board — if
begin()fails, try the other. - Pin TLS before you ship.
Nodrix.begin()connects encrypted but unverified on first run; addNodrix.setCACert()for production, covered in Connect an ESP32 over HTTPS.
Build the dashboard
| Widget | Bind to | Shows |
|---|---|---|
| Value | temperature | current temperature |
| Value | humidity | relative humidity |
| Gauge | pressure | barometric pressure, ~980–1040 hPa |
| Chart | pressure | the pressure trend — the storm-teller |
| Chart | temperature | the day’s temperature curve |
The pressure chart is the one to watch. Absolute pressure matters less than its slope: a slow rise means settling, fair weather; a steady fall over a few hours is the classic sign of an approaching low and likely rain. Once you’ve watched it for a week against what the sky actually did, you’ll read an incoming front off that line before any app tells you.
Add the storm alert
Weather stations reward one good automation. A rapid pressure drop is the signal worth a
notification: trigger on a new pressure reading, and alert when it falls meaningfully below where
it sat a few hours ago (a threshold around 1000 hPa is a reasonable absolute floor for “weather
coming” in many regions; tune it to yours). Action: Telegram — “Pressure dropping, {{value}} hPa —
weather likely turning.” Swap the channel for Discord or SMS without touching the logic, per
ESP32 notifications.
Going further
- Take it outside on a battery. Deep sleep makes an outdoor node last months; house it in a vented radiation shield to keep sun and rain off the sensor — see ESP32 battery life.
- Add rain and wind. A tipping-bucket gauge (a counted reed switch), an anemometer, and a wind vane each add a variable and a widget without changing the loop’s shape.
- Compare to the forecast. Pull your own history through the read API and chart it against a weather service’s numbers — your microclimate almost never matches the regional forecast exactly, and the gap is the interesting part.
- Run several stations. Sun and shade, indoors and out, ground and roof — each node reports its own variables to one dashboard.
Notes
- Your microclimate, not a regional guess. The sensor measures your location; the API can’t.
- No broker, no legacy cloud. HTTPS to your own Cloudflare account — no MQTT, no ThingSpeak or Blynk caps, history that stays yours behind the read API.
- Battery-friendly by design. Slow weather plus deep sleep equals months on a cell.