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.