Projet DIY

Station météo connectée avec Raspberry Pi : construire, coder, afficher

Construire une station meteo maison avec un Raspberry Pi et un capteur BME280 : cablage I2C, code Python, dashboard web Flask avec Chart.js, et service systemd pour tourner en continu.

Il y a un collège de Bobigny dans lequel j’ai mené un atelier de six semaines sur la mesure environnementale. Une élève de seize ans, Célia, a construit sa station météo dans une boîte en carton, l’a posée sur le rebord de fenêtre, et a passé les trois semaines suivantes à regarder sa courbe de température nocturne baisser pendant la vague de froid de décembre. Ce moment précis où les données abstraites deviennent quelque chose de réel, c’est exactement ce que ce projet apporte.

On va construire une station météo qui mesure température, humidité et pression atmosphérique toutes les minutes, stocke les données localement, et les affiche sur un mini-dashboard web accessible depuis n’importe quel appareil sur le réseau domestique.

Matériel nécessaire

ComposantPrix indicatifRôle
Raspberry Pi (n’importe quel modèle avec GPIO)35-60 €Cerveau de la station
Capteur BME280 (breakout board I2C)4-8 €Température + humidité + pression en un seul module
Câbles dupont femelle-femelle (4 fils)1 €Connexion I2C (VCC, GND, SDA, SCL)
Carte microSD + alim (si pas déjà en place)15-20 €Système + stockage données

Total hors Pi : 5 à 9 euros. C’est l’un des projets les moins chers qui existent en IoT domestique. Si tu hésitais entre un BME280 et un DHT22 (l’autre capteur classique), le BME280 gagne dans la plupart des cas : il mesure aussi la pression atmosphérique (le DHT22 ne le fait pas), dérive moins sur la durée, répond plus vite, et utilise le bus I2C standard plutôt que le protocole 1-wire propriétaire du DHT22. Sur la précision pure de température, le DHT22 est légèrement meilleur (±0,5 °C contre ±1 °C pour le BME280) — mais cette différence reste théorique en usage station météo (les deux dérivent vite hors plage 0-65 °C). Le DHT22 coûte 2 euros de moins ; sa fragilité au-dessus de 90 %HR et son protocole capricieux justifient l’écart de prix.

Câblage I2C

Quatre fils, pas de résistance, pas de composant supplémentaire. L’I2C est le protocole idéal pour les capteurs qui n’ont pas besoin de débit élevé.

Broche BME280Broche PiNom
VIN (ou VCC)Pin 1 (3,3V)Alimentation
GNDPin 6 (GND)Masse
SDAGPIO 2 (Pin 3)Data I2C
SCLGPIO 3 (Pin 5)Clock I2C

Après branchement, active I2C si ce n’est pas déjà fait (sudo raspi-config → Interface Options → I2C → Enable). Vérifie que le capteur est détecté :

sudo i2cdetect -y 1

Tu devrais voir l’adresse 0x76 ou 0x77 dans la grille. Si rien n’apparaît : vérifie les soudures sur le breakout, inverse SDA et SCL (ça arrive souvent), et confirme que l’alimentation est sur 3,3V et non 5V (certains breakouts tolèrent les deux, mais pas tous).

Script Python de lecture

#!/usr/bin/env python3
"""
meteo.py — Lecture du BME280 + stockage CSV
"""

import board
import adafruit_bme280.advanced as adafruit_bme280
import csv
import os
from datetime import datetime
from time import sleep

# Initialisation I2C + capteur
i2c = board.I2C()
bme = adafruit_bme280.Adafruit_BME280_I2C(i2c, address=0x76)

# Calibration altitude locale (optionnel, améliore la pression affichée)
bme.sea_level_pressure = 1013.25  # hPa, ajuster selon météo du jour
# Note self-heating : le BME280 chauffe légèrement (~0,5-1°C) en mode normal
# (mesure continue). Pour minimiser, basculer en mode forced :
# bme.mode = adafruit_bme280.MODE_FORCE  # mesure à la demande puis sleep

CSV_FILE = "/home/pi/meteo/data.csv"
os.makedirs(os.path.dirname(CSV_FILE), exist_ok=True)

# Écrire l'en-tête si fichier inexistant
if not os.path.exists(CSV_FILE):
    with open(CSV_FILE, "w", newline="") as f:
        csv.writer(f).writerow(["timestamp", "temp_c", "humidity_pct", "pressure_hpa"])

print("Station météo démarrée. Ctrl+C pour arrêter.")

try:
    while True:
        now = datetime.now().isoformat(timespec="seconds")
        temp = round(bme.temperature, 1)
        hum = round(bme.relative_humidity, 1)
        pres = round(bme.pressure, 1)

        print(f"[{now}] {temp}°C | {hum}% HR | {pres} hPa")

        with open(CSV_FILE, "a", newline="") as f:
            csv.writer(f).writerow([now, temp, hum, pres])

        sleep(60)  # une mesure par minute

except KeyboardInterrupt:
    print()  # saut de ligne
    print("Arrêt propre.")

Installe les dépendances avant de lancer :

sudo apt install python3-pip -y
pip3 install adafruit-circuitpython-bme280

Le script écrit une ligne par minute dans un fichier CSV. Au bout de 24 heures, tu as 1440 points de mesure, soit un graphique de température avec une résolution d’une minute. Le fichier CSV grossit de moins de 1 Mo par mois, ce qui est négligeable même sur une carte SD de 16 Go.

Dashboard web avec Flask

Pour visualiser les données sans ouvrir le CSV à la main, on monte un mini-serveur web Flask qui affiche les dernières mesures et un graphique des 24 dernières heures.

#!/usr/bin/env python3
"""
dashboard.py — Serveur web Flask pour la station météo
"""

from flask import Flask, render_template_string
import csv

app = Flask(__name__)
CSV_FILE = "/home/pi/meteo/data.csv"

TEMPLATE = """


    
    
    Station météo Raspberry Pi
    
    


    

Station météo Raspberry Pi

{{ last.temp }} °CTempérature
{{ last.hum }} %Humidité
{{ last.pres }} hPaPression
""" @app.route("/") def index(): rows = [] with open(CSV_FILE) as f: for row in csv.DictReader(f): rows.append(row) last_24h = rows[-1440:] if len(rows) > 1440 else rows chart_data = { "labels": [r["timestamp"][-8:-3] for r in last_24h[::10]], "temp": [float(r["temp_c"]) for r in last_24h[::10]], "hum": [float(r["humidity_pct"]) for r in last_24h[::10]], } import json last = {"temp": rows[-1]["temp_c"], "hum": rows[-1]["humidity_pct"], "pres": rows[-1]["pressure_hpa"]} if rows else {} return render_template_string(TEMPLATE, last=last, chart_data=json.dumps(chart_data)) if __name__ == "__main__": app.run(host="0.0.0.0", port=5000)
pip3 install flask
python3 dashboard.py

Ouvre http://nom-du-pi.local:5000 depuis n’importe quel navigateur du réseau local. Tu verras la dernière mesure en gros et un graphique Chart.js des dernières 24 heures. L’échantillonnage à 1 point sur 10 (une mesure toutes les 10 minutes affichée) garde le graphique lisible sans noyer le navigateur. Pour accéder au dashboard en dehors de chez toi, la solution propre est un VPN (WireGuard), pas d’exposer le port 5000 sur Internet.

Faire tourner en continu avec systemd

Pour que le script de lecture et le dashboard se lancent automatiquement au démarrage du Pi, on crée deux services systemd :

# /etc/systemd/system/meteo-reader.service
[Unit]
Description=Station météo - lecteur BME280
After=network.target

[Service]
ExecStart=/usr/bin/python3 /home/pi/meteo/meteo.py
WorkingDirectory=/home/pi/meteo
Restart=always
User=pi

[Install]
WantedBy=multi-user.target
sudo systemctl enable meteo-reader
sudo systemctl start meteo-reader
sudo systemctl status meteo-reader

Même principe pour le dashboard Flask. Après ça, le Pi démarre et commence à mesurer sans intervention humaine. La station méteo de Célia, au collège de Bobigny, a tourné quatre mois sur un Pi Zero 2 W avec cette configuration exacte avant que la carte SD ne rende l’âme (remplacée en dix minutes, les données étaient sauvegardées sur un partage réseau Samba).

Améliorations possibles

  • Écran OLED SSD1306 (5 euros) : afficher les mesures en temps réel sur un petit écran 128×64 pixels fixé au boîtier, sans avoir à ouvrir un navigateur.
  • Alertes par Telegram : un bot Telegram qui envoie un message si la température descend sous 5 °C ou si l’humidité dépasse 80 %. Vingt lignes de Python avec la bibliothèque python-telegram-bot.
  • Capteur de qualité de l’air (CCS811 ou SGP30) : ajouter un indice de CO2 et de COV. Connexion I2C, même bus que le BME280, même principe de lecture.
  • Envoi vers InfluxDB + Grafana : pour les utilisateurs avancés qui veulent un dashboard professionnel avec rétention longue et agrégations temporelles. InfluxDB tourne sur Pi 4/5 sans problème.

Le guide ultime du Raspberry Pi couvre les bases si tu débutes, et le tutoriel SSH headless de Claire explique comment administrer ton Pi serveur à distance. Pour un capteur température seul (sans humidité ni pression), le DS18B20 (IC nu ~1 €, sonde étanche câblée 3-5 €) est une alternative intéressante pour mesurer la température d’un bassin, d’un congélateur ou d’un sol extérieur. Bus 1-Wire, plusieurs capteurs en parallèle sur la même ligne.

Autres projets DIY

Projet DIY

Robot 2 roues autonome avec Raspberry Pi : le tutoriel complet

Le projet parfait pour démarrer en robotique DIY : construire un petit robot mobile qui évite les obstacles, avec un Raspberry Pi, un module L298N, deux moteurs et un capteur ultrason. Matériel, câblage, code Python commenté.