STATION METEO Arduino basique

petit montage a base d’ ARDUINO pour faire une station météo avec 3 fonctions basiques: température , pression et hygrométrie et une fonction d’enregistrement des données sur carte SD.

MATERIEL:

  • un Arduino Uno
  • un SD RTC shield (DeekRobot ou Adafruit)
  • une carte SD
  • un module DHT 22
  • un module BMP280
  • alimentation par pile 9V et cordon jack

SD RTC SHIELD:

sa fonction est de proposer sur un shield les fonctions lecture/écriture sur carte SD ainsi qu’une horloge temps réelle a pile de sauvegarde. cette carte a été abordée de façon plus détaillée ici .

le module DHT 22

c’est le même type de module que le DHT11 utilisé en exemple dans la rubrique ARDUINO SD RTC shiel mais avec des caractéristiques plus performantes ( plage de température et précision). comme le DHT 11 , il délivre la température et l’hygrométrie

le module BMP280

le module BMP280 délivre lui 2 informations ; une température et une pression

CABLAGE

broche out du DHT22 sur la broche 2 de l’arduino et Vcc et GND sur 5V et GND arduino

pour le BMP280, nous allons l’utiliser en mode I2C . il faut donc brancher GND et Vcc sur GND et 5V arduino et SCL et SDA du BMP280 sur les broche SCL et SDA de l’arduino uno . l’arduino UNO possede 2 paires de broches I2C ( SCL + SDA)=> voir le pinout ICI

le SD RTC shield doit etre “pluggué” sur l’arduino UNO puis les 2 composants (DHT22 et BMP280) ainsi que la pile reliés a l’UNO ( le SD shield n’est pas représenté sur le schéma fritzing ci dessus) : pour le DHT22 et le BMP280 , utiliser une petite platine proto .

NOTA: attention, une pile type 9V ne permet un fonctionnement que de quelques heures. pour une station météo d’observatoire , il faudra soit une alim secteur soit une alim batterie sur panneau solaire.

PROGRAMME ARDUINO

le programme est un “melting-pot” de plusieurs programmes d’exemples joints avec les différentes librairies utilisées.

très synthétiquement, on charge les différentes librairies nécessaires ( wire.h pour l’I2C, SPI.h pour le lecteur SD, SD.h pour l’utilisation de la carte SD, RTClib.h pour l’horloge temps réel, Adafruit_BMP.h pour le BMP280, DHT.H pour le DHT22), puis on defini quelques constante et brochage . le programme void setup lance les differentes fonctions et parametres liées aux librairies, la boucle “void loop” lit les données des capteurs et les stocke dans des variables ainsi que année, mois, jour et heures/minutes/secondes de l’horloge RTC.

pour la temperature , on recuperer les 2 temperatures t1 et t2 des 2 capteurs et on calcule la moyenne des 2 => ligne ” tm = (t1+t2)/2

une serie de parametres “filename[x] permet de definir chaque caractère du nom de fichier d’enregistrement des données => un fichier par jour de l’année suivant la syntaxe : année mois jour. puis le fichier est ouvert , les données enregistrées dedans sous forme string CSV et le fichier est refermé , le programme attends 60 secondes puis recommence => un enregistrement de données toutes les minutes.

#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <RTClib.h>
#include <Adafruit_BMP280.h>
#include "DHT.h"
const int chipSelect = 10;
#define DHTPIN 2 
#define DHTTYPE DHT22
DHT dht(DHTPIN, DHTTYPE);
RTC_DS1307 RTC;
Adafruit_BMP280 bmp; // I2C

char filename [] = "00000000.CSV";

void setup() {
  Serial.begin(9600);
  Wire.begin();
  RTC.begin();
  // ligne suivante pour initialiser l'heure du RTC/PC  la premiere fois 
  // decocher les // , telecharger , puis remettre les // 
  // RTC.adjust(DateTime(__DATE__, __TIME__));
  dht.begin();
  bmp.begin(); 
   /* config par defaut suivant datasheet */
  bmp.setSampling(Adafruit_BMP280::MODE_NORMAL,     
                  Adafruit_BMP280::SAMPLING_X2,     
                  Adafruit_BMP280::SAMPLING_X16,    
                  Adafruit_BMP280::FILTER_X16,     
                  Adafruit_BMP280::STANDBY_MS_500); 
  SD.begin(chipSelect);               
}

void loop() { 
  float h = dht.readHumidity();
  float t1 = dht.readTemperature();
  float t2 = bmp.readTemperature();
  float p = bmp.readPressure();
  float  tm = (t1+t2)/2 ;   
  DateTime now = RTC.now();
  uint16_t year1 = now.year();
  uint16_t month1 = now.month();
  uint16_t day1 = now.day();
  uint16_t hour1 = now.hour();
  uint16_t minute1 = now.minute();
  uint16_t second1 = now.second();
  filename[0] = (year1/1000)%10 + '0';
  filename[1] = (year1/100)%10 + '0';
  filename[2] = (year1/10)%10 + '0';
  filename[3] = (year1)%10 + '0';
  filename[4] = month1/10 + '0'; 
  filename[5] = (month1)%10 + '0'; 
  filename[6] = day1/10 + '0'; 
  filename[7] = (day1)%10 + '0';
  filename[8] = '.';
  filename[9] = 'c';
  filename[10] ='s';
  filename[11] ='v';
  File dataFile = SD.open(filename, FILE_WRITE);
  String dataReg = String(year1) + "/" + String( month1) + "/" + String(day1) +";" + String(hour1) + ":"+ String(minute1) + ":" + String(second1) + ";" + String(tm) + ";" + String(h) + ";" + String(p) + ";" ; 
  dataFile.println(dataReg);
  dataFile.close();
  delay(60000);
}

voici un exemple de données enregistrées:

fichier CSV ouvert avec wordpad: date ; heure ; température ; humidité ; pression (en pascals)

le même fichier CSV ouvert avec LibreOffice ou Excel , l’enregistrement avec des “;” séparant les paquets de données permet de récupérer chaque paquet dans une colonne différente sur le tableur.

AMELIORATION

nous allons améliorer la station météo en ajoutant un écran LCD I2C 4 lignes de 20 caractères pour y afficher , date et heure sur la première ligne, température sur la deuxième ligne , humidité et pression sur la troisième ligne. la quatrième ligne est en réserve pour la vitesse et la direction du vent .

le schéma de câblage avec l’écran I2C devient:

le programme deviens (évolutions en bleu):

#include <Wire.h>
#include <SPI.h>
#include <LiquidCrystal_I2C.h>
#include <SD.h>
#include <RTClib.h>
#include <Adafruit_BMP280.h>
#include "DHT.h"
const int chipSelect = 10;
#define DHTPIN 2 
#define DHTTYPE DHT22
DHT dht(DHTPIN, DHTTYPE);
RTC_DS1307 RTC;
Adafruit_BMP280 bmp; // I2C
LiquidCrystal_I2C lcd(0x27,20,4);
char filename [] = "00000000.CSV";
void setup() {
  Serial.begin(9600);
  lcd.init();
  lcd.backlight();
  Wire.begin();
  RTC.begin();
  // ligne suivante pour initialiser l'heure du RTC/PC  la premiere fois 
  // decocher les // , telecharger , puis remettre les // 
  // RTC.adjust(DateTime(__DATE__, __TIME__));
  dht.begin();
  bmp.begin(); 
   /* config par defaut suivant datasheet */
  bmp.setSampling(Adafruit_BMP280::MODE_NORMAL,     
                  Adafruit_BMP280::SAMPLING_X2,     
                  Adafruit_BMP280::SAMPLING_X16,    
                  Adafruit_BMP280::FILTER_X16,     
                  Adafruit_BMP280::STANDBY_MS_500); 
  SD.begin(chipSelect);               
}
void loop() { 
  float h = dht.readHumidity();
  float t1 = dht.readTemperature();
  float t2 = bmp.readTemperature();
  float p = bmp.readPressure();
  float tm = (t1+t2)/2;  
  DateTime now = RTC.now();
  uint16_t year1 = now.year();
  uint16_t month1 = now.month();
  uint16_t day1 = now.day();
  uint16_t hour1 = now.hour();
  uint16_t minute1 = now.minute();
  uint16_t second1 = now.second();
  filename[0] = (year1/1000)%10 + '0';
  filename[1] = (year1/100)%10 + '0';
  filename[2] = (year1/10)%10 + '0';
  filename[3] = (year1)%10 + '0';
  filename[4] = month1/10 + '0'; 
  filename[5] = (month1)%10 + '0'; 
  filename[6] = day1/10 + '0'; 
  filename[7] = (day1)%10 + '0';
  filename[8] = '.';
  filename[9] = 'c';
  filename[10] ='s';
  filename[11] ='v';  
  String date = String(day1) + "/" + String(month1) + "/" + String(year1);
  String time = String(hour1) + ":" + String(minute1) + ":" + String(second1);
  lcd.setCursor(0,0);
  lcd.print(date) ;
  lcd.setCursor(11,0);
  lcd.print(time) ;
  lcd.setCursor(7,1);
  lcd.print(tm) ; 
  lcd.setCursor(12,1);
  lcd.print(char(223)) ;
  lcd.setCursor(13,1);
  lcd.print("C") ;     
  lcd.setCursor(0,2);
  lcd.print(h) ;
  lcd.setCursor(5,2);
  lcd.print("%Hu") ; 
  int roundp =  int(p);
  lcd.setCursor(9,2);
  lcd.print(p) ;
  lcd.setCursor(18,2);
  lcd.print("Pa") ;  
  File dataFile = SD.open(filename, FILE_WRITE);
  String dataReg = String(year1) + "/" + String( month1) + "/" + String(day1) +";" + String(hour1) + ":"+ String(minute1) + ":" + String(second1) + ";" + String(tm) + ";" + String(h) + ";" + String(p) + ";" ; 
  dataFile.println(dataReg);
  dataFile.close();
  delay(60000);
}

et visuellement , le montage fini en fonctionnement , ressemble a cela:

la version finale de la station integrera un anemometre et une girouette

pour rendre la station autonome , elle sera alimentée par un panneau solaire 12V – 5 watts alimentant une batterie 12V.