Day 4 of 5
⏱ ~60 minutes
Raspberry Pi in 5 Days — Day 4

Real Projects

Theory done. Today you'll build three complete projects: a weather station, a motion-triggered camera, and an LED strip controller.

Weather Station with Web Dashboard

Combine the DHT22 (temperature/humidity) and BMP280 (barometric pressure) to build a weather station. Log readings to a SQLite database. Serve a Flask web app on port 5000 that displays a live chart using Chart.js. The Pi stays on your local network — visit http://raspberrypi.local:5000 from any device. This is a complete IoT device with persistent storage and a web UI.

Motion-Triggered Camera

Connect a Pi Camera Module or USB webcam. Use the picamera2 library (Pi Camera) or opencv-python (USB cam) to capture images. Connect a PIR motion sensor to GPIO17 — it outputs HIGH when motion is detected. Write a loop: when PIR is HIGH, capture a photo, save with timestamp filename, send an email notification using Python's smtplib.

Addressable LED Strip (NeoPixels)

WS2812B NeoPixels (addressable RGB LEDs) are controlled over a single data wire using precise timing. The rpi_ws281x library handles the protocol. Connect data to GPIO18 (hardware PWM), 5V power to a separate 5V supply (strips draw 60mA per LED at full brightness — 300-LED strip = 18A at 5V), and a common ground. Build animations: rainbow cycle, theater chase, color wipe, sparkle.

python
#!/usr/bin/env python3
# Weather station with SQLite + Flask dashboard
# pip3 install flask adafruit-circuitpython-dht

import sqlite3, time, threading
from flask import Flask, jsonify, render_template_string
import board, adafruit_dht

app = Flask(__name__)
dht = adafruit_dht.DHT22(board.D4, use_pulseio=False)

# Initialize database
def init_db():
    conn = sqlite3.connect('weather.db')
    conn.execute('''CREATE TABLE IF NOT EXISTS readings
        (id INTEGER PRIMARY KEY, ts REAL, temp REAL, humidity REAL)''')
    conn.commit(); conn.close()

def record_reading():
    while True:
        try:
            t, h = dht.temperature, dht.humidity
            conn = sqlite3.connect('weather.db')
            conn.execute('INSERT INTO readings (ts,temp,humidity) VALUES (?,?,?)',
                         (time.time(), t, h))
            conn.commit(); conn.close()
        except: pass
        time.sleep(30)

@app.route('/api/data')
def data():
    conn = sqlite3.connect('weather.db')
    rows = conn.execute('SELECT ts,temp,humidity FROM readings ORDER BY ts DESC LIMIT 100').fetchall()
    conn.close()
    return jsonify([{'ts':r[0],'temp':r[1],'hum':r[2]} for r in reversed(rows)])

HTML = '''<!DOCTYPE html><html><head><title>Weather Station</title>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script></head><body>
<h2>Pi Weather Station</h2>
<canvas id="chart" width="800" height="300"></canvas>
<script>
async function update(){
  const d=await fetch('/api/data').then(r=>r.json());
  new Chart(document.getElementById('chart'),{type:'line',
    data:{labels:d.map(r=>new Date(r.ts*1000).toLocaleTimeString()),
      datasets:[{label:'Temp (C)',data:d.map(r=>r.temp),borderColor:'red',tension:.3},
                {label:'Humidity (%)',data:d.map(r=>r.hum),borderColor:'blue',tension:.3}]},
    options:{responsive:true}});
}
update(); setInterval(update,30000);
</script></body></html>'''

@app.route('/')
def index(): return HTML

if __name__=='__main__':
    init_db()
    threading.Thread(target=record_reading, daemon=True).start()
    app.run(host='0.0.0.0', port=5000, debug=False)
    print('Visit http://raspberrypi.local:5000')
💡
Run the Flask app as a systemd service so it starts automatically on boot: create /etc/systemd/system/weather.service with ExecStart=/usr/bin/python3 /home/pi/weather.py, then sudo systemctl enable weather && sudo systemctl start weather.
📝 Day 4 Exercise
Build the Weather Station
  1. Copy the weather station code to your Pi. Install dependencies: pip3 install flask adafruit-circuitpython-dht
  2. Run it: python3 weather.py. Visit http://raspberrypi.local:5000 from another device on the same network.
  3. Let it run for 1 hour. Does the chart show temperature variation? (Open a window or breathe on the sensor to test responsiveness.)
  4. Create a systemd service file to auto-start on boot. Test by rebooting the Pi and verifying the web app comes up automatically.
  5. Extend the dashboard: add a humidity chart, show min/max for today, display the last update timestamp.

Day 4 Summary

  • Flask + SQLite is the simplest full-stack IoT data logger — runs entirely on the Pi
  • Systemd services auto-start apps on boot — the Pi becomes a self-contained appliance
  • picamera2 handles Pi Camera Module; opencv handles USB webcams
  • WS2812B NeoPixels need hardware PWM (GPIO18) and a separate 5V power supply — do not power from Pi's 5V pin
Challenge

Add email alerts to the weather station: when temperature exceeds 30°C or drops below 10°C, send an email using Python's smtplib with Gmail SMTP. Implement a cooldown so you don't get spammed (max one alert per 30 minutes per condition). Store the Gmail credentials in environment variables, not in the code.

Finished this lesson?