ESP32 Weather Station with ESPHome: Temperature, Rain, Wind and Light

Build an ESP32 weather station with ESPHome and Home Assistant using BME280 temperature/humidity/pressure, BH1750 light, tipping-bucket rain, anemometer pulses and an analogue wind vane.

An ESP32 and ESPHome can build a surprisingly complete local weather station without writing a custom Arduino application. A practical design can measure temperature, humidity, barometric pressure, rainfall, wind speed, wind direction and ambient light, then send every measurement directly to Home Assistant for dashboards, history and automation.

The important part is not simply connecting as many sensors as possible. Outdoor weather measurements depend heavily on sensor placement, calibration and mechanical installation. A perfect BME280 inside a hot waterproof box will give bad temperature readings; an anemometer beside a wall will report building turbulence rather than useful wind; and a tipping-bucket gauge that is not level will under-read rain.

This guide builds the station as a modular ESPHome project:

BME280       → temperature + humidity + pressure
BH1750       → illuminance
Anemometer   → wind-speed pulses
Wind vane    → analogue direction
Tipping bucket → rain pulses
ESP32        → ESPHome → Home Assistant

Recommended Weather Station Hardware

MeasurementSuggested sensor/interfaceESP32 connection
TemperatureBME280 or dedicated SHT sensorI²C
HumidityBME280 or SHT4xI²C
PressureBME280/BMP280I²C
IlluminanceBH1750I²C
Wind speedReed/Hall pulse anemometerDigital pulse input
Wind directionResistor-ladder wind vaneADC input
RainfallTipping-bucket gaugeDigital pulse input

A classic ESP32-WROOM DevKit is a good controller because it has several ADC-capable pins, hardware pulse counting, mature ESPHome support and enough GPIO for a complete station.

Why BME280 Is a Good Weather-Station Sensor

BME280 combines three useful weather values on one I²C device:

  • Temperature.
  • Relative humidity.
  • Barometric pressure.

Current ESPHome supports BME280 over either I²C or SPI and operates it in forced mode: the sensor wakes for a measurement and then returns to sleep until the next update.

A simple outdoor configuration is:

i2c:
  sda: GPIO21
  scl: GPIO22
  scan: true

sensor:
  - platform: bme280_i2c
    address: 0x76

    temperature:
      name: "Outdoor Temperature"
      id: outdoor_temperature

    humidity:
      name: "Outdoor Humidity"
      id: outdoor_humidity

    pressure:
      name: "Atmospheric Pressure"
      id: atmospheric_pressure

    update_interval: 30s

Some modules use I²C address 0x77, so check the ESPHome I²C scan if the device is not found.

For the sensor differences and the common fake/mislabeled-module problem, see our BMP280 vs BME280 comparison and ESP32 BME280 wiring guide.

Do Not Put the BME280 Inside the Main Electronics Box

This is one of the easiest ways to ruin an otherwise good station.

The ESP32 and voltage regulator produce heat. A sealed enclosure also traps warm air and blocks ambient humidity exchange. The result is typically:

Temperature → too high
Relative humidity → too low
Daily temperature peaks → exaggerated

Mount the climate sensor in a separate ventilated radiation shield. Keep direct sun and rain off the sensor while still allowing free airflow.

Pressure sensing is less sensitive to radiation than temperature, but the enclosure must still communicate with ambient atmospheric pressure.

Add BH1750 Ambient Light

BH1750 is a convenient digital illuminance sensor and shares the same I²C bus as BME280.

sensor:
  - platform: bh1750
    name: "Outdoor Illuminance"
    id: outdoor_illuminance
    address: 0x23
    update_interval: 30s

ESPHome’s current BH1750 component defaults to address 0x23; pulling the sensor’s address pin high typically selects 0x5C.

Illuminance is useful for more than a graph. Home Assistant can use it for:

  • Outdoor-light automation.
  • Awning/shutter decisions.
  • Detecting very dark storm conditions.
  • Comparing sunny/cloudy periods.

A BH1750 is an illuminance sensor, not a calibrated solar-radiation pyranometer. Lux should not be relabelled as W/m² without a properly characterised optical conversion.

BH1750 Outdoor Mounting

The sensor should see ambient light but remain protected from water. A transparent cover changes the optical response, especially if the material yellows or has strong spectral filtering.

For home automation, this is normally acceptable after comparing the installed sensor against expected daylight levels. For scientific solar measurements, use an instrument designed for that purpose.

Wind Speed with a Pulse Anemometer

Many inexpensive cup anemometers contain a reed switch or Hall sensor that generates pulses as the cups rotate.

ESPHome’s pulse_counter component is a good fit. On supported ESP32 variants it can use the hardware pulse counter peripheral, which makes pulse measurement accurate without relying on slow Home Assistant updates.

sensor:
  - platform: pulse_counter
    pin:
      number: GPIO27
      mode:
        input: true
        pullup: true

    id: wind_pulse_rate
    name: "Wind Pulse Rate"

    count_mode:
      rising_edge: INCREMENT
      falling_edge: DISABLE

    update_interval: 10s

The raw pulse-counter value is useful for commissioning, but it is not yet wind speed.

Wind Speed Must Be Calibrated for Your Anemometer

There is no universal conversion from pulses to km/h or m/s. Depending on the instrument:

  • One revolution may create one pulse.
  • One revolution may create two or more pulses.
  • The manufacturer may specify Hz per m/s.
  • The output may already be internally calibrated.

ESPHome’s pulse counter reports a rate based on detected pulses. Apply the manufacturer’s conversion factor only after confirming how the instrument is specified.

Conceptually:

wind speed =
measured pulse rate × manufacturer calibration factor

Do not copy a random conversion constant from another weather-station kit simply because the anemometers look similar.

Our ESPHome pulse_meter vs pulse_counter guide explains the difference between frequency-style rate measurement and accumulated pulse totals.

Debounce the Wind Sensor Carefully

A mechanical reed switch can bounce and create several electrical edges from one physical closure. Too little filtering over-reads wind; too much filtering loses genuine high-speed pulses.

Use the anemometer’s maximum expected pulse frequency to calculate a sensible debounce/filter limit rather than choosing an arbitrary large delay.

Wind Direction with an Analogue Wind Vane

Many hobby weather-station wind vanes contain a resistor ladder. Different vane positions connect different resistance combinations, producing a set of discrete voltages through an external divider.

Connect the divided signal to a suitable ESP32 ADC pin, for example GPIO34 on the classic ESP32:

sensor:
  - platform: adc
    pin: GPIO34
    id: wind_vane_voltage
    name: "Wind Vane Voltage"
    attenuation: auto
    update_interval: 2s
    entity_category: diagnostic

    filters:
      - median:
          window_size: 7
          send_every: 3

Current ESPHome supports ADC measurements directly on variant-specific ADC pins. Use attenuation: auto only when the voltage range is compatible with the selected ESP32 and never feed 5 V directly into a 3.3 V ADC.

Calibrate Wind Direction from Measured Voltages

Do not assume every eight- or sixteen-position vane has the same resistor ladder.

Commission it manually:

  1. Point the vane exactly north.
  2. Record the filtered ADC voltage.
  3. Repeat for NE, E, SE, S, SW, W and NW—or every supported position.
  4. Create voltage windows midway between neighbouring measured values.
  5. Publish both the numeric bearing and a text compass direction if useful.

Keep the raw ADC voltage as a diagnostic entity. If the vane later reports the wrong direction, you can immediately see whether the electrical reading has drifted.

Tipping-Bucket Rain Gauge

A tipping-bucket gauge collects rain through a funnel. When one side of a small calibrated bucket fills, it tips, triggers a reed switch and exposes the other bucket.

rain
  ↓
funnel
  ↓
calibrated bucket
  ↓
tip
  ↓
reed-switch pulse
  ↓
ESP32

Each physical tip corresponds to a fixed rainfall depth determined by the gauge geometry. Common gauges may be 0.1 mm, 0.2 mm, 0.254 mm, 0.2794 mm or another value per tip. Use the value for your actual gauge.

Simple Rain Pulse Input

For a gauge specified as an example 0.2 mm per tip, the principle is:

10 tips × 0.2 mm = 2.0 mm rain

A pulse input can count the tips, then ESPHome/Home Assistant converts the count to millimetres.

Use hardware/software debounce appropriate to the reed switch. Rain gauges produce slow pulses, so rejecting switch bounce is generally much easier than on a fast anemometer.

Our dedicated Tipping-Bucket Rain Gauge with ESP32, ESPHome and Home Assistant guide in this article batch will cover persistent totals, rain-rate calculation and calibration in more detail.

Why Rain Total and Rain Rate Are Different

Rainfall total answers:

How many millimetres fell today?

Rain rate answers:

How intense is the rain right now?

A burst of two bucket tips in one minute can indicate heavy rain even if the day’s total is still small. Conversely, 10 mm accumulated slowly over many hours can have a low instantaneous rain rate.

Keep both measurements as separate Home Assistant entities.

Complete ESPHome Skeleton

esphome:
  name: garden-weather-station
  friendly_name: Garden Weather Station

esp32:
  board: esp32dev
  framework:
    type: esp-idf

logger:

api:
  encryption:
    key: !secret api_encryption_key

ota:
  - platform: esphome
    password: !secret ota_password

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password

i2c:
  sda: GPIO21
  scl: GPIO22
  scan: true

sensor:
  - platform: bme280_i2c
    address: 0x76
    temperature:
      name: "Outdoor Temperature"
    humidity:
      name: "Outdoor Humidity"
    pressure:
      name: "Atmospheric Pressure"
    update_interval: 30s

  - platform: bh1750
    address: 0x23
    name: "Outdoor Illuminance"
    update_interval: 30s

  - platform: pulse_counter
    pin:
      number: GPIO27
      mode:
        input: true
        pullup: true
    name: "Wind Pulse Rate"
    id: wind_pulse_rate
    update_interval: 10s
    count_mode:
      rising_edge: INCREMENT
      falling_edge: DISABLE

  - platform: adc
    pin: GPIO34
    name: "Wind Vane Voltage"
    id: wind_vane_voltage
    attenuation: auto
    update_interval: 2s
    filters:
      - median:
          window_size: 7
          send_every: 3

This is the starting framework. Add the manufacturer-specific wind conversion and rain-tip conversion only after the physical sensors have been identified and tested.

Add Wi-Fi Diagnostics

An outdoor weather station may be near the edge of Wi-Fi coverage. Add diagnostics before blaming sensor wiring for missing data:

sensor:
  - platform: wifi_signal
    name: "Weather Station WiFi RSSI"
    update_interval: 60s
    entity_category: diagnostic

  - platform: uptime
    name: "Weather Station Uptime"
    entity_category: diagnostic

If the station randomly disappears, use our ESPHome Wi-Fi Disconnects troubleshooting guide before changing the weather-sensor code.

Outdoor Power

A fixed station can use:

  • Low-voltage cable from an indoor PSU.
  • PoE with a suitable converter.
  • Solar panel + rechargeable battery.

For a permanent outdoor installation, mains voltage should remain indoors or inside equipment/enclosures specifically designed and installed for that environment. Running 5–12 V SELV to the station is generally much easier to make safe and weather-resistant.

Solar Weather Station Considerations

A solar station is possible, but continuous Wi-Fi usually dominates the power budget.

Options include:

  • Keep the ESP32 awake continuously for instant wind/rain updates and size the battery/solar panel accordingly.
  • Use light sleep rather than deep sleep so pulse counting remains practical.
  • Use a separate ultra-low-power pulse counter/wake circuit if very long battery life is required.
  • Separate slow climate sampling from always-on rain/wind pulse measurement.

A station that must record every rain tip cannot simply sleep for 30 minutes with all pulse inputs inactive.

Weatherproofing the Electronics

The ESP32, regulator and terminals belong inside a proper weather-resistant enclosure. Use:

  • Cable glands.
  • Drip loops.
  • Corrosion-resistant connectors.
  • Strain relief.
  • Condensation management.
  • Surge/transient consideration on long outdoor cables.

A waterproof enclosure can still collect condensation internally when temperature changes. Mount cable entries thoughtfully and avoid placing an exposed PCB at the lowest point where water can collect.

Sensor Placement Is the Biggest Accuracy Factor

SensorBad locationBetter location
Temperature/humidityInside sealed sunny boxVentilated radiation shield
Rain gaugeUnder roof/treeLevel, open sky
AnemometerBeside wall/fenceClear mast with minimal obstruction
Wind vaneUnaligned mountingPhysically aligned to true/local reference north
BH1750Permanent shadow from enclosureConsistent open-light exposure

Moving a wind sensor away from a wall can improve real-world usefulness more than changing from an inexpensive to an expensive sensor.

Calibrate the Rain Gauge

Even if the manufacturer specifies a millimetres-per-tip value, verify it mechanically.

  1. Make sure the gauge is level.
  2. Measure a known volume of water.
  3. Introduce it slowly enough for the bucket mechanism to operate normally.
  4. Count the registered tips.
  5. Compare the calculated rainfall with the collector area/gauge specification.
  6. Adjust the conversion factor if the gauge provides mechanical calibration screws.

Pouring water too quickly can overwhelm the tipping mechanism and produce a meaningless calibration result.

Calibrate Wind Direction After Final Installation

Bench-testing the vane is not enough. The mast or sensor head must also be physically aligned.

If the north reference is mounted 15° clockwise from north, every direction reported by the electronics will be wrong by roughly 15° even though the ADC decoding is perfect.

Home Assistant Dashboard

A useful dashboard should show both current conditions and trends:

  • Outdoor temperature.
  • Humidity.
  • Barometric pressure and 24-hour trend.
  • Current wind speed.
  • Recent maximum/gust value.
  • Wind direction.
  • Today’s rain.
  • Current rain rate.
  • Illuminance.
  • Weather-station RSSI and uptime in a diagnostic section.

Long-term pressure and rainfall history is usually more useful than a dashboard full of rapidly changing raw readings.

Useful Home Assistant Automations

Once the station is reliable, its measurements can feed practical automation.

Weather conditionPossible automation
Rain startsClose roof window / stop irrigation
High windRetract awning
Low outdoor lightEnable exterior lighting
Very high temperatureClose shutters / notify
Rain in last 24hSkip garden watering
Rapid pressure fallDashboard/weather alert context

For physical protection such as awning retraction, design sensible failsafes and do not depend on one hobby sensor as the only safety mechanism in severe weather.

Integrate with Smart Irrigation

The weather station fits naturally with our ESP32 Smart Irrigation Controller.

Instead of relying only on an internet forecast, Home Assistant can know:

  • Whether it is raining now.
  • How many millimetres actually fell today.
  • Whether soil is already wet.
  • Recent temperature/light conditions.

Combine those with the capacitive soil-moisture sensor guide to make the watering decision from local data.

Common Problems

SymptomLikely cause / first check
Outdoor temperature always too highSensor heated by sun/ESP32/enclosure
Humidity looks consistently lowTemperature bias or poor ventilation
Pressure works but no humidityModule may actually be BMP280
Wind speed is exactly 2× expectedWrong pulses-per-revolution/calibration factor
Wind direction jumps between sectorsADC noise; add filtering and better voltage windows
Rain total is far too highReed-switch bounce counted as multiple tips
Rain total is lowGauge not level, blocked funnel or missed pulses
BH1750 saturates/looks wrong outdoorsOptical cover, orientation or sensor range
Station disappears during stormsPower/surge/Wi-Fi/enclosure moisture issue
Wind vane directions all offsetPhysical north alignment error

Recommended Build Order

  1. Bench-test ESP32, Wi-Fi and OTA.
  2. Add BME280 and verify climate values.
  3. Add BH1750 on the same I²C bus.
  4. Test wind pulse input by manually rotating the anemometer.
  5. Record every wind-vane ADC position.
  6. Test rain-gauge tips manually.
  7. Add pulse debounce/filtering.
  8. Install sensors outdoors.
  9. Recalibrate wind orientation and rain gauge after installation.
  10. Only then use the measurements for Home Assistant automations.

Final Recommendation

For a practical ESP32 weather station, start with a reliable core rather than trying to make every possible measurement on day one:

BME280 → temperature / humidity / pressure
BH1750 → light
Pulse counter → anemometer
ADC → wind vane
Pulse input → tipping-bucket rain

ESPHome already provides the building blocks. The quality of the finished weather station comes from mechanical installation and calibration: ventilate the climate sensor, level the rain gauge, place the wind sensors in clean airflow and measure the actual conversion constants of the hardware you bought.

Once that foundation is correct, Home Assistant becomes an excellent front end for weather history, irrigation decisions, awning protection, lighting automation and local outdoor-condition dashboards.

Related Weather and Sensor Guides

Official ESPHome Resources

Share your love