Capteur de température et d’humidité sans fil

L’objectif de ce tutoriel est de concevoir un capteur de température et d’humidité sans fil avec un Arduino Pro Mini sur batterie et de récupérer ces informations sur le logiciel de domotique Jeedom tournant sur un Raspberry Pi.

Côté émetteur, l’Arduino Pro Mini est alimenté par une batterie Li-Ion de 3,7 V et les mesures de température et d’humidité sont réalisées grâce à un capteur DHT22. Les données sont envoyées au récepteur via un module radio HC12.

Côté récepteur, les données sont reçues par une Raspberry Pi grâce à un autre module radio HC12. Les données sont transmisses au serveur domotique Jeedom via le protocole MQTT. Les données stockées dans le serveur Jeedom sur le Raspberry Pi peuvent être visualisées depuis n’importe quel équipement (smartphone, tablette…) si le Raspberry Pi est connecté au réseau wifi.

Ce tutoriel est composé de deux parties :

  1. Réalisation du capteur sans fil avec un Arduino Pro Mini
  2. Intégration des données dans le logiciel domotique Jeedom sur un Raspberry Pi

Mots clés : Arduino ; Capteur sans fil HC12 ; RF 433 MHz; Raspberry Pi ; Jeedom ; MQTT

Le récepteur HC12 et le Raspberry Pi à gauche – L’émetteur HC12, le capteur DHT22 et le microcontrôleur Arduino Pro Mini à droite

Première partie : réalisation du capteur sans fil avec un Arduino Pro Mini

Le Matériel

Liste du matériel nécessaire pour le capteur sans fil :

Arduino Pro Mini

Il existe deux versions de l’Arduino Pro Mini : la version 3,3 V / 8 MHz et la version 5 V 16 MHz.

L’Arduino Pro Mini version 3,3 V / 8 MHz convient parfaitement à notre émetteur radio, pour plusieurs raisons :

  • sa taille idéale pour un petit boitier extérieur
  • sa consommation minimale lorsque la LED a été supprimée (dessoudée ou détruite avec un fer à souder comme montré sur la photo ci-dessous)
  • son alimentation 3,35 – 12 V parfaite pour une batterie Li-Ion de 3,7 V
  • sa puissance à 8 MHz largement satisfaisante pour notre application
Suppression de la LED

Le module radio HC12

Module radio HC12

Le module radio HC12 permet des communications radio longue distance (jusqu’à 1000m), il est donc particulièrement adapté dans le cas où le capteur sans fil extérieur est placé dans le jardin et que le récepteur est à l’intérieur de la maison.

La communication avec le module HC12 se fait au travers d’une interface série, ce qui simplifie grandement son utilisation sur divers équipements (Arduino, Raspberry Pi…).

Le module opère sur une bande de fréquence de 433.4 MHz à 473 MHz, avec une puissance de transmission maximale de 100mW (20dBm).

Configuration du module HC12

Il faut passer le module en mode « commande » afin de pouvoir configurer le module. Pour ce faire, il faut mettre la valeur de la pin SET à un niveau bas (broche 4 l’Arduino mise à LOW) et envoyer la commande au module.

Canal :

Le choix du canal se fait par la commande « AT+Cxxx » où xxx est le numéro du canal. Dans ce tutoriel nous choisirons le canal 1 qui correspond à la fréquence 433,4 MHz.

Puissance :

La puissance d’émission est réglée par la commande « AT+ Px » ou x correspond à la puissance de transmission. Afin de limiter la puissance au seuil autorisé en France, nous utiliserons x=4 qui correspond à 6.3mW (8dBm).

Mode de communication radio série :

Le module supporte 4 modes différents de communication radio série (FU1, FU2, FU3 et FU4). Le mode est sélectionné par la commande « AT+FUx ».

Attention : Par défaut, le module est configuré pour transmettre sur le canal 1 (433.4 MHz) à la puissance de 100mW. Afin de respecter la réglementation locale, la puissance d’émission maximale sur la bande de fréquence 433 MHz est de 10mW (10dBm). Et la bande de fréquence 433 MHz s’étend de 433.05 à 434.79 MHz. Donc sur le module HC 12 seuls les canaux 1 (433.4 MHz), 2 (433.8 MHz), 3 (434.2 MHz) et 4 (434.6 MHz) seront autorisés, ainsi qu’une puissance P4 (8 dBm, 6.3 mW). Les canaux 5 à 100 et les puissances P5 à P8 sont interdits en France.

Le capteur de température et humidité DHT22

Le capteur de température/humidité utilisé est le AM2302 – DHT22. Il communique avec le microcontrôleur via un port série. Il peut être alimenté de 3,3 V à 6 V et convient donc à notre montage alimenté par batterie de 3,7 V nominal et 4,2 V maximal.

L’autre intérêt de ce capteur est sa faible consommation au repos: 50 µA. Ce qui est très important car nous ne remontons les températures que toutes les 30 minutes et le montage sera donc la plupart du temps en veille.

Schéma du montage

Il faut relier le module HC12 au microcontrôleur (Arduino) via une liaison série. Nous utiliserons les PIN 2 et 3 de l’Arduino avec une liaison série logicielle (SoftwareSerial), afin de laisser la liaison série de l’Arduino disponible pour la mise au point du projet.

La pin SET du HC12 permet de sélectionner le mode programmation de ce module. Elle est reliée à la PIN 4 de l’Arduino afin de pouvoir sélectionner le mode « normal » ou « commande » via l’application.

La communication des données du capteur de température/humidité AM2302 – DHT22 vers le microcontrôleur se fait au travers d’une seule broche, la PIN 7 de l’Arduino sera utilisée.

Le circuit est alimenté par une batterie Li-Ion de 3.7V (tension maximale de 4.2V et tension nominale de 3,7V).

Programme Arduino

Inclure la bibliothèque simplesleep (http://sparks.gogo.co.nz/SimpleSleep.zip) via le menu de l’IDE Arduino «Croquis / Inclure une bibliothèque / Ajouter la bibliothèque .ZIP ». Cette bibliothèque permet de mettre l’Arduino en veille prolongée afin d’en limiter la consommation électrique.

Inclure la bibliotheque « DHT sensor library » via le menu « Outils / Gérer les bibliothèques ».

Le programme se contente de lire les données du capteur DHT22 toutes les 30 minutes et d’envoyer la température et l’humidité sur la liaison radio via le module HC12.

Le message radio envoyé est formaté sous la forme de chaîne de caractères de format « S1:XX.XX:YY.YY:ZZ.ZZ » ou S1 indiqeur que c’est le capteur numéro 1, XX.XX de type float est la température en °C et YY.YY de type float est l’humidité et ZZ.ZZ de type float est la tension de la batterie. Par exemple, si la température est de 19,5°C, l’humidité de 51 % et la tension de la batterie 3,7 V, la chaîne envoyée sera par le capteur 1 sera « S1:19.50:51.00:3.70 ».

Afin de limiter la consommation électrique, le module HC12 et l’Arduino sont mis en veille entre deux émissions radio. Le capteur DHT-22 se positionne en veille automatiquement lorsque il n’y a pas de lecture via son port série.

#include "DHT.h"
#include "SoftwareSerial.h" 
#include "SimpleSleep.h"

#define DHTPIN      7           // PIN 7 reliée à DAT du DHT22
#define DHTTYPE     DHT22       // Capteur de type DHT22

#define HC12RXPIN   2           // PIN 2 reliée au RX du HC12
#define HC12TXPIN   3           // PIN 3 reliée au TX du HC12
#define HC12SETPIN  4           // PIN 4 reliée au SET du HC12

#define IDENTIFIANT_CAPTEUR 1   // Utiliser un identifiant différent pour chaque capteur

DHT dht(DHTPIN, DHTTYPE);       // Configuration du capteur DHT22
SoftwareSerial HC12Serial(HC12TXPIN, HC12RXPIN);  // Configuration du port série logiciel pour le HC12

SimpleSleep Sleep;              // Sleep permet la mise en veille basse consommation de l'arduino

const float InternalReferenceVoltage = 1.105; // Cette valeur dépend de chaque micro-contrôleur et doit être mesurée par un voltmètre

// Mesure la tension de la batterie qui alimente l'Arduino
// en utilisant cette tension comme référence et en mesurant
// la référence interne à 1,1 V avec le convertisseur
// Analogique-Numérique
// **
// **
float getBatteryVoltage(){
  float batteryVoltage=0.0;
 
  ADCSRA =  bit(ADEN);   // Active le convertisseur ADC
  ADCSRA |= bit (ADPS0) |  bit (ADPS1) | bit (ADPS2);  // Prescaler de 128
  
  ADMUX = bit (REFS0); // Positionne AVcc (tension d'alimentation du convertisseur) comme tension de référence
  ADMUX |= bit (MUX3) | bit (MUX2) | bit (MUX1); // Le canal d'entrée de l'ADC est mis sur la référence interne de 1.1V
  delay (10);                       // Laissons la mesure se stabiliser
  bitSet (ADCSRA, ADSC);            // Demarrons la conversion  
  while (bit_is_set(ADCSRA, ADSC))  // Attendons que la conversion soit finie
    { }

  batteryVoltage = InternalReferenceVoltage / ADC * 1024.0;
  Serial.print("ADC=");
  Serial.print(ADC);
  Serial.print(" , Voltage=");
  Serial.println(batteryVoltage);
  return(batteryVoltage); 
}

// Met le HC12 en veille en lui envoyant la commande AT+SLEEP
// **
// **
void SleepHC12() {
  //Serial.println("HC12 entre en veille");

  // Positionne le HC12 en mode programmation (AT) et envoie la commande "AT+SLEEP"
  digitalWrite(HC12SETPIN,LOW);   
  delay(250);
  HC12Serial.println("AT+SLEEP");
  delay(250);
  
  // Vérifie la réponse de la commande, doit être "OK+SLEEP"
  if(HC12Serial.available() > 0)  {
    String input = HC12Serial.readString();
    if (input != "OK+SLEEP\r\n") {
      Serial.println("Erreur lors de l'entree en veille");
      Serial.println(input);
      }
    }

  // Positionne le HC12 en mode normal afin que le module entre en veille
  digitalWrite(HC12SETPIN,HIGH);  
  delay(250);
}

// Sors le HC12 du mode veille en lui envoyant la commande AT
// **
// **
void wakeupHC12() {
  //Serial.println("HC12 sors du mode veille");

  // Positionne le HC12 en mode programmation (AT) et envoie la commande "AT"  
  digitalWrite(HC12SETPIN,LOW);
  delay(250);
  HC12Serial.println("AT");
  delay(250);

  // Vérifie la réponse de la commande, doit être "OK"
  if(HC12Serial.available() > 0)  { // send data FROM HC-12
    String input = HC12Serial.readString();
    if (input != "OK\r\n") {
      Serial.println("Erreur lors de la sortie de veille");
      Serial.println(input);
      }
    }  
    
  // Positionne le HC12 en mode normal    
  digitalWrite(HC12SETPIN,HIGH);
  delay(250);
}


// Configuration 
// -------------
void setup() {

  pinMode(HC12TXPIN, INPUT);    // TX du HC12 est une PIN en entrée sur l'arduino
  pinMode(HC12RXPIN, OUTPUT);   // RX du HC12 est une PIN en sortie sur l'arduino
  pinMode(HC12SETPIN,OUTPUT);   // SET du HC12 est une PIN en sortie sur l'arduino
  
  Serial.begin(9600);
  Serial.setTimeout(20);
  HC12Serial.begin(9600);         
  HC12Serial.setTimeout(20);
  
  // Démarrage du DHT22
  dht.begin();
  Serial.println("Capteur DHT 22 opérationnel");

  // Positionne le HC12 en mode programmation (AT)   
  digitalWrite(HC12SETPIN,LOW);
  delay(250);

  // Configuration par default du HC12 (canal 1, 20dBm, FU3, 9600 bauds)
  HC12Serial.println("AT+DEFAULT"); 
  delay(250);

  // Vérifie la réponse de la commande, doit être "OK+DEFAULT"
  if(HC12Serial.available() > 0)  {
    String input = HC12Serial.readString();
    if (input != "OK+DEFAULT\r\n") {
      Serial.println("Erreur lors de la configuration par default");
      Serial.println(input);      
      }
    }
    
  // Configuration de la puissance d'emission à 8 dBm (P4)
  HC12Serial.println("AT+P4");       
  delay(250);

  // Vérifie la réponse de la commande, doit être "OK+P4"
  if(HC12Serial.available() > 0)  {
    String input = HC12Serial.readString();
    if (input != "OK+P4\r\n") {
      Serial.println("Erreur lors de la configuration par default");
      Serial.println(input);      
      }
    }

  // Positionne le HC12 en mode normal    
  digitalWrite(HC12SETPIN,HIGH);  
  delay(250);

  // Vérifie si le HC12 est prêt
  if (HC12Serial.isListening()) {
    Serial.println("Module radio HC12 opérationnel");
  } else {
    Serial.println("Erreur du module radio HC12");
  }
  
  // Configure la PIN de la LED en sortie
  pinMode(LED_BUILTIN, OUTPUT);

}

// Boucle principale 
// -----------------
void loop() {

  String myStr;

  // Lit la température et l‘humidité du capteur DHT22 
  float h = dht.readHumidity();
  float t = dht.readTemperature();
  float batt = getBatteryVoltage();
  
  // Si la lecture du capteur est valide, envoyer les informations par radio
  if (isnan(h) || isnan(t)) {
    Serial.println("Erreur de lecture du DHT22 !");
  }
  else {
    // Allume la LED pour signifier le début de l'emission radio
    digitalWrite(LED_BUILTIN, HIGH);  
    
    // Reveille le HC12
    wakeupHC12();                     

    // Envoi le message "S1:XX:YY:ZZ" par radio (XX  = temperature ; YY = humidité ; ZZ = batterie voltage)
    myStr = "S"+ String(IDENTIFIANT_CAPTEUR) + ":" + String(t) +':'+String(h) +':'+String(batt);
    HC12Serial.print(myStr);

  // Eteind la LED pour signifier la fin de l'emission radio
    digitalWrite(LED_BUILTIN, LOW);  
  }

  // Attente pour permettre la fin de l'emission du message radio
  delay(250);

  // Mise en veille du HC12
  SleepHC12();        

  // Mise en veille de l'arduino pendant 30 minutes
  Sleep.deeplyFor(1800000);
}

Consommation électrique

Afin de réduire la consommation électrique, j’ai choisi les options suivantes :

  1. Suppression de la LED Power de l‘Arduino (dessoudée ou détruite)
  2. Mise en veille du module radio HC12 entre deux mesures
  3. Mise en veille de l’Arduino entre deux mesures

Ces différentes options permettent de réduire l’intensité du circuit en mode veille à 68 µA. Ce qui est crucial car le circuit sera en veille 99,94 % du temps.

Lorsque l’Arduino n’est pas en veille pour effectuer la mesure et émettre le message radio, l’intensité du courant passe à 23mA mais ne dure que 1 seconde. Puisque les émissions radio sont effectuées toutes les 30 minutes, l’intensité moyenne en mode émission est donc de 23 mA * 1/1800 = 12,7 µA.

Avec une intensité moyenne totale de 80,7 µA le dispositif aura une autonomie d’environ 12391 heures (516 jours) avec une batterie de 1000 mAh.

Tension de la batterie

Le convertisseur analogique-numérique de l’Arduino est paramétrer de la façon suivante afin de mesurer la tension d’alimentation du circuit :

  • Tension de référence = AVcc (la tension d’alimentation du convertisseur analogique-numérique, qui correspond à la tension de la batterie dans notre circuit)
  • Tension d’entrée à mesurer = tension interne 1,1 V

La mesure de la tension interne fixe de 1,1 V par le convertisseur nous permet de déduire la tension de la batterie par la formule suivante :

Tension de la batterie = (1.1 V / résultat de la conversion analogique-numérique) * 1024

Choix du canal radio

Si vous possédez un tuner radio, vérifiez que la fréquence du canal choisi n’est pas trop encombrée dans votre entourage.

Comme on le voit dans l’image ci-dessous, le canal 2 (433,8 MHz) est assez encombré chez moi et j’ai donc sélectionné le canal 1 (433,4 MHz).


C’est la fin de la première partie de ce tutoriel, nous allons voir dans la seconde partie comment récupérer les données dans un serveur Jeedom tournant sur un Raspberry Pi.