Tutoriel Complet - Bibliothèque STM32_DHT

Interface C pour capteurs de température et d'humidité DHT11, DHT22, et DHT21 sur microcontrôleurs STM32

Consultez la librairie sur GitHub.

1. Introduction

La bibliothèque STM32_DHT est une interface C conçue pour faciliter la communication entre les microcontrôleurs STM32 et les capteurs de température et d'humidité de la famille DHT (DHT11, DHT22, DHT21). Cette bibliothèque utilise le framework HAL (Hardware Abstraction Layer) de ST Microelectronics pour assurer la portabilité entre les différentes familles de microcontrôleurs STM32.

Note : Cette bibliothèque a été conçue pour être simple à utiliser tout en offrant une communication fiable avec les capteurs DHT, qui utilisent un protocole de communication série à fil unique (one-wire) non standard.

2. Compatibilité et Prérequis

Compatibilité Matérielle

  • Toutes les familles de microcontrôleurs STM32 supportant HAL et disposant d'un périphérique I2C.
  • Capteur DHT11, DHT22 et DHT21.

Prérequis Logiciels

  • Un microcontrôleur STM32.
  • STM32CubeIDE.
  • Le bus I2C sur lequel se troue votre capteur doit être configuré et initialisé dans votre projet.
  • La librairie HAL STM32_DHT présente dans le répertoire STM32_Libraries.

3. Les Capteurs DHT

Les capteurs DHT sont des capteurs numériques de température et d'humidité abordables et populaires dans les projets électroniques. La bibliothèque supporte trois variantes principales :

Modèle Plage de Température Précision Température Plage d'Humidité Précision Humidité Fréquence de Lecture
DHT11 0 à 50°C ±2°C 20 à 80% RH ±5% RH 1 Hz (une fois par seconde)
DHT22 / AM2302 -40 à 80°C ±0.5°C 0 à 100% RH ±2% RH 0.5 Hz (une fois toutes les 2 secondes)
DHT21 / AM2301 -40 à 80°C ±0.5°C 0 à 100% RH ±2% RH 0.5 Hz (une fois toutes les 2 secondes)
Note : Le DHT21 est fonctionnellement identique au DHT22, mais dans un boîtier différent. Du point de vue de la programmation, ils sont traités de la même manière.

4. Principe de Fonctionnement

Les capteurs DHT utilisent un protocole de communication série propriétaire sur un bus à fil unique. Le processus de communication se déroule comme suit :

  1. Signal de démarrage : Le microcontrôleur envoie un signal bas puis haut pour initier la communication
  2. Réponse du capteur : Le capteur répond par un signal bas puis haut
  3. Transfert de données : Le capteur envoie 40 bits (5 octets) de données :
    • 8 bits pour la partie entière de l'humidité
    • 8 bits pour la partie décimale de l'humidité
    • 8 bits pour la partie entière de la température
    • 8 bits pour la partie décimale de la température
    • 8 bits pour la somme de contrôle (checksum)

La bibliothèque STM32_DHT gère toute cette communication et effectue la conversion des valeurs brutes en données utilisables (température en °C et humidité relative en %).

Important : Le protocole des capteurs DHT nécessite une précision temporelle en microsecondes, c'est pourquoi un timer configuré correctement est essentiel pour le bon fonctionnement de cette bibliothèque.

3. Fichiers de la librairie

  • STM32_DHT.h : Fichier d'en-tête contenant les déclarations des fonctions et constantes.
  • STM32_DHT.c : Fichier source contenant l'implémentation des fonctions.

n'oubliez pas de modifier le fichier STM32_DHT.h pour l'adapter à votre configuration matérielle #include "stm32l0xx_hal.h" // Remplacez stm32l0xx_hal.h si vous utilisez une autre série de carte ex : stm32f4xx_hal.h.

5. Installation et Configuration

Pour installer la bibliothèque dans votre projet STM32 :

  1. Créez un dossier nommé STM32_DHT dans le répertoire Drivers de votre projet STM32 et copiez y les fichiers STM32_DHT.h et STM32_DHT.c.
  2. Ajoutez les chemins d'inclusion : dans les propriétés de votre projet STM32CubeIDE, dans C/C++ General, > Paths and Symbols > Onglet Includes, dans GNU ajoutez le chemin vers le dossier STM32_DHT.

N'oublier pas d'activer le float dans les propriétés du projet pour afficher le nombres flottants dans le printf.

6. Branchement du Capteur

Brochage des capteurs DHT

Les capteurs DHT ont généralement 3 ou 4 broches :

  • VCC : Alimentation (3.3V ou 5V selon le modèle)
  • DATA : Signal de données
  • GND : Masse
  • NC : Non connecté (sur certains modèles à 4 broches)

Connexion au STM32

  • VCC → 3.3V (DHT22/21) ou 5V (DHT11)
  • DATA → Broche GPIO de votre choix (D2 -> PA10 dans l'exemple)
  • GND → GND

Il est recommandé d'ajouter une résistance pull-up de 4.7kΩ à 10kΩ entre VCC et DATA pour stabiliser le signal.

Note : Bien que la bibliothèque configure une résistance pull-up interne, une résistance externe est généralement recommandée pour une communication plus fiable, surtout avec des câbles longs.
Diagramme de connexion DHT22 avec STM32

7. Configuration du Timer

La bibliothèque nécessite un timer précis pour mesurer les intervalles de temps du protocole DHT. Voici comment configurer un timer STM32 pour qu'il compte en microsecondes :

Configuration avec STM32CubeMX

  1. Ouvrez votre projet dans STM32CubeMX
  2. Activez un timer (par exemple, TIM1)
  3. Configurez-le comme suit :
    • Clock Source: Internal Clock
    • Prescaler: (Fréquence d'horloge en MHz - 1)
      • Par exemple, si votre horloge système est à 80MHz, utilisez 79
    • Counter Period: 0xFFFFFF - 1 (65534)
    • Counter Mode: Up
  4. Générez le code et vérifiez la configuration dans le fichier de configuration du timer

Configuration Manuelle

// Configuration du timer pour compter en microsecondes
htim1.Instance = TIM1;
htim1.Init.Prescaler = 79;         // Pour une horloge système de 80MHz
htim1.Init.CounterMode = TIM_COUNTERMODE_UP;
htim1.Init.Period = 0xFFFFFF - 1;    // Valeur maximale pour un timer 16 bits
htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim1.Init.RepetitionCounter = 0;
htim1.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
HAL_TIM_Base_Init(&htim1);
        
Formule du Prescaler : Pour obtenir une base de temps en microsecondes, utilisez cette formule :
Prescaler = (Fréquence d'horloge système en Hz / 1,000,000) - 1
Par exemple, pour 80MHz : Prescaler = (80,000,000 / 1,000,000) - 1 = 79

8. Utilisation de la Bibliothèque

8.1 Inclusion de la Bibliothèque

Pour utiliser la bibliothèque, incluez le fichier d'en-tête dans votre programme main.c :


/* USER CODE BEGIN Includes */
#include <stdio.h>                // Pour printf
#include "STM32_DHT.h"                  // Inclure la bibliothèque STM32_DHT
/* USER CODE END Includes */
            

8.2 Fonctions pour le `prinf` et la gestions des erreurs de la dht.h

Incluez le fichier d'en-tête dans la section USER CODE BEGIN Includes :


/* USER CODE BEGIN 0 */
/**
 * @brief Fonction de sortie pour printf
 *
 * Cette fonction redirige la sortie de printf vers l'UART2.
 * Elle est utilisée pour afficher des messages sur le terminal série.
 *
 * @param ch Le caractère à envoyer
 * @return int Le caractère envoyé
 */
int __io_putchar(int ch) {
	HAL_UART_Transmit(&huart2, (uint8_t*) &ch, 1, 0xFFFF); // Pour Envoyer le caractère via UART
	// ITM_SendChar(ch);                 // Option alternative pour envoyer le caractère via ITM
	return ch;
}
/* USER CODE END 0 */
            

8.3 Initialisation

Initialisez le capteur dans la section USER CODE BEGIN 2 :


/* USER CODE BEGIN 2 */
HAL_Delay(250); // Attendre 250ms pour la stabilisation
printf("test STM32_DHT\r\n"); // Affiche un message de test dans la console/

HAL_TIM_Base_Start(&htim2); // Démarrer le timer utilisé pour les délais en microsecondes

DHT_Sensor DHT22sensor; // Déclaration de la structure pour le capteur DHT22
DHT_Init(&DHT22sensor, &htim2, GPIOA, GPIO_PIN_10, DHT22); // Initialise le capteur DHT22 sur GPIOA, PIN 10 avec TIM2

float data[2]; // Tableau pour stocker la température [0] et l'humidité [1]
DHT_GetData(&DHT22sensor, data); // Lance une lecture pour réveiller le capteur
HAL_Delay(100); // Attendre 100ms pour la stabilisation
/* USER CODE END 2 */
            
Important : Le timer doit être démarré avant l'appel à DHT_Init. Assurez-vous qu'il est configuré pour compter en microsecondes.

8.4 Lecture des Données

Pour lire les données de température et d'humidité dans la section USER CODE BEGIN WHILE :

            
/* USER CODE BEGIN WHILE */
while (1)
{
    HAL_StatusTypeDef result = DHT_GetData(&DHT22sensor, data); // Lire les données du capteur
    if (result == HAL_OK) { // Si ok
        printf("Température: %.1f°C, Humidité: %.1f%%\r\n", data[0], data[1]);
    } else if (result == HAL_ERROR) { // Si erreur de somme de contrôle ou autre erreur générale
        printf("Erreur lors de la lecture du capteur\r\n");
    } else if (result == HAL_TIMEOUT) { // Si pas de réponse du capteur ou timeout pendant la communication
        printf("Timeout lors de la communication avec le capteur\r\n");
    }
    HAL_Delay(2000);
    /* USER CODE END WHILE */
            
Attention : Les capteurs DHT ont besoin d'un temps de récupération entre les lectures. Attendez au moins 2 secondes entre chaque appel à DHT_GetData(), surtout pour les DHT22/21.

9. Dépannage

Problèmes Courants et Solutions

Problème Causes Possibles Solutions
HAL_TIMEOUT lors de la communication
  • Mauvais branchement
  • Timer mal configuré
  • Capteur défectueux
  • Vérifiez les connexions
  • Assurez-vous que le timer compte bien en microsecondes
  • Essayez avec un autre capteur
HAL_ERROR (erreur de checksum)
  • Interférences électriques
  • Câble DATA trop long
  • Alimentation instable
  • Utilisez une résistance pull-up externe
  • Raccourcir le câble ou utiliser un câble blindé
  • Vérifiez l'alimentation du capteur
Valeurs incorrectes ou incohérentes
  • Mauvaise interprétation des données
  • Type de capteur mal configuré
  • Sources de chaleur à proximité
  • Vérifiez le paramètre de type dans DHT_Init
  • Éloignez le capteur des sources de chaleur
  • Calibrez le capteur si nécessaire

Débogage

Pour faciliter le débogage, vous pouvez ajouter des instructions de trace dans votre code :


/* USER CODE BEGIN WHILE */
while (1)
{
    // Exemple de débogage détaillé
    HAL_StatusTypeDef result = DHT_GetData(&DHT22sensor, data);

    switch (result) {
        case HAL_OK:
            printf("Lecture réussie - Température: %.1f°C, Humidité: %.1f%%\r\n", data[0], data[1]);
            printf("Données brutes - T1: %u, T2: %u, H1: %u, H2: %u, Sum: %u\r\n",
            DHT22sensor.temp1, DHT22sensor.temp2, DHT22sensor.hum1, DHT22sensor.hum2, DHT22sensor.SUM);
            break;
        case HAL_ERROR:
            if (DHT22sensor.CHECK != DHT22sensor.SUM) {
                printf("Erreur de checksum - Calculé: %u, Reçu: %u\r\n", DHT22sensor.CHECK, DHT22sensor.SUM);
            } else {
                printf("Erreur générale\r\n");
            }
            break;
        case HAL_TIMEOUT:
            printf("Timeout - Pas de réponse du capteur\r\n");
            break;
        default:
            printf("Erreur inconnue\r\n");
            break;
    }

    HAL_Delay(2000);
    /* USER CODE END WHILE */
    

10. Utilisation Avancée

Utilisation de Plusieurs Capteurs

La bibliothèque permet d'utiliser plusieurs capteurs DHT simultanément sur différentes broches GPIO. Voici comment procéder :


/* USER CODE BEGIN 2 */
HAL_Delay(250); // Attendre 250ms pour la stabilisation
printf("test STM32_DHT\r\n"); // Affiche un message de test dans la console

HAL_TIM_Base_Start(&htim2); // Démarrer le timer utilisé pour les délais en microsecondes
DHT_Sensor dht11Sensor;     // Déclaration de la structure pour le capteur DHT11
DHT_Sensor dht22Sensor;     // Déclaration de la structure pour le capteur DHT22

DHT_Init(&dht11Sensor, &htim2, GPIOB, GPIO_PIN_3, DHT11);   // Initialise le capteur DHT11 sur GPIOB, PIN 3 avec TIM2
DHT_Init(&dht22Sensor, &htim2, GPIOA, GPIO_PIN_10, DHT22);  // Initialise le capteur DHT22 sur GPIOA, PIN 10 avec TIM2

float dht11Data[2]; // Tableau pour stocker la température [0] et l'humidité [1] de DHT11
float dht22Data[2]; // Tableau pour stocker la température [0] et l'humidité [1] de DHT22

DHT_GetData(&dht11Sensor, dht11Data);       // Lance une lecture pour réveiller le capteur DHT11
DHT_GetData(&DHT22sensor, dht22Data);       // Lance une lecture pour réveiller le capteur DHT22
HAL_Delay(100); // Attendre 100ms pour la stabilisation
/* USER CODE END 2 */
            

/* USER CODE BEGIN WHILE */
while (1)
    {   
    
        // Lecture du premier capteur
        if (DHT_GetData(&dht11Sensor, dht11Data) == HAL_OK) {
            printf("DHT11 - Temp: %.1f°C, Hum: %.1f%%\r\n", dht11Data[0], dht11Data[1]);
        }
        
        HAL_Delay(100); // Petit délai entre les lectures pour éviter les interférences
        
        // Lecture du deuxième capteur
        if (DHT_GetData(&dht22Sensor, dht22Data) == HAL_OK) {
            printf("DHT22 - Temp: %.1f°C, Hum: %.1f%%\r\n", dht22Data[0], dht22Data[1]);
        }
        
        HAL_Delay(2000); // Attendre avant le prochain cycle de lecture
        /* USER CODE END WHILE */
            
Note : Lors de l'utilisation de plusieurs capteurs, assurez-vous de respecter les temps de récupération recommandés pour chaque type de capteur.

Échantillonnage et Moyennage

Pour améliorer la fiabilité des mesures, vous pouvez implémenter un système d'échantillonnage multiple avec moyennage (copier les sections nécessaires dans votre code):


/* USER CODE BEGIN Includes */
#include <stdio.h>      // Pour printf
#include "STM32_DHT.h"  // Inclure la bibliothèque STM32_DHT
/* USER CODE END Includes */
            

/* USER CODE BEGIN PTD */
// Structure pour stocker les données moyennées
typedef struct {
    float tempSum;
    float humSum;
    uint8_t sampleCount;
    uint8_t maxSamples;
    float avgTemp;
    float avgHum;
    uint32_t lastSampleTime;
} DHT_AveragingData;

// Initialisation de la structure de moyennage
void DHT_InitAveraging(DHT_AveragingData* avgData, uint8_t samples) {
    avgData->tempSum = 0.0f;
    avgData->humSum = 0.0f;
    avgData->sampleCount = 0;
    avgData->maxSamples = samples;
    avgData->avgTemp = 0.0f;
    avgData->avgHum = 0.0f;
    avgData->lastSampleTime = 0;
}
/* USER CODE END PTD */
            

/* USER CODE BEGIN PD */
#define SAMPLE_INTERVAL 2000 // Intervalle d'échantillonnage en ms
/* USER CODE END PD */
            

/* USER CODE BEGIN PFP */
// Ajouter un échantillon et calculer la moyenne si assez d'échantillons
HAL_StatusTypeDef DHT_AddSampleAndAverage(DHT_Sensor* sensor, DHT_AveragingData* avgData);
/* USER CODE END PFP */
            

/* USER CODE BEGIN 0 */
/**
* @brief Fonction de sortie pour printf
*
* Cette fonction redirige la sortie de printf vers l'UART2.
* Elle est utilisée pour afficher des messages sur le terminal série.
*
* @param ch Le caractère à envoyer
* @return int Le caractère envoyé
*/
int __io_putchar(int ch) {
    HAL_UART_Transmit(&huart2, (uint8_t*) &ch, 1, 0xFFFF); // Pour Envoyer le caractère via UART
    // ITM_SendChar(ch); // Option alternative pour envoyer le caractère via ITM
    return ch;
}

// Ajouter un échantillon et calculer la moyenne si assez d'échantillons
HAL_StatusTypeDef DHT_AddSampleAndAverage(DHT_Sensor* sensor, DHT_AveragingData* avgData) {
    float data[2];
    HAL_StatusTypeDef result;

    // Vérifier le temps écoulé depuis le dernier échantillon
    uint32_t currentTime = HAL_GetTick();
    if (currentTime - avgData->lastSampleTime < SAMPLE_INTERVAL) { 
        // Pas assez de temps écoulé, attendre 
        return HAL_BUSY; 
    }
    // Lecture du capteur 
    result=DHT_GetData(sensor, data); 
    avgData->lastSampleTime = currentTime;

    if (result == HAL_OK) {
        // Ajouter les données à la somme
        avgData->tempSum += data[0];
        avgData->humSum += data[1];
        avgData->sampleCount++;

        // Si nous avons assez d'échantillons, calculer la moyenne
        if (avgData->sampleCount >= avgData->maxSamples) {
            avgData->avgTemp = avgData->tempSum / avgData->maxSamples;
            avgData->avgHum = avgData->humSum / avgData->maxSamples;

            // Réinitialiser pour le prochain cycle
            avgData->tempSum = 0.0f;
            avgData->humSum = 0.0f;
            avgData->sampleCount = 0;

            return HAL_OK; // Moyennes calculées
        }
        return HAL_BUSY; // Pas encore assez d'échantillons
    }
    return result; // Erreur lors de la lecture
}
/* USER CODE END 0 */
            

/* USER CODE BEGIN 2 */
HAL_Delay(250); // Attendre 250ms pour la stabilisation
printf("test STM32_DHT\r\n"); // Affiche un message de test dans la console/

HAL_TIM_Base_Start(&htim2); // Démarrer le timer2 utilisé pour les délais en microsecondes

DHT_Sensor DHT22sensor; // Déclaration de la structure pour le capteur DHT22
DHT_Init(&DHT22sensor, &htim2, GPIOA, GPIO_PIN_10, DHT22); // Initialise le capteur DHT22 sur GPIOA, PIN 10 avec TIM2

float data[2]; // Tableau pour stocker la température [0] et l'humidité [1]
DHT_GetData(&DHT22sensor, data); // Lance une lecture pour réveiller le capteur
HAL_Delay(100); // Attendre 100ms pour la stabilisation

// Initialiser la structure de moyenne avec 5 échantillons
DHT_AveragingData averagingData;
DHT_InitAveraging(&averagingData, 5);
/* USER CODE END 2 */
            

/* USER CODE BEGIN WHILE */
while (1)
{
    // Tenter d'ajouter un échantillon et calculer la moyenne si possible
    HAL_StatusTypeDef status = DHT_AddSampleAndAverage(&DHT22sensor, &averagingData);

    // Si des moyennes ont été calculées, les afficher
    if (status == HAL_OK) {
        printf("Moyennes calculées - Température: %.1f°C, Humidité: %.1f%%\r\n",
        averagingData.avgTemp, averagingData.avgHum);
    }
    // Si erreur de lecture, afficher un message
    else if (status != HAL_BUSY) {
        printf("Erreur de lecture du capteur: %d\r\n", status);
    }

    // Attendre avant la prochaine itération (petit délai pour ne pas surcharger le CPU)
    HAL_Delay(500);
    /* USER CODE END WHILE */
            
Conseil : Le moyennage est particulièrement utile pour les applications nécessitant des mesures précises, comme le contrôle climatique ou les stations météo.

Conclusion

La bibliothèque STM32_DHT vise à simplifier l'utilisation des capteurs DHT avec les microcontrôleurs STM32 en encapsulant la complexité de la communication et de la conversion des données. En suivant ce tutoriel, vous devriez être en mesure de configurer, brancher et lire les données de température et d'humidité de vos capteurs DHT11, DHT22 et DHT21.