MICROCONTROLLEURS
COURS 4
Marin Iuliana
Mesure de la température
• Pour cela nous allons utiliser un CI (Circuit Intégré), le
TMP36.
• Il a 3 pattes, la masse, le signal et le +5V, et est simple à
utiliser.
• Il sort 10 millivolts par degré sur la patte de signal.
• Pour permettre de mesurer des températures négatives il
y a un offset de 500mV
• − 25° C = 750 mV
• − 0° C = 500mV
• − -25° C = 250 mV)
Mesure de la température
Pour convertir ces valeurs en degrés, nous
allons utiliser les capacités mathématiques de
l’Arduino.
Ensuite pour le visualiser nous allons utiliser un
outil assez puissant fourni par le logiciel : la
console de debug. Nous allons envoyer les valeurs
par une connexion série pour les afficher à
l’écran.
Est-ce qu'on doit se poser des questions sur la
fréquence d'échantillonnage ici ?
Oui on peut se la poser, mais ça ne sert à rien vu
la rapidité des variations de nos températures. 3
Schema
4
Schema
5
6
Arduino, une espèce à protéger
Jusqu’à maintenant, nous nous sommes toujours
contentés de faire circuler du courant du microcontrôleur
à la masse (sauf pour les entrées analogiques).
Au lieu d’utiliser les pattes du microcontrôleur seulement
sous forme de sortie (OUTPUT), nous pouvons aussi les
utiliser sous forme d’entrée (INPUT) ; c’est-à-dire qu’au
lieu d’être raccordée à la masse, la patte sera raccordée
au +5V.
− Tout se passera bien, si au niveau du programme, la patte est
configurée comme INPUT. Mais, si elle devait être configurée en
OUTPUT et réglée à 0V (LOW) par erreur, il est presque certain
que le microcontrôleur finira immédiatement au paradis des puces
électroniques grillées.
7
Résistances de protection
Protection des entrées numériques Pour éviter de
condamner notre microcontrôleur à la chaise électrique,
nous allons devoir le protéger. Cela peut se faire en
connectant sur la patte du microcontrôleur utilisé comme
INPUT une résistance d’une centaine d’Ohms qui limitera le
courant en cas de fausse manœuvre. Comme notre kit
contient des résistances de 330 Ω, c’est celle que nous
utiliserons.
Protéger votre Arduino doit devenir un réflexe. Si on doit
mettre un INPUT, on protège avec une résistance au cas où
on se trompe dans le code. 8
Résistances Pull-Up / Pull-Down
Une résistance de rappel, aussi appelée résistance de
tirage (en anglais pull-up resistor), est une résistance
dans un circuit électronique, située entre la source
d'alimentation et une ligne, et qui amène délibérément
cette même ligne soit à l'état haut (1 logique) pour une
résistance de rappel haut, soit à l'état bas (0 logique)
pour une résistance de rappel bas.
9
Observons l'état d'un bouton
Résistance de
protection
Modèle théorique :
− Lorsque l’on presse le bouton poussoir, on envoie +5 Volts sur D4, qui sera
interprété comme un 1.
− Lorsqu’on relâche le bouton, il n’y a plus de courant qui arrive sur D4, ce
qui sera interprété comme un 0. On a donc un signal binaire: allumé/éteint
(on/off).
Pourtant contrairement au cas théorique, fermer ou ouvrir un circuit (via un
interrupteur ou un bouton poussoir) ne génère pas forcément un signal clair :
− Le circuit non connecté à la source peut agir comme une antenne dans un
environnement pollué d'ondes électromagnétiques (proches des moteurs par
exemple). Cela va générer dans le circuit un courant qui peut être interprété
comme un signal.
− Il peut rester dans un circuit récemment ouvert un niveau d'énergie. Cela
provoque des cas d'indétermination. Le signal qui a été coupé peut être considéré
comme encore actif par un microcontrôleur. 10
Avec une résistance pull-down
Observons ce schéma
Ce montage contient une résistance de 10 kΩ (soit 10000
Ω), qu’on appelle pull- down (littéralement tirer-en-bas).
Cette résistance permet de tirer le potentiel vers le bas
(pulldown). En français, on appelle aussi ceci un rappel
au moins.
Le but d'une résistance de pull-down est donc
d’évacuer les courants vagabonds et de donner un
signal clair.
11
Avec une résistance pull-down
Si on presse le bouton, 5 Volts sont alors appliqués sur
l'entrée. Le courant va prendre le chemin le plus simple,
soit par la résistance de 220 Ω et finit par arriver sur D4.
Si on relâche le bouton, la résistance pull-down ramène
l'entrée à la masse (puisqu’elle est connectée à la masse).
12
Avec une résistance pull-up
Observons ce schéma :
Si on le compare au schéma d’un circuit avec une résistance pull-
down, on constate une inversion entre la terre et le +5V.
En effet, lorsque le circuit est ouvert, une tension de +5V est
appliquée à l’entrée D4.
Lorsqu’on appuie sur le bouton poussoir, le courant électrique va
passer par le chemin offrant le moins de résistance, soit directement
par la masse (Gnd), sans passer par l’entrée D4.
Le fonctionnement est donc inversé par rapport à la résistance pull-
down.
13
Résistance pull-down ou pull-up
À notre niveau, la seule chose qui va changer entre une résistance pull-down et
une résistance pull-up est la lecture de l’information:
Avec une résistance pull-down, par défaut, l’entrée sur la patte est égale à 0.
Avec une résistance pull-up, par défaut, l’entrée sur la patte est égale à 1.
Dans le code if (digitalRead(bouton) == 1 ), sera respectivement la valeur
d’entrée lorsque le circuit est fermé (pull-down) ou ouvert (pull-up).
Remarque :
− La résistance est ici de 10KOhms, c'est une valeur assez commune permettant
d'identifier facilement un circuit de pull-up/down.
− Il est possible de diminuer cette résistances à 4.7 KOhms mais cela
consommera aussi plus de courant.
− Il n'est pas conseillé d'utiliser une résistance de pull-up de plus de 10KOhms. À
partir de 100 KOhms, la résistance de pull-up/down interfère avec la circuiterie
interne du micro-contrôleur et le résultat (la détection) deviendrait incertain.
14
Montage avec résistance pull-down
15
Allume la LED quand on presse
16
Allume la LED quand on presse
17
Les PIN et modes
Les broches analogiques peuvent être utilisées en tant que broches
numériques, représentées par les nombres 14 (entrée analogique 0) à
19 (entrée
analogique 5).
Chacune des broches numériques possède une résistance interne
de pull-up de 20 à 50 KOhms déconnectée par défaut.
La broche numérique 13 est plus difficile à utiliser que les autres en
tant qu'entrée numérique car elle est associée à une résistance et sa
LED soudées sur le circuit imprimé de la carte sur la plupart des
cartes.
− Si vous activez la résistance interne de rappel au plus de 20KOhms, cela mettra
la broche à 1,7V au lieu des 5V théoriques car la LED et la résistance associées à
la broche abaisse la tension, qui est toujours considérée au niveau BAS (LOW).
Ainsi, si vous devez utiliser la broche 13 en tant qu'entrée numérique, utiliser une
résistance de rappel au plus externe.
18
pinMode()
Description
− Configure la broche spécifiée pour qu'elle se comporte soit en
entrée, soit en sortie.
Syntaxe
− pinMode(broche, mode)
Paramètres
− broche: le numéro de la broche de la carte Arduino dont le
mode de fonctionnement (entrée ou sortie) doit être défini.
− mode: soit INPUT (entrée en anglais) ou OUTPUT (sortie en
anglais) 19
digitalWrite()
Description
− Met un niveau logique HIGH (HAUT en anglais) ou LOW (BAS
en anglais) sur une broche numérique.
Si la broche a été configurée en SORTIE avec l'instruction
pinMode(), sa tension est mise à la valeur correspondante :
5V (ou 3.3V sur les cartes Arduino 3.3V) pour le niveau HAUT,
0V (masse) pour le niveau BAS.
Syntaxe
− digitalWrite(broche, valeur)
Paramètres
− broche: le numéro de la broche de la carte Arduino
− valeur : HIGH ou LOW (ou bien 1 ou 0)
20
digitalWrite()
Si la broche est configurée en ENTRÉE, écrire un niveau
HAUT sur cette broche a pour effet d'activer la résistance
interne de 20KOhms de "rappel au plus" (pullup) sur cette
broche. À l'inverse, mettre un niveau BAS sur cette broche
en ENTRÉE désactivera le pullup interne.
Exemple :
pinMode(pin, INPUT); // configure la broche en entrée
digitalWrite(pin, HIGH); // écrit la valeur HIGH (=1) sur la broche en entrée
// ce qui active la résistance de "rappel au +" (pullup) au plus de la broche
Cette instruction met la valeur 0/1 dans le bit de donnée
qui est associé à chaque broche, ce qui explique qu'on
puisse le mettre à 1, même si la broche est en entrée.
21
Description
digitalRead()
− Lit l'état (= le niveau logique) d'une broche précise en entrée
numérique, et renvoie la valeur HIGH (HAUT en anglais) ou LOW
(BAS en anglais).
Syntaxe
− digitalRead(broche)
Paramètres
− broche : le numéro de la broche numérique que vous voulez lire.
(int)
Valeur retournée
− Renvoie la valeur HIGH (HAUT en anglais) ou LOW (BAS en
anglais)
Remarque : Si la broche numérique en entrée n'est connectée à rien,
l'instruction digitalRead() peut retourner aussi bien la valeur HIGH ou
LOW ( et cette valeur peut changer de façon aléatoire) 22
Exemple: on allume encore une LED avec
un bouton mais avec le pull up interne!
23
analogRead()
Description
− Lit la valeur de la tension présente sur la broche spécifiée. La carte
Arduino comporte 6 voies (8 voies sur le Mini et le Nano, 16 sur le
Méga) connectées à un convertisseur analogique- numérique 10
bits. Cela signifie qu'il est possible de transformer la tension
d'entrée entre 0 et 5V en une valeur numérique entière comprise
entre 0 et 1023. Il en résulte une résolution (écart entre 2
mesures) de : 5 volts / 1024 intervalles, autrement dit une
précision de 0.0049 volts (4.9 mV) par intervalle !
− Une conversion analogique-numérique dure environ 100 µs
(100 microsecondes soit 0.0001 seconde) pour convertir
l'entrée analogique, et donc la fréquence maximale de
conversion est environ de 10 000 fois par seconde.
24
analogRead()
Syntaxe
− analogRead(broche_analogique)
Paramètres
− broche_analogique : le numéro de la broche analogique (et non le
numéro de la broche numérique) sur laquelle il faut convertir la
tension analogique appliquée (0 à 5 sur la plupart des cartes
Arduino, 0 à 7 sur le Mini et le Nano, 0 à 15 sur le Mega)
Valeur renvoyée
− valeur int (0 to 1023) correspondant au résultat de la mesure
effectuée
Remarque :
− Si la broche analogique est laissée non connectée, la valeur
renvoyée par la fonction analogRead() va fluctuer en fonction de
plusieurs facteurs (tels que la valeur des autres entrées analogiques,
la proximité de votre main vis à vis de la carte Arduino, etc.). 25
Exemple de lecture et d'envoi sur le Serial
26
analogWrite()
Description
− Génère une impulsion de largeur / période voulue sur une broche de
la carte Arduino (onde PWM - Pulse Width Modulation en anglais ou
MLI - Modulation de Largeur d'Impulsion en français).
Peut-être utilisé pour faire briller une LED avec une luminosité
variable ou contrôler un moteur à des vitesses variables.
− Après avoir appelé l'instruction analogWrite(), la broche générera
une onde carrée stable avec un "duty cycle" (fraction de la période
où la broche est au niveau haut) de longueur spécifiée (en %),
jusqu'à l'appel suivant de l'instruction analogWrite() (ou bien encore
l'appel d'une instruction digitalRead() ou digitalWrite() sur la même
broche). La fréquence de l'onde PWM est approximativement de 490
Hz (soit 490 périodes par seconde).
27
analogWrite()
Remarque : Sur les nouvelles
cartes Arduino (incluant le Mini et
le BT) avec le microcontrôleur
ATmega168, cette fonction
fonctionne sur les broches 3,5,
6, 9, 10 et 11. Les cartes plus
anciennes USB et série basée
sur l'ATmega8 ne supporte
l'instruction analogWrite() que
sur les broches 9, 10 et 11.
28
analogWrite()
Syntaxe
− analogWrite(broche, valeur);
Paramètres
− Broche : la broche utilisée pour "écrire" l'impulsion. Cette broche devra être une
broche ayant la fonction PWM, Par exemple, sur la UNO, ce pourra être une des
broches 3, 5 ,6
,9 ,10 ou 11.
− valeur: la largeur du "duty cycle" (proportion de l'onde carrée qui est au niveau
HAUT) : entre 0 (0% HAUT donc toujours au niveau BAS) et 255 (100% HAUT
donc toujours au niveau HAUT).
Notes
− Il n'est pas nécessaire de faire appel à l'instruction pinMode() pour mettre la
broche en sortie avant d'appeler la fonction analogWrite().
− L'impulsion PWM générée sur les broches 5 et 6 pourront avoir des "duty cycle" plus
long que prévu. La raison en est l'interaction avec les instructions millis() et delay(),
qui partagent le même timer interne que celui utilisé pour générer l'impulsion de
sortie PWM. 29
Exemple
• Fixer la luminosité d'une LED proportionnellement à la valeur de la tension lue
depuis un potentiomètre.
30
Quelques fonctions bien utiles
Mathématiques
− min(x, y)
− max(x, y)
− abs(x)
− constrain(x, a, b)
− map(valeur, fromLow, fromHigh, toLow, toHigh)
− pow(base, exposant)
− sq(x)
− sqrt(x)
Temps
− unsigned long millis()
− unsigned long micros()
− delay(ms)
− delayMicroseconds(us)
31
constrain(x, a, b)
Description
− Contraint un nombre à rester dans une fourchette précise.
Syntaxe
− constrain(x,a,b)
Paramètres
− x: le nombre qui doit être contraint, tout type de donnée.
− a: la limite inférieure de la fourchette, tout type de donnée.
− b: la limite supérieure de la fourchette, tout type de donnée.
Valeur renvoyée
− Renvoie x si x a une valeur comprise entre a et b
− Renvoie a si x est inférieur à a
− Renvoie b si x est plus grand que b 32
map(value, fromLow, fromHigh, toLow, toHigh)
Description
− Ré-étalonne un nombre d'une fourchette de valeur vers une
autre fourchette.
Ainsi, une valeur basse source sera étalonnée en une valeur basse
de destination, une valeur haute source sera étalonnée en une
valeur haute de destination, une valeur entre les deux valeurs
source sera étalonnée en une valeur entre les deux valeurs
destinations, en respectant la proportionnalité.
Cette fonction est très utile pour effectuer des
changements d'échelle automatiques.
− Cette fonction ne contraint pas les valeurs à rester dans les limites
indiquées, car les valeurs en dehors de la fourchette sont parfois
attendues et utiles. L'instruction constrain() doit être utilisée
également avant ou après cette fonction, si les limites de la
fourchette utilisée doivent être respectées. 33
map(value, fromLow, fromHigh, toLow, toHigh)
− La limite basse de chaque fourchette peut être supérieure ou
inférieure à la limite haute, dès lors l'instruction map() peut être
utilisée pour inverser l'ordre des valeurs, par exemple :
y = map(x, 1, 50, 50, 1);
− y évolue en sens inverse de x (càd si x = 1, y=50 et
inversement)
− Cette instruction supporte également des valeurs négatives, tel que
dans cet exemple :
y = map(x, 1, 50, 50, -100);
− Cette utilisation est aussi valide et fonctionne normalement.
− L'instruction map() utilise des valeurs entières qui, par définition, ne
peuvent fournir les décimales, alors que les calculs le devraient. Ausi
la partie décimale est tronquée, et les valeurs ne sont pas arrondies
ou moyennées. 34
map(value, fromLow, fromHigh, toLow, toHigh)
Syntaxe
− map (valeur, limite_basse_source, limite_haute_source,
limite_basse_destination, limite_haute_destination)
Paramètres
− valeur : le nombre à ré-étalonner
− limite_basse_source: la valeur de la limite inférieure de la
fourchette de départ
− limite_haute_source: la valeur de la limite supérieure de la
fourchette de départ
− limite_basse_destination: la valeur de la limite inférieure de la
fourchette de destination
− limite_haute_destination: la valeur de la limite supérieure de la
fourchette de destination
Valeur renvoyée
− La valeur ré-étalonnée 35
Exemple de l'utilisation de map
• Fixer la luminosité d'une LED proportionnellement à la valeur de la tension lue
depuis un potentiomètre.
36
Pour les matheux
Voici la fonction entière map :
long map(long x, long in_min, long in_max, long out_min, long out_max)
{
return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}
Comme nous l'avons vu map est fonction très puissante et
très utile en pratique puisqu'elle permet de réaliser une
adaptation d'échelle de valeur (entre la valeur d'une
conversion analogique numérique brute et la valeur réelle
de la tension par exemple) en une seule ligne, là où
plusieurs lignes de calcul seraient normalement
nécessaires.
37
delay(ms)
Description
− Réalise une pause dans l'exécution du programme pour la durée
(en millisecondes) indiquée en paramètre. (Pour mémoire, il y a
1000 millisecondes dans une seconde !)
Syntaxe
− delay (ms);
Paramètres
− ms (unsigned long): le nombre de millisecondes que dure la pause
38
Avertissements concernant delay(ms)
Bien qu'il soit facile de faire clignoter une LED avec l'instruction delay(), et que de
nombreux programmes utilisent de courtes pauses pour de nombreuses tâches
telles que la commutation, l'utilisation de l'instruction delay() a des inconvénients
non négligeables.
− Aucune lecture de valeur sur un capteur, opération mathématique ou manipulation de bits
ne peut avoir lieu durant une instruction delay(), et en effet, cela fait stopper toute autre
activité le temps de l'exécution de la pause.
Pour une autre approche du contrôle des temporisations, voir l'instruction millis() et le
− programme d'exemple de clignotement sans délai.
Les programmeurs avancés évitent habituellement d'utiliser l'instruction delay() pour des
pauses supérieures à 10 millisecondes, à moins que le programme Arduino ne soit très
simple.
Certaines choses se font cependant même lorsque l'instruction delay() est
exécutée sur le microcontrôleur ATmega, car l'instruction delay() ne désactive pas
les interruptions.
− Les communications série qui arrivent sur la broche RX sont prises en compte, la
génération d'impulsion PWM (analogWrite) et l'état des broches stables sont
maintenus, et les interruptions fonctionnent comme elles le doivent. 39
delayMicroseconds(us)
Description
− Stoppe le programme pendant la durée (en microsecondes)
indiquée en paramètre. (Pour mémoire, il y a 1000
microsecondes dans une milliseconde, et un million de
microsecondes dans un seconde).
− Actuellement, la valeur la plus grande qui peut produire une pause
précise est 16383. Ceci pourra changer dans les versions futures
d'Arduino. Pour des délais plus longs que quelques milliers de
microsecondes, vous devriez plutôt utiliser l'instruction delay().
Syntaxe
− delayMicroseconds(us)
Paramètres
− us: le nombre de microsecondes que doit durer la pause.
40
Avertissements concernant
delayMicroseconds(us)
• Cette fonction fonctionne de façon très précise pour des
valeurs de 3 microsecondes et plus. Nous ne pouvons pas
assurer que l'instruction delayMicroseconds donnera un
résultat correct pour des durées plus courtes.
L'instruction delayMicroseconds(0) générera un délai
beaucoup plus long qu'attendu (1020 µs environ), comme
si on utilisait un nombre négatif comme paramètre.
41
millis()
Description
− Renvoie le nombre de millisecondes depuis que la carte
Arduino a commencé à exécuter le programme courant.
Ce nombre débordera (c'est-à-dire sera remis à zéro)
après 50 jours approximativement.
Syntaxe
− variable_unsigned_long=millis();
Valeur retournée
− Le nombre de millisecondes depuis que le programme
courant a démarré. Renvoie un long non signée.
42
Exemple
unsigned long time;
void setup(){
[Link](9600);
}
void loop(){
[Link]("Time: ");
time = millis();
//affiche sur le PC le temps depuis que le programme a démarré
[Link](time);
// pause d'une seconde afin de ne pas envoyer trop de données au PC
delay(1000);
}
43
Faire clignoter sans delay
44
Description
micros()
− Renvoie le nombre de microsecondes depuis que la carte Arduino a
démarré le programme en cours. Ce nombre déborde (repasse à
0) après approximativement 70 minutes.
Sur les cartes Arduino à 16Mhz (par exemple le Nano), cette fonction
a une résolution de 4 microsecondes (ce qui veut dire que la valeur
retournée est toujours un multiple de quatre, autrement dit que la
fonction compte de quatre en quatre). Sur les cartes Arduino à 8Mhz
(par exemple Lilypad), cette fonction a une résolution de 8
microsecondes.
Syntaxe
− variable_unsigned_long=micros();
Valeur renvoyée
− Le nombre de microsecondes écoulées depuis que le programme en
cours a démarré, sous la forme d'un nombre de type unsigned
long. 45
Merci de votre attention!
46