Capteurs de température et d’humidité DHT11 et DHT22
Ce tutoriel explique comment mettre en oeuvre des capteurs de température et d’humidité relative DHT11 et DHT22 (Grove et autres) en MicroPython. Ces capteurs sont très peu onéreux. Le DHT22, tout du moins dans l’implémentation en module Grove que nous avons testée, donne des mesures très précises et fiables d’humidité et de température. Notez bien que le DHT11 n’est pas capable de mesurer des températures inférieures à 0°C. Les figures ci-dessous montrent un module Grove intégrant un DHT11 (à gauche) et un module Grove intégrant un DHT22 (à droite).


Crédit images : Seeed Studio
Ces capteurs utilisent un protocole de communication qui leur est propre et qui ne nécessite que trois fils : une masse, une alimentation et une seule ligne de communication. Ce protocole est particulièrement délicat à programmer car il implique des mesures de fronts de signaux avec une précision de quelques millisecondes.
Matériel requis
- Une carte d’extension de base Grove
- La carte NUCLEO-WB55
- Un module Grove Temperature&Humidity Sensor Pro (DHT22)
Le code MicroPython
Les scripts présentés ci-après sont disponibles dans la zone de téléchargement.
Il faut ajouter le fichier dht.py dans le répertoire du périphérique PYBLASH. Editez maintenant le script main.py et copiez-y le code qui suit :
# Objet du script : utiliser un capteur d'humidité et de température
# de la famille DHT (DHT11 ou DHT22).
import dht # Pour gérer les DHT11 et DHT22
from time import sleep_ms # Pour temporiser
# Instanciation du DHT22
capteur = dht.DHT22('D2')
# Pour un DHT11, utilisez simplement cette syntaxe :
# capteur = dht.DHT11('D2')
while True:
# Structure de gestion des exceptions
try:
# On mesure et on lit les résultats
capteur.measure()
temp = capteur.temperature()
humi = capteur.humidity()
# Si les deux mesures renvoient 0 simultanément
if humi == 0 and temp == 0:
raise ValueError("Erreur capteur")
# Formattage (arrondis) des mesures
temperature = round(temp,1)
humidity = int(humi)
# Affichage des mesures
print('=' * 40) # Imprime une ligne de séparation
print("Température : " + str(temperature) + " °C")
print("Humidité relative : " + str(humidity) + " %")
# Si une exception est capturée
except Exception as e:
print(str(e) + '\n')
# Temporisation de deux secondes
sleep_ms(2000)
Affichage sur le terminal série de l’USB User
Une fois le script lancé avec CTRL-D, vous pourrez observer les valeurs d’humidité et de température qui défilent :

Pour aller plus loin
Les scripts présentés ci-après sont disponibles dans la zone de téléchargement.
Si le protocole de communication des capteurs DHTxx vous intéresse, vous trouverez une explication (pour Arduino) à ce sujet ici et une implémentation explicite en MicroPython à base de timers pour le DHT22 ici.
Ce dernier exemple aurait pu servir de base à notre tutoriel, mais après adaptation pour la NUCLEO-WB55, il est apparu qu’il fonctionne correctement avec la révision 1.17 mais pas avec certaines révisions antérieures.
- Tout d’abord la bibliothèque dht22.py :
# Exemple adapté de https://github.com/kurik/uPython-DHT22/blob/master/main.py
# Construction d'un pilote pour le DHT22 en utilisant un timer pour compter les
# fronts (descendants) des signaux.
from time import sleep_ms # Pour temporiser
from pyb import ExtInt, Pin, Timer # Pour gérer les broches, les interruptions des broches et les Timers.
# Nous devons utiliser ici des variables globales car toute allocation de variable locale
# entrainerait un délai qui planterait la communication.
data = None
timer = None
micros = None
FALL_EDGES = const(42) # La réception comporte 42 fronts descendants
times = list(range(FALL_EDGES))
index = 0
# Le gestionnaire d'interruptions : capture la réponse du capteur après lee START
def edge(line):
global index
global times
global micros
times[index] = micros.counter()
if index < (FALL_EDGES - 1): # Pour éviter un dépassement de buffer s'il y a du bruit sur la ligne
index += 1
# Initialisation du capteur
def init(timer_id = 2, data_pin = 'D2'):
global data
global micros
# Broche de la ligne de communication
data = Pin(data_pin)
# Identifiant du timer sélectionné
timer = timer_id
# Paramètres pour un timer de fréquence 1 microseconde
micros = Timer(timer, prescaler=65, period=0x3fffffff)
# Gestionnaire de l'interruption du timer
ExtInt(data, ExtInt.IRQ_FALLING, Pin.PULL_UP, edge)
def do_measurement():
global data
global micros
global index
# Envoie la commande START
data.init(Pin.OUT_PP)
data.low()
micros.counter(0)
while micros.counter() < 25000:
pass
# Passe la broche en IN
data.high()
micros.counter(0)
index = 0
data.init(Pin.IN, Pin.PULL_UP)
# Après 5 millisecondes, la mesure doit être terminée
sleep_ms(5)
# Lis les données renvoyées par le capteur
def process_data():
global times
i = 2 # On ignore les deux premiers fronts descendants qui sont la réponse à la commande START
result_i = 0
result = list([0, 0, 0, 0, 0])
while i < FALL_EDGES:
result[result_i] <<= 1
if times[i] - times[i - 1] > 100:
result[result_i] += 1
if (i % 8) == 1:
result_i += 1
i += 1
[int_rh, dec_rh, int_t, dec_t, csum] = result
humidity = ((int_rh * 256) + dec_rh)/10
temperature = (((int_t & 0x7F) * 256) + dec_t)/10
if (int_t & 0x80) > 0:
temperature *= -1
comp_sum = int_rh + dec_rh + int_t + dec_t
if (comp_sum & 0xFF) != csum:
raise ValueError('La somme de contrôle est incorrecte')
return (humidity, temperature)
def measure():
do_measurement()
if index != (FALL_EDGES -1):
raise ValueError('Echec du transfert de données : %s fronts descendants seulement' % str(index))
return process_data()
- Ensuite le fichier main.py :
# Exemple adapté de https://github.com/kurik/uPython-DHT22/blob/master/main.py
# Objet du script : Mise en oeuvre du capteur de température et humidité DHT22
# Deuxième approche : utilisation d'une classe exploitant les interruption d'un timer
import dht22 # Pour gérer le DHT22
from time import sleep_ms # Pour temporiser
# Initialisation du pilote du DHT22.
# On a besoin du timer 2 pour celui-ci
dht22.init(timer_id = 2, data_pin = 'D2')
while True:
# Pour gérer les exceptions
try:
# Recupération des mesures (2-uple)
(hum, tem) = dht22.measure()
# En cas de retour erroné sur les deux mesures simultanément
if hum == 0 and tem == 0:
raise ValueError("Erreur capteur")
# Formattage (arrondis) des mesures
temp = round(tem,1)
humi = int(hum)
# Affichage des mesures
print('=' * 40) # Imprime une ligne de séparation
print("Température : " + str(temp) + " °C")
print("Humidité relative : " + str(humi) + " %")
# Si une exception est survenue
except Exception as e:
print(str(e) + '\n')
# Temporisation de deux secondes
sleep_ms(2000)