Projet : station météo
Présentation du projet
Dans ce projet final, on assemble tout ce qu'on a appris pour construire une station météo autonome. Elle mesure la température, l'humidité et la pression atmosphérique, affiche les données sur un écran LCD, et les enregistre sur une carte SD pour un suivi dans le temps.
Matériel nécessaire
- Arduino Uno (ou compatible)
- Capteur DHT11 — température (0–50 °C) et humidité relative (20–90 %)
- Capteur BMP280 — pression atmosphérique et température (I2C)
- Afficheur LCD I2C 16×2 — module avec adaptateur PCF8574
- Module carte SD — avec carte microSD formatée en FAT32
- Breadboard et fils de connexion
- Résistance 10 kΩ (pull-up pour le DHT11)
Schéma de câblage
Voici comment connecter chaque composant à l'Arduino Uno :
DHT11 (données numériques)
- VCC → 5 V
- GND → GND
- DATA → pin 7 (avec résistance pull-up 10 kΩ vers 5 V)
BMP280 (I2C)
- VCC → 3.3 V
- GND → GND
- SDA → pin A4 (SDA Arduino Uno)
- SCL → pin A5 (SCL Arduino Uno)
LCD I2C 16×2
- VCC → 5 V
- GND → GND
- SDA → pin A4 (bus I2C partagé avec BMP280)
- SCL → pin A5 (bus I2C partagé avec BMP280)
Module carte SD (SPI)
- VCC → 5 V
- GND → GND
- MOSI → pin 11 (SPI MOSI)
- MISO → pin 12 (SPI MISO)
- SCK → pin 13 (SPI SCK)
- CS → pin 10 (Chip Select)
Le BMP280 et le LCD partagent le même bus I2C (pins A4/A5). Ils ont des adresses différentes
(BMP280 : 0x76 ou 0x77 ; LCD : 0x27 en général), donc ils coexistent
sans problème. Utilise un scanner I2C pour vérifier les adresses de tes modules si tu n'obtiens
rien à l'écran.
Bibliothèques nécessaires
Installe ces bibliothèques depuis le Gestionnaire de bibliothèques (menu Outils → Gérer les bibliothèques…) de l'IDE Arduino :
DHT sensor librarypar Adafruit — pour le DHT11Adafruit BMP280 Librarypar Adafruit — pour le BMP280LiquidCrystal I2Cpar Frank de Brabander — pour l'écran LCDSD— bibliothèque officielle Arduino, déjà incluse dans l'IDE
Dépendance automatique : quand tu installes DHT sensor library,
l'IDE te propose aussi d'installer Adafruit Unified Sensor. Accepte — c'est une
dépendance requise. De même pour Adafruit BMP280 Library.
Code étape par étape
Étape 1 — Lire le DHT11
Commence par tester le DHT11 seul avant d'assembler le projet complet.
La bibliothèque DHT fournit les méthodes readTemperature() et readHumidity().
// Test du capteur DHT11
#include <DHT.h>
#define PIN_DHT 7
#define TYPE_DHT DHT11
DHT dht(PIN_DHT, TYPE_DHT);
void setup() {
Serial.begin(9600);
dht.begin();
Serial.println("DHT11 prêt");
}
void loop() {
float temp = dht.readTemperature(); // °C
float hum = dht.readHumidity(); // %
// Vérifier si la lecture a réussi
if (isnan(temp) || isnan(hum)) {
Serial.println("Erreur de lecture DHT11 !");
} else {
Serial.print("Temp : ");
Serial.print(temp);
Serial.print(" °C Humidité : ");
Serial.print(hum);
Serial.println(" %");
}
delay(2000); // Le DHT11 ne peut pas être lu plus d'1 fois/2 s
}
Étape 2 — Lire le BMP280
Le BMP280 communique en I2C. La bibliothèque Adafruit gère la conversion des valeurs brutes du capteur en Pascals et en degrés Celsius.
// Test du capteur BMP280
#include <Wire.h>
#include <Adafruit_BMP280.h>
Adafruit_BMP280 bmp;
void setup() {
Serial.begin(9600);
if (!bmp.begin(0x76)) {
Serial.println("BMP280 non trouvé ! Vérif câblage ou adresse (0x76 / 0x77)");
while (1); // blocage
}
Serial.println("BMP280 prêt");
}
void loop() {
float temp = bmp.readTemperature(); // °C
float pression = bmp.readPressure() / 100.0F; // Pa → hPa
Serial.print("Temp BMP : "); Serial.print(temp); Serial.print(" °C ");
Serial.print("Pression : "); Serial.print(pression); Serial.println(" hPa");
delay(2000);
}
Étape 3 — Afficher sur le LCD I2C
L'objet LiquidCrystal_I2C prend en paramètre l'adresse I2C du module,
le nombre de colonnes (16) et de lignes (2).
setCursor(col, row) positionne le curseur.
// Test de l'afficheur LCD I2C
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
// Adresse 0x27, 16 colonnes, 2 lignes
LiquidCrystal_I2C lcd(0x27, 16, 2);
void setup() {
lcd.init();
lcd.backlight();
lcd.setCursor(0, 0); // col 0, ligne 0
lcd.print("Station Meteo");
lcd.setCursor(0, 1); // col 0, ligne 1
lcd.print("Initialisation...");
delay(2000);
lcd.clear();
}
void loop() {
lcd.setCursor(0, 0);
lcd.print("Temp: 22.5 C ");
lcd.setCursor(0, 1);
lcd.print("Hum: 58 % ");
delay(2000);
}
Le programme complet
On assemble maintenant les trois capteurs et l'afficheur dans un seul programme. Le LCD alterne entre deux pages : température/humidité (DHT11) et pression (BMP280).
#include <DHT.h>
#include <Wire.h>
#include <Adafruit_BMP280.h>
#include <LiquidCrystal_I2C.h>
// ===== CONFIGURATION =====
#define PIN_DHT 7
#define TYPE_DHT DHT11
DHT dht(7, DHT11);
Adafruit_BMP280 bmp;
LiquidCrystal_I2C lcd(0x27, 16, 2);
// Variables de mesure
float temperature = 0;
float humidite = 0;
float pression = 0;
// Contrôle de l'affichage alterné
bool affichePage1 = true;
unsigned long dernierChangement = 0;
const unsigned long DELAI_AFFICHAGE = 3000; // ms
unsigned long derniereLecture = 0;
const unsigned long DELAI_LECTURE = 2000;
// ===== SETUP =====
void setup() {
Serial.begin(9600);
// Initialisation LCD
lcd.init();
lcd.backlight();
lcd.setCursor(0, 0); lcd.print("Station Meteo");
lcd.setCursor(0, 1); lcd.print("Demarrage...");
// Initialisation DHT11
dht.begin();
// Initialisation BMP280
if (!bmp.begin(0x76)) {
lcd.setCursor(0, 1);
lcd.print("BMP280 ERR! ");
Serial.println("BMP280 non trouvé !");
while (1);
}
delay(2000);
lcd.clear();
Serial.println("Prêt.");
}
// ===== LIRE LES CAPTEURS =====
void lireCapteurs() {
float t = dht.readTemperature();
float h = dht.readHumidity();
if (!isnan(t) && !isnan(h)) {
temperature = t;
humidite = h;
}
pression = bmp.readPressure() / 100.0F;
}
// ===== AFFICHER SUR LCD =====
void afficherLCD() {
if (affichePage1) {
// Page 1 : température + humidité
lcd.setCursor(0, 0);
lcd.print("Temp: ");
lcd.print(temperature, 1);
lcd.print(" C ");
lcd.setCursor(0, 1);
lcd.print("Hum: ");
lcd.print(humidite, 0);
lcd.print(" % ");
} else {
// Page 2 : pression atmosphérique
lcd.setCursor(0, 0);
lcd.print("Pression : ");
lcd.setCursor(0, 1);
lcd.print(pression, 1);
lcd.print(" hPa ");
}
}
// ===== LOOP =====
void loop() {
unsigned long maintenant = millis();
// Lire les capteurs toutes les 2 secondes
if (maintenant - derniereLecture >= DELAI_LECTURE) {
derniereLecture = maintenant;
lireCapteurs();
// Aussi envoyer sur le port série
Serial.print("T:"); Serial.print(temperature); Serial.print("C ");
Serial.print("H:"); Serial.print(humidite); Serial.print("% ");
Serial.print("P:"); Serial.print(pression); Serial.println("hPa");
}
// Changer de page toutes les 3 secondes
if (maintenant - dernierChangement >= DELAI_AFFICHAGE) {
dernierChangement = maintenant;
affichePage1 = !affichePage1;
afficherLCD();
}
}
Enregistrement sur carte SD
On ajoute l'enregistrement dans un fichier meteo.csv sur la carte SD.
Chaque ligne contient un numéro de mesure, la température, l'humidité et la pression.
Le fichier s'ouvre en mode append (FILE_WRITE) pour ne pas écraser les données.
// En haut du fichier, ajouter :
#include <SPI.h>
#include <SD.h>
#define PIN_CS_SD 10
bool sdDisponible = false;
unsigned long compteurMesures = 0;
// Dans setup(), après les autres init :
if (!SD.begin(PIN_CS_SD)) {
Serial.println("Carte SD non trouvée — données non enregistrées");
sdDisponible = false;
} else {
sdDisponible = true;
// Écrire l'en-tête CSV si le fichier n'existe pas encore
if (!SD.exists("meteo.csv")) {
File f = SD.open("meteo.csv", FILE_WRITE);
if (f) {
f.println("mesure,temperature_C,humidite_pct,pression_hPa");
f.close();
}
}
Serial.println("Carte SD prête.");
}
// Fonction d'enregistrement à appeler après lireCapteurs()
void enregistrerSD() {
if (!sdDisponible) return;
File fichier = SD.open("meteo.csv", FILE_WRITE);
if (fichier) {
compteurMesures++;
fichier.print(compteurMesures); fichier.print(",");
fichier.print(temperature, 1); fichier.print(",");
fichier.print(humidite, 0); fichier.print(",");
fichier.println(pression, 1);
fichier.close();
} else {
Serial.println("Erreur ouverture meteo.csv");
}
}
// Dans loop(), après lireCapteurs() :
enregistrerSD();
Le fichier meteo.csv sur la carte SD ressemblera à :
mesure,temperature_C,humidite_pct,pression_hPa
1,22.5,58,1013.2
2,22.6,57,1013.1
3,22.5,58,1013.3
4,22.7,56,1013.0
Une fois la carte SD retirée et connectée à ton ordinateur, tu peux ouvrir ce fichier dans un tableur (Excel, LibreOffice Calc, Google Sheets) pour tracer des graphiques d'évolution sur la journée.
Améliorations possibles
Affichage alterné par bouton
Ajoute un bouton sur la pin 2 pour basculer manuellement entre les pages du LCD au lieu d'attendre le timer :
#define PIN_BOUTON 2
// Dans setup() :
pinMode(PIN_BOUTON, INPUT_PULLUP); // résistance pull-up interne
// Dans loop() — détecter un appui (LOW = appuyé avec INPUT_PULLUP) :
static bool etatPrecedent = HIGH;
bool etatActuel = digitalRead(PIN_BOUTON);
if (etatPrecedent == HIGH && etatActuel == LOW) {
// Front descendant = appui détecté
affichePage1 = !affichePage1;
afficherLCD();
delay(50); // anti-rebond simple
}
etatPrecedent = etatActuel;
Idées pour aller plus loin
- Ajouter un module RTC DS3231 (horloge temps réel) pour horodater les mesures dans le CSV
- Ajouter une alarme LED ou buzzer si la température dépasse un seuil
- Remplacer l'Arduino par un ESP8266 ou ESP32 pour envoyer les données en WiFi
- Publier les mesures via le protocole MQTT vers un broker (Mosquitto) et les afficher dans Grafana ou Home Assistant
Prochaine étape : avec un ESP8266 NodeMCU, tu peux remplacer
presque tout le câblage par du WiFi. La bibliothèque PubSubClient permet d'envoyer
les mesures en MQTT en moins de 20 lignes de code supplémentaires. C'est le point de départ
d'une vraie domotique DIY.
Bilan du module Arduino
Tu as parcouru les 8 leçons du module. Voici ce que tu maîtrises maintenant :
- L'environnement Arduino : IDE, carte Uno, structure
setup()/loop() - Les entrées/sorties numériques :
pinMode(),digitalWrite(),digitalRead() - Les entrées analogiques :
analogRead(), conversion en tension, capteurs résistifs - Le PWM :
analogWrite(), contrôle de LED et de moteur DC - La communication série :
Serial.print(),Serial.read(), moniteur série - Les bibliothèques I2C et SPI : Wire, adressage, EEPROM externe, modules courants
- Un projet complet : capteurs DHT11 et BMP280, afficheur LCD, enregistrement SD
- DHT11 sur pin numérique (pin 7) — lecture toutes les 2 secondes minimum. Toujours vérifier
isnan(). - BMP280 et LCD partagent le bus I2C (A4/A5) — chacun a son adresse, pas de conflit.
- La carte SD utilise le bus SPI (pins 10–13) — ne jamais utiliser pin 10 pour autre chose.
- Utilise
millis()au lieu dedelay()pour gérer plusieurs temporisations en parallèle sans bloquer le programme. - Le fichier CSV permet une analyse facile des données dans un tableur ou avec Python/matplotlib.
- Prochaine étape : ESP8266/ESP32 pour passer du hardware au IoT connecté.