AppDesigner - Arduino - Capteur DHT22

Connaître le taux d'humidité d'un milieu est particulièrement utile. Plusieurs domaines sont concernés : l’agro industrie, l’industrie du médicament, le tertiaire et bien plus encore.

En environnement domestique, le confort des êtres humains est assuré lorsque ce taux se situe entre 30%  et 70%, selon la température.

Ce tuto a pour but d’utiliser le capteur DHT22, pour mesurer la température et le taux d’humidité d’un lieu, puis, afficher en direct ces grandeurs sur une interface graphique, avec une possibilité de Data  Logging.

Matériel nécessaire:

          • Arduino,
          • Un capteur DHT22,
          • Une résistance de 330 Ohms 1/4 W,
          • Une LED pour visualiser lorsque l’utilisateur enregistre les données,
          • AppDesigner et la boîte à outil Instruments Control Toolbox.

 

Présentation du DHT22:

Le DHT22 est un capteur de température et d'humidité à bas coût. Il utilise une thermistance pour mesurer la température et un capteur capacitif pour mesurer le taux d'humidité dans l'air.

L’unique sortie  du capteur délivre sous forme de signaux numériques la mesure du taux d'humidité et la température, codée chacune sur 16 bits. Ces données sont transmises au microcontrôleur à l’aide d’un protocole de communication propriétaire, qui n’est pas le même que celui employé par les composants de la famille Dallas Semiconductors (les mémoires EEPROM Dallas par exemple).

Un logique 1 est représenté par un niveau logique bas de 50µs suivi d'un niveau chronogramme logique 1 dhtlogique haut de 70µs.

 

Un logique 0 est représenté par un niveau logique bas de 50µs suivi d'un niveau logique haut de 26µs.chronogramme logique 0 dht

 

 

Ce composant communique de façon asynchrone avec le microcontrôleur.

Le microcontrôleur démarre l'échange (Start), en mettant à 0 la ligne de transmission de données pendant 500µs puis relâche la ligne.

Le DHT22 répond (Resp) en en mettant cette même ligne à 0 pendant 80µs puis à 1 pendant la même durée (80µs). Puis l'envoi des données commence, avec l'humidité en premier sur deux octets, suivit de la température sur deux octets aussi. Le bit de poids fort de l'octet haut de la température représente le signe. La température est négative si ce bit est égal à 1; ou positive lorsque le bit est égal à 0.

Pour finir un octet de vérification (Check-sum) est envoyé par le capteur au microcontrôleur, puis l'envoi des données prend fin, et le capteur relâche la ligne de transmission (Release) qui se remet aussitôt à l'état logique 1.

 Chronogrammes dht 22

Une transmission dure en moyenne 5ms.

Brochage:

brochage dht22

(+) : alimentation, +Vcc, Out : sortie de données humidité et température, (-) : masse 0V.

Spécifications  techniques:

          • Alimentation: 3,3 ou 5 Vcc
          • Consommation: 1 - 1,5 mA
          • Consommation en veille : 40 – 50µA
          • Interface 3 broches : Vcc, Data Out, GND
          • Protocole de communication : Bus 1 ligne
          • Résolution : 0.1
          • Plage de mesure:
             > température: -40 à 80 °C
             > humidité: 0 à 100 % RH
          • Précision:
             > température: ± 0,5 °C
             > humidité: ± 2 % RH
          • Fréquence d'échantillonnage: 2 s
          • Dimensions: 45 x 15 x 10 mm

Note: pour certains modèles de capteurs, il est recommandé de relier la broche de sortie des données à une résistance de Pull Up de 4,7K à 10K. Autrement, il faudra activer la résistance interne de Pull Up sur l’entrée-sortie concernée au cas où Arduino est utilisé.

Le modèle mis en œuvre dans ce tuto en possède déjà.

 

Le montage d’essai :

dht22 arduino appdesigner 

Programmation:

Côté Arduino:

Le programme Arduino n'a rien de particulier. Il a été calqué sur l'exemple proposé par le site Adafruit. Sa mise en œuvre toute simple consiste à envoyer sur la liaison série le taux d’humidité et la température.

 

//DHT22 sensor test program 
#include <DHT.h>
//
#define DHTPIN 4    //Digital pin connected to the sensor
#define ledPin 5    //LED is connected here
//
#define DHTTYPE  DHT22   //DHT 22(AM2302)
DHT dht(DHTPIN, DHTTYPE);
//
char ledValue;
//
long dhtSampleTime = 1000; //recommended time
long blinkLedTime = 200; //
unsigned long previousDhtTime, previousLedTime;
unsigned long currentTime;
void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  //initialize device
  dht.begin();
  //
  pinMode(ledPin, OUTPUT);
  previousDhtTime = 0;
  previousLedTime = 0; 
}

void loop() {
  // put your main code here, to run repeatedly:
  // Read serial input
   
        if (Serial.available() > 0)
             {
                ledValue = Serial.read();                             
             }
  //
  //
  if (ledValue == 'T') // from serial
         {
              currentTime = millis();
              if(currentTime - previousLedTime >= blinkLedTime) 
                {
                  previousLedTime = currentTime;
                   {
                      digitalWrite(ledPin, !digitalRead(ledPin)); //blink
                   }
                }
          }
  if (ledValue == 'F') // from serial
          {
              digitalWrite(ledPin, LOW);
          }
  //
  // Read sensor and write data to serial port
  currentTime = millis();
  if(currentTime - previousDhtTime > dhtSampleTime)
    { 
       previousDhtTime = currentTime;
       float humidity = dht.readHumidity(); //read sensor humidity
       float temperature = dht.readTemperature(); //read temperature as degre Celsius
       //Check if any reads failed exit and try again
       if (isnan(humidity) || isnan(temperature)){
            Serial.println("Failed to read from DHT sensor!");
            return;
          }
       //Send to serial
       Serial.print(humidity);
       Serial.print(F(" and "));
       Serial.println(temperature);
    }
}

 

La librairie dht.h  est chargée en premier. Dans cette librairie se trouve toutes les fonctions prédéfinies pour gérer le capteur. Ensuite les variables sont déclarées.

La fonction Setup() met en service la liaison série, ainsi que l’objet dht  du capteur.

Dans la boucle principale du programme main() on commence par vérifier si des données en provenance de l’ordinateur sont présentes sur la liaison série;  si le caractère ‘T’ est reçu, la LED sur la sortie Arduino clignote; ou si c’est le caractère ‘F’, la LED s’éteint.

Le test qui suit, vérifie des données envoyées  par le capteur sont erronées, dans ce cas, un message d’erreur est affiché et une nouvelle lecture est relancée.

Les données valides sont envoyées, sous forme d’une chaine de caractère sur la liaison série. Avec en premier le taux d'humidité, suivi d'un " and " (attention aux espaces) et de la température.

 

Côté Matlab:

L'interface graphique utilisateur construite à l'aide de AppDesigner, ressemblera à ceci:

capture face avant dht22 sensor app

 

Les variables partagées:

Toutes les variables partagées par les fonctions de ce programme se trouvent ici :

 

properties (Access = private)
        s % Serial        
        serialStatus % 
        sensorTemperature % sensor temperature read value
        sensorHumidity % sensor humidity read value
        t_now % Computer time data now
        temperatureData = [] % data for plotting
        humidityData = [] %
        t_live = [] % time array for plotting
        Logging = false % 
 end

 

s : pour créer la liaison série ;

serialStatus : variable interne pour connaître l’état de la liaison série ;

sensorTemperature : cette variable mémorise la température instantanée envoyée par le capteur sur la liaison série.

sensorHumidity : cette variable mémorise l’humidité relative instantanée envoyée par le capteur sur la liaison série.

t_now : chaque lecture est horodatée. La date est mémorisée dans cette variable.

temperatueData : mémorise sous forme d’un tableau, toutes les températures lues sur la liaison série, pour être utilisé par le graphique.

humidityData : mémorise sous forme d’un tableau, tous les taux d’humidité relative lus sur la liaison série, pour être utilisé par le graphique.

t_live : mémorise sous forme d’un tableau, l’instant de lecture de chaque donnée lue sur la liaison série.

Logging : est une variable interne, qui permet d’activer ou de désactiver le data logging.

 

Les Helper Function:

La fonction buttonsState() :

Cette fonction définit l’état activé ou désactivé des boutons ou commutateurs pendant les différente phases d’utilisation de l’interface graphique.  Cette helper function est appelée selon les cas par les Callbacks de chacun des boutons.

 

function buttonsState(app, state)
            switch state
                case "Connected"
                    
                    app.Lamp.Color = 'green';
                    app.DisconnectButton.Enable = "on";   
                    app.Switch.Enable = "on";
                    app.ConnectButton.Enable = "off";
                    app.PORTDropDown.Enable = "off";
                    app.BaudDropDown.Enable ="off";
                    app.StartButton.Enable = "off";
                    app.StopButton.Enable = "off";

                case "Disconnected"

                    app.Lamp.Color = [.60,0.68,0.60];
                    app.serialStatus = false;
                    app.ConnectButton.Enable = "on";
                    app.PORTDropDown.Enable = "on";
                    app.BaudDropDown.Enable ="on";
                    app.DisconnectButton.Enable = "off";

                case "Startup"

                    app.Switch.Enable = "off";
                    app.DisconnectButton.Enable = "off";
                    app.StartButton.Enable = "off";
                    app.StopButton.Enable = "off";

                case "Logtofile"

                   app.Switch.Enable = "off";
                   app.StartButton.Enable ="off";
                   app.StopButton.Enable = "on";

                case "Waitforlogging"

                    app.StopButton.Enable ="off";
                    app.StartButton.Enable = "on";
                    app.Switch.Enable = "on";
           end
 end

 

La fonction acquireData() :

 

function acquireData(app)
            app.t_now = datetime("now","TimeZone","Europe/Paris"); % get curren time
            value = readline(app.s); % get data from serial
            numericValue = str2double(regexp(value,' and ','split')); % result is array of 2 elements
            app.sensorHumidity = numericValue(1,1); % the first element is humdity
            app.sensorTemperature = numericValue(1,2); % the second one is temperature
            app.humidityData = [app.humidityData, app.sensorHumidity]; % store data in an array
            app.temperatureData = [app.temperatureData, app.sensorTemperature];
            app.t_live = [app.t_live, app.t_now]; 
 end

 

Cette fonction effectue l’acquisition de l’humidité, de la température et de l’heure, puis stocke toutes ces valeurs dans les trois tableaux humidityData, temperatureData et t_live

Les données envoyée sur la liaison série sont des chaînes de caractères au format :

« Humidite and Temperature ». 

La fonction prédéfinie regexp() se charge de transformer cette chaine de caractère en un tableau ayant pour éléments de deux chaines de caractères « Humidite » et « Temperature ».  Ces données sous transformées en format numérique grâce à la fonction prédéfinie str2double().

 

La fonction plot_data() :

 

function plot_data(app)
            % define first x lower and upper limits for plotting area
            x_lower = app.UIAxes.XLim(1);
            x_upper = app.UIAxes.XLim(2);
            % so we want to plot few value then update x axes values
            if (app.t_now > x_upper)
                refresh_t = seconds(10); % update time values every 10 sec
                app.UIAxes.XLim = [x_lower + refresh_t, app.t_now + refresh_t];
                % also define x ticks, we take five value for this
                app.UIAxes.XTick = linspace(x_lower + refresh_t, app.t_now + refresh_t, 5);
            end
            plot(app.UIAxes, app.t_live, app.humidityData, 'b', app.t_live, app.temperatureData, 'r','LineWidth',1.5);
            legend(app.UIAxes, 'Hr(%)', 'T(°C)');
 end

 

Cette fonction se charge d’assurer la représentation graphique de la température(en couleur rouge) et du taux d’humidité (en couleur bleue) en fonction du temps dont l’unité est au format "HH :mm :ss" .

L’axe des temps est constitué de cinq valeurs, et rafraichi toutes les 10 secondes.

 

La fonction display_live_data() :

 

 function display_live_data(app)
            app.HmaxEditField.Value = max (app.humidityData);
            app.TmaxCEditField.Value = max (app.temperatureData);
            app.HEditField.Value = app.sensorHumidity;
            app.TCEditField.Value = app.sensorTemperature;
 end

 

Cette fonction envoie dans les zones d’éditions numérique les contenus des variables sensorHumidity, sensorTemperature, le taux d’humidité relative, la température, ainsi les valeurs maximales enregistrées de ces deux grandeurs.

 

La fonction processDataReceived() :

 

 function dataToRow = processDataReceived(~, hum, temp, eventtime)
            dataToRow = {eventtime};
            hum = {hum};
            temp = {temp};
            dataToRow = {dataToRow{1}, hum{1}, temp{1}}; % then formatting this in a single row
 end

 

Cette fonction met sous la forme {{instant_de_la_lecture}, {humidité}, {température}} ; les données humidité et température horodatées lues sur la liaison série.

 

La fonction logDataTofile()

 

function logDataToFile(app)
            filename = 'DHTsensor_data.csv';            
            filepath = 'pwd';
            logFile = fullfile(filepath, filename);
            persistent rowIndex;
            if isempty(rowIndex)
                rowIndex = 1;
            else
                rowIndex = rowIndex + 1;
            end
            logData = processDataReceived(app, app.sensorHumidity, app.sensorTemperature, datetime);
            writecell(logData, logFile,'WriteMode','append');
 end

 

Enregistre les mesures capturées toutes les secondes au format csv, dans le répertoire de travail Matlab. Un autre répertoire peut être choisi il suffit d’indiquer son chemin complet.

Les données sont enregistrées lignes par lignes dans le fichier, y compris pour un nouvel enregistrement. 

 

La Startup function:

Cette fonction crée les paramètres de configuration de la liaison série, définit les limites du graphe, ainsi que le format d’affichage du temps en HH :mm :ss, la grille et le style de graphe encadré.

 

function startupFcn(app)
            app.PORTDropDown.Items = ["Com Port...",serialportlist('available')];           
            buttonsState(app,"Startup");
            % Plot invisible point to initiate datetime ruler
            plot(app.UIAxes, datetime("now","TimeZone",'Europe/Paris'), 50);
            % Set x limits and x ticks format
            this_time = datetime("now","TimeZone",'Europe/Paris','Format','HH:mm:ss');
            x_lower = this_time(1) - seconds(5);
            x_upper = this_time(1);
            app.UIAxes.XLim = [x_lower, x_upper];
            app.UIAxes.XAxis.TickLabelFormat = 'HH:mm:ss';
            app.UIAxes.XTick = linspace(x_lower, x_upper, 5);
            app.UIAxes.YLim = [0, 100];
            app.UIAxes.Box = 'on';
            grid(app.UIAxes,"on");
 end

 

Les Callbacks:

Le Callback du bouton Connect :

 

function ConnectButtonPushed(app, event)
            app.PORTDropDown.Items = ["Com Port...",serialportlist('available')];
            app.s = serialport(app.PORTDropDown.Value,str2double(app.BaudDropDown.Value));
            configureTerminator(app.s,"CR/LF");
            buttonsState(app,"Connected");
            app.serialStatus = true;
 end

 

Active la liaison série, puis désactive certains boutons de l’interfaces graphique en appelant la fonction buttonsState(). La variable serialStatus est positionnée à true pour indiquer que la liaison série est active.

 

Le Callback du commutateur d’acquisition « Switch »:

 

 function SwitchValueChanged(app, event)
            value = app.Switch.Value;
            if app.serialStatus
                app.DisconnectButton.Enable = "off";
                app.StartButton.Enable ="on";
                while(strcmp(value,'On'))
                    acquireData(app);
                    pause(0.1);
                    plot_data(app);
                    display_live_data(app);
                    if app.Logging
                        logDataToFile(app);
                    end
                    value = app.Switch.Value;
                end
                
                app.DisconnectButton.Enable = "on";
                app.StartButton.Enable ="off";
                app.StopButton.Enable = "off";
           end
 end

 

Ce Callback permet de démarrer la acquisition des données sur la liaison série. Lors d’un changement de position du commutateur de la position Off à la position On. Le bouton Disconnect devient inactif ; le bouton "Start" qui actionne le Data Logging devient actif.

Puis on rentre dans une boucle et on y reste tant que ce bouton occupe la position « On ». A l’intérieur de  la boucle la fonction d’acquisition acquireData() est appelée, ainsi les fonctions plot_data() et display_live_data().  Si la variable interne Logging est active, la fonction logDataToFile() est appelée.

L’état du Switch est mémorisé dans la variable value à chaque tour de boucle. Lorsque cette variable prend la valeur « Off », on sort de la boucle, puis le bouton Disconnect redevient actif, les deux boutons Start et Stop du panneau Data Logging deviennent inactifs.

Le Callback du bouton Start :

 

   function StartButtonPushed(app, event)
            app.Logging = true;
            write(app.s,'T',"char");
            buttonsState(app,'Logtofile');
   end

 

Il permet d’activer la variable interne Logging, puis d’envoyer sur la liaison série le caractère ‘T’ qui permet de faire clignoter la LED sur la sortie Arduino afin d’indiquer le début de l’enregistrement.

Puis la fonction buttonsState() est appelée avec le paramètre Logtofile.  Certains boutons deviennent inactifs.

 

Le Callback du bouton Stop:

 

    function StopButtonPushed(app, event)
            app.Logging = false;
            write(app.s,'F',"char");
            buttonsState(app,'Waitforlogging');
    end

 

Il désactive la variable Logging, ce qui a pour effet d’arrêter l’enregistrement des données, envoie le caractère ‘F’ sur la liaison série pour éteindre la diode connectée sur la sortie Arduino,  puis appelle la fonction buttonsState() avec le paramètre Waitforlogging.  Le bouton Stop devient inactif, le commutateur « Switch » devient actif, ainsi que le bouton Start.

 

Le Callback du bouton Disconnect:

 

   function DisconnectButtonPushed(app, event)
            buttonsState(app, 'Disconnected');
            delete(app.s);
   end

 

Ce Callback appelle la fonction buttonsState() avec le paramètre Disconnected, certains boutons, ainsi que le bouton Disconnect deviennent inactifs. Le bouton Connect devient actif.

Puis l’objet liaison série « s  » est désactivé et effacé.

 

Test fonctionnel:

La vidéo ci-après résume en image cet article, et présente l'affichage des données en Live sur l'interface graphique:

 

 

Conclusion:

Cette interface graphique peut encore être améliorée. On peut proposer par exemple le choix du répertoire à l'utilisateur pour enregistrer le fichier log; ou bien arranger l'affichage du graphe.

Le capteur DHT22 est lent et basic. Mais il constitue un véritable compromis pour un Hobbyiste qui veut réaliser thermomètre – hygromètre avec un Data Logger. Ce type de capteur trouve aussi sa place dans des VMC à commande électronique à bas coût.

 

JtBB

ressources:

https://learn.adafruit.com/dht/using-a-dhtxx-sensor-with-arduino

https://www.mathworks.com

https://www.mathworks.com/matlabcentral/fileexchange/72441-dht22-add-on-library-for-arduino

Tuto : configurer une liaison série avec arduino, allumer une led

Ce site web utilise des cookies

Certains d’entre eux sont essentiels pour son fonctionnement et d’autres nous aident à améliorer l’expérience utilisateur (cookies traceurs). Vous pouvez décider vous-même si vous autorisez ou non ces cookies. Merci de noter que, si vous les rejetez, certaines fonctionnalités du site pourront être défaillantes.