Pressure Sensor Code with Forecasting
📊 Pressure Sensor Code with Weather Forecasting - Predict Rain 24 Hours in Advance
📊 What You'll Learn:
- 🌡️ Measure barometric pressure using BMP280/BME280 sensor
- 📈 Calculate pressure trends to predict weather 12-48 hours in advance
- 🌧️ Detect approaching storms from rapid pressure drops
- ☀️ Generate automatic weather forecasts from sensor data
Barometric pressure is the most reliable indicator of upcoming weather. A falling pressure means rain is coming. A rapid drop means a storm is approaching. This lesson teaches you to read pressure trends and generate your own forecasts - no internet required!
📊 Pressure Trend Interpretation Guide
| 3-Hour Trend (hPa) | Meaning | Weather Forecast | Farm Action |
|---|---|---|---|
| > +3.0 hPa | Rapidly Rising | ☀️ Clearing - high pressure moving in | Good for harvesting, spraying |
| +1.0 to +3.0 hPa | Rising | 🌤️ Improving - weather getting better | Plan outdoor work |
| -1.0 to +1.0 hPa | Stable | ☁️ No change - current conditions continue | Normal operations |
| -3.0 to -1.0 hPa | Falling | 🌧️ Worsening - rain likely in 12-24 hours | Reduce irrigation, prepare for rain |
| < -3.0 hPa | Rapidly Falling | ⛈️ Storm approaching! Rain within 6-12 hours | 🚨 Emergency: Secure equipment, skip irrigation |
Short-term fluctuations (1-hour trends) can be noisy. The 3-hour trend is more reliable for forecasting. A consistent drop over 3+ hours is a strong indicator of approaching bad weather. For storm warnings, also check the rate of drop - faster drop = more severe storm.
🔌 BMP280/BME280 Wiring
═══════════════════════════════════════════════════════════════════════════════
BMP280 / BME280 WIRING (I2C)
═══════════════════════════════════════════════════════════════════════════════
BMP280/BME280 Sensor ESP32 Dev Board
══════════════════════ ══════════════════
VCC (3.3V/5V) ──────────► 3.3V
GND ──────────► GND
SDA ──────────► GPIO21 (I2C SDA)
SCL ──────────► GPIO22 (I2C SCL)
Address options:
- Connect SDO to GND → Address 0x76 (most common)
- Connect SDO to 3.3V → Address 0x77
⚠️ BME280 includes humidity sensor (BMP280 = pressure only)
Both work with same code - BME280 gives extra humidity data
═══════════════════════════════════════════════════════════════════════════════
📖 Complete Pressure Weather Station Code
/*
* Complete Barometric Pressure Weather Station
* Predicts weather using pressure trends
* BMP280/BME280 sensor with 24-hour memory
*
* Features:
* - Real-time pressure readings
* - 1h, 3h, 6h, 12h, 24h pressure trends
* - Weather forecasting without internet
* - Storm warnings and alerts
*/
#include <Wire.h>
#include <Adafruit_BMP280.h>
#include <WiFi.h>
#include <HTTPClient.h>
// ========== SENSOR CONFIGURATION ==========
#define I2C_SDA 21
#define I2C_SCL 22
#define BMP280_ADDRESS 0x76 // Or 0x77
Adafruit_BMP280 bmp;
// ========== DATA STORAGE ==========
const int MAX_READINGS = 48; // 48 hours at 1 reading per hour
float pressureHistory[MAX_READINGS];
float temperatureHistory[MAX_READINGS];
float humidityHistory[MAX_READINGS]; // Only for BME280
int readingIndex = 0;
int readingCount = 0;
// ========== STATISTICS ==========
float pressureMin = 9999;
float pressureMax = 0;
float pressureAvg = 0;
float pressureTrend1h = 0;
float pressureTrend3h = 0;
float pressureTrend6h = 0;
float pressureTrend12h = 0;
float pressureTrend24h = 0;
unsigned long lastReading = 0;
const unsigned long READING_INTERVAL = 3600000; // 1 hour
// ========== ALTITUDE CORRECTION ==========
float stationAltitude = 0; // meters above sea level (0 for sea level)
// ========== WIFI (Optional) ==========
const char* ssid = "YOUR_WIFI";
const char* password = "YOUR_PASSWORD";
// ========== ADD PRESSURE READING ==========
void addPressureReading(float pressure, float temp, float humidity) {
pressureHistory[readingIndex] = pressure;
temperatureHistory[readingIndex] = temp;
if (humidity >= 0) humidityHistory[readingIndex] = humidity;
readingIndex = (readingIndex + 1) % MAX_READINGS;
if (readingCount < MAX_READINGS) readingCount++;
// Update statistics
if (pressure < pressureMin) pressureMin = pressure;
if (pressure > pressureMax) pressureMax = pressure;
// Calculate average
pressureAvg = 0;
for (int i = 0; i < readingCount; i++) {
pressureAvg += pressureHistory[i];
}
pressureAvg = pressureAvg / readingCount;
}
// ========== CALCULATE PRESSURE TREND ==========
float calculateTrend(int hours) {
if (readingCount < hours) return 0;
int currentIdx = (readingIndex - 1 + MAX_READINGS) % MAX_READINGS;
int pastIdx = (readingIndex - 1 - hours + MAX_READINGS) % MAX_READINGS;
float currentPressure = pressureHistory[currentIdx];
float pastPressure = pressureHistory[pastIdx];
return (currentPressure - pastPressure) / hours; // hPa per hour
}
// ========== UPDATE ALL TRENDS ==========
void updateTrends() {
if (readingCount < 2) return;
pressureTrend1h = calculateTrend(1);
pressureTrend3h = calculateTrend(3);
pressureTrend6h = calculateTrend(6);
pressureTrend12h = calculateTrend(12);
pressureTrend24h = calculateTrend(24);
}
// ========== WEATHER FORECAST GENERATOR ==========
String generateForecast() {
float trend = pressureTrend3h; // 3-hour trend is most reliable
if (trend > 2.5) {
return "☀️ Clearing rapidly - High pressure moving in. Great weather ahead!";
} else if (trend > 1.0) {
return "🌤️ Improving conditions - Becoming sunnier. Good for outdoor work.";
} else if (trend > -1.0) {
return "☁️ Steady conditions - Current weather will continue.";
} else if (trend > -2.5) {
return "🌧️ Deteriorating - Rain likely within 12-24 hours. Reduce irrigation.";
} else {
return "⛈️ Storm approaching! Rapid pressure drop. Heavy rain likely within 6-12 hours. Take precautions!";
}
}
// ========== CHECK FOR STORM WARNING ==========
int getStormWarning() {
// Returns severity: 0=none, 1=watch, 2=warning, 3=emergency
if (pressureTrend3h < -4.0) return 3; // Emergency - severe storm
if (pressureTrend3h < -3.0) return 2; // Warning - storm approaching
if (pressureTrend3h < -2.0 && pressureTrend24h < -5.0) return 1; // Watch
return 0;
}
// ========== FROST WARNING ==========
bool checkFrostRisk(float temperature) {
if (temperature < 3.0 && pressureTrend3h > 1.0) {
return true; // Clear, cold night = frost risk
}
return false;
}
// ========== READ SENSORS ==========
void readSensors() {
float pressure = bmp.readPressure() / 100.0F; // Convert Pa to hPa
float temperature = bmp.readTemperature();
// Optional: BME280 humidity reading
// float humidity = bme.readHumidity();
float humidity = -1; // Placeholder for BMP280
// Altitude correction (if needed)
if (stationAltitude > 0) {
pressure = pressure + (stationAltitude / 8.4);
}
addPressureReading(pressure, temperature, humidity);
}
// ========== DISPLAY PRESSURE REPORT ==========
void displayReport() {
Serial.println("\n╔══════════════════════════════════════════════════════════════╗");
Serial.println("║ 📊 BAROMETRIC REPORT ║");
Serial.println("╚══════════════════════════════════════════════════════════════╝");
Serial.printf("\n📊 CURRENT PRESSURE: %.1f hPa\n", pressureHistory[(readingIndex - 1 + MAX_READINGS) % MAX_READINGS]);
Serial.printf(" 📈 3h Trend: %.1f hPa/hour\n", pressureTrend3h);
Serial.println("\n📈 PRESSURE TRENDS:");
Serial.printf(" 1-hour: %.1f hPa/hour\n", pressureTrend1h);
Serial.printf(" 3-hour: %.1f hPa/hour %s\n", pressureTrend3h,
pressureTrend3h < 0 ? "⬇️ Falling" : (pressureTrend3h > 0 ? "⬆️ Rising" : "➡️ Stable"));
Serial.printf(" 6-hour: %.1f hPa/hour\n", pressureTrend6h);
Serial.printf(" 12-hour: %.1f hPa/hour\n", pressureTrend12h);
Serial.printf(" 24-hour: %.1f hPa/hour\n", pressureTrend24h);
Serial.println("\n🌤️ WEATHER FORECAST:");
Serial.println(" " + generateForecast());
int storm = getStormWarning();
if (storm > 0) {
Serial.println("\n⚠️ STORM ALERT:");
if (storm == 3) Serial.println(" 🚨 EMERGENCY: Severe storm approaching! Take cover immediately!");
else if (storm == 2) Serial.println(" ⚠️ WARNING: Storm approaching within 12 hours! Secure equipment.");
else Serial.println(" ℹ️ WATCH: Pressure falling - monitor for worsening conditions.");
}
Serial.println("\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n");
}
// ========== CONNECT TO WIFI (Optional) ==========
void connectWiFi() {
Serial.print("📡 Connecting to WiFi");
WiFi.begin(ssid, password);
int attempts = 0;
while (WiFi.status() != WL_CONNECTED && attempts < 20) {
delay(500);
Serial.print(".");
attempts++;
}
if (WiFi.status() == WL_CONNECTED) {
Serial.println("\n✅ WiFi connected!");
} else {
Serial.println("\n⚠️ WiFi connection failed - running offline");
}
}
// ========== SETUP ==========
void setup() {
Serial.begin(115200);
delay(1000);
// Initialize I2C
Wire.begin(I2C_SDA, I2C_SCL);
// Initialize BMP280
if (!bmp.begin(BMP280_ADDRESS)) {
Serial.println("❌ BMP280 not found! Check wiring and address.");
while (1) delay(100);
}
// Configure BMP280 for weather monitoring (less noise)
bmp.setSampling(Adafruit_BMP280::MODE_NORMAL, // Normal mode
Adafruit_BMP280::SAMPLING_X2, // Temperature oversampling
Adafruit_BMP280::SAMPLING_X16, // Pressure oversampling
Adafruit_BMP280::FILTER_X16, // Filter for noise reduction
Adafruit_BMP280::STANDBY_MS_1000); // Standby time
Serial.println("========================================");
Serial.println("📊 BAROMETRIC WEATHER STATION v2.0");
Serial.println(" Pressure-based weather forecasting");
Serial.println("========================================\n");
// Optional: Connect to WiFi
// connectWiFi();
Serial.println("✅ Sensor ready! Collecting pressure data...\n");
Serial.println("💡 Tip: Need 24 hours of data for accurate trends\n");
// Take initial readings to fill buffer
for (int i = 0; i < 6; i++) {
readSensors();
updateTrends();
delay(10000);
}
}
// ========== LOOP ==========
void loop() {
unsigned long now = millis();
if (now - lastReading >= READING_INTERVAL) {
readSensors();
updateTrends();
displayReport();
// Optional: Send to OceanRemote
// sendToOceanRemote();
lastReading = now;
}
delay(1000);
}
A wheat farmer in Ethiopia used pressure trend forecasting to predict a storm:
- 📉 Pressure drop detected: -4.2 hPa in 3 hours at 8 AM
- 🌧️ Forecast generated: "Storm approaching within 12 hours"
- ⏰ Action taken: Harvested wheat 2 days early
- 💧 Result: Saved 80% of crop before hail destroyed remaining fields
"The pressure sensor warned us about the storm before local radio. We harvested early and saved our crop." - Wheat Farmer, Ethiopia
- 📍 Need 24 hours of data: Trends become accurate after a full day of readings
- 📍 Watch the acceleration: Pressure drop speeding up? Storm severity increasing.
- 📍 Combine with humidity: Falling pressure + rising humidity = rain confirmed
- 📍 Altitude correction: For highland farms (1,500m+), correct pressure to sea level for standard references
- 📍 Filter noise: Use oversampling (SAMPLING_X16) and filter (FILTER_X16) for stable readings
- ✅ Pressure falling (-1 to -3 hPa/3h): Rain likely in 12-24 hours → reduce irrigation
- ✅ Pressure rapidly falling (< -3 hPa/3h): Storm approaching → emergency action
- ✅ Pressure rising (+1 to +3 hPa/3h): Clearing weather → good for harvesting
- ✅ Pressure stable (±1 hPa/3h): Current conditions continue → normal operations
- ✅ BMP280/BME280 ($5-10): Affordable pressure sensor for farm forecasting
- ✅ No internet needed: Forecast from local pressure readings
- Apply these concepts directly to your farm or project.
- Take notes on important details for the quiz.
- Use the button below to track your progress.