Build a Standalone Weather Station with a Raspberry Pi and Open‑Source Sensors
Ever looked out the window and wondered why the forecast keeps missing the mark? A personal weather station lets you collect the data you actually care about, right from your backyard. Plus, it’s a great excuse to dust off that Pi you’ve been hoarding for “later.” In this post I’ll walk you through a simple, low‑cost setup that runs on a Raspberry Pi, a few open‑source sensors, and a bit of code you can tweak as you like.
What You’ll Need
The Pi
Any model that has GPIO pins will do, but I recommend a Pi 4 with at least 2 GB RAM. The extra RAM helps when you start logging data to a local database or serving a web page. If you’re tight on budget, a Pi Zero W works fine – just remember the Wi‑Fi antenna is a bit weaker.
Sensors
| Sensor | What it measures | Typical price |
|---|---|---|
| BME280 | Temperature, humidity, pressure | $8‑$12 |
| Anemometer (DIY or commercial) | Wind speed | $10‑$20 |
| Rain gauge (tipping bucket) | Rainfall amount | $5‑$10 |
| Light sensor (TSL2591) | Ambient light | $4‑$6 |
All of these have open‑source libraries for Python, which keeps the code tidy. You can start with just the BME280 and add the others later.
Other Bits
- Micro‑SD card (16 GB or more) with Raspberry Pi OS Lite
- Power supply (5 V 2.5 A for Pi 4, 5 V 1.2 A for Pi Zero)
- Small enclosure or weatherproof box – I used a recycled plastic storage bin and drilled holes for the sensors.
- Jumper wires, breadboard, and a few zip ties
Wiring the Sensors
BME280
The BME280 talks over I²C, which means you only need two wires: SDA (data) and SCL (clock). Connect SDA to GPIO 2 (pin 3) and SCL to GPIO 3 (pin 5). Power the sensor with 3.3 V (pin 1) and ground to any GND pin.
Anemometer
Most hobby anemometers output a pulse each time the cup spins. Hook the pulse wire to a GPIO pin set as input (I use GPIO 17). Add a 10 kΩ pull‑down resistor to keep the line low when there’s no pulse.
Rain Gauge
A tipping‑bucket gauge works the same way as the anemometer – each tip generates a pulse. I wired it to GPIO 27 with the same pull‑down setup.
Light Sensor
The TSL2591 also uses I²C, so you can share the SDA and SCL lines with the BME280. Just make sure each device has a unique address; the libraries handle that automatically.
Setting Up the Software
1. Install the OS
Flash Raspberry Pi OS Lite onto the SD card, boot the Pi, and run sudo raspi-config to enable I²C and SSH. I like to give the Pi a static IP so I can reach it easily from my laptop.
2. Install Python Libraries
sudo apt update
sudo apt install -y python3-pip i2c-tools
pip3 install adafruit-circuitpython-bme280 adafruit-circuitpython-tsl2591 RPi.GPIO
The RPi.GPIO library lets us count pulses from the anemometer and rain gauge.
3. Write a Simple Data Logger
Create a file called weather_station.py. Below is a stripped‑down version that reads all sensors and writes a CSV line every minute.
#!/usr/bin/env python3
import time, csv, datetime
import board, busio
import adafruit_bme280
import adafruit_tsl2591
import RPi.GPIO as GPIO
# --- GPIO setup ---
ANEMO_PIN = 17
RAIN_PIN = 27
GPIO.setmode(GPIO.BCM)
GPIO.setup(ANEMO_PIN, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
GPIO.setup(RAIN_PIN, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
# counters
wind_count = 0
rain_count = 0
def anemo_callback(channel):
global wind_count
wind_count += 1
def rain_callback(channel):
global rain_count
rain_count += 1
GPIO.add_event_detect(ANEMO_PIN, GPIO.RISING, callback=anemo_callback, bouncetime=10)
GPIO.add_event_detect(RAIN_PIN, GPIO.RISING, callback=rain_callback, bouncetime=10)
# --- I2C sensors ---
i2c = busio.I2C(board.SCL, board.SDA)
bme = adafruit_bme280.Adafruit_BME280_I2C(i2c)
light = adafruit_tsl2591.TSL2591(i2c)
# calibration constants
WIND_FACTOR = 2.4 # km/h per pulse (depends on your anemometer)
RAIN_FACTOR = 0.279 # mm per tip (depends on gauge)
def log_data():
global wind_count, rain_count
now = datetime.datetime.utcnow().isoformat()
temperature = bme.temperature
humidity = bme.relative_humidity
pressure = bme.pressure
lux = light.lux
wind_speed = wind_count * WIND_FACTOR
rain_mm = rain_count * RAIN_FACTOR
row = [now, temperature, humidity, pressure, lux, wind_speed, rain_mm]
with open('weather_log.csv', 'a', newline='') as f:
writer = csv.writer(f)
writer.writerow(row)
# reset counters for next interval
wind_count = 0
rain_count = 0
if __name__ == '__main__':
# write header once
with open('weather_log.csv', 'w', newline='') as f:
writer = csv.writer(f)
writer.writerow(['timestamp','temp_C','humidity_%','pressure_hPa','lux','wind_kmh','rain_mm'])
while True:
log_data()
time.sleep(60) # wait one minute
The script does three things:
- Counts pulses from the wind and rain sensors.
- Reads temperature, humidity, pressure, and light.
- Writes everything to a CSV file that you can later import into Excel or Grafana.
4. Run It as a Service
You don’t want to have to log in and start the script every time the Pi boots. Create a systemd service:
[Unit]
Description=Raspberry Pi Weather Station
After=network.target
[Service]
ExecStart=/usr/bin/python3 /home/pi/weather_station.py
WorkingDirectory=/home/pi
StandardOutput=inherit
StandardError=inherit
Restart=always
User=pi
[Install]
WantedBy=multi-user.target
Save this as /etc/systemd/system/weather.service, then enable it:
sudo systemctl daemon-reload
sudo systemctl enable weather.service
sudo systemctl start weather.service
Now the station runs in the background, even after a power cut.
Visualizing the Data
If you’re comfortable with a bit of web work, I like to throw the CSV into Grafana using the built‑in SimpleJSON data source. For a quick look, you can also install flask and serve a tiny page that reads the latest line and shows a pretty chart with Chart.js. The code is a few dozen lines and lives in the same repo as the logger.
Protecting Your Hardware
A weather station lives outside, so waterproofing is key. I used silicone sealant around every wire entry point and added a small vent with a breathable membrane to let pressure equalize without letting water in. The BME280 is rated for outdoor use, but the PCB can still corrode over time, so a thin layer of conformal coating helps.
Don’t forget to give the Pi some ventilation. A small heat‑sink on the CPU and a tiny fan (powered from the Pi’s 5 V rail) keep the board from throttling on hot summer days.
Going Further
- Add a solar panel – a 5 V panel with a charge controller can keep the Pi running forever, even on cloudy days.
- Push data to an online service – Thingspeak or InfluxDB Cloud let you see your station alongside others worldwide.
- Add alerts – Use
smtplibto email you when temperature drops below a threshold, or when rain starts.
Building a weather station is a perfect blend of hardware tinkering and software fun. You get instant feedback, you learn how to read sensor data, and you end up with a useful tool that beats any generic forecast. Grab that Pi, solder a few pins, and let the sky be your lab.
- → Build a Raspberry Pi‑Powered Smart Mirror with Voice Control – Step‑by‑Step Tutorial @techhobbyfusion
- → Step-by-step Guide to Building a Low-cost Raspberry Pi Weather Station for Classroom Learning @stemcasters
- → Understanding the Growing Threat of Supercell Storms: What Every Homeowner Should Know @skywatchinsights
- → Troubleshooting Common UART Communication Errors on Raspberry Pi: A DIY Checklist @serialcablechronicles
- → Step-by-step Guide: Building a Low-cost Ultrasonic Distance Sensor for Raspberry Pi @sensorcraft