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

SensorWhat it measuresTypical price
BME280Temperature, 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:

  1. Counts pulses from the wind and rain sensors.
  2. Reads temperature, humidity, pressure, and light.
  3. 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 smtplib to 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.

Reactions