UKOnline

Transmission du signal du capteur

Maintenant que l'on a une meilleure vue de la chaine de transmission, on va s'intéresser à la récupération des données depuis les capteurs par l'Arduino. Pour cela, on va d'abord devoir comprendre le type et le contenu du signal de sortie du capteur. Ensuite, on doit réaliser la connexion physique entre le capteur et l'Arduino. Enfin, il faut lire les données envoyées par le capteur, et éventuellement les traiter, pour en extraire les valeurs des grandeurs physiques mesurées.

Capteur LM35

Commençons par nous intéresser au LM35, qui permet de mesurer la température ambiante. Pour rappel, le capteur produit un signal de sortie analogique, avec une sensibilité linéaire de 10 mV/°C. On va donc connecter la sortie du capteur sur une pin analogique de l'Arduino.

La tension mesurée sur une pin analogique est convertie par l'Arduino en une donnée numérique encodée sur 10 bits, c'est-à-dire un nombre entier compris entre $0$ et $1023$. Si la pin est alimentée avec une tension de 5 V, on peut alors avoir une résolution $V_r$ de :

$$V_r = \frac{5 V}{1024} = 0,\!0049 V = 4,\!9 mV.$$

Si la valeur lue sur la pin analogique est $0$, cela signifie que la tension qui lui est appliquée est comprise dans l'intervalle $[0 V; 4,\!9 mV[$. L'intervalle de tensions $[0 V; 5 V]$ est en fait divisé en $1024$ intervalles de mêmes longueurs, numérotés de $0$ à $1023$. De manière générale, le $i$ème intervalle correspond donc à une tension lue dans l'intervalle :

$$I_i = \left[ i \cdot 4,\!9 mV; (i + 1) \cdot 4,\!9 mV \right[.$$

Pour convertir la valeur $i$ lue sur la pin analogique, qui correspond donc à un numéro d'intervalle, en une température, on convertit d'abord $i$ en une tension $V_m$ entre 0 V et 5 V :

$$V_m = i \cdot V_r = i \cdot \frac{5000}{1024} = i \cdot 4,\!9\;[\textrm{mV}].$$

On transforme ensuite la tension mesurée $V_m$ en une température $t$ en degrés Celsius à l'aide de la sensibilité linéaire qui indique que 10 mV correspondent à 1 °C :

$$t = \frac{V_m}{10} = \frac{i \cdot 5000}{1024 \cdot 10} = i \cdot 0,\!49\;[\textrm{$^\circ$C}].$$

Pour être rigoureux et précis, on ne peut en fait pas connaitre la température précise, étant donné la conversion analogique-numérique faite par l'Arduino, représentant la valeur lue sur 10 bits. On sait en fait juste que l'on se trouve dans l'intervalle de températures :

$$t_i = \left[ i \cdot 0,\!49 °C; (i + 1) \cdot 0,\!49 °C \right[.$$

Câblage

Comme on l'a vu à la section 1.2, utiliser le LM35 est très facile. Il y a simplement trois connexions à faire : la tension d'alimentation, la masse et la sortie. La figure 5 montre le schéma de câblage pour connecter le capteur à l'Arduino. Il faut placer le LM35 avec sa face plate vers l'avant et sa face arrondie vers l'arrière. On connecte ensuite la patte de gauche aux 5 V fournis par l'Arduino, la patte de droite à la masse et, enfin, la patte centrale à la pin analogique A1. Une fois cela fait, le LM35 sera bien alimenté lorsque l'Arduino sera allumée et son signal de sortie pourra être lu par la pin analogique A1.

Câblage du LM35
Pour connecter le LM35 à une Arduino, il y a simplement trois connexions à faire, avec sa face plate vers l'avant : la tension d'alimentation (patte gauche), la masse (patte droite) et la sortie vers une pin analogique (patte centrale).

Sketch

Il ne reste plus qu'à programmer l'Arduino pour lire la sortie du capteur et la convertir en une température en degrés Celsius. On commence d'abord avec l'en-tête du sketch où l'on va juste définir le mot LM35 comme étant équivalent à A1, le numéro de la pin analogique sur laquelle le signal de sortie du LM35 a été connecté.

Vient ensuite la fonction d'initialisation où l'on va faire deux choses. On configure d'abord la pin A1 en mode entrée, à l'aide de la fonction pinMode, c'est-à-dire que le microcontrôleur de l'Arduino va pouvoir lire un signal depuis le monde extérieur via cette pin, en l'occurrence lire le signal de sortie du LM35. On configure également le port série sur 9600 bauds avec la fonction Serial.begin, ce qui permet de communiquer entre l'Arduino et l'ordinateur sur lequel elle est connectée.

Vient enfin la fonction boucle principale, répétée indéfiniment. Elle se compose de trois étapes :

  1. La première étape consiste à lire l'entrée analogique A1 avec la fonction analogRead. On obtient comme résultat un nombre entier compris entre $0$ et $1023$, que l'on stocke dans la variable i.
  2. On applique ensuite les formules expliquées en début de section pour convertir la valeur lue sur la pin analogique en une température, stockée dans la variable t. La première opération trouve la tension $V_m$ en mV et la seconde la température $t$ en °C.
  3. Enfin, la dernière étape consiste à envoyer la température mesurée vers l'ordinateur, via le port série, et puis d'attendre une seconde, grâce à la fonction delay, avant de lire à nouveau le signal de sortie du LM35.

On se retrouve donc avec le code suivant où les trois étapes ont été séparées par des lignes vides. La différence entre les fonctions Serial.print et Serial.println est que la seconde fonction ajoute un retour à la ligne après avoir envoyé son texte, ce que ne fait pas la première.

La figure 6 montre le résultat d'exécution de ce sketch, obtenu sur l'ordinateur. Au départ, la température est stable, oscillant entre 25,88 °C et 26,37 °C. Ensuite, elle se met à grimper suite au doigt que l'on a posé sur le capteur, pour atteindre 28,32 °C. Une fois le doigt retiré, la température redescend, et finira par atteindre de nouveau les mêmes valeurs qu'au début du lancement du sketch.

Exécution mesure température avec LM35
Les textes envoyés depuis l'Arduino vers son port série avec les fonctions Serial.print et Serial.println se retrouvent affichés dans une fenêtre de l'Arduino IDE, sur l'ordinateur auquel l'Arduino est connectée, et on peut ainsi obtenir les mesures de la température ambiante faites par le LM35.

Capteur DHT11

Voyons maintenant comment utiliser le DHT11 avec l'Arduino, pour mesurer l'humidité relative de l'air. Pour rappel, le capteur produit un signal de sortie numérique en suivant le protocole 1-Wire. On va donc connecter la sortie du capteur sur une pin numérique de l'Arduino.

Lorsqu'il est mis sous tension, le capteur ne fait rien, car il est en mode stand-by. Pour qu'il se mette à prendre une mesure, il faut lui envoyer un signal de départ par le bus 1-Wire. Le DHT11 mesure ensuite l'humidité relative, ainsi que la température ambiante, et envoie les résultats forme d'un signal numérique. Les deux valeurs mesurées, ainsi qu'une somme de contrôle, sont encodées sur 40 bits qui sont transmis en une trame par le capteur en une fois, bit après bit.

La figure 7 montre le détail de la trame de bits transmise. Pour les deux valeurs mesurées, les huit bits de poids fort représentent la partie entière et les huit de poids faible la partie décimale. La somme de contrôle contient les huit bits de poids faible de la somme des quatre premiers octets de la trame.

Trame transmise par DHT11
Le DHT11 encode le résultat de ses mesures en une unique trame de 40 bits contenant l'humidité relative et la température, chacune sur 16 bits, et une somme de contrôle sur 8 bits.

Prenons, par exemple, la séquence suivante 00100001 00000000 00011010 00000000 00111011, où les parties décimales des deux grandeurs mesurées sont à $0$. L'humidité relative vaut $(00100001)_2 = (33)_{10}$ % et la température vaut $(00011010)_2 = (26)_{10}$ °C. De plus, on peut vérifier que la trame est correcte car $(00100001)_2 + 0 + (00011010)_2 + 0 = (00111011)_2$.

Comme on l'a vu à la section 1.3, le signal de sortie va alterner entre des signaux hauts et bas, dont les durées en microsecondes vont être utilisées pour représenter les messages échangés sur le bus 1-Wire. Pour s'en sortir avec l'Arduino, il va donc falloir être capable de mesurer ces durées, ce qui est évidemment tout à fait possible.

Câblage

Connecter le DHT11 à l'Arduino est aussi facile qu'avec le LM35, il suffit de connecter la tension d'alimentation, la masse et la sortie. La figure 8 montre le schéma de câblage où on peut voir, de gauche à droite, que la première patte est connectée aux 5 V, la deuxième à la pin numérique $2$ et la quatrième à la masse. La troisième patte n'est pas utilisée et ne doit pas être connectée. Enfin, il ne faut pas oublier la résistance de pull-up de 10 kΩ entre la première et la deuxième patte, pour stabiliser le signal sur le bus. Une fois cela fait, le DHT11 sera bien alimenté lorsque l'Arduino sera allumée et il pourra être utilisé.

Câblage du DHT11
Pour connecter le DHT11 à une Arduino, il y a simplement trois connexions à faire, de gauche à droite : la tension d'alimentation (première patte), la sortie vers une pin numérique (deuxième patte) et la masse (quatrième patte).

Sketch

Voyons maintenant comment programmer l'Arduino pour communiquer avec le DHT11, lui faire prendre une mesure, récupérer le résultat sous forme d'une trame de 40 bits et la convertir pour obtenir la mesure d'humidité relative. On commence par l'en-tête du sketch où l'on définit le mot DHT11 comme étant équivalent à 2, la pin numérique sur laquelle le signal de sortie du DHT11 a été connecté.

La fonction d'initialisation est similaire à celle du LM35. On configure la pin $2$ en mode entrée, avec pinMode, et le port série.

Vient ensuite la fonction boucle principale, qui se base sur plusieurs fonctions détaillées plus loin dans la section. Pour obtenir la mesure d'humidité relative depuis le capteur, il faut suivre un protocole très précis, présenté à la section 1.3.2. Pour rappel, la première chose à faire consiste à envoyer un signal de départ depuis l'Arduino vers le capteur (sendStartSignal). Si cette étape s'est bien passée, on peut alors lire les données envoyées par le capteur et obtenir une trame de 40 bits en réponse, c'est-à-dire cinq octets (readFrame). Il ne reste plus qu'à vérifier que les données ont bien été transmises, sans erreur, en vérifiant la somme de contrôle (checkFrame). Si c'est le cas, on peut afficher l'humidité relative qui se trouve dans le premier octet de la trame. Enfin, on attend cinq secondes avant une nouvelle mesure.

Voyons maintenant le détail des trois fonctions utilisées dans la fonction boucle principale. Tout d'abord, la fonction sendStartSignal permet d'initier la prise de mesure par le capteur. Pour rappel, il y a plusieurs étapes à suivre très précisément :

  1. L'Arduino doit d'abord envoyer un signal bas sur le bus 1-Wire, pendant entre 1 ms et 10 ms. Pour ce faire, on change la configuration de la pin $2$ en mode sortie, on envoie un signal bas avec la fonction digitalWrite, appelée avec LOW comme second paramètre, et on attend 10 ms avec la fonction delay.
  2. L'Arduino doit ensuite envoyer un signal haut, ce que l'on fait de nouveau avec digitalWrite, et attendre la réponse du capteur qui va abaisser le signal sur le bus, dans un délai compris entre 20 µs et 40 µs. On attend cette réponse avec la fonction delayMicroseconds, qui permet d'attendre des microsecondes. Pour être certain de ne pas la manquer, on va attendre 50 µs.
  3. La réponse du capteur commence donc par un abaissement du signal. Le signal bas reste pendant 80 µs, puis il redevient haut pendant également 80 µs. Pour vérifier cela, on va utiliser la fonction pulseIn qui permet d'attendre une pulsation et mesurer sa durée. Utilisée avec HIGH comme second paramètre, elle va attendre que le signal passe de bas à haut et compter combien de temps il reste à haut, avant de repasser à bas. Si tout s'est bien passé, la fonction doit donc renvoyer une valeur proche de $80$. Dans notre code, on va prendre une petite marge de sécurité et considérer que le signal de départ a bien été reçu, et que le capteur a validé sa réception, si on mesure un signal haut pendant plus de 75 µs. Il ne faut pas oublier de repasser la pin $2$ en INPUT avant de pouvoir utiliser pulseIn.

La fonction sendStartSignal renvoie donc un booléen, qui va indiquer si l'envoi du signal de départ a bien été reçu et confirmé par le capteur.

Vient ensuite la fonction readFrame qui va lire le résultat des mesures effectuées par le capteur. Pour rappel, il envoie ce résultat en une trame de 40 bits. Pour chaque bit, le capteur envoie un signal bas sur le bus pendant 50 µs et enchaine avec un signal haut, pendant entre 26 µs et 28 µs pour indiquer un « $0$ » et pendant 70 µs pour un « $1$ ». La fonction readFrame procède en deux étapes :

  1. On commence par initialiser un tableau de $40$ cases pour y stocker la trame envoyée par le capteur. On va ensuite répéter $40$ fois la même opération à l'aide d'une boucle, à savoir mesurer la longueur des pulsations à l'aide de pulseIn. Si la durée est supérieure à 40 µs, c'est qu'on a reçu un « $1$ » et sinon c'est un « $0$ ».
  2. On va ensuite transformer la trame de 40 bits en une séquence de 5 octets, en extrayant les octets l'un après l'autre avec la fonction auxiliaire extractByte, qui n'est pas détaillée dans ce cours.

Finalement, la fonction readFrame va donc remplir le tableau de 5 octets qui lui est passé en paramètre, avec les données reçues du capteur.

Enfin, pour terminer, il reste la fonction checkFrame qui permet de vérifier si la trame envoyée par le capteur a été transmise correctement, et sans erreur, vers l'Arduino. Il faut que le dernier octet de la somme des quatre premiers octets de la trame soit égal à la somme de contrôle, qui se trouve dans le cinquième octet de la trame. Néanmoins, avec le DHT11 de la société Aosong, les parties décimales de l'humidité relative et de la température sont toujours à zéro, ce qui simplifie le calcule. On peut n'additionner que le premier et le troisième octet de la trame.

Librairie

Le sketch auquel on est arrivé ci-dessus est assez complexe. Pour y arriver, il nous a fallu d'abord bien comprendre le fonctionnement du capteur, et du protocole de communication qu'il utilise, et ensuite de l'implémenter en Arduino. Il est évident que toutes les personnes qui travaillent avec ce capteur ne vont pas à chaque fois réécrire tout ce code. Une librairie Arduino est un ensemble de codes, écrit par d'autres et mis à disposition de tous, que vous pouvez télécharger sur l'IDE Arduino, pour utiliser les fonctions qui y sont définies. Pour manipuler le DHT11, plusieurs librairies existent dont la DHT sensor library proposée par Adafruit, qui dépend de Adafruit Unified Sensor, qu'il faut donc également télécharger sur son ordinateur. La figure 9 montre comment utiliser cette librairie pour capturer l'humidité relative avec le DHT11. On ne va pas détailler ce sketch dans le cadre de ce cours.

Un sketch Arduino se compose de trois parties, à savoir une en-tête, la fonction d'initialisation qui s'exécute une fois au lancement et la fonction boucle principale dont le contenu se répète en boucle indéfiniment.

La figure 10 montre le résultat d'exécution de ce sketch avec le traceur série de l'IDE Arduino. Cet outil permet d'obtenir un graphe qui dessine l'évolution des valeurs envoyées sur le port série au cours du temps, dans notre cas l'humidité relative de l'air et la température ambiante.

Au départ, les valeurs se mettent toutes les deux à monter suite à plusieurs expirations d'air d'un humain juste en face du capteur. L'humidité relative de l'air monte jusqu'à 60 % et la température ambiante atteint presque 30 °C. Après un certain temps, l'humidité relative et la température reviennent à leur valeur initiale, après quelques petites oscillations, à savoir 40 % et 23 °C.

Exécution mesure humidité relative avec DHT11
Le traceur série de l'IDE Arduino permet d'afficher l'évolution de l'humidité relative de l'air et de la température ambiante au cours du temps tels que capturés par le capteur DHT11.

Module de détection sonore

Enfin, terminons ce chapitre en utilisant le module de détection sonore avec l'Arduino, pour détecter si le niveau sonore dépasse ou non un seuil maximal configuré sur le capteur. Pour rappel, ce capteur produit une sortie logique que l'on va pouvoir récupérer en connectant sa sortie sur une pin numérique de l'Arduino.

Ce capteur est très facile à utiliser, autant au niveau du câblage que de la programmation. Aussitôt mis sous tension, il va surveiller de manière continue le niveau sonore. Pour savoir si le seuil maximal est dépassé, on regarde juste la valeur de sortie qui sera haute si le niveau sonore est sous le seuil et basse s'il dépasse le seuil configuré.

Câblage

Connecter le module de détection sonore à l'Arduino est aussi facile qu'avec le LM35, il suffit de connecter la tension d'alimentation, la masse et la sortie. La figure 11 montre le schéma de câblage où l'on voit, de gauche à droite, que la première patte est connectée à la masse, la deuxième à la pin numérique $4$ et la troisième aux 5 V. Une fois cela fait, le capteur sera bien alimenté lorsque l'Arduino sera allumée et son signal de sortie pourra être lu par la pin numérique $4$.

Câblage du module de détection sonore
Pour connecter le module de détection sonore à une Arduino, il y a simplement trois connexions à faire, de gauche à droite : la masse (première patte), la sortie vers une pin numérique (deuxième patte) et la tension d'alimentation (troisième patte).

Sketch

Le code à produire pour récupérer la sortie logique générée par le module de détection sonore est très simple. Comme pour les deux capteurs précédents, l'en-tête définit le mot SOUND_DETECTOR comme étant équivalent à 4, la pin numérique sur laquelle le signal de sortie du module de détection sonore a été connecté.

La fonction d'initialisation configure la pin $4$ en mode entrée, avec la fonction pinMode, et le port série.

Enfin, il reste la fonction boucle principale dont le but est simplement de surveiller le niveau sonore. Comme la sortie du capteur est simplement un signal logique, on peut simplement lire sa valeur, quand on veut, grâce à la fonction digitalRead. Un signal haut signifie que le niveau sonore est normal et un signal bas indique que le niveau sonore dépasse le seuil maximal configuré. Dans ce cas, outre l'allumage d'une LED sur le module, on affiche simplement un message d'alerte à l'écran.