Capteur de température et humidité sans fil (HTU21D)

Capteur de température et humidité sans fil (HTU21D)

On va réaliser un petit capteur d’humidité et température sans fil à base du htu21d qui est un petit capteur numérique qui se connecte sur le bus I²C / TWI d’un microcontrôleur, ou d’un Raspberry Pi. Il est très économe en courant puisqu’il est donné pour maximum 0.14µA en veille et 500µA pendant une mesure. Sa tension d’alimentation est comprise entre 1.5 et 3.6V, on peut aisément l’alimenter avec une pile ou un accumulateur pour en faire un capteur autonome avec un très faible consommation électrique. La partie radio est gérée par un module nrf24l01+.

htu21d

Le module HTU21D

Le module est disponible sur sparkfun, ebay, bangood… pour quelques dollars. Sur celui-ci, les deux résistances de pull-up du bus I²C sont intégrées mais pas connectées. Pour les activer, il est nécessaire de relier les trois points au centre du module avec une goutte de soudure.

 

 

Le circuit

Le cœur du circuit est un ATMega328p de chez Atmel, le même qui équipe les Arduino Uno. Pour un grain de place, on utilise l’oscillateur interne de 8MHz. Voici les explication pour ajouter ce type de configuration comme hardware à l’IDE Arduino et ainsi compiler le code pour  utiliser un atmega328p en standalone.

Il est alimenté par un accumulateur LiFePO4 (Lithium Fer Phosphate) 14500, donc de la taille d’une pile AA. La tension nominale de l’accu est de 3.2V, ce qui est pratique vu les tensions de fonctionnement du capteur et du nrf24l01. De plus, ils présentent moins de risques que les accus LiIon ou LiPo.

La température et le taux d’humidité sont transmis toutes les 5 minutes. Toutes les 12h, la tension de la batterie est mesurée via un pont diviseur de tension pour que la mesure soit inférieure à la référence de tension interne de 1.1V, puis elle est également transmise au serveur. Le reste du temps, le microcontrôleur est en veille profonde (PowerDown) pour ne consommer seulement quelques µA.

 

Le programme

#include <LowPower.h>
#include <nRF24L01.h>
#include <printf.h>
#include <RF24.h>
#include <RF24_config.h>
#include <Wire.h>
#include <stdint.h>
#include "SparkFunHTU21D.h"

#define DEBUG 1

#define SLEEP_A 25 //5min
#define SLEEP_B 5400 //12h
#define VT_PIN 14 //A0
#define RF24_ON 7 //D6

uint8_t node_address[5] = {"1Node"};
uint8_t server_address[5] = {"2Node"};

HTU21D htu21d;
RF24 radio(9,10);
uint8_t plainRadioBuffer[32] = {0};
uint16_t cntA = SLEEP_A;
uint16_t cntB = SLEEP_B;

void setup_radio(){
radio.begin();
radio.setChannel(1);
radio.setDataRate(RF24_250KBPS);
radio.setPALevel(RF24_PA_MAX);
radio.setCRCLength(RF24_CRC_16);
radio.setRetries(3, 15);
radio.setAutoAck(1);
radio.openReadingPipe(1, node_address);
radio.openWritingPipe(server_address);

#if DEBUG==1
radio.printDetails();
#endif
}

void setup() {
#if DEBUG==1
Serial.begin(9600);
Serial.println(F("Setup"));
#endif
analogReference(INTERNAL);
htu21d.begin();
pinMode(RF24_ON, OUTPUT);
digitalWrite(RF24_ON, HIGH);
}

void loop() {

if(cntA == SLEEP_A || cntB == SLEEP_B){
//power on radio
digitalWrite(RF24_ON, LOW);
delay(100);
setup_radio();

if(cntA == SLEEP_A){
float humd = htu21d.readHumidity();
float temp = htu21d.readTemperature();

#if DEBUG==1
Serial.print(F("Measures : "));
Serial.print(temp);
Serial.print(F("°C - "));
Serial.print(humd);
Serial.println(F("%"));
#endif

memcpy(plainRadioBuffer, "DATA", 4);

memcpy(plainRadioBuffer+4, &temp, 4);
memcpy(plainRadioBuffer+8, &humd, 4);

radio.write(plainRadioBuffer, 32);
cntA = 0;
}

if(cntB == SLEEP_B){
float voltage = analogRead(VT_PIN);
voltage = voltage * 1.1 * ((1670000.0)/470000.0) / 1024.0;

memcpy(plainRadioBuffer, "VOLT", 4);
memcpy(plainRadioBuffer+4, &voltage, 4);

radio.write(plainRadioBuffer, 32);
cntB = 0;
}

//power down radio
digitalWrite(RF24_ON, HIGH);
}
++cntA;
++cntB;

#if DEBUG==1
Serial.println(F("Sleep for 8 seconds"));
#endif
LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF);
}

10 réflexions sur « Capteur de température et humidité sans fil (HTU21D) »

  1. Bonjour,
    Pouvez-vous détaillez un peu plus la partie « comparaison avec la tension de référence pour jauger le niveau de batterie restant » ?
    J’aimerais réaliser la même chose avec une li-po.
    Raphael

    1. Bonjour,
      Le convertisseur analogique-numérique de l’atmega328p a plusieurs références de tension possibles :

      • Externe : sur la broche AREF
      • Externe : Vcc
      • Interne : 1.1V

      Vu qu’on désire mesurer Vcc et qu’on ne dispose d’aucune autre tension de référence, on utilise la référence 1.1V interne.

      La tension Vcc à mesurer va se situer grosso modo entre 3.3V et 2.8V pour une LiFe, entre 4.2V et 3.7V pour une LiPo. Elle est supérieure à la tension de référence. On va utiliser un pont diviseur de tension pour ramener la tension à mesurer dans un intervalle 0-1.1V.
      Pour une Lipo on peut ainsi faire un pont diviseur avec une résistance de 100k et 330k : 4.2V * (100k/(330k+100k)) < 1.1V. Si la mesure nous retourne 900, on aura ainsi une tension de 900*(1.1V/1024)*((330k+100k)/100k)=4.16V

      1. Pour une alimentation directe sans régulateur, pas besoin de pont diviseur, il suffit de comparer la tension d’alimentation qui vaut 1023 (ADC 10 bit) à la tension de référence de 1.1V (dont la valeur en bit fluctue en fonction de la tension d’alimentation), sans utiliser de pin analogique ni résistance ni condensateur… Le pont diviseur n’est utile que si on utilise un régulateur et que la tension mesurée est supérieure à la tension d’alimentation (régulateur 3.3V et batterie Li-ion de 4.2V max par exemple). De plus le pont diviseur sans mosfet pour le couper consomme en permanence, l’utilisation de grandes résistances diminue cette consommation, mais devient sensible au « bruit ».

        1. Bonjour,
          Je ne connaissais pas cette méthode pour mesurer la tension d’alimentation, pour ces circuits alimentés par des piles type CR2032 ça doit en effet être bien plus intéressant.

    1. Bonjour,

      Actuellement j’en ai réalisé 6 pour mon appartement, ils ont tourné un an et demi sur l’accu de 700mA (600mA réel lors de la charge). Je les ai rechargé en déménageant mais ils fonctionnaient encore correctement.

      Bonne soirée.

  2. Dans une optique de faible consommation, le pont diviseur devrait être supprimé puisque sans régulateur la comparaison VCC / 1.1V permet de contrôler la tension de la batterie (qui vaut VCC) sans composant ni consommation supplémentaire.
    De même le mosfet pour couper l’alimentation du module radio est probablement contre productif, le module radio possédant un mode veille à 900nA qui pourrait être suffisant (la sortie de veille consomme probablement moins d’énergie que de redémarrer le module radio à chaque transmission), mais surtout couper l’alimentation sans s’assurer de couper les pins SCK, CS ou MOSI entraîne une consommation possible par alimentation du module radio via ces pins (état haut par défaut).
    D’après vos chiffres, 1.5 an pour 600mAh donne une consommation de 600 / 1.5*365*24 = 45µA. il est probable que vous puissiez diviser par 5 cette consommation.

  3. Bonjour, comment peut-on utiliser ce capteur pour envoyer des données détectées à une base de données MSQL?
    En plus, pour l’interfacer avec Arduino IDE, ne demande-t-il pas d’être connecté physiquement au à l’ordinateur?

    1. Bonjour,

      Pour pouvoir envoyer les données à une base de données MySQL, il faut un récepteur basé aussi sur un module nrf24 d’un côté et ethernet de l’autre (comme la passerelle https://blog.zesanglier.fr/2019/12/08/passerelle-nrf24-ethernet/) ou avec un ESP32 qui lui a une connexion wifi.
      Ce récepteur recevra d’un côté les données transmises par le capteur (il peut déjà leur faire subir un traitement), puis ensuite peut les envoyer à une base de données via une page php ou via un serveur rest.

      Le capteur a besoin d’être connecté à l’ordinateur (comme expliqué dans le lien https://github.com/MCUdude/MiniCore) uniquement pour le développement, configurer les adresses du nrf24 et transférer le programme. Ensuite le capteur est autonome.

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *