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
| Measurement | Suggested sensor/interface | ESP32 connection |
|---|---|---|
| Temperature | BME280 or dedicated SHT sensor | I²C |
| Humidity | BME280 or SHT4x | I²C |
| Pressure | BME280/BMP280 | I²C |
| Illuminance | BH1750 | I²C |
| Wind speed | Reed/Hall pulse anemometer | Digital pulse input |
| Wind direction | Resistor-ladder wind vane | ADC input |
| Rainfall | Tipping-bucket gauge | Digital 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:
- Point the vane exactly north.
- Record the filtered ADC voltage.
- Repeat for NE, E, SE, S, SW, W and NW—or every supported position.
- Create voltage windows midway between neighbouring measured values.
- 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
| Sensor | Bad location | Better location |
|---|---|---|
| Temperature/humidity | Inside sealed sunny box | Ventilated radiation shield |
| Rain gauge | Under roof/tree | Level, open sky |
| Anemometer | Beside wall/fence | Clear mast with minimal obstruction |
| Wind vane | Unaligned mounting | Physically aligned to true/local reference north |
| BH1750 | Permanent shadow from enclosure | Consistent 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.
- Make sure the gauge is level.
- Measure a known volume of water.
- Introduce it slowly enough for the bucket mechanism to operate normally.
- Count the registered tips.
- Compare the calculated rainfall with the collector area/gauge specification.
- 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 condition | Possible automation |
|---|---|
| Rain starts | Close roof window / stop irrigation |
| High wind | Retract awning |
| Low outdoor light | Enable exterior lighting |
| Very high temperature | Close shutters / notify |
| Rain in last 24h | Skip garden watering |
| Rapid pressure fall | Dashboard/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
| Symptom | Likely cause / first check |
|---|---|
| Outdoor temperature always too high | Sensor heated by sun/ESP32/enclosure |
| Humidity looks consistently low | Temperature bias or poor ventilation |
| Pressure works but no humidity | Module may actually be BMP280 |
| Wind speed is exactly 2× expected | Wrong pulses-per-revolution/calibration factor |
| Wind direction jumps between sectors | ADC noise; add filtering and better voltage windows |
| Rain total is far too high | Reed-switch bounce counted as multiple tips |
| Rain total is low | Gauge not level, blocked funnel or missed pulses |
| BH1750 saturates/looks wrong outdoors | Optical cover, orientation or sensor range |
| Station disappears during storms | Power/surge/Wi-Fi/enclosure moisture issue |
| Wind vane directions all offset | Physical north alignment error |
Recommended Build Order
- Bench-test ESP32, Wi-Fi and OTA.
- Add BME280 and verify climate values.
- Add BH1750 on the same I²C bus.
- Test wind pulse input by manually rotating the anemometer.
- Record every wind-vane ADC position.
- Test rain-gauge tips manually.
- Add pulse debounce/filtering.
- Install sensors outdoors.
- Recalibrate wind orientation and rain gauge after installation.
- 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
- BMP280 vs BME280 — choosing the right Bosch pressure/environment sensor.
- ESP32 BME280 Wiring + ESPHome — detailed BME280 setup.
- ESPHome pulse_meter vs pulse_counter — pulse rate and total counting.
- ESP32 Smart Irrigation Controller — use local rain/weather data for watering decisions.
- Capacitive Soil Moisture with ESPHome — combine soil and weather data.
Official ESPHome Resources
- ESPHome BME280 — temperature, pressure and humidity over I²C/SPI.
- ESPHome BH1750 — digital illuminance sensor.
- ESPHome Pulse Counter — hardware pulse counting on ESP32.
- ESPHome ADC Sensor — analogue wind-vane inputs.