Les capteurs


Les capteurs et périphériques

Principes et théorie

Objectifs

Ce chapitre a pour but de faire un petit tour d’horizon des différents capteurs et de leur mise en place.
Une mise en exemple sera faite avec le code de base pour réaliser un serveur Web.

Les types de capteurs

Il existe une multitude de capteurs:

  • Capteur de distance
  • Capteur de température
  • Capteur de présence
  • Capteur de pression-humidité
  • Capteur de position (potentiomètre, joystick, fin de course)
  • Capteur de particules fines
  • Capteur d’accélération

Les modes de transmission

Voici les différentes façon de communiquer.
Pour nos exemples, nous nous baserons sur deux périphériques qui communiquent entre eux.

  • Simplex: la communication est unidirectionnel , c’est à dire que le périphérique A envoie des informations au périphérique B mais le B ne peut pas envoyer au A.
  • Figure – L’analogie du mode Simplex
  • Half-duplex: la communication se fait dans les deux sens mais avec un décalage dans le temps. Si le périphérique A communique, le B ne peut pas envoyer des informations en meme temps que le A.
  • Figure – L’analogie du mode Half-Duplex
  • Full-duplex: les périphériques peuvent communiquer en même temps, comme dans une conversation téléphonique.
  • Figure – L’analogie du mode Full-Duplex

Les protocoles de communication

Pour communiquer, de nombreux protocoles existent mais voici les principaux.

Le bus I2C

Le bus I2C est un bus informatique qui a émergé dans les années 80 pendant la «guerre des standards» lancée par les acteurs du monde électronique.
Conçu par Philips pour les applications de domotique et d’électronique domestique, il permet de relier facilement un microcontrôleur et différents circuits récepteurs tels que des capteurs de pression, température….
C’est un bus série synchrone bidirectionnel half-duplex avec 2 broches utilisées pour communiquer :

  • SDA : Serial Data (ligne de données)
  • SCL : Serial Clock (ligne d’horloge)

Une masse est commune aux périphériques.
Les échanges ont toujours lieu entre un seul maître et un (ou tous les) esclave(s), toujours à l’initiative du maître [note] et pour éviter les conflits électriques les broches SDA et SCL sont de type Collecteur Ouvert. Il faut donc ajouter des résistances de tirage mais ces dernières sont généralement intégrées.

Figure – Les résistances de rappel du bus I2C

Il existe d’innombrables périphériques exploitant ce bus, il est même implémentable par logiciel dans n’importe quel microcontrôleur.
A chaque composant est attribué une adresse physique qui permettra les échanges.
Cette adresse est codée sur 7 bits, ce qui fait que le bus I2C peut supporter en théorie 127 périphériques [note].
Par exemple, on pourra trouver sur un même bus I2C :

  • 1 écran OLED (adresse 0x3C)
  • 1 écran LCD (0x27)
  • 1 capteur de pression BME180 (0x35)
Figure – Un réseau de capteurs
Figure – Une capture de trame I2C

Les changements d’adresses

Lorsqu’on souhaite connecter plusieurs périphériques ayant la même adresse (par exemple 2 capteurs de température), il est possible pour certains périphériques de mettre certaines broches à un certain niveau logique pour définir l’adresse.

Le bus SPI

Le bus SPI[note] SPI est full-duplex et développé par Motorola dans le milieu des années 80.
La liaison est de type maitre-esclave ou le maitre sélectionne l’esclave avec qui il veut communiquer avec une broche \genericPin{SS}.
Le bus comporte 4 broches :

  • SCLK : Serial Clock, Horloge (généré par le maître)
  • MOSI : Master Output Slave Input (généré par le maître)
  • MISO : Master Input Slave Output (généré par l’esclave)
  • SS : Slave Select, Actif à l’état bas (généré par le maître)
Figure – Un bus SPI

Protocole

  • Le maître génère l’horloge et sélectionne l’esclave avec qui il veut communiquer par l’utilisation du signal SS
  • L’esclave répond aux requêtes du maître

La liaison UART

\index{UART}
La liaison UART est une liaison série avec deux broches :

  • RX
  • TX

Il permet uniquement de faire communiquer plus de deux appareils entre eux, contrairement aux bus I2C ou SPI, on ne peut pas relier plusieurs périphériques.

Figure – Une communication UART

Protocole

  • Un bit de start toujours à 0 pour synchroniser la communication
  • Un champ de données de 7 à 8 bits
  • Un bit de parité (paire ou impaire)
  • Un bit de stop
Figure – Le protocole UART

Au repos, la ligne est au niveau logique HAUT.

Vitesse de communication

La liaison étant asynchrone, il faut que les périphériques communiquent à la même vitesse. Cette dernière est normalisée et représente le nombre de bit par seconde (baud[note])

  • 1 200 bauds
  • 2 400 bauds
  • 4 800 bauds
  • 9 600 bauds
  • 19 200 bauds
  • 38 400 bauds
  • 57 600 bauds
  • 115 200 bauds

Une trame en exemple

On constate bien que le niveau au repos est au niveau HAUT.

Figure – Une capture de trame UART à 9600 bauds

D’autres exemple

  • Le bus CAN[note] est un bus série half-duplex couramment utilisé dans l’industrie automobile et avionique. La transmission suit le principe de transmission en paire différentielle et possèdent donc deux lignes CAN L (CAN LOW) et CAN H (CAN HIGH). Tous les équipements, appelés noeuds, souhaitant communiquer via le bus sont connectés et peuvent échanger des informations.
  • Protocole One-Wire qui utilise un seul câble pour communiquer.
  • Protocole MODBus [note]

Les capteurs de distance

Différentes technologies sont utilisées pour mesurer une distance, cependant elles possèdent leurs avantages et inconvénients.

  • Infrarouge
    • Bon marché
    • Assez précis
    • Non-linéaires
    • Sensibilité à la lumière ambiante
    • Dépend du coefficient de réflexion lumineuse de la surface en face du capteur
  • Laser
    • Très précis
    • Longue distance
    • Prix
  • Ultra-sonore
    • Prix
    • Ne dépend pas de la couleur de la surface en face du capteur
    • Précision parfois arbitraire

Les capteurs infrarouges

Ce capteur envoie une tension qui dépend de la distance de l’objet.

Figure – Un capteur de distance infrarouge

Cependant, cette tension n’est pas proportionnelle à la distance[note]

Figure – La tension de sortie en fonction de la distance

Les capteurs ultrasons

Principe

Le principe de ce capteur repose sur le temps de propagation d’une onde sonore dans l’air.
En connaissant le temps d’une aller-retour et la vitesse de propagation, on peut déterminer la distance de l’objet.

Figure – Un capteur de distance HCSR-04

Séquence de la mesure

  • On envoie une impulsion de 10µs sur la broche \lbl{green}{PIN}{TRIGGER} du capteur.
  • Le capteur envoie une dizaine d’impulsions ultrasonores à 40 kHz
  • Les ondes se propagent et rebondissent sur l’obstacle
  • Le capteur renvoie le temps de propagation avec la broche \lbl{green}{PIN}{ECHO} en mettant la sortie à
  • l’état haut durant le temps de l’aller-retour.

Figure – L’algorithme de la mesure

Voici le relevé de la broche \lbl{green}{PIN}{TRIGGER} et \lbl{green}{PIN}{ECHO}

Figure – Les broches TRIGGER et ECHO

Les écrans OLED

Les écrans OLED[note] sont des afficheurs graphiques compacts avec une résolution de 128×64 pixels ou 64×32 pixels.
Leur résolution plus élevée que des écrans LCD permet de faire des petits dessins.
Ces écrans utilisent le protocole I2C pour communiquer.

Figure – Un écran OLED

Les capteurs de température

Les capteurs numériques

Les capteurs de température DHTXX[note] sont des capteurs de température et d’humidité fonctionnant entre 3.3 et 5V.

Protocole

Le protocole de communication se fait sur un seul câble.[note]

Figure – Une trame du capteur DHT22

Branchements

Figure – Le capteur DHT22

Les capteurs analogiques

Enfin, certains capteurs transmettent leurs données via une tension analogique.
Pour certains capteurs, il suffire le lire une tension pour obtenir indirectement la grandeur physique. Par exemple, le capteur LM35 sort une tension de 10 mV/°C.

Figure – Le capteur de température LM35

Si le capteur sort une tension de 210 mV, cela veut dire qu’il fait 21°C.

Les capteurs PIR

Figure – Un capteur PIR

Principe

Les capteurs PIR (Passive-Infra-Red) détectent les rayonnements infrarouges émis par un objet.
Puisque tout objet émet un rayonnement infrarouge, le capteur PIR est muni de deux cellules sensibles aux infrarouges qui vont détecter ces rayons infrarouges réfléchit ou émit par l’objet.
Lorsqu’il n’y a pas de mouvement, le niveau d’infrarouge reçu est le même pour les deux cellules. Lors du passage d’un objet, l’émission de ces rayons va être modifiée sur une cellule puis sur l’autre ce qui va permettre de détecter le mouvement.
Le cache blanc, qui couvre et protège généralement le capteur, est une lentille de Fresnel avec plusieurs facettes qui permet de concentrer le rayonnement infrarouge sur les cellules.

Utilisation

Ces capteurs possèdent une broche de sortie qui est mise à l’état HAUT pendent une certaine durée
[note] lorsqu’il y a détection d’un mouvement.
\begin{numeric}{Diagramme temporel du capteur}
Présence & [green] LLLLLLHHHHHHHLLLLLLHHHLLLLLLLLLLLLHHHHHHLLLLL
OUT & [blue] LLLLLLLHHHHHHHHLLLLLHHHHHHHHLLLLLLLHHHHHHHHLL
\end{numeric}

Applications

  • Allumage d’une lumière à la détection d’un mouvement
  • Activation d’une alarme lors de l’intrusion d’une personne

Les relais électromagnétiques

Principe

Les relais sont des interrupteurs commandés électriquement.
Une bobine alimentée sous faible tension (5 à 24 V) génère un champ électromagnétique qui fait déplacer une membrane qui va ouvrir ou fermer le circuit.
Le relai offre une isolation galvanique entre le circuit de commande et de puissance, c’est à dire qu’il n’y a aucune liaison conductrice entre ces deux circuits.
Un relai est caractérisé par :

  • La tension de commande : 5 à 24V
  • Le courant de coupure : Ex 30A
  • La tension maximale dans le circuit de puissance : Ex 230V
  • Sa position au repos[note] : Normalement Ouvert (NO) ou
  • Normalement Fermé (NF)

  • Sa durée de vie : les relais sont garantis pour un nombre de commutation, par exemple 1 million.

Symbole

Le relai se symbolise de la façon suivante :

Figure – Le symbole du relai

On distingue clairement la partie de commande (rectangle) et le circuit qui s’ouvre ou se ferme pour laisser passer le courant.

La diode de roue libre

La bobine de commande du relai nécessite un certain courant [note] qu’une broche de microcontrôleur ne peut pas fournir.
Pour cela on utilise un composant qui fera l’interface entre le microcontrôleur et le relai : le transistor.

Figure – Utilisation d’un relai

Cependant, lors de la fermeture du relai [note], le courant est brutalement coupé, or, les bobines s’opposent aux variations de courant.
Cela engendre une surtension qui va se répercuter sur le transistor.
Cette surtension vaut :
\( U = L\cdot \frac{dI}{dt}\)
Avec :

  • U la tension en Volt aux bornes de la bobine
  • L la valeur en Henry de l’inductance[note]
  • I la variation de courant en Ampère dans la bobine

On met donc une diode en parallèle de la bobine pour que l’énergie accumulée dans la bobine passe dans la diode.
Cette diode est appelé diode de roue libre.
En exemple, une simulation sans diode est faite avec LTSpice :

Figure – Une simulation LTSpice

On active le transistor pendant 100 ms puis on le désactive et on observe la tension aux bornes du transistor.

Figure – Une surtension sur le transistor

On constate un pic à 24V, c’est à dire le double de l’alimentation 12V.
Maintenant, faisons la même simulation avec une diode de roue libre. Pour ces diodes, on privilégie des diodes Schottky à commutation rapide.

Figure – Une surtension plus faible

La surtension ne vaut plus que quelques dizaines de mV.

En pratique

Pour utiliser des relais avec des microcontrôleurs, on utilise le plus souvent des relais qui intègrent une interface de contrôle.

Figure – Un relai avec une interface de contrôle

Il suffit généralement d’alimenter le relai en 5V constant et une broche active le relai si elle passe au niveau logique HAUT.

Les codes suivants seront utilisés avec le serveur Web mis en place avec l’ESP12.
Cela permettra de réaliser une interface plus élaborée avec des capteurs et actionneurs.

Utilisation du DHT11

Objectif

L’intégration du code permettant de lire la température permettra d’obtenir l’interface suivante, à savoir un graphique pour
visualiser la température et l’humidité en temps réel.

Figure – Le rendu de l’interface

Branchements

Figure – Le branchement du module DHT

Programme de test

Avant de tester le code complet du DHT11/22 avec le serveur Web , on va essayer le module DHT sans le serveur.
Pour cela, on va téléverser le programme suivant[note]{FILE}{temperature\_humidite.ino}} :



    #include "DHT.h"
#define DHTPIN D2 //Broche du capteur

#define DHTTYPE DHT11 // DHT 11
//#define DHTTYPE DHT22 // DHT 22
//#define DHTTYPE DHT21 // DHT 21

DHT dht(DHTPIN, DHTTYPE);

void setup() {

Serial.begin(115200);
dht.begin(); //Initialisation du capteur
}

void loop() {

float h = dht.readHumidity(); //Récupère la température
float t = dht.readTemperature(); //récupère l'humidité

Serial.print("Humidite: ");
Serial.print(h);
Serial.print("\% Temperature: ");
Serial.print(t);
Serial.println("C ");

delay(2000);

}

Si vous obtenez le résultat suivant en lançant la console série, c’est que le capteur est fonctionnel.

Figure – Le capteur DHT fonctionnel

Il ne vous reste plus qu’à lancer le programme \lbl{red}{FILE}{Serveur\_Web\_DHT11\_Graphe.ino}.

Explications

Pour gérer les températures et les valeurs d’humidité dans le temps, un tableau ‘circulaire’ est utilisé dans le programme.
Il consiste à remplir au fur et à mesure un tableau et quand celui-ci est plein, on décale les valeurs pour ajouter la dernière.
Prenons un exemple avec un tableau de 5 éléments auquel on cherche à ajouter le cycle suivant : 21,22,21,22,23,24,25,26
\begin{numeric}{Les tableaux ‘circulaires’}
Etape Initial & 2D{0} 2D{0} 2D{0} 2D{0} 2D{0}
Ajout de ’21’ & 2D{21} 2D{0} 2D{0} 2D{0} 2D{0}
Ajout de ’22’ & 2D{21} 2D{22} 2D{0} 2D{0} 2D{0}
Ajout de ’21’ & 2D{21} 2D{22} 2D{21} 2D{0} 2D{0}
Ajout de ’22’ & 2D{21} 2D{22} 2D{21} 2D{22} 2D{0}
Ajout de ’23’ & 2D{21} 2D{22} 2D{21} 2D{22} 2D{23}
Ajout de ’24’ & 2D{22} 2D{21} 2D{22} 2D{23} 2D{24}
Ajout de ’25’ & 2D{21} 2D{22} 2D{23} 2D{24} 2D{25}
Ajout de ’26’ & 2D{22} 2D{23} 2D{24} 2D{25} 2D{26}
\end{numeric}%
Ce mouvement cyclique est géré par la fonction \lbl{blue}{FUNC}{updateRings} dans le fichier \lbl{purple}{LIB}{circularRings.h}
La fonction principale pour gérer le graphique est la fonction \lbl{blue}{FUNC}{getString} :



    temperature = dht.readTemperature();
humidity = dht.readHumidity();

Une fois ces deux données lues, on actualise les tableaux circulaires contenant les températures, les valeurs d’humidité et les références du graphique [note].



    updateRings(¤t_index, NB_DATA_TEMP, temperature, humidity); //Mise à jour des tableaux

On créer ensuite les chaines de caractères pour générer le graphique :



    String dataTemperatures = concatenateArray(temperatures, current_index);
String dataHumidities = concatenateArray(humidities, current_index);
String dataReferences = concatenateArray(references, current_index); //Tableau contenant toutes les valeurs à 0, pour afficher la référence sur le graphique

String dataTime ="[";
for (int i=current_index;i>0;i--) {
dataTime += "'"+String(i)+"',";
}
dataTime += "]";

Une fois toutes les données, on génère la page dans son intégralité :



const String fullPageContent = "\
\
Serveur Web CREPP\
\
\
\
\
\
\

Interface ESP12


\

Contrôle de la LED sur la broche D4


\
\


\

Mesure de la température et humidité avec le module DHT11 sur la broche D2


\

\
>>> Temperature : "+String(temperature)+" C
\
>>> Humidite : "+String(humidity)+"%\
\
\
\
";

Utilisation du HC-SR04

Branchements

Figure – Branchement du capteur

Code complet



#define TRIGGER_PIN D5  //Broche Trigger
#define ECHO_PIN D6 //Broche Echo
#define SOUND_VELOCITY 0.034 //Vitesse en cm/us
float distance = 0.0;
void setup() {
Serial.begin(9600); //Communication à 9600 bauds
pinMode(TRIGGER_PIN, OUTPUT); //Broche Trigger en sortie
pinMode(ECHO_PIN, INPUT); //Broche Echo en entrée
digitalWrite(TRIGGER_PIN, LOW);
}//End setup
void loop() {
digitalWrite(TRIGGER_PIN, HIGH); //Envoie une impulsion de 10us
delayMicroseconds(10);
digitalWrite(TRIGGER_PIN, LOW);

int duration = pulseIn(ECHO_PIN, HIGH); //Récupère le temps à l'état Haut de la broche ECHO
distance = duration * SOUND_VELOCITY/2; //Distance en cm, v=d/t
Serial.print("Distance (cm) = ");
Serial.println(distance);

delay(1000);
}

Utilisation d’un capteur PIR

Branchements

Figure – Branchement du capteur PIR

Code complet



#define LED D2    //Broche de la LED
#define OUT D7 //Broche du capteur PIR

int status = LOW; //Statut du mouvement : LOW : pas de mouvement détecté
bool outValue = 0; //Valeur du capteur
long beginTime = 0; //instant du déclenchement lors de la ldétection d'un mouvement

void setup()
{

pinMode(LED, OUTPUT); //LED en sortie
pinMode(OUT, INPUT); //Broche du capteur en entrée
Serial.begin(9600); //Vitesse de communication à 9600 bauds
}//End setup

void loop(){

outValue = digitalRead(OUT); //Lire létat du capteur

if (outValue == HIGH) //Détection d'un mouvement
{
digitalWrite(LED, HIGH); //Allume la LED

if (status == LOW)
{
Serial.println(">>> Mouvement ");
status = HIGH; //Mise à jour du statut du capteur
beginTime = millis(); //Sauvegarde du temps

}//End if

}
else //Aucun mouvement
{

digitalWrite(LED, LOW); //Eteint la LED

if(status == HIGH) //Fin de détection
{
Serial.print(">>> Fin du mouvement");
status = LOW; //Mise à jour du statut du capteur
unsigned long duree = millis() - beginTime; //Calcul de la durée du mouvement
Serial.print(">>> Duree = ");
Serial.print(duree);
Serial.println(" ms");

}//End if
}//End else
}//End loop

Utilisation d’un écran OLED

Récupération de l’adresse I2C

Pour tous les périphériques I2C, il convient de connaître l’adresse du périphérique. Or parfois on ne s’en rappel plus.
Il existe un code qui permet de scanner toutes les adresses possibles et d’afficher l’adresse du composant qui est relié au bus I2C.
Voici le code, disponible dans les exemples de la classe Wire [note] :



void loop()
{
byte error, address;
int nDevices;

Serial.println("Scanning...");

nDevices = 0;
for(address = 1; address < 127; address++ )
{
Wire.beginTransmission(address);
error = Wire.endTransmission();

if (error == 0)
{
Serial.print("I2C device found at address 0x");
if (address<16) {
Serial.print("0");
}
Serial.print(address,HEX);
Serial.println(" !");
nDevices++;
}
else if (error==4)
{
Serial.print("Unknow error at address 0x");
if (address<16) {
Serial.print("0");
}
Serial.println(address,HEX);
}
}
if (nDevices == 0) {
Serial.println("No I2C devices found\n");
}
else {
Serial.println("done\n");
}
delay(5000);

}

Code complet



  #include "SSD1306Ascii.h"
#include "SSD1306AsciiAvrI2c.h"

#define I2C_ADDRESS 0x3C

SSD1306AsciiAvrI2c oled;

void setup() {

//Init size
oled.begin(&Adafruit128x64, I2C_ADDRESS);
oled.setFont(Adafruit5x7);
oled.clear();
oled.set2X();


oled.println("CREPP");
oled.set1X();
oled.println("Club de");
oled.println("Robotique et");
oled.println("d'Electronique");
oled.println("Programmable");

}
void loop() {

}

Branchements

Figure – Branchements de l’éran OLED
Figure – L’écran OLED fonctionnel