ESP32 Weather Station Project
Overview
This project creates a complete weather station using an ESP32 microcontroller that reads temperature, humidity, and pressure data from sensors and displays the information on an OLED screen.
Components Required
Hardware
- ESP32 Development Board (ESP32-WROOM-32 or similar)
- BME280 Sensor Module (Temperature, Humidity, Pressure)
- 0.96" I2C OLED Display (SSD1306, 128x64 pixels)
- Breadboard or PCB
- Jumper Wires
- Micro USB Cable
- Optional: 3D printed enclosure
Software Libraries
- Adafruit BME280 Library
- Adafruit SSD1306 Library
- Adafruit GFX Library
- Wire Library (built-in)
Wiring Diagram
BME280 Connections
BME280 → ESP32
VCC → 3.3V
GND → GND
SCL → GPIO 22 (SCL)
SDA → GPIO 21 (SDA)
OLED Display Connections
OLED → ESP32
VCC → 3.3V
GND → GND
SCL → GPIO 22 (SCL)
SDA → GPIO 21 (SDA)
Note: Both devices share the same I2C bus (SDA/SCL pins)
Arduino Code
#include <WiFi.h>
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
// OLED Display Settings
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1
#define SCREEN_ADDRESS 0x3C
// Create objects
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
Adafruit_BME280 bme;
// WiFi credentials (optional - for future web features)
const char* ssid = "YOUR_WIFI_SSID";
const char* password = "YOUR_WIFI_PASSWORD";
// Sensor variables
float temperature;
float humidity;
float pressure;
float altitude;
// Display update interval
unsigned long lastUpdate = 0;
const unsigned long updateInterval = 2000; // Update every 2 seconds
void setup() {
Serial.begin(115200);
// Initialize I2C
Wire.begin();
// Initialize OLED Display
if (!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
Serial.println(F("SSD1306 allocation failed"));
for (;;);
}
// Initialize BME280
if (!bme.begin(0x76)) { // Try address 0x76 first
if (!bme.begin(0x77)) { // If that fails, try 0x77
Serial.println("Could not find a valid BME280 sensor, check wiring!");
while (1);
}
}
// Configure BME280 settings
bme.setSampling(Adafruit_BME280::MODE_NORMAL,
Adafruit_BME280::SAMPLING_X2, // temperature
Adafruit_BME280::SAMPLING_X2, // pressure
Adafruit_BME280::SAMPLING_X2, // humidity
Adafruit_BME280::FILTER_X16,
Adafruit_BME280::STANDBY_MS_500);
// Clear display
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
display.setCursor(0, 0);
display.println("Weather Station");
display.println("Initializing...");
display.display();
// Optional: Initialize WiFi
initWiFi();
delay(2000);
Serial.println("Weather Station Ready!");
}
void loop() {
if (millis() - lastUpdate >= updateInterval) {
readSensors();
updateDisplay();
printToSerial();
lastUpdate = millis();
}
// Add small delay to prevent watchdog timer issues
delay(10);
}
void readSensors() {
temperature = bme.readTemperature();
humidity = bme.readHumidity();
pressure = bme.readPressure() / 100.0F; // Convert Pa to hPa
altitude = bme.readAltitude(1013.25); // Sea level pressure in hPa
}
void updateDisplay() {
display.clearDisplay();
// Title
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
display.setCursor(25, 0);
display.println("WEATHER STATION");
// Draw separator line
display.drawLine(0, 12, 128, 12, SSD1306_WHITE);
// Temperature
display.setCursor(0, 16);
display.print("Temp: ");
display.print(temperature, 1);
display.print(" C");
// Humidity
display.setCursor(0, 28);
display.print("Humid: ");
display.print(humidity, 1);
display.print(" %");
// Pressure
display.setCursor(0, 40);
display.print("Press: ");
display.print(pressure, 1);
display.print(" hPa");
// Altitude (optional)
display.setCursor(0, 52);
display.print("Alt: ");
display.print(altitude, 0);
display.print(" m");
display.display();
}
void printToSerial() {
Serial.println("=== Weather Station Reading ===");
Serial.print("Temperature: ");
Serial.print(temperature);
Serial.println(" °C");
Serial.print("Humidity: ");
Serial.print(humidity);
Serial.println(" %");
Serial.print("Pressure: ");
Serial.print(pressure);
Serial.println(" hPa");
Serial.print("Altitude: ");
Serial.print(altitude);
Serial.println(" m");
Serial.println("==============================");
}
void initWiFi() {
// Uncomment and configure if you want WiFi connectivity
/*
WiFi.begin(ssid, password);
Serial.print("Connecting to WiFi");
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println();
Serial.print("Connected! IP address: ");
Serial.println(WiFi.localIP());
*/
}
// Function to handle sensor errors
void handleSensorError() {
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
display.setCursor(0, 0);
display.println("SENSOR ERROR!");
display.println("Check connections");
display.display();
Serial.println("Sensor reading error!");
delay(1000);
}
Setup Instructions
1. Hardware Assembly
- Connect the BME280 and OLED display to the ESP32 using the wiring diagram above
- Both devices use I2C communication and share the same SDA/SCL pins
- Ensure all connections are secure and use the correct voltage (3.3V)
2. Software Setup
- Install the Arduino IDE
- Add ESP32 board support:
- Go to File → Preferences
- Add
https://dl.espressif.com/dl/package_esp32_index.jsonto Additional Board Manager URLs - Go to Tools → Board → Boards Manager and install "esp32"
- Install required libraries:
- Go to Sketch → Include Library → Manage Libraries
- Install: "Adafruit BME280 Library", "Adafruit SSD1306", "Adafruit GFX Library"
- Upload the code:
- Select your ESP32 board (Tools → Board → ESP32 Dev Module)
- Select the correct COM port
- Upload the sketch
3. Testing
- Open the Serial Monitor (115200 baud rate)
- You should see sensor readings every 2 seconds
- The OLED display should show current weather data
Features
Current Features
- Real-time sensor readings every 2 seconds
- OLED display showing temperature, humidity, pressure, and altitude
- Serial monitor output for debugging
- Error handling for sensor connectivity issues
Possible Enhancements
- WiFi connectivity for web-based monitoring
- Data logging to SD card or cloud
- Weather forecasting based on pressure trends
- Alerts for extreme weather conditions
- Battery power with sleep modes for portable use
- Web server to view data remotely
- Historical data graphs
- Multiple sensor locations (indoor/outdoor)
Troubleshooting
Common Issues
- OLED not displaying: Check I2C address (try 0x3C or 0x3D)
- BME280 not found: Check I2C address (try 0x76 or 0x77)
- Jumbled display: Check power supply and connections
- No sensor readings: Verify wiring and library installations
Verification Steps
- Use I2C scanner code to detect device addresses
- Check all solder joints and connections
- Verify power supply voltage (should be 3.3V)
- Test each component individually
Power Consumption
- ESP32: ~80mA (active), ~5µA (deep sleep)
- BMP180: ~5µA (standby), ~1000µA (measuring)
- DHT11: ~0.5mA (standby), ~1.5mA (measuring)
- OLED: ~20mA (on), ~0µA (off)
For battery operation, implement deep sleep between readings to extend battery life significantly. Note that DHT11 requires longer wake times due to its slower response.
Enclosure Ideas
- 3D printed weather-resistant case
- Clear acrylic case for indoor use
- Ventilated enclosure for accurate readings
- Wall-mounted or desktop versions
This weather station provides a solid foundation for environmental monitoring and can be easily expanded with additional features!
Comments