1. Introduction

Vivant en Suisse depuis quelques années, j’ai appris à faire face aux conditions climatiques assez changeantes suivant la saison. Cependant, après que la masse d’air sec et froid ayant traversé l’Europe par le fameux canal « Moscou – Paris »[1] s’abatte sur la Suisse et fasse descendre le mercure jusqu’aux dix degrés négatifs, j’ai eu l’idée de construire et programmer ma propre station météo, étant donné que je ne consulte que très rarement les journaux ou les prévisions météorologiques.

Le but de ce projet sera la programmation d'un capteur de pression et de température. Les informations récoltées seront stockées dans une base de données (SQLite) afin de dresser un historique, un site web sera conçu pour analyser ces dernières, et des pronostics météorologiques pourront même être avancés après un certain nombre de mesures.

2. Matériel et méthode

2.1. Matériel

La réalisation de ce projet nécessitera un certain équipement, détaillé ci-dessous.

2.1.1. Hardware

  • Un Raspberry Pi 3
  • Basic 16x2 Character LCD - RGB Backlight 5V2
  • SparkFun Barometric Pressure Sensor Breakout - BMP1803
  • Une planche à pain (« breadboard »)
  • Des fils de connexion/d’alimentation

Un ordinateur (plus puissant que le Raspberry) sera probablement utile, surtout du point de vue de la gestion du site web et de la base de données.

2.1.2. Software

Une librairie sera nécessaire pour le capteur de pression/température :

  • Adafruit_Python_BMP[2]

Une autre le sera pour l'écran LCD :

  • Adafruit_CharLCD[3]

Enfin, nous aurons besoin des librairies sqlite3 (pour la base de données), de datetime, time et sys.

2.2. Méthode

2.2.1. Branchements

Il y a beaucoup de connexions à réaliser. Ci dessous un schéma fait par moi-même à l'aide de l'application Fritzing[4]. J'ai trouvé les branchements de l'écran sur le site PiMyLifeUp[5] qui explique très bien comment manipuler un LCD (en anglais). Les documents accompagnant la librairie du BMP180 précisent les branchements nécessaires pour une communication en I2C.

 schema.png

La seule différence entre le schéma et mon montage personnel est que mon écran peut afficher une lumière de fond, un dernier fil est donc ajouté entre le pin 3.3V du Raspberry et le dernier pin de mon LCD (qui comporte non pas 16 mais 18 pins). Les autres branchements restent exactement les mêmes.

LCD Raspberry Pi
pin 1 ground rail
pin 2 5V rail
pin 3 pin central du potentiomètre
pin 4 GPIO25 (pin 22)
pin 5 ground rail
pin 6 GPIO24 (pin 18)
pin 11 GPIO23 (pin 16)
pin 12 GPIO17 (pin 11)
pin 13 GPIO18 (pin 12)
pin 14 GPIO22 (pin 15)
pin 15 5V rail
pin 16 ground rail
BMP180 Raspberry Pi
pin 2 (+) 3.3V pin (pin 1 ou 17)
pin 3 (-) ground rail
pin 4 (CL) SCL pin (pin 28)
pin 5 (DA) SDA pin (pin 27)

2.2.2. Importation des libairies

Après avoir copié les librairies quelque part sur le Raspberry, on exécute la commande suivante à partir du terminal dans chacune des librairies:

sudo python setup.py install

Les librairies du BMP180 et de l'écran sont maintenant prêtes à être utilisées. La librairie SQLite3 est préinstallée sur la plupart des ordinateurs cependant j'ai dû l'installer sur le Raspberry en entrant ceci dans le terminal :

sudo apt-get install sqlite3

2.2.3. Configuration du Pi en serveur web

Afin que la page web soit visible, il faut configurer le Raspberry en serveur web ("web server" en anglais). Pour cela, le site du Raspberry propose un tutoriel très complet[6].

Pour résumer, il faut installer sur le Pi Apache (un serveur HTTP) et PHP (un langage de programmation pour les pages web dynamiques). Un fichier nommé index.php sera créer dans le répertoire /var/www/html, et servira de contenu pour l'affichage de la page web.

Après cette opération, il suffit de rentrer l'adresse IP du Raspberry dans un navigateur pour accéder à la page web (seules les machines connectées au même Wi-Fi ont accès à cette page).

3. Programmation

Passons à présent aux codes Python de ce projet. Il y en a deux, un pour le capteur, l'écran et la base de données et un autre pour la page web.

3.1. La base de données

SQLite3 étant déjà installée (cf. section 2.2.2.), nous pouvons créer une base de données (BDD) à partir du terminal dans laquelle seront stockées les valeurs recueillies par le capteur, ainsi que l'heure à laquelle elles ont été transférées dans la BDD. Une clé primaire (auto-incrémentée) sera aussi ajoutée.

Créons donc la base nommée "meteo.db" :

sqlite3 meteo.db

Après qu'un court message soit affiché, nous pouvons taper des commandes SQL, qui (pour sqlite3) se finissent par un point-virgule. Créons une table appelée "samples" dans laquelle se trouvent quatre colonnes: "id" (clé primaire), "time" (date et heure de prélèvement), "temperature" et "pressure".

create table samples(id INTEGER PRIMARY KEY AUTOINCREMENT, 
                                    time TEXT, temperature TINYINT, pressure SMALLINT);

Le point-virgule est très important. Nous avons à présent une table dans une BDD prête à recevoir des données.

3.2. Le code Python

Commençons par indiquer que le langage de programmation est Python et que l'encodage de caractère est utf-8.

#! /usr/bin/python
# -*- coding: utf-8 -*-

On importe les librairies:

import Adafruit_BMP.BMP085 as BMP085
import Adafruit_CharLCD as LCD
import sqlite3
import datetime
import time
import sys

On établit la connexion avec la BDD:

conn = sqlite3.connect('meteo')

On raccourcit certaines fonctions:

sleep = time.sleep

sensor = BMP085.BMP085()

c = conn.cursor()

On déclare la configuration des pins du Raspberry pour le LCD:

lcd_rs        = 25
lcd_en        = 24
lcd_d4        = 23
lcd_d5        = 17
lcd_d6        = 18
lcd_d7        = 22
lcd_backlight = 4
lcd_columns = 16
lcd_rows = 2

On initialise les pins du LCD:

lcd = LCD.Adafruit_CharLCD(lcd_rs, lcd_en, lcd_d4, lcd_d5, lcd_d6, lcd_d7, lcd_columns, lcd_rows, lcd_backlight)

Maintenant que nous avons tout installé, nous pouvons déclarer une boucle "while" dans un bloc "try". C'est dans ce bloc que les valeurs de la température et de la pression seront traitées par le Raspberry, affichées sur le LCD et envoyées dans la base de données.

try:
   while True:
       temp = sensor.read_temperature()
       pressure = sensor.read_pressure()/100
       
       temp = str(temp)
       pressure = str(pressure)
#bloc temp lcd.set_cursor(0,0) lcd.message('temp.=') lcd.set_cursor(6,0) lcd.message(temp) lcd.set_cursor(11,0) lcd.message('deg.') #bloc pres lcd.set_cursor(0,1) lcd.message('pres. =') lcd.set_cursor(8,1) lcd.message(pressure) lcd.set_cursor(12,1) lcd.message('hPa') sleep(3600) lcd.clear() sleep(0.1) #bloc bdd zeit = datetime.datetime.now() temp = float(temp) pressure = float(pressure) c.execute("INSERT INTO samples(time, temperature, pressure) VALUES (?, ?, ?);", (zeit, temp, pressure)) conn.commit() pass

On raccourcit dans un premier temps des fonctions de température et de pression (et on convertit par la même occasion la pression en hPa).

Dans le bloc "temp", on place le curseur à gauche du LCD pour afficher "temp. =", puis on le déplace vers la droite pour afficher respectivement la valeur de la température et l'unité "deg.".

On répète l'opération dans le bloc "pres", en plaçant cette fois-ci le curseur sur la ligne au-dessous.

On définit le temps d'affichage sur le LCD, ici 3600 secondes car on effectue un prélèvement toutes les heures. On l'actualise ensuite en un dixième de seconde.

On passe ensuite au bloc "bdd", dans lequel les variables sont définies comme nombres à virgule flottante (float) et la date et l'heure est prise grâce à la librairie datetime (variable "zeit"). Les variables sont ensuite toutes transférées dans la BDD. On effectue un "commit" pour enregistrer les données.

La gestion des exceptions est ensuite écrite. La commande "ctrl + C" arrêtera le programme, et une erreur dans l'exécution du code mènera à un retour en arrière de la part de la BDD.

Finalement, on ferme la connexion à la base de données.

Il est à noter que les variables "temp" et "pressure" sont définies dans un premier temps comme une chaîne de caractère (str). La raison pour cela est que dans la librairie du LCD, la fonction "lcd.message()" n'accepte que ce format de variable. Dans un second temps les variables sont reconverties en virgules flottantes (float) pour être ainsi transférées dans la base de données.

3.3. Le site web

Le Raspberry est maintenant configuré comme serveur web, et dispose d'un fichier nommé index.php qui sera affiché par le navigateur utilisé. Afin de consulter la page web, il faut connecter le Pi au Wi-Fi et entrer son adresse IP dans le navigateur. Le langage HTML peut être utilisé afin d'insérer du contenu statique, et un fichier CSS peut être créé dans le but de modifier la présentation du document. PHP est quant à lui utilisé pour afficher un contenu dynamique, comme par exemple le contenu de la base de données en créant une connexion et en effectuant des requêtes[7].

4. Résultats

Le code Python marche très bien. Les valeurs sont effectivement transférées sur l'écran LCD et dans la base de données. Les valeurs de la pression atmosphérique sont étrangement en dessous des vraies valeurs (les valeurs récoltées tournent souvent autour de 950 hPa, soit une forte dépression, quand il fait très beau et chaud à l'extérieur). Cependant, la connexion n'a pas pu se faire, et ce pour des raisons incertaines. Les lignes de codes étant inspirées du site web de PHP (cf. note 7), il est étrange que cela ne fonctionne pas. Puisque les insérer dans le code HTML provoque une erreur générale d'affichage, j'ai préféré déplacer le code PHP à la fin du code HTML.

Ci dessous un échantillon de la base de données, tous les relèvement étant pris dans un intervalle de 5 secondes. J'ai volontairement fait varier la température pour mettre en évidence les capacités du Pi.

id temps (Y-M-D h:m:s:ms) température (°C) pression (hPa)
7 2018-05-03 21:27:41.895508 21.3 943
8 2018-05-03 21:27:47.196947 23.9 943
9 2018-05-03 21:27:52.389357 25.8 943
10 2018-05-03 21:27:57.696854 27.1 943
11 2018-05-03 21:28:02.996990 27.6 943

Voici ce à quoi le matériel assemblé ressemble. Les fils de connexions sont disposés tels que je l'ai décris plus haut (cf. partie 2.2.1). A l'extrémité de la natte se trouve le Raspberry.

rendu du projet

En plus de cela, j'ai programmé une page web, cependant les informations de la base de données sont absentes.

page_web_p.png

5. Discussion

Il est vrai que la température et la pression seules créent difficilement une station météo, mais le principe reste le même, quelques soient les données ajoutées. La véracité des informations concernant les prévisions ne pourrait en être qu'augmentée.

Afin que le matériel soit utilisable en extérieur, il serait judicieux de le protéger des l'humidité, sans toutefois l'isoler complètement, de sorte que la température captée soit la température extérieure.

Afin de trouver des résultats plus précis, on pourrait aussi prendre l'altitude en compte, étant donnée que la pression de l'air diminue à mesure que l'altitude augmente.

Ce projet a été extrêmement enrichissant car il m'a permis de connaître le comportement à avoir lorsque je dispose d'un capteur mais ne sais pas comment l'utiliser. Les bases de données ont aussi été un nouveau concept; j'ai été très étonné par leur simplicité d'utilisation.

Mon seul regret aura été de ne pas parvenir à manipuler les données à l'aide de PHP sur la page web. La syntaxe de SQLite3 étant relativement pauvre, je n'ai pas trouvé le moyen de me connecter, et encore moins de transférer les données.

6. Conclusion

Mon objectif était de créer une station météo qui aurait affiché les valeurs de la température et de la pression atmosphérique sur un écran et aurait envoyé ces mêmes données dans une base de données alimentant une page web dynamique. Je peux aujourd'hui dire que ce but n'a été que partiellement atteint, cependant je suis très satisfait de la partie réalisée. J'ai longtemps travaillé sur ce projet, la partie nécessitant le plus de temps étant la base de données. La mise en place du matériel a aussi été compliquée.

Afin d'améliorer mon projet, je pense que l'utilisation d'une base plus puissante que SQLite soit de mise, ainsi qu'une meilleure calibration du capteur de pression. Du côté de la page web, il serait intéressant de créer des graphiques de la température et de la pression en fonction du temps, pour établir une tendance générale sur la semaine, par exemple (on pourrait pour cela s'aider de la librairie pChart[8]). Ceci permettrait aussi d'être plus précis pour les prévisions. On pourrait aussi ajouter d'autres capteurs, comme un hygromètre (taux d'humidité dans l'air)[9] ou encore un capteur de luminosité (quantité d'ensoleillement)[10].

Références

Notes

[1] http://bit.ly/2FTnlhn

[2] http://bit.ly/1was5pD

[3] https://bit.ly/2HtHHSA

[4] http://fritzing.org/home/

[5] https://pimylifeup.com/raspberry-pi-lcd-16x2/

[6] https://bit.ly/1RadDJd

[7] https://bit.ly/2rEINQI

[8] http://www.pchart.net/

[9] https://bit.ly/2Il2QLb

[10] https://bit.ly/2rFagBI