.. -*- mode: rst -*- .. -*- coding: utf-8 -*- Maintenant que nous avons vu comment contrôler les sorties de la carte Arduino, il est temps de se poser la question d'utiliser les entrées de la carte : c'est par ce moyen que nous allons pouvoir donner de l'information au programme, à travers des capteurs qui nous fournirons des informations sur le monde extérieur. Lire une valeur analogique ========================== Lecture de la tension --------------------- Il existe six ports sur la carte Arduino permettant de lire des valeurs analogiques (`A0` — `A5`). Par exemple, la tension peut être lue le port `A0` sur avec l'instruction :index:`analogRead` `analogRead(A0)` [#]_. Celle-ci est lue sur dix bits (soit une valeur comprise entre `0` et `1023`), en fonction de la tension d'alimentation de la carte Arduino (normalement 5 |V|). .. [#] https://www.arduino.cc/en/Reference/AnalogRead .. raw:: latex \begin{center} \begin{tikzpicture}[scale=2.5] \foreach \x in {0,0.5,...,5} { \pgfmathtruncatemacro\result{\x * 1023 / 5} \draw (\x,-4pt) -- (\x,4pt) node [below,yshift=-20] {\pgfmathprintnumber{\result}} node [above] {$\x$ V}; } \draw (0,0) -- (5.0,0); \end{tikzpicture} \end{center} .. note:: Lors de l'écriture sur un port analogique, la précision est réalisée sur huit bits (soit une valeur comprise entre `0` et `255`). Attention donc en redirigeant l'entrée d'un port vers une sortie ! On peut donc utiliser la carte comme un voltmètre simple, pour mesurer une tension entre 0 |V| et la tension d'alimentation (5 |V|). La formule suivante permet de calculer la tension en fonction de la valeur retournée par la fonction `AnalogRead` : .. math:: V = \frac{5 \times \mathtt{AnalogRead()}}{1023} Utiliser l'Arduino comme ohmmètre --------------------------------- Notre premier montage pour illustrer la lecture d'une valeur consiste à utiliser l'Arduino pour connaître la valeur d'une résistance. Nous allons utiliser un *pont diviseur* (voir le schéma) avec une résistance connue, et une autre dont on souhaitera déterminer la valeur : en lisant la tension :math:`V_A`, il sera possible de déterminer la valeur de la résistance inconnue. .. figure:: content/pont_diviseur.pdf :width: 50% :align: center Le pont diviseur La plus simple représentation du diviseur de tension consiste à placer deux résistances électriques en série. Ce type d'association de résistances étant omniprésent dans les montages électriques, le pont diviseur en devient une des notions fondamentales en électronique. Il est possible de calculer facilement la valeur de :math:`V_A` dans le montage, à la condition de connaitre les valeurs des résistances et la valeur de la tension Vcc. La première formule à utiliser est celle de la loi d'Ohm qui permet de citer cette équation : .. math:: I = \frac{V_\text{cc}}{R_1+R_2} En utilisant la loi d'Ohm une seconde fois, il est possible de déterminer l'équation suivante: .. math:: V_a = R_2 \times I Dans la formule ci-dessous, il suffit de remplacer le courant :math:`I` par sa valeur équivalente (la première équation) pour déterminer facilement l'équation de :math:`V_A`: .. math:: V_a = R_2 \times (\frac{V_\text{cc}}{R_1+R_2}) **Exemple** Prenons les valeurs suivantes : - :math:`V_\text{cc}`: 9V - :math:`R_1`: 1k :math:`\Omega` - :math:`R_2`: 3k :math:`\Omega` .. math:: V_a &= R_2 \times \frac{V_\text{cc}}{R_1 + R_2} \\ &= 3000 \times \frac{9}{1000+3000} \\ & = \frac{27000}{4000} \\ &= 6.75V La différence de potentiel :math:`V_A` sera égal à 6.75 |V| en utilisant les valeurs précédentes. Dans notre cas, nous connaissons la tension ainsi que la valeur de la résistance :math:`R_2`. Donc en reprenant la formule du calcul de :math:`V_A` nous obtenons : .. math:: %V_a &= R_2 \times \frac{V_\text{cc}}{R_1 + R_2} \\ %(R_1 + R_2) \times V_a &= R_2 \times V_\text{cc} \\ %R_1 \times V_a + R_2 \times V_a &= R_2 \times V_\text{cc} \\ %R_1 \times V_a &= R_2 \times V_\text{cc} - R_2 \times V_a \\ %R_1 &= \frac{R_2 \times V_\text{cc}}{V_a} - \frac{R_2 \times V_a}{V_a} \\ %R_1 &= \frac{R_2 \times V_\text{cc}}{V_a} - R_2 \\ %R_1 &= R_2 \times \left(\frac{V_\text{cc}}{V_a} - 1\right) \\ R_1 &= R_2 \times \left(\frac{1023}{\mathtt{AnalogRead()}} - 1\right) .. .. note:: .. .. .. La dernière ligne du calcul peut se retrouver ainsi : on sait que la tension .. lue par fonction `analogRead()` est échelonée de `0` à `1023` par rapport à .. la tension d'alimentation, ce que l'on peut représenter dans la ligne .. suivante : .. .. .. math:: .. .. V_A &= \frac{V_\text{cc} \times \mathtt{AnalogRead()}}{1023} && \text{donc} \\ .. \frac{V_\text{cc}}{V_A} &= \frac{V_\text{cc}}{\frac{V_\text{cc} \times \mathtt{AnalogRead()}}{1023}} \\ .. \frac{V_\text{cc}}{V_A} &= V_\text{cc} \times {\frac{1023}{V_\text{cc} \times \mathtt{AnalogRead()}}} \\ .. \frac{V_\text{cc}}{V_A} &= \frac{1023}{\mathtt{AnalogRead()}} Contrôle théorique ~~~~~~~~~~~~~~~~~~ Ce programme en python permet de prédire les différentes valeurs qui seront lues par la carte Arduino. Il reproduit (dans une certaine mesure) les erreurs d'arrondis qui seront susceptible d'arriver sur la carte lors du calcul des valeurs : .. sidebar:: Programme Ce programme va calculer la tension :math:`V_A`, la valeur lue par la fonction `analogRead`, la valeur de la résistance calculée, et l'intensité qui traverse les composants. .. include:: ../content/ohm.py :code: python .. raw:: latex \pagebreak Il permet de construire le tableau de valeurs suivant (avec :math:`R_2` = 1000 :math:`\Omega`, et :math:`V_\text{cc}` = 5 |V|) : .. sidebar:: Tension théorique Ce tableau est construit à partir de la différence de potentielle théorique au niveau de la résistance :math:`R_2`. Les valeurs réelles seront toujours légèrement différentes lors du montage. =================== ================= ============= =================== Résistance Tension théorique Valeur lue Résistance calculée =================== ================= ============= =================== 10 :math:`\Omega` 4,95 |V| 1012 10 220 :math:`\Omega` 4,1 |V| 838 220 1k :math:`\Omega` 2.5 |V| 511 1 001 10k :math:`\Omega` 0,45 |V| 93 10 000 220k :math:`\Omega` 0,02 |V| 4 254 750 =================== ================= ============= =================== Au delà de 220k :math:`\Omega`, la tension qui traverse :math:`R_2` devient si faible que la valeur lue par la fonction `analogRead` tombe à `0`, ce qui empêche toute mesure. En prenant une valeur plus importante pour la résistance :math:`R_2`, la plage d'erreur sera plus faible pour des valeurs plus importante de :math:`R_1` Montage ------- Le montage reste simple à mettre en place, il ne nécessite que deux résistances (dont celle dont on souhaite calculer la valeur). .. figure:: content/arduino_ohmetre.pdf :width: 70% Arduino comme ohmmètre La résistance :math:`R_1` sera calculée en fonction de la valeur de :math:`R_2`. La résistance :math:`R_2` peut être choisie avec une valeur de 1000 :math:`\Omega` par défaut, et changée en fonction du besoin. Le programme reprend la formule que nous avons calculé ci-dessus, et affiche le résultat sur la console. .. code-block:: arduino // La résistance r2 doit être connue et // renseignée dans le programme int r2 = ...; void setup() { Serial.begin(9600); } void loop() { int r1 = r2 * ((1023 / (float)analogRead(A0)) - 1); Serial.print("R1: "); Serial.println(r1); delay(1000);// wait for a second } .. [#] https://www.arduino.cc/en/Serial/Print .. note:: Nous découvrons à l'occasion de ce programme la librairie `Serial` [#]_ qui permet d'envoyer des données à l'ordinateur via le port |usb|. Il s'agit d'un moyen pratique pour transmettre une valeur lue sur la carte. Nous pourrions enrichir ce schéma avec une sortie sur un écran |lcd| plutôt que d'envoyer l'information vers l'ordinateur : nous aurons ainsi un ohmmètre autonome ! Capteur de proximité infrarouge =============================== Dans un projet de robot mobile, il est nécessaire de tester la présence d'objets à proximité pour éviter que celui-ci ne percute les obstacles. .. sidebar:: Capteur infrarouge .. image:: content/Sharp_GP2Y0A21YK.jpg :align: center :width: 100% Nous retrouvons deux types de senseurs sur les robots : des senseurs optiques, ou par ultrasons. Le senseur Sharp relève de la première catégorie. Il permet de détecter la présence d'un objet entre 10 et 80 cm, à partir du retour de lumière infrarouge. Montage général --------------- Le schéma suivant indique comment placer les différents câbles du connecteur :smallcaps:`JST`. .. sidebar:: Condensateur Le condensateur présent sur le schéma permet ici de lisser les variations de la tension. On l'appelle *Condensateur de découplage* [#]_. .. [#] https://fr.wikipedia.org/wiki/Condensateur_de_d%C3%A9couplage .. figure:: content/capteur_infra.pdf :width: 100% Arduino, `GP2Y0A21YK` :Cable Rouge: +5 |V| :Cable Noir: GND/Masse :Cable Jaune ou Blanc: Entrée Analogique `A0` Tension de sortie ~~~~~~~~~~~~~~~~~ .. sidebar:: Tension d'entrée Même si le composant supporte une tension allant jusque 7 |V|, il fonctionne de manière optimale avec des valeurs allant de 4,5 à 5,5 |V|. La tension de sortie, sur le fil jaune, nous indique la distance de l'objet. Celle-ci varie entre 0,5 |V| et 3 |V| selon la distance de l'obstacle [#]_. .. [#] http://www.sharp-world.com/products/device/lineup/data/pdf/datasheet/gp2y0a21yk_e.pdf .. image:: content/gp2y0a21yk_e.pdf :width: 100% .. Mesure de la tension en fonction de la distance Exemple ~~~~~~~ Ce programme lit l'entrée sur la broche `A0` et allume une |led| si un objet est détecté à proximité (±20 |cm|) : .. code-block:: arduino int ledPin = 9; // LED connected to digital pin 9 void setup() {} void loop() { int sensorValue = analogRead(A0); if (sensorValue < 220) sensorValue = 0; analogWrite(ledPin, sensorValue >> 2); delay(200); // delay 200 milliseconds } .. Déclencher le capteur sur demande .. --------------------------------- .. .. Plutôt que d'activer le capteur en continu, nous allons modifier le programme .. pour n'activer la détection d'objets seulement en cas de mouvements du robot .. (il n'est pas nécessaire de chercher à tester les obstacles si le robot ne se .. déplace pas). Cela permettra d'augmenter l'autonomie du robot (en contre-partie .. d'un port digital utilisé). La consommation du composant étant de 30 |mA|, nous .. pouvons connecter directement la broche à l'Arduino, il sera capable de fournir .. le courant nécessaire. .. .. Le capteur nécessite un délai minimal avant de fournir une valeur fiable. .. .. Créer une tension seuil .. ----------------------- .. .. Nous n'avons pas un besoin réel d'évaluer la distance de l'objet, simplement de .. pouvoir arrêter le robot s'il s'approche trop près d'un objet. Si l'on connaît .. la distance d'arrêt souhaitée (et donc la tension) avant de construire le .. robot, nous pouvons paramétrer le seuil de déclenchement de l'alarme, et .. utiliser une broche digitale au lieu d'une broche analogique. .. -*- mode: rst -*- .. -*- coding: utf-8 -*- Gérer les interruptions ======================= Lors de la lecture d'une mesure, le programme effectue sa mesure *au moment où l'instruction est exécutée*. Généralement, la vitesse d'exécution du microcontroleur est suffisante pour lire l'information à un moment où un autre du cycle, mais il arrive parfois que nous souhaitions être sûr de ne manquer aucun évènement. Dans ce cas, l'architecture standard du programme ne fonctionne plus, car nous n'avons pas la garantie que toutes les informations seront bien traitées. .. admonition:: Des exemples :class: note On peut retrouver ce genre de situation dans des contrôles très bref, par exemple un codeur rotatif va envoyer un "click" a chaque fois que l'utilisateur fait tourner la roue, si le click n'est pas traité au moment où il est émis, l'information est perdue…