Notre deuxième station météo
Notre deuxième station météo

Si ce n’est pas encore fait, je vous propose de commencer par lire la présentation générale de ce projet ici

Sur le même modèle que la partie 2, nous allons réaliser un deuxième module météo, qui, en plus d’un capteur de température, apportera une mesure de l’hygrométrie et une mesure de la pression atmosphérique.

Si vous ne souhaitez qu’un module, vous pouvez si vous le souhaiter enrichir votre premier montage. Il faudra alors sans doute adapter le code de cette partie afin qu’il soit compatible avec les pins que vous avez choisi sur votre arduino.

Et comme toujours, exercez vous sur une platine d’essai avant de souder!

Matériel nécessaire

Pour les tests:

En utilisation nominale :

  • Un arduino nano ou équivalent
    • Pour ce montage, j’ai un arduino pro micro, mais cela ne devrait pas avoir d’influence
  • Des PCBs
  • Si elles ne sont pas fournies avec vos modules radio, des antennes
  • Si vous souhaitez créer une boite pour votre montage final, il vous sera utile de déporte le port USB : Voici ce dont vous aurez besoin

Présentation générale

Dans les grandes lignes, ce module est très similaire au précédent. Il est contacté par l’arduino maître, effectue ses mesures et les renvoie.

Il enverra cependant plus d’informations puisqu’en plus de la température, l’hygrométrie et la pression atmosphérique sont mesurées.

Trois librairies supplémentaires sont utilisées

  • SFE_BMP180: pour la gestion du baromètre
  • DHT: pour la gestion de l’hygromètre
  • OneWire: Comme à la partie 2

Les librairies doivent être collés dans le répertoire libraries de l’IDE

Pour le DHT, de nombreuses informations sur son utilisation sont disponibles ici

Le montage

Et voilà le schéma!

Une station météo évoluée

Les points importants du montage:

  • Le baromètre BMP180 communique avec l’arduino via les ports SDA et SCL.
    • Sur l’arduino nano, ou sur l’arduino UNO, ils correspondent respectivement aux pins A4 et A5, comme explicité ici
    • Ces pins diffèrent en fonction de l’arduino, faites attention dans le cas ou vous travaillez sur un autre arduino
  • Les pins SCL et SDA sont inhérents aux bus I2C qui permet à plusieurs composants de communiquer à travers les même pins, comme pour le bus 1-Wire
  • Pour le HC12, rien de neuf par rapport à la partie 2
    • SET: 10
    • TXD: 9
    • RXD: 7
  • Pour le DS18B20, rien de neuf non plus
    • DATA: 5
    • Une résistance de tirage entre le +5V et le pin DATA
  • Le DHT22 se branche normalement sur un pin
    • DATA: 3

Le code

Voila le code que je vous propose pour gérer l’ensemble de ces composants. N’hésitez pas à proposer des améliorations!

exclave_meteo.ino

#include <OneWire.h>
#include <SFE_BMP180.h>
#include <Wire.h>

#include <SoftwareSerial.h>
#include <DHT.h>


#define VW_MAX_MESSAGE_LEN 200
#define SET_PIN 10
#define ALTITUDE 68.0 // Altitude Appartement

#define DHTTYPE DHT22
#define DHTPIN 3

/* Broche du bus 1-Wire */
const byte BROCHE_ONEWIRE = 5;
boolean sendInfos = false;

SoftwareSerial hc12(9, 7);
DHT dht(DHTPIN, DHTTYPE);
SFE_BMP180 pressure;

char EOT[1];
char EOL[1];


/* Code de retour de la fonction getTemperature() */
enum DS18B20_RCODES {
  READ_OK,  // Lecture ok
  NO_SENSOR_FOUND,  // Pas de capteur
  INVALID_ADDRESS,  // Adresse re?ue invalide
  INVALID_SENSOR  // Capteur invalide (pas un DS18B20)
};

/* Cr?ation de l'objet OneWire pour manipuler le bus 1-Wire */
OneWire ds(BROCHE_ONEWIRE);


/**
 * Fonction de lecture de la temp?rature via un capteur DS18B20.
 */
byte getTemperature(float *temperature, byte reset_search) {
  byte data[9], addr[8];
  // data[] : Donn?es lues depuis le scratchpad
  // addr[] : Adresse du module 1-Wire d?tect?
  
  /* Reset le bus 1-Wire ci n?cessaire (requis pour la lecture du premier capteur) */
  if (reset_search) {
    ds.reset_search();
  }
 
  /* Recherche le prochain capteur 1-Wire disponible */
  if (!ds.search(addr)) {
    // Pas de capteur
    Serial.println("NO SENSOR");
    return NO_SENSOR_FOUND;
  }
  
  /* V?rifie que l'adresse a ?t? correctement re?ue */
  if (OneWire::crc8(addr, 7) != addr[7]) {
    // Adresse invalide
    Serial.println("INVALID_ADDRESS");
    return INVALID_ADDRESS;
  }
 
  /* V?rifie qu'il s'agit bien d'un DS18B20 */
  if (addr[0] != 0x28) {
    // Mauvais type de capteur
    Serial.println("INVALID_SENSOR");
    return INVALID_SENSOR;
  }
 
  /* Reset le bus 1-Wire et s?lectionne le capteur */
  ds.reset();
  ds.select(addr);
  
  /* Lance une prise de mesure de temp?rature et attend la fin de la mesure */
  ds.write(0x44, 1);
  delay(800);
  
  /* Reset le bus 1-Wire, s?lectionne le capteur et envoie une demande de lecture du scratchpad */
  ds.reset();
  ds.select(addr);
  ds.write(0xBE);

 /* Lecture du scratchpad */
  for (byte i = 0; i < 9; i++) {
    data[i] = ds.read();
  }
   
  /* Calcul de la temp?rature en degr? Celsius */
  *temperature = ((data[1] << 8) | data[0]) * 0.0625; 
  
  // Pas d'erreur
  return READ_OK;
}

byte getPression(double *Pout, double *p0out){
  char status;
  double T,P,p0,a;
  //Debut mesure temp
  status = pressure.startTemperature();
  
  if (status != 0)
  {
    delay(status);
    status = pressure.getTemperature(T);
    {
      //Debut mesure Pression
      status = pressure.startPressure(3);
      if (status != 0)
      {
        delay(status);
        status = pressure.getPressure(P,T);
        if (status != 0)
        {
          *Pout = P;
          p0 = pressure.sealevel(P,ALTITUDE);
          *p0out = p0;
          return 0;
        }
      }
    }
  }
  return -1;
}

void readSerial(unsigned int MAXBUF, char* buffer){
  
    buffer[0] = 0;
    int i = 0;
    while(hc12.available() && i < MAXBUF){
      
      buffer[i++] = hc12.read();
      delay(10);
    }
  }    

/** Fonction setup() **/
void setup() {

  /* Initialisation du port s?rie */
  Serial.begin(2400);
  
  int i = 0;
  dht.begin();
    
  pinMode(SET_PIN,OUTPUT);
  digitalWrite(SET_PIN,LOW);
  delay(300);
  hc12.begin(2400);
  hc12.print("AT+B2400");
  delay(200);
  hc12.print("AT+C093");
  delay(200);
  hc12.print("AT+P8");
  delay(200);
  digitalWrite(SET_PIN,HIGH);// enter transparent mode
  
  if (pressure.begin())
    Serial.println("BMP180 init success");
  else
  {
    Serial.println("BMP180 init fail\n\n");
  }
  
  EOT[0] = 4;
  EOL[0] = '\n';
}


void reinitBuf(char* buf, int bufsize)
{
  for(int i = 0 ; i < bufsize; i++){
    buf[i] = 0;
  }
}

/** Fonction loop() **/
void loop() {
  byte taille_messageRx = 8;
  char messageRx[taille_messageRx];
  readSerial(taille_messageRx, messageRx);
  if (messageRx[0] != 0) {
    Serial.println((char*)messageRx);
    if(strncmp((char*)messageRx, "CALL QT", 7) == 0){
      Serial.println((char*) "Appel recu"); // Affiche le message
      sendInfos=true;
    }
  }
  
  if(sendInfos){
    delay(800);
    //TEMPERATURE
    float temperature = 0;
    /* Lit la temp?rature ambiante ? ~1Hz */
    if (getTemperature(&temperature, true) != READ_OK) {
      Serial.println(F("Erreur de lecture du capteur temp?rature"));
      return;
    }
  
    //PRESSION
    double P,p0;
    boolean pressionOk = true;
    if (getPression(&P, &p0) != 0) {
      Serial.println(F("Erreur de lecture du capteur pression"));
      pressionOk = false;
    }
    
    //HYGRO
    float hum = dht.readHumidity();;
    boolean hygroOk = true;
    if (isnan(hum)) {
      hygroOk = false;
      Serial.println(F("Failed to read from DHT sensor!"));
    }          
      
    char message[100] = "";
    reinitBuf(message, 100);
    char buf[10];
      
    strcat(message, "RECE QT\n");
 
    reinitBuf(buf, 10);;
    strcat(message, "RECE T ");
    dtostrf(temperature, 2, 2, buf);
    strcat(message, buf);
    strcat(message, "\n");
    
    if(pressionOk){
      reinitBuf(buf, 10);
      strcat(message, "RECE AP ");
      dtostrf(P, 4, 1, buf);
      strcat(message, buf);
      strcat(message, "\n");
    
      reinitBuf(buf, 10);
      strcat(message, "RECE RP ");
      dtostrf(p0, 4, 1, buf);
      strcat(message, buf);
      strcat(message, "\n");
    }
    
    if(hygroOk){
      reinitBuf(buf, 10);
      strcat(message, "RECE HH ");
      dtostrf(hum, 4, 2, buf);
      strcat(message, buf);
    }
    strcat(message, EOT);
    strcat(message, "\n");
    Serial.print(message);
    Serial.println("");
    hc12.flush();
    hc12.write(message);
    sendInfos = false;
  }
}  

Les pins peuvent être paramétrés:

  • Ligne 13
  • Ligne 16
  • Ligne 19

La pression relative que le code communique, celle que vous entendez à la météo, dépend de votre altitude. Il faut donc configurer votre altitude ligne 10.

Elle est calculée par rapport à la pression absolue, également communiquée par l’arduino

Par ailleurs, n’oubliez pas de configurer le HC12 dans la fonction setup pour qu’il soit compatible avec l’arduino maître

Une fois qu’une demande de mesure est reçue, les 3 mesures seront prises successivement, formatées, et envoyées à l’arduino maître!

Modification du programme Java

Maintenant que cette nouvelle station météo est prête, activez la dans le fichier de configuration

  • mode.meteo1.activated=1

Conclusion

Voila! Vous avez maintenant deux stations météo, et une application qui les pilote! Les graphiques de votre site web devraient commencer à se remplir 🙂

Le chapitre suivant traitera d’un module permettant un contrôle automatique du chauffage

Dernière modification: 12 novembre 2019

Auteur

Commentaires

Écrire une réponse ou un commentaire

Votre adresse email ne sera pas publiée.

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.