DIY ESP32 Smart Weather Station
Complete Build Guide for 2026 — Beginner Friendly
Want to know the exact temperature, humidity, and barometric pressure at your doorstep — updated in real time on a crisp E-Ink screen? In this guide, you will build a WiFi-connected ESP32 weather station from scratch. No prior electronics experience needed. By the end, you will have a sleek, low-power device that reads local sensor data, fetches online forecasts, and displays everything on a beautiful e-paper screen.
1. Parts List & Cost Breakdown
Here is everything you need. Total cost sits between $18 and $30 USD depending on where you source components. All parts are widely available on Amazon, AliExpress, and Adafruit.
| Component | Purpose | Est. Cost |
|---|---|---|
| ESP32 DevKit V1 | Microcontroller with WiFi & Bluetooth | $5–8 |
| BME280 Sensor | Temperature, humidity, pressure | $3–5 |
| 2.9" E-Ink Display (IL3829 / SSD1680) | Low-power, sunlight-readable screen | $7–12 |
| Breadboard + Jumper Wires | Prototyping connections | $2–3 |
| USB-C Cable | Power & programming | $1–2 |
| Total | $18–30 |
Optional: a 3.7V LiPo battery ($4) and TP4056 charging module ($1) if you want it to run untethered.
2. Getting to Know the ESP32 Board
The ESP32 is a low-cost, dual-core microcontroller with built-in WiFi and Bluetooth. Below is a simplified pinout diagram highlighting the pins we will use in this project.
Fig 1. ESP32 DevKit V1 — pins highlighted for this project
The green pins (GPIO 21 & 22) handle I2C communication with the BME280 sensor. The orange pins handle SPI for the E-Ink display. The yellow pins provide 3.3V power to our peripherals.
3. Step-by-Step Wiring Guide
We have two devices to connect: the BME280 sensor (via I2C) and the 2.9" E-Ink display (via SPI). Here is the complete wiring schematic.
Fig 2. Wiring schematic — I2C for the sensor, SPI for the display
BME280 Sensor Wiring (I2C)
| BME280 Pin | ESP32 Pin |
|---|---|
| VCC | 3V3 |
| GND | GND |
| SDA | GPIO 21 |
| SCL | GPIO 22 |
E-Ink Display Wiring (SPI)
| E-Ink Pin | ESP32 Pin |
|---|---|
| VCC | 3V3 |
| GND | GND |
| DIN (MOSI) | GPIO 23 |
| CLK (SCK) | GPIO 18 |
| CS | GPIO 5 |
| DC | GPIO 17 |
| RST | GPIO 16 |
| BUSY | GPIO 4 |
4. Arduino IDE Setup & Sensor Code
Installing the Board & Libraries
- Open Arduino IDE 2.x (download from
arduino.ccif you have not already). - Go to File → Preferences and add this URL to Additional Board Manager URLs:
https://espressif.github.io/arduino-esp32/package_esp32_index.json - Go to Tools → Board Manager, search for esp32, and install the latest package.
- Install these libraries via Sketch → Include Library → Manage Libraries:
Adafruit BME280Adafruit Unified SensorGxEPD2(E-Ink display driver)ArduinoJson(for weather API parsing)
Reading the BME280 Sensor
This sketch reads temperature, humidity, and pressure from the BME280 and prints the values to the Serial Monitor.
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>
Adafruit_BME280 bme; // I2C mode
void setup() {
Serial.begin(115200);
// Initialize BME280 at default I2C address 0x76
if (!bme.begin(0x76)) {
Serial.println("BME280 not found! Check wiring.");
while (1) delay(10);
}
Serial.println("BME280 ready.");
}
void loop() {
Serial.printf("Temp: %.1f C Humidity: %.1f%% Pressure: %.0f hPa\n",
bme.readTemperature(),
bme.readHumidity(),
bme.readPressure() / 100.0);
delay(5000);
}
Upload this sketch. Open the Serial Monitor at 115200 baud. You should see readings updating every 5 seconds. If you see "BME280 not found," try address 0x77 instead — some boards use that alternate address.
5. WiFi Setup & Weather API Integration
Next, let us connect the ESP32 to your WiFi network and fetch a real weather forecast from the free Open-Meteo API (no API key required).
#include <WiFi.h>
#include <HTTPClient.h>
#include <ArduinoJson.h>
const char* ssid = "YOUR_WIFI_SSID";
const char* password = "YOUR_WIFI_PASS";
void connectWiFi() {
WiFi.begin(ssid, password);
Serial.print("Connecting to WiFi");
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("\nConnected! IP: " + WiFi.localIP().toString());
}
void fetchForecast() {
HTTPClient http;
// Open-Meteo: free, no API key needed
http.begin("https://api.open-meteo.com/v1/forecast"
"?latitude=40.71&longitude=-74.01"
"¤t_weather=true");
int code = http.GET();
if (code == 200) {
JsonDocument doc;
deserializeJson(doc, http.getString());
float temp = doc["current_weather"]["temperature"];
float wind = doc["current_weather"]["windspeed"];
Serial.printf("Forecast: %.1f C, Wind: %.1f km/h\n", temp, wind);
}
http.end();
}
Replace the latitude/longitude values with your own location. You can find your coordinates on Google Maps — right-click any point and copy the numbers. Call connectWiFi() in setup() and fetchForecast() in loop() with a delay of 10 minutes between calls to stay within rate limits.
6. E-Ink Display Setup & Rendering
E-Ink (electronic paper) displays are perfect for weather stations. They consume zero power when not updating and are readable in direct sunlight. We will use the popular GxEPD2 library to drive our 2.9-inch screen.
Fig 3. E-Ink display mockup — the final weather station UI
Display Code Snippet
#include <GxEPD2_BW.h>
#include <Fonts/FreeSansBold18pt7b.h>
#include <Fonts/FreeSans9pt7b.h>
// 2.9" display, 296x128 pixels
GxEPD2_BW<GxEPD2_290_T94, GxEPD2_290_T94::HEIGHT> display(
GxEPD2_290_T94(5, 17, 16, 4)); // CS, DC, RST, BUSY
void drawWeather(float temp, float hum, float pres) {
display.setRotation(1); // landscape
display.setFullWindow();
display.firstPage();
do {
display.fillScreen(GxEPD_WHITE);
// Large temperature
display.setFont(&FreeSansBold18pt7b);
display.setCursor(10, 50);
display.printf("%.1f C", temp);
// Smaller details
display.setFont(&FreeSans9pt7b);
display.setCursor(10, 85);
display.printf("Humidity: %.0f%%", hum);
display.setCursor(10, 110);
display.printf("Pressure: %.0f hPa", pres);
} while (display.nextPage());
}
The GxEPD2 library uses a paged drawing approach to save RAM. The do...while loop lets the library render the screen in chunks. Call drawWeather() after each sensor read and API fetch to update the display.
7. Putting It All Together
Here is the main loop flow that ties sensor reading, WiFi data, and display rendering into one cohesive program:
void setup() {
Serial.begin(115200);
display.init(115200);
connectWiFi();
if (!bme.begin(0x76)) {
Serial.println("Sensor error!");
return;
}
}
void loop() {
// 1. Read local sensors
float temp = bme.readTemperature();
float hum = bme.readHumidity();
float pres = bme.readPressure() / 100.0;
// 2. Fetch online forecast
fetchForecast();
// 3. Update E-Ink display
drawWeather(temp, hum, pres);
// 4. Deep sleep for 10 minutes (saves battery)
esp_sleep_enable_timer_wakeup(600 * 1000000ULL);
esp_deep_sleep_start();
}
Using deep sleep is the secret to battery longevity. The ESP32 draws under 10 microamps while sleeping. With a 2000mAh LiPo, this station can run for months between charges.
8. Bonus: Web Dashboard for Remote Monitoring
Want to check your weather data from your phone? The ESP32 can also serve a tiny web page on your local network. Alternatively, you can push data to a free cloud service like ThingSpeak or Adafruit IO. Here is what a simple dashboard might look like:
Fig 4. Web dashboard concept — accessible from any device on your network
To serve this from the ESP32 itself, use the built-in WebServer library. Create a simple HTML page that displays the latest readings and auto-refreshes with a <meta http-equiv="refresh"> tag. For cloud dashboards, ThingSpeak is the easiest option — just POST your data to their API and they handle charting automatically.
9. Enclosure & Housing Ideas
Your weather station needs protection from the elements. Here are three popular approaches, from easiest to most polished:
Junction Box
A simple weatherproof ABS junction box from the hardware store. Drill holes for the sensor and a USB cable. Cost: ~$3.
3D-Printed Case
Design or download a custom case from Thingiverse or Printables. Use PETG filament for UV and weather resistance.
Stevenson Screen
The gold standard for weather stations. Louvered sides allow airflow while shielding from rain and direct sun. 3D-printable designs are available online.
- Mount the sensor away from direct sunlight to avoid inflated temperature readings.
- Keep it at least 1.5 meters off the ground for accurate ambient readings.
- Ensure adequate airflow around the BME280 — do not seal it inside a fully closed box.
- Point the E-Ink screen where you can see it (or skip it and use the web dashboard only).
10. Next Steps & Upgrades
Once your basic station is working, here are some ideas to take it further:
- Add a rain gauge — a tipping bucket sensor connected to a GPIO interrupt can measure rainfall in mm.
- Wind speed sensor — an anemometer module gives you a complete outdoor weather picture.
- MQTT integration — push data to Home Assistant or Node-RED for home automation triggers (e.g., close blinds if UV is high).
- Solar power — a small 6V solar panel with a TP4056 module lets the station run indefinitely off-grid.
- Multi-sensor mesh — deploy multiple ESP32 nodes around your property using ESP-NOW (peer-to-peer, no WiFi router needed).
- Historical logging — store data on a micro-SD card or push it to InfluxDB + Grafana for beautiful time-series charts.
You Did It!
You now have a fully functional ESP32 weather station that reads local sensors, fetches online forecasts, and displays everything on a crisp E-Ink screen. Total cost: under $30. Total satisfaction: priceless.
Have questions? Drop a comment below. Happy building!
Comments
Post a Comment