Station météo

Réalisation d’un station météo au sein d’un lycée - Documentation

Ce billet de blog est en cours de rédaction et d'amélioration.
Cela est donc normal si des informations s'ajoutent au fil des jours :)

Bonjour ! Un projet de station météorologique à été lancée dans mon lycée et voici donc un petit billet de blog ayant l’objectif d’expliquer au mieux l’ensemble de l’installation, principalement logicielle, d’une station météo à base de Raspberry Pi et d’un capteur BME280, qui permet de mesurer la pression, la température et l’humidité directement ensemble et avec une précision vraiment intéressante.

Si vous ne souhaitez que visionnez directement les données receuillies par la station du projet « Senghor Météo » , je vous invite à cliquer sur le lien suivant : https://io.adafruit.com/meteosenghor/dashboards/meteo-senghor

Sinon, passons maintenant à la réalisation de ce projet !

Matériels :

Installation :

Installation du Raspberry Pi 3 :

Téléchargement de l’image du système d’exploitation pour le Raspberry Pi sur le site de la fondation Rapsberry pi : https://www.raspberrypi.com/software/operating-systems/

On choisira la version Raspberry Pi OS Lite dans le cadre de ce projet afin de restreindre la quantité de mémoire utilisée en installant uniquement les logiciels et bibliothèques utiles.

A l’aide du logiciel Rufus, on installe l’image disque sur une carte SD.

Configuration du réseau wifi et du proxy réseau :

Afin de pouvoir se connecter à distance sur le Raspberry Pi, on crée à la racine de la carte SD un fichier appelé ssh  . Attention à ne pas mettre une extension de nom de fichier !

Pour connecter le Raspberry Pi à Internet, 2 options :

Dans notre cas, on utilise le wifi, on doit donc créér un fichier à la racine de la carte SD qui sera appelé wpa_supplicant.conf. A l’aide d’un éditeur de texte, on le complète des lignes suivantes :

country=fr
update_config=1
ctrl\_interface=/var/run/wpa\_supplicant

network={
 scan_ssid=1
 ssid="MaBoxInternet"
 psk="ClefSecurite"
}

Ne pas oublier de remplacer le ssid par celui de sa box et le mot de passe par celui qui correspond !

Source : https://raspberry-pi.fr/raspberry-pi-sans-ecran-sans-clavier/

Si votre réseau utilise un serveur proxy, n’hésitez pas à regarder le lien suivant pour le configurez sur le Raspberry Pi, cela est notamment nécessaire pour le mettre à jour ou installer les bibliothèques : https://artheodoc.wordpress.com/2019/06/04/configuration-du-proxy-ou-serveur-mandataire-raspberry-pi-sous-raspbian/

Installation des bibliothèques python pour la lecture des données du capteur BME280 :

Pour l’installation du capteur BME280 et ses bibliothèques, le lien suivant vous sera d’une très grande utilité : https://www.raspberryme.com/utilisation-du-capteur-de-temperature-et-de-pression-bme280-i2c-en-python/

Afin d’utiliser la platerforme Adafruit IO, il vous faudra vous créer un compte. Vous devrez ensuite vous rendre dans la partie « feeds » et créer les flux suivants :

N’oubliez pas de récupérer au passage votre identifiant et votre token de connexion, cela vous sera utile pour le suite !

Il sera nécessaire d’installer la librairie d’Adafruit IO :

pip3 install adafruit-io

Code de récupération et envoi des données sur Adafruit IO :

import time
from bme280 import *                        # Gestion capteur BME280
from Adafruit_IO import Client              # Gestion envoie donnée

# Connexion à Adafruit IO
aio = Client('Identifiant', 'Token')

# Initialisation des flux
temperature_feed = aio.feeds("temperature")
pression_feed = aio.feeds("pression")
humidite_feed = aio.feeds("humidite")

# Affichage information identification capteur
(chip_id, chip_version) = readBME280ID()
print("Chip ID     :", chip_id)
print("Version     :", chip_version)

while True:
    # Récupération des données du capteur
    temperature, pression, humidite = readBME280All()
    
    # Affichage des données
    print("[LOGS] Données :  ",temperature, "°C |",round(pression,2), "hPa |",round(humidite,2), "%")

    # Envoie des données sur Adafruit IO
    aio.send_data(temperature_feed.key, temperature)
    aio.send_data(pression_feed.key, pression)
    aio.send_data(humidite_feed.key, humidite)

    # Attente de 10 secondes avant la mesure suivante
    time.sleep(10)

On va maintenant installer PM2 qui est un utilitaire permettant de lancer automatiquement et simplement un programme au démarrage du Raspberry Pi.

Installation de nodejs et npm pour installer pm2

sudo apt install nodejs npm
sudo npm cache clean -f
sudo npm install -g n
sudo n stable

Installation de PM2 pour gérer le lancement automatique

sudo npm install pm2@latest -g

Pour activer le lancement automatique de PM2, tapez la commande suivante et suivez les instructions :

pm2 startup

On lance maintenant notre script python de collecte de données :

pm2 start meteo.py
pm2 save

et pour vérifier le bon foncionnement de notre processus automatisé on utilisera la commande ci-dessous :

pm2 list

Second Raspberry Pi (en intérieur):

Source : https://simonhearne.com/2020/pi-influx-grafana/

Installation de InfluxDB :

On ajoute le dépot de InfluxDB à apt :

wget -qO- https://repos.influxdata.com/influxdb.key | sudo apt-key add -

source /etc/os-release 

echo "deb https://repos.influxdata.com/debian $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/influxdb.list

On mets à jour ensuite apt avec les nouveaux dépots et on installe InfluxDB:

sudo apt update && sudo apt install -y influxdb

On lance ensuite le service influxdb et on le configure pour qu’il se lance automatiquement au démarrage :

sudo systemctl unmask influxdb.service
sudo systemctl start influxdb
sudo systemctl enable influxdb.service

Nous sommes maintenant en capacité de lancer le client Influx avec la commande influx et nous allons créer un nouvel utilisateur administrateur, ici nommé grafana, que nous utiliserons plus tard et on vérifie que l’utilisateur est bien créé :

create database meteo
use meteo
    
create user grafana with password '<VotreMotDePasseIci>' with all privileges
grant all privileges on meteo to grafana
    
show users

L’affichage retourner devrait être celui-ci :

user admin
---- -----
grafana true

Si l’affichage est bon, c’est fini ! Vous pouvez maintenant quitter la console en tapant exit.

Installation de Grafana :

Nous devons également ajouter le package de Grafana à apt :

wget -q -O - https://packages.grafana.com/gpg.key | sudo apt-key add -
echo "deb https://packages.grafana.com/oss/deb stable main" | sudo tee /etc/apt/sources.list.d/grafana.list

On mets à jour les dépots et on installe Grafana :

sudo apt update && sudo apt install -y grafana

On active le service et on le configure pour un démarrage automatique au lancement du Raspberry Pi :

sudo systemctl unmask grafana-server.service
sudo systemctl start grafana-server
sudo systemctl enable grafana-server.service

On peut maintenant vérifier le bon fonctionnement de Grafana en allant, à travers notre navigateur, sur : http://<ipaddress>:3000.

Si cela marche correctement, vous pouvez vous connecter avec l’identifiant et le mot de passe par défaut :admin. Vous devrez configurer un nouveau mot de passe administrateur par la suite.

Ajouter Influx comme source dans Grafana :

Maintenant que Influx et Grafana fonctionne correctemenr, nous devons les connecter ensemble. Connecter vous sur Grafana et allez dans la partie « Data Sources ». Selectionnez « Add data source » puis InfluxDB dans la catégorie « Time series databases ».

Puisque les deux services tournent sur le même Raspberry Pi, configurez l’URL sur localhost (127.0.0.1) et utilisez le port par défaut d’influx 8086:

Configuration Grafana HTTP

Nous devons maintenant créer une nouvelle base de donnée et rentrant les informations que nous avons précisez plus tôt:

Configuration Grafana utilisateur

Appuyez sur le bouton « Save & test » pour vérifier et enregistrer les informations et créer la connexion entre Grafana et notre base de donnée Influx :

Configuration Grafana terminée

Récupérer les données météo :

Maintenant que nous avons configurée notre base de donnée, il nous faut collecter les données de notre capteur BME280.

On installe la librairie pour InfluxDB :

sudo pip install influxdb

On utilise maintenant le code suivant, qui sera exécuté sur le Raspberry Pi avec le capteur BME280, pour collecter les mesures toutes les 10 secondes :

import datetime
from influxdb import InfluxDBClient
import time
from bme280 import *                        # Gestion capteur BME280

# Configuration d'Influx - Editez ici
ifuser = "grafana"
ifpass = "<VotreMotDePasseIci>"
ifdb   = "meteo"
ifhost = "<VotreIP>" #127.0.0.1 si la base de données est sur le même Raspberry PI
ifport = 8086
measurement_name = "mesure_meteo"


# Connexion à Influx
ifclient = InfluxDBClient(ifhost,ifport,ifuser,ifpass,ifdb)


# Affichage information identification capteur
(chip_id, chip_version) = readBME280ID()
print("Chip ID     :", chip_id)
print("Version     :", chip_version)


while True:
    # Récupération de l'horodatage de la mesure
    horodatage = datetime.datetime.utcnow()

    # Récupération des données du capteur
    temperature, pression, humidite = readBME280All()

    # Affichage des données
    print("[LOGS] Horodatage:",horodatage,"| Données :  ",temperature, "°C |",round(pression,2), "hPa |",round(humidite,2), "%")


    # Formatage des données comme une seule mesure pour influx
    body = [
        {
            "measurement": measurement_name,
            "time": horodatage,
            "fields": {
                "pression": pression,
                "temperature": temperature,
                "humidite": humidite
            }
        }
    ]

    # Enregistrement de la mesure
    ifclient.write_points(body)

    # Attente de 10 secondes avant la mesure suivante
    time.sleep(10)

A vous de créer un magnifique dashboard et de jouer avec les options pour afficher vos données toutes neuves !

Connexion à distance et accès aux données sur le web

Afin de pouvoir récupérer les données à distance, la solution la plus simple est d’utiliser la platerforme Adafruit IO pour accéder aux données, mais une autre solution est de mettre en place une redirection de ports, ou d’utiliser un service comme LocalTunnel permettant l’accès à un service sans modifier la configuration réseau, pour accéder à la page de Grafana.

Capacité autonome de la station

Dans le cadre de ce projet, et la difficulté de tirer une rallonge électrique en extérieur dans ce contexte n’aidant pas, nous avons décider d’alimenter notre station météo grâce à une carte d’extension PiJuice HAT associé à un panneau solaire de 40W et une batterie de 12 000 mAh. Le Raspberry Pi est configuré pour s’allumer toutes les 10 minutes, effectuer la collecte des données, se connecter simultanément à un second Raspberry Pi, servant de serveur pour la base de données, et à Adafruit IO pour pouvoir accéder facilement aux données depuis n’importe où, puis s’éteinds jusqu’au prochain cycle.

Code final de la station météo

Voici donc le code final de la station, tournant actuellement en permanence au lycée, et gérant l’envoi des données sur Grafana et Adafruit IO, les cycles d’allumages et la batterie.

import datetime
from influxdb import InfluxDBClient
import time
from bme280 import *                        # Gestion capteur BME280

from Adafruit_IO import Client
from pijuice import PiJuice
from subprocess import call

# Connect to pijuice hat
pijuice = PiJuice(1,0x14)

# Connect to Adafruit IO
aio = Client("<Identifiant>", "<Token>")
print("Connexion réussie !")

# Initialisation flux adafruit io

temperature_feed = aio.feeds("temperature")
pression_feed = aio.feeds("pression")
humidite_feed = aio.feeds("humidite")
batterie_feed = aio.feeds("charge-batterie")

print("initialitation flux réussis !")

# influx configuration - edit these
ifuser = "grafana"
ifpass = "<MDP>"
ifdb   = "meteo"
ifhost = "<IP_INFUX>"
ifport = 8086
measurement_name = "mesure_meteo"


# connect to influx
ifclient = InfluxDBClient(ifhost,ifport,ifuser,ifpass,ifdb)


# Affichage information identification capteur
(chip_id, chip_version) = readBME280ID()
print("Chip ID     :", chip_id)
print("Version     :", chip_version)


def capture():
    # take a timestamp for this measurement
    temps = datetime.datetime.utcnow()

    # Get battery charge level
    data_charge = pijuice.status.GetChargeLevel()
    charge_level = data_charge["data"]

    # Récupération des données du capteur
    temperature, pression, humidite = readBME280All()

    # Affichage des données
    print("[LOGS] Date:",temps,"| Batterie : ",charge_level,"% | Données :  ",temperature, "°C |",round(pression,2), "hPa |",round(humidite,2), "%")

    # Envoie des données sur Adafruit IO
    aio.send_data(temperature_feed.key, temperature)
    aio.send_data(pression_feed.key, pression)
    aio.send_data(humidite_feed.key, humidite)
    aio.send_data(batterie_feed.key, charge_level)
    # format the data as a single measurement for influx
    body = [
        {
            "measurement": measurement_name,
            "time": temps,
            "fields": {
                "pression": pression,
                "temperature": temperature,
                "humidite": humidite,
                "niveau_batterie": charge_level
            }
        }
    ]

    # write the measurement
    ifclient.write_points(body)

### MAIN ###
capture()

print("fin mesure, au revoir !")

pijuice.rtcAlarm.SetWakeupEnabled(True)

call("sudo shutdown -h now", shell=True)

En espérant que ce projet vous aura intéressé et surtout n’hésitez pas à envoyez un mail en cas de question !

Si vous avez une question concernant le projet, n’hésitez pas à envoyer un mail à l’adresse e-mail du projet : senghormeteo[@]protonmail.com

Si vous souhaitez me contacter directement, moi, l’ours geek écrivant ces lignes, envoyez un mail à postmaster[@]ursusnocte.fr