Chers lecteurs et lectrices, savez-vous qu’il est toujours aussi difficile de faire une introduction et une conclusion pour chaque chapitre ? C’est pourquoi je n’ai choisi ici que de dire ceci : amusez-vous bien avec les LCD !
Consigne
Dans ce TP, on se propose de mettre en place un système de supervision, comme on pourrait en retrouver dans un milieu industriel (en plus simple ici, bien sûr !) ou dans d’autres applications. Le but sera d’afficher des informations sur l’écran LCD en fonction d’évènements qui se passent dans le milieu extérieur. Ce monde extérieur sera représenté par les composants suivants :
- Deux boutons, qui pourraient représenter par exemple deux barrières infrarouges et dont le signal reçu passe de 1 à 0 lorsqu’un objet passe devant.
- Deux potentiomètres. Le premier sert de "consigne" et est réglé par l’utilisateur. Le second représentera un capteur. À titre d’exemple, sur la vidéo à la suite vous verrez un potentiomètre rotatif qui représentera la consigne et un autre sous forme de glissière qui sera le capteur.
- Enfin, une LED rouge nous permettra de faire une alarme visuelle. Elle sera normalement éteinte mais si la valeur du capteur dépasse celle de la consigne alors elle s’allumera.
Comportement de l’écran
L’écran que j’utilise ne propose que 2 lignes et 16 colonnes. Il n’est donc pas possible d’afficher toutes les informations de manière lisible en même temps. On se propose donc de faire un affichage alterné entre deux interfaces. Chaque interface sera affichée pendant cinq secondes à tour de rôle. La première affichera l’état des boutons. On pourra par exemple lire :
Bouton G : ON
Bouton D : OFF
La seconde interface affichera la valeur de la consigne et celle du capteur. On aura par exemple :
Consigne : 287
Capteur : 115
(Sur la vidéo vous verrez "gauche / droite" pour symboliser les deux potentiomètres, chacun fait comme il veut/peut ).
Enfin, bien que l’information "consigne/capteur" ne s’affiche que toutes les 5 secondes, l’alarme (la LED rouge), elle, doit être visible à tout moment si la valeur du capteur dépasse celle de la consigne. En effet, imaginez que cette alarme représentera une pression trop élevée, ce serait dommage que tout explose à cause d’un affichage 5 secondes sur 10 ! Je pense avoir fait le tour de mes attentes ! Je vous souhaite un bon courage, prenez votre temps, faites un beau schéma/montage/code et à bientôt pour la correction !
Un montage sur simulateur interactif, sans code, est disponible dans la correction, après la partie qui explique le schéma électronique.
Correction
Le montage
Vous en avez l’habitude maintenant, je vais vous présenter le schéma puis ensuite le code. Pour le schéma, je n’ai pas des milliers de commentaires à faire. Parmi les choses auxquelles il faut être attentif se trouvent :
- Des condensateurs de filtrage pour éviter les rebonds parasites créés par les boutons
- Mettre les potentiomètres sur des entrées analogiques
- Brancher la LED dans le bon sens et ne pas oublier sa résistance de limitation de courant
Et en cas de doute, voici le schéma (qui est un peu fouillis par endroit, j’en suis désolé) !
Voici le montage sans code sur simulateur :
!(https://www.tinkercad.com/things/dtakMEfdxxs)
Le code
Là encore, je vais reprendre le même schéma de fonctionnement que d’habitude en vous présentant tout d’abord les variables globales utilisées, puis les initialisations pour continuer avec quelques fonctions utiles et la boucle principale.
Les variables utilisées
Dans ce TP, beaucoup de variables vont être déclarées. En effet, il en faut déjà 5 pour les entrées/sorties (2 boutons, 2 potentiomètres, 1 LED), j’utilise aussi deux tableaux pour contenir et préparer les messages à afficher sur la première et deuxième ligne. Enfin, j’en utilise 4 pour contenir les mesures faites et 4 autres servant de mémoire pour ces mesures. Ah et j’oubliais, il me faut aussi une variable contenant le temps écoulé et une servant à savoir sur quelle "interface" nous sommes en train d’écrire. Voici un petit tableau résumant tout cela ainsi que le type des variables.
Nom | Type | Description |
---|---|---|
boutonGauche | const int |
Broche du bouton de gauche |
boutonDroite | const int |
Broche du bouton de droite |
potentiometreGauche | const int |
Broche du potar "consigne" |
potentiometreDroite | const int |
Broche du potar "alarme" |
ledAlarme | const int |
Broche de la LED d’alarme |
messageHaut[16] | char |
Tableau représentant la ligne du haut |
messageBas[16] | char |
Tableau représentant la ligne du bas |
etatGauche | int |
État du bouton de gauche |
etatDroite | int |
État du bouton de droite |
niveauGauche | int |
Conversion du potar de gauche |
niveauDroite | int |
Conversion du potar de droite |
etatGauche_old | int |
Mémoire de l’état du bouton de gauche |
etatDroite_old | int |
Mémoire de l’état du bouton de droite |
niveauGauche_old | int |
Mémoire de la conversion du potar de gauche |
niveauDroite_old | int |
Mémoire de la conversion du potar de droite |
temps | unsigned long |
Pour mémoriser le temps écoulé |
ecran | boolean |
Pour savoir sur quelle interface on écrit |
Le setup
Maintenant que les présentations sont faites, nous allons passer à toutes les initialisations. Le setup n’aura que peu de choses à faire puisqu’il suffira de régler les broches en entrées/sorties et de mettre en marche l’écran LCD.
Quelques fonctions utiles
Afin de bien séparer notre code en morceaux logiques, nous allons écrire plusieurs fonctions, qui ont toutes un rôle particulier. La première d’entre elles sera celle chargée de faire le relevé des valeurs. Son objectif sera de faire les conversions analogiques et de regarder l’état des entrées numériques. Elle stockera bien entendu chacune des mesures dans la variable concernée.
Ensuite, deux fonctions vont nous permettre de déterminer si oui ou non il faut mettre à jour l’écran. En effet, afin d’éviter un phénomène de scintillement qui se produit si on envoi des données sans arrêt, on préfère écrire sur l’écran que si nécessaire. Pour décider si l’on doit mettre à jour les "phrases" concernant les boutons, il suffit de vérifier l’état "ancien" et l’état courant de chaque bouton. Si l’état est différent, notre fonction renvoie true
, sinon elle renvoie false
. Une même fonction sera codée pour les valeurs analogiques. Cependant, comme les valeurs lues par le convertisseur de la carte Arduino ne sont pas toujours très stables (je rappelle que le convertisseur offre plus ou moins deux bits de précision, soit 20mV de précision totale), on va faire une petite opération. Cette opération consiste à regarder si la valeur absolue de la différence entre la valeur courante et la valeur ancienne est supérieure à deux unités. Si c’est le cas, on renvoi true
, sinon false
.
Une dernière fonction nous servira à faire la mise à jour de l’écran. Elle va préparer les deux chaines de caractères (celle du haut et celle du bas) et va ensuite les envoyer successivement sur l’écran. Pour écrire dans les chaines, on vérifiera la valeur de la variable ecran
pour savoir si on doit écrire les valeurs des potentiomètres ou celles des boutons. L’envoi à l’écran se fait simplement avec print()
comme vu antérieurement. On notera le clear()
de l’écran avant de faire les mises à jour. En effet, sans cela les valeurs pourraient se chevaucher (essayez d’écrire un OFF puis un ON, sans clear(), cela vous fera un "ONF" à la fin).
La boucle principale
Nous voici enfin au cœur du programme, la boucle principale. Cette dernière est relativement légère, grâce aux fonctions permettant de repartir le code en unité logique. La boucle principale n’a plus qu’à les utiliser à bon escient et dans le bon ordre ( ) pour faire son travail. Dans l’ordre il nous faudra donc :
- Récupérer toutes les données (faire les conversions, etc.).
- Selon l’interface courante, afficher soit les états des boutons soit les valeurs des potentiomètres si ils/elles ont changé(e)s.
- Tester les valeurs des potentiomètres pour déclencher l’alarme ou non.
- Enfin, si 5 secondes se sont écoulées, changer d’interface et mettre à jour l’écran.
Simple non ? On ne le dira jamais assez, un code bien séparé est toujours plus facile à comprendre et à retoucher si nécessaire ! Allez, comme vous êtes sages, voici le code de cette boucle (qui va de paire avec les fonctions expliquées précédemment) :
Programme complet
Voici enfin le code complet. Vous pourrez le copier/coller et l’essayer pour comparer si vous voulez. Attention cependant à déclarer les bonnes broches en fonction de votre montage (notamment pour le LCD).
Et la solution interactive qui va bien (attention cette dernière s’execute assez lentement) :
!(https://www.tinkercad.com/embed/gTNctfyQIyi)