Objectifs pédagogiques

Les principaux objectifs de ce sujet de travaux pratiques sont :

  • de manipuler des variables de types entiers et de type byte, et de comprendre la différence d'emploi de ces deux types ;
  • de découvrir la pratique des entrées analogiques.

Les exercices sont aussi l'occasion de consolider les éléments de langage mis en œuvre aux TP précédents, en particulier les techniques de codage pour obtenir des programmes réactifs.

Pour traiter ce sujet de TP, il est recommandé d'avoir étudié les chapitres C3‑I ‑II ‑III ‑VI & ‑VII. Des renvois aux principaux éléments de cours requis sont indiqués au fur et à mesure des questions.

Mise en situation

Spécifications matérielles générales

Les deux exercices sont à traiter dans l'environnement de simulation en ligne Tinkercad , en implémentant préalablement le montage électronique en figure ci‑contre, qui comprend :

  • une carte Arduino Uno R3 ;
  • une platine d'essai (breadboard) de taille moyenne, dont les rails « + » et «  » sont respectivement reliés aux broches 5V et GND de la carte Arduino ;
  • une série de 8 led (en partant de la droite, 5 jaunes puis 3 rouges) telles que :
    • les anodes sont respectivement reliées aux broches 2 à 9 du port numérique de la carte ; ces broches doivent donc être configurées dans les programmes comme des sorties (cf. chap. C2‑VIII ) ;
    • les cathodes sont reliées au rail «  » de la platine, chacune via un résistor de limitation de courant de 220 Ω ;
  • un potentiomètre (résistor variable) W à bouton tournant, de résistance totale 10 kΩ, alimenté en tension par les rails « + » et «  » de la platine, et dont le curseur (contact mobile) est relié directement à l'entrée analogique A0 de la carte.

Spécifications logicielles générales

L'exercice 1 consiste à allumer de droite à gauche, en temps réel un nombre de led proportionnel à la position du bouton tournant du potentiomètre, pour simuler un bargraphe W.

L'exercice 2 reprend la spécification de l'exercice 1 en ajoutant la persistance temporaire de la dernière led rouge allumée la plus à gauche pour signaler tout pic de tension « élevée » sur la broche du curseur du potentiomètre.

Travail demandé

Il est recommandé de traiter les exercices dans l'ordre.

Préalablement, dans un nouveau circuit sous Tinkercad :

  • effectuer le câblage de la partie matérielle conformément à la figure ci‑dessus ;
  • vérifier le câblage par branchements directs temporaires, typiquement en reliant les anodes des led au potentiel de référence 5V de la carte.

Pour coder les programmes, il est vivement recommandé de ne pas travailler directement dans Tinkercad, mais d'utiliser un éditeur de code externe comme VS Code, à paramétrer pour obtenir une coloration syntaxique adaptée au langage C++ (cf. chap. C2‑X ).

On s'efforcera de respecter les règles de bonnes pratiques de codage, notamment pour le nommage des données, l'indentation et l'aération du code (cf. chap. C2‑X ).

  • Au fur et à mesure, enregistrer chaque fichier source en le nommant conformément à la numérotation des exercices, c'est‑à‑dire par exemple :
    Ct31_exNvX.ino
    où N est le numéro de l'exercice et X la version du programme.
  • Tous ces fichiers doivent être regroupés dans un répertoire d'exercices nommé par exemple TP_C3-1, lui‑même placé dans le répertoire principal de programmation PROG_C, lui‑même placé dans répertoire personnel d'étudiant.

Remarque. Comme on n'expérimente pas ici avec une véritable carte Arduino, il n'est pas indispensable de créer un répertoire de projet distinct pour chaque programme.

Enfin, pour tester le bon fonctionnement de chaque programme, procéder par copier‑coller dans la fenêtre d'édition de Tinkercad. En cas de modifications ponctuelles de mise au point, ne pas oublier d'effectuer un copier‑coller inverse dans l'éditeur de code et d'enregistrer les modifications.

Répondre aux questions supplémentaires sur feuille ou cahier.

Consignes de codage

Déclarer les constantes globales de type int8_t :

  • POTENTIOMETER_PIN pour désigner le numéro de broche du potentiomètre ;
  • FIRST_LED_PIN et LAST_LED_PIN pour désigner les numéros de broches respectifs de la première led et de la dernière led du bargraphe ;
  • NUMBER_OF_LED pour mémoriser le nombre de led du bargraphe, en utilisant les identificateurs des deux constantes précédentes pour coder sa valeur par une expression constante.
  • Remarque : NUMBER_OF_LED mémorise une valeur cardinale (une quantité) alors que FIRST_LED_PIN et LAST_LED_PIN mémorisent des valeurs ordinales (des positions sur une échelle) – cf. l'introduction du chap. C3‑II . L'expression qui détermine la valeur NUMBER_OF_LED doit tenir compte de cette différence conceptuelle.
    Pour s'aider, on peut réfléchir sur l'exemple d'une règle graduée sur laquelle on cherche à compter le nombre k de divisions entre deux divisions n et m choisies, l'une et l'autre incluses dans le compte.

Coder la fonction setup pour configurer et initialiser toutes les sorties utilisées du port numérique de la carte (comme au TP C2-2 ).

  1. Bargraphe simple
  2. Implémenter dans la fonction loop le programme temps‑réel d'animation du bargraphe en suivant l'algorithme en quatre étapes décrit ci‑dessous :
    1. Lire la valeur analogique de la tension sur la broche reliée au curseur du potentiomètre (cf. chap. C3‑VII ) et la mémoriser dans une variable entière nommée potentiometerValue, en choisissant le type plus approprié.
    2. Calculer et mémoriser le nombre de led à allumer sur le bargraphe dans une variable entière nommée numberOfLitLed, en choisissant le type plus approprié. Dans un premier temps, on pourra utiliser la fonction map (cf. chap. C2‑VIII ).
    3. * Dans un deuxième temps, on cherchera une alternative à la fonction map, afin d'obtenir une meilleure répartition sur la course du potentiomètre pour l'allumage successif des led, spécifiée en figure ci‑contre par les valeurs seuils de la variable potentiometerValue (cf. l'exercice 5 de la feuille C3 ).
    4. Dans une version v1 du programme, à l'aide d'une boucle for avec une variable d'itération ledPin parcourant tous les numéros de broches, allumer ou éteindre les led en tenant compte de la valeur de numberOfLitLed. Dans cette boucle, on codera la condition à exprimer sur ledPin pour déterminer s'il faut la mettre au niveau logique HAUT ou BAS en raisonnant sur la figure ci‑contre (on peut notamment déterminer le décalage entre le numéro de la première led à allumer et son numéro de broche correspondant).
    5. Remarques :
      • Comme supra  (pour coder l'expression de la constante NUMBER_OF_LED), on observe que ledPin mémorise une valeur ordinale (un numéro) alors que numberOfLitLed mémorise une valeur cardinale (une quantité). La condition logique de répétition de la boucle for sur sa variable d'itération ledPin doit tenir compte de cette différence conceptuelle.
      • De plus, pour coder un programme robuste (au cas où le câblage des led serait amené à changer, et donc les numéros des broches qui les contrôlent), la condition logique sur ledPin doit aussi tenir compte de la constante FIRST_LED_PIN.
      • Pour s'aider, on peut encore réfléchir sur l'exemple d'une règle graduée sur laquelle on cherche cette fois à déterminer la division d'arrivée m en partant de la division n (incluse), et en comptant un numéro k de divisions (les divisions de départ et d'arrivée étant incluses dans le compte).
    6. Dans une version v2 du programme :
      • déclarer variable d'état ledStates de type byte et de valeur initiale 0b00000000 (cf. chap. C3‑III ). On va faire en sorte que chacun de ses bits encode par 0 ou 1 la valeur logique de l'état d'une led particulière du bargraphe, selon qu'elle doit être respectivement éteinte ou allumée.
      • À l'aide d'une boucle for avec une variable d'itération bitRank parcourant les bits de ledStates, et en utilisant la fonction bitSet (cf. chap. C3‑III ), mettre à 1 tous les bits de rang strictement inférieur à la valeur de numberOfLitLed.
      • Remarque : Avec la fonction mathématique pow (cf. chap. C2‑IV ), on peut calculer directement la valeur de ledStates en fonction de celle de numberOfLitLed. On peut alors se passer de la boucle for supra.
      • À l'aide d'une boucle for avec une variable d'itération ledPin parcourant tous les numéros de broches, allumer ou éteindre les led en codant dans le deuxième argument de la fonction digitalWrite la valeur du bit de ledStates correspondant à la valeur de ledPin, et lue grâce à la fonction bitRead (cf. chap. C3‑III ).
  3. * Bargraphe à crêtes persistantes
  4. Modifier le programme de l'exercice précédent pour qu'il affiche les pics de tension élevée, c'est‑à‑dire que si une ou plusieurs led rouges s'allument, celle de plus haut rang reste allumée durant au moins une seconde même si, entre‑temps, le niveau de tension sur le curseur du potentiomètre diminue (cf. l'image ci‑contre et la vidéo de fonctionnement d'un égaliseur Hi‑Fi au lien suivant Y).
    Pour implémenter cette fonctionnalité, il suffit de coder quelques traitements supplémentaires entre les étapes c) et d) de l'algorithme du programme de l'exercice précédent. On peut par exemple :
    • créer une variable entière nommée maxNumberOfLitLed pour mémoriser à tout instant le nombre maximal de led qui ont été allumées depuis le dernier pic de tension ;
    • utiliser une variable entière nommée previousMillis pour mémoriser la valeur rendue par la fonction millis lors du dernier pic de tension et une constante nommée PERSISTENCE_DURATION (à déclarer de type entier non signé) qui définit en millisecondes la durée de persistance d'allumage de la led rouge allumée de plus haut rang ;
    • modifier la valeur de maxNumberOfLitLed seulement si la variable numberOfLitLed prend une valeur supérieure ou égale au numéro de la première led rouge et supérieure à la dernière valeur de maxNumberOfLitLed, et actualiser alors la valeur de previousMillis
    • Mettre à 1 le bit de ledStates correspondant à la led ciblée par maxNumberOfLitLed :
      • s'il s'agit d'une led rouge ;
      • et si la condition temporelle d'allumage est encore vraie ;
      sinon réinitialiser à 0 la valeur de maxNumberOfLitLed.