Temperature, Humidity and Atmospheric Pressure Sensor (BME280) - Outdoor [RUA]

Project Overview

The Outdoor Environmental Sensor Project is a low-power autonomous system designed to monitor temperature, relative humidity, and atmospheric pressure in an outdoor environment. The system prioritizes energy efficiency, reliability, and long-term autonomy, making it suitable for continuous operation using standard AA batteries.

An ESP32 microcontroller collects data from a BME280 sensor, transmits the measurements via Wi-Fi to a Raspberry Pi, and immediately enters deep sleep mode to minimize power consumption. The Raspberry Pi stores, processes, and exposes the data through a web-based interface. You can see here: https://joelbonifacio.dynip.sapo.pt/electro6.1.html

Hardware Components
  • DFRobot FireBeetle 2 ESP32-C6 Module;
  • DFRobot SEN0236 - BME280 - Environmental Sensor (Connected via SPI mode);
  • Raspberry Pi 4;
  • 3 × AA Alkaline Batteries (2500 mAh);
  • Outdoor weather-resistant enclosure for testing.

Fig.1 - Materials: ESP32, BME280, batteries, support for the batteries and cables.

BME280 Technical Specifications
ParameterValue
Temperature Range-40 °C to +85 °C
Temperature Accuracy±1.0 °C
Humidity Range0 – 100 % RH
Humidity Accuracy±3 % RH
Response Time1 second
Hysteresis±1% RH
Pressure Range300 – 1100 hPa
Absolute Accuracy±1 hPa
Relative Accuracy±0.12 hPa (equivalent to ±1 meter in altitude)
RMS Noise0.2 Pa
Communication InterfaceSPI
Operating Voltage3.3 V
Communication InterfaceI2C (Gravity Connector) or SPI
ESP32 ↔ BME280 Wiring Diagram (SPI)
ESP32 BME280 (SPI) GPIO 14 GND GPIO 18 (SCK) GPIO 23 (MOSI) GPIO 19 (MISO) GPIO 21 (CS) VCC GND SCK SDI SDO CS
FireBeetle 2 ESP32-C6 Firmware (Low Power Mode + SPI)



// ----- CONFIGURAÇÃO HARDWARE -----
// O fio VCC do sensor BME280 liga AQUI, e não nos 3.3V fixos.
// Isto permite desligar o sensor e o LED vermelho completamente.

#define SENSOR_POWER_PIN 14 
#define BME_CS 21 
#define SPI_SCK 18
#define SPI_MISO 19
#define SPI_MOSI 23

Adafruit_BME280 bme(BME_CS);

// ----- CONFIGURAÇÃO WIFI (IP ESTÁTICO) -----
const char* ssid = 
const char* password = 

// Configurações de Rede Fixa
IPAddress local_IP(); 
IPAddress gateway();  
IPAddress subnet();
IPAddress primaryDNS();     

const char* serverURL = ;

// ----- SLEEP -----
const uint64_t SLEEP_MINUTES = 15;
const uint64_t SLEEP_MICROS = SLEEP_MINUTES * 60ULL * 1000000ULL;

void setup() {
  // Serial.begin(115200); // Descomentar apenas para testes. Em produção, desligar poupa tempo.

  // ------------------------------------------------
  // PASSO 1: LIGAR E LER O SENSOR (O Wi-Fi ainda está desligado!)
  // ------------------------------------------------
  pinMode(SENSOR_POWER_PIN, OUTPUT);
  digitalWrite(SENSOR_POWER_PIN, HIGH); // LIGAR O SENSOR E O LED VERMELHO
  delay(10); // Esperar 10ms para o sensor arrancar

  SPI.begin(SPI_SCK, SPI_MISO, SPI_MOSI);
  
  if (!bme.begin(BME_CS)) {
    // Se o sensor falhar, vamos dormir logo para não gastar bateria
    goToSleep();
  }

  // Configurar para ler apenas 1 vez (Forced Mode)
  bme.setSampling(Adafruit_BME280::MODE_FORCED,
                  Adafruit_BME280::SAMPLING_X1,
                  Adafruit_BME280::SAMPLING_X1,
                  Adafruit_BME280::SAMPLING_X1,
                  Adafruit_BME280::FILTER_OFF);

  bme.takeForcedMeasurement(); // Medição instantânea
  float temp = bme.readTemperature();
  float hum = bme.readHumidity();
  float pres = bme.readPressure() / 100.0F;

  // *** POUPANÇA CRÍTICA ***
  // Desligamos o sensor e o LED vermelho AGORA.
  // Eles não gastam energia enquanto o Wi-Fi conecta.
  digitalWrite(SENSOR_POWER_PIN, LOW); 
  
  // ------------------------------------------------
  // PASSO 2: CONECTAR WI-FI
  // ------------------------------------------------
  WiFi.mode();
  WiFi.config(); 
  WiFi.begin();

  // Timeout curto (10s). Se não der, desiste.
  int wifiTimeout = 20; 
  while (WiFi.status() != WL_CONNECTED && wifiTimeout > 0) {
    delay(500);
    wifiTimeout--;
  }

  if (WiFi.status() == WL_CONNECTED) {
    // ------------------------------------------------
    // PASSO 3: ENVIAR DADOS
    // ------------------------------------------------
    StaticJsonDocument<200> doc;
    doc["temperature"] = temp;
    doc["humidity"] = hum;
    doc["pressure"] = pres;
    
    String json;
    serializeJson(doc, json);
    
    int response = http.POST(json);
    http.end();
  }

  // ------------------------------------------------
  // PASSO 4: DORMIR
  // ------------------------------------------------
  goToSleep();
}

void goToSleep() {
  // Desliga Wi-Fi explicitamente
  WiFi.disconnect(true);
  WiFi.mode(WIFI_OFF);
  esp_sleep_enable_timer_wakeup(SLEEP_MICROS);
  esp_deep_sleep_start();
}


void loop() {
  // Não é necessário usar loop, porque o ESP32 acorda sozinho do deep sleep
}

Fig.2 - FireBeetle 2 ESP32-C6 partial code.

.

Python Services on Raspberry Pi
  • Flask API for data ingestion;
  • SQLite database logger;
  • Data aggregation and statistics.
Apache Reverse Proxy (XXXX.conf)

Apache is configured as a reverse proxy to forward /api/rua requests to the internal Flask service. This isolates backend services and provides clean, stable URLs for the frontend.

Power Consumption Analysis

Project: Sensor Sala

Technical Power Consumption & Battery Life Report

This report details the energy efficiency optimizations for the outdoor BME280 sensor unit. Powered by a FireBeetle 2 ESP32-C6 and a 3-cell NiMH battery pack (2500mAh total).

Total Capacity 2500 mAh
Usable Energy (85%) 2125 mAh
Reading Interval 15 Minutes
Nominal Voltage 3.6 V

1. Consumption Profile (Per Cycle)

Strategic optimizations include Static IP for faster handshakes and GPIO Power Gating to kill the sensor's parasitic LED during sleep.

Operating Phase Duration Current Draw
Hardware Wake & Sensing (GPIO 27 Active) 0.2 s 30 mA
WiFi Transmission (Static IP Handshake) 2.5 s 180 mA
Deep Sleep Mode (Ultra-low power) 897.3 s 0.025 mA

2. Energy Calculations

We measure the energy cost of one full 900-second (15 min) cycle in milliampere-seconds (mAs):

Cost_Sensing = 30mA * 0.2s = 6.0 mAs
Cost_WiFi = 180mA * 2.5s = 450.0 mAs
Cost_Sleep = 0.025mA * 897.3s = 22.4 mAs
------------------------------------------
Total Cost Per Cycle = 478.4 mAs

Average continuous current consumption:

Average Current = 478.4 mAs / 900 s = 0.53 mA

3. Battery Life Estimation

Based on the usable capacity of 2125 mAh:

Total Hours = 2125 mAh / 0.53 mA = 4009 hours
Theoretical Days = 4009 / 24 = 167 Days

Real-World Expected Autonomy

Adjusted for battery self-discharge (NiMH characteristic) and efficiency losses in the voltage regulator (30% Safety Factor):

~116 Days

Previous autonomy was 3.7 days. The current implementation provides a 3000% improvement in battery performance.

Using 3 AA Batteries Instead of 4 Batteries AA

Using 3 AA alkaline batteries provide an initial voltage of approximately 4.5 V, which is safely handled by the ESP32 onboard regulator. Usar 4 baterias elevaria a tensão para 6V, excedendo a gama ideal do regulador e aumentando a dissipação térmica.

SPI Was Mandatory Instead of I²C

During development, the use of I²C combined with active Wi-Fi on the ESP32 caused intermittent communication failures and bus lockups. Migrating the BME280 to SPI provided a dedicated, synchronous communication channel, fully eliminating the instability.

Outdoor Weather-Resistant Enclosure For Testing

I bought a waterproof box and made some minor modifications to adapt it to this project. It has two large holes in the bottom for ventilation, and right above them is the BME280 sensor. The goal is to prevent water from entering, especially since it's windy and raining heavily here (which is quite common), but at the same time, to avoid interfering with the sensor readings. I also put a very fine green mesh to prevent insects from getting in and covering the sensor hole. Now it will be screwed to the outside wall of the house.

P.S. - It will not be exposed directly to sun/rain.

This is the final result:

Fig.3 - Outdoor weather-resistant enclosure I.

Fig.4 - Outdoor weather-resistant enclosure II.

Fig.5 - Outdoor weather-resistant enclosure III.

Fig.6 - Outdoor weather-resistant enclosure IV.

Fig.7 - Outdoor weather-resistant enclosure on the wall below the balcony.

Vented Radiation Shield Implementation

You can see more in the Solidworks section.

Leave A Comment