Table des matières

TP 1 Informatique Embarquée CESI

Dire aux étudiants de se connecter en ge2i / ge2i et d'utiliser le navigateur firefox

Installation et lancement de wokwi2gtkwave

En début de chaque séance, taper ALT+F2 puis saisir gnome-terminal . Dans le terminal copier coller le texte suivant et laisser ouvert le terminal:

echo commence
mkdir -p ~/wokwi
cd ~/wokwi
rm  wokwi2gtkwave.py
wget https://raw.githubusercontent.com/bvandepo/wokwi2gtkwave/main/wokwi2gtkwave.py
chmod a+x wokwi2gtkwave.py
python3 ./wokwi2gtkwave.py
echo fini

Informations avant de commencer!

bvdp.inetdoc.net_files_iut_tp_pic_warning.jpeg Pour faire le TP, vous devrez bien lire le sujet, ne pas sauter de parties, ne pas inventer de prototypes de fonctions mais bien respecter ce qui est demandé, car les fonctions que vous écrirez devront pouvoir être substituées à d'autres fonctions ayant les mêmes prototypes. Les marges de manœuvre dont vous disposez sont au niveau de l'implémentation de ces fonctions, mais les prototypes font partie du cahier des charges et ne sont pas négociables! Le TP se déroulera sur plusieurs séances, il est de votre responsabilité de conserver les fichiers que vous aurez produits; pour cela, sauver l'URL de votre projet sur Wokwi et également LE CONTENU DU CODE pour éviter toute perte. Vous devrez également conserver les chronogrammes intéressants pour pouvoir les revoir à posteriori et les comparer.

Prise en main du programme d'exemple

Vous allez dans un premier temps utiliser un programme existant pour en comprendre le fonctionnement puis vous devrez écrire votre propre programme avec des contraintes différentes. Ouvrir dans une autre fenêtre: https://wokwi.com/arduino/libraries/SevSeg/SevSeg_Counter

Puis, en haut à gauche, cliquer sur “Save a copy”. Comme pour te TD, vous devriez vous loguer et conserver cette URL ainsi que sauvegarder votre programme à la fin de la séance et vous l'envoyer par mail (car vous travaillez sur un compte local sur le PC).

Analyse de la schématique et des composants

Lire la documentation du composant afficheur 7 segments multiplexé à 4 chiffres: https://docs.wokwi.com/parts/wokwi-7segment

En lisant le fichier diagram.json, déterminer le type d'afficheur 7 segments utilisé.

Relever sur papier les connexions électriques entre l'Arduino (avec la numérotation Arduino) et l'afficheur

En plus de la numérotation des broches Arduino, vous devrez également relever la correspondance avec les broches du microcontrôleur ATMEGA328P. Les connecteurs IOL et IOH (avec la numérotation Arduino de 0 à 13) à droite sont respectivement pilotés par les registres PORTD et PORTB sur le schéma suivant:

Regrouper les broches des différents signaux et dire par quoi elles sont pilotées. Par exemple, les 7 segments sont pilotés par …

Schéma de la carte Arduino UNO R3: https://bvdp.inetdoc.net/files/cesi/Arduino_Uno_Rev3-schematic.pdf

Utilisation d'une librairie haut niveau pour piloter l'afficheur

Dans le programme fourni, la valeur à afficher est transmise via sevseg.setNumber(val, position_point_décimal); puis sevseg.refreshDisplay() doit être appelée régulièrement pour réaliser une étape du balayage

Analyser le code fourni et comprendre l'utilisation du timer par scrutation qui a été abordée au dernier TD.

Modifier la schématique pour reproduire le schéma suivant:

Au besoin, le fichier de schématique est disponible sur: https://bvdp.inetdoc.net/files/cesi/tp1/diagram1.json

Adapter le code pour piloter l'affichage avec la valeur 10bits lue sur le Convertisseur Analogique Numérique via l'entrée A0. Ajouter également l'affichage sur la console de Debug de la valeur lue en décimal suivie d'un retour à la ligne. Vérifier en simulation le bon fonctionnement du système pour différentes positions du potentiomètre.

Analyse des signaux de commande de l'afficheur

Ajouter à la schématique le composant “Logic Analyzer (8 channels)” et connecter

Au besoin, le fichier de schématique est disponible sur: https://bvdp.inetdoc.net/files/cesi/tp1/diagram2.json

Lancer une simulation puis l’arrêter. Un fichier portant l'extension vcd est téléchargé, le sauver dans le dossier Téléchargements (si l'option est proposée, cocher toujours effectuer cette action).

Nous allons automatiser l'affichage des chronogrammes contenus dans ce fichier pour cela, ouvrir un terminal en pressant ALT+F2 puis xterm et touche Entrée. Copiez coller dans ce terminal le texte suivant (il faudra ensuite laisser ce terminal ouvert pendant toute la durée où vous souhaitez pouvoir afficher les chronogrammes):

echo commence
mkdir -p ~/wokwi
cd ~/wokwi
rm -f wokwi2gtkwave.py && wget --no-check-certificate  https://raw.githubusercontent.com/bvandepo/wokwi2gtkwave/main/wokwi2gtkwave.py
python3 ./wokwi2gtkwave.py 
echo fini

Relancer une simulation puis l’arrêter. Vous devriez voir une fenêtre gtkwave s'ouvrir et afficher le chronogramme, sinon appeler l'enseignant. Sur le chronogramme, vous pourrez zoomer à l'aide de la molette de la souris en maintenant la touche CTRL pressée. Les fichiers chronogrammes sont automatiquement déplacés dans un sous dossier ~/wokwi/vcdforgtkwave que vous pourrez renommer à posteriori si vous voulez en conserver certaines versions et éviter qu'elles ne soient écrasées.

Interprétez les chronogrammes:

Programme avec votre propre librairie

Le programme d'exemple étant maintenant compris (normalement…), vous allez devoir écrire vous même les fonctions permettant de piloter l'afficheur.

Numérotation des digits et segments

Nous utiliserons une numérotation un peu différente de celle de la documentation de l'afficheur 7 segments fournie en: https://docs.wokwi.com/parts/wokwi-7segment

numérotation TP rôle affichage sur le chronogramme
digit 0 chiffre le plus à gauche (miliers) D0
digit 1 chiffre (centaines) D1
digit 2 chiffre (dizaines) D2
digit 3 chiffre le plus à droite (unités) D3
segment 0 à 3 segment A à D non visibles
segment 4 segment E D4
segment 5 segment F D5
segment 6 segment G D6
segment 7 point décimal DP D7

Changements par rapport à l'exercice précédent

La librairie utilisée précédemment est très générique, ce qui signifie qu'elle peut être utilisée dans plusieurs configurations différentes en s'adaptant facilement (par exemple à différents type et taille d'afficheurs, à différente familles de microcontrôleurs). La librairie que vous allez écrire sera moins générique mais sera spécifique et optimisée pour un microcontrôleur et un afficheur particulier, les deux étant connectés d'une manière fixe. Ceci nous permettra d'illustrer la commande à bas niveau en pilotant les broches du microcontrôleur directement via ses registres.

Dans cet exercice, pour changer, nous allons utiliser un autre type de cablage de l'afficheur. Pour changer le type d'afficheur du schéma, remplacer dans le fichier diagram.json dans les attributs du composant “wokwi-7segment”

"attrs": { "digits": "4", "common": "anode" }

par

"attrs": { "digits": "4", "common": "cathode" }

Avec cet afficheur, vous devrez balayer les différents digits (actifs à l'état bas) et pour chaque digit piloter les segments (actifs à l'état haut) qui doivent s'allumer. VOUS DEVREZ ABSOLUMENT veiller à ce que:

  1. il n'y ait jamais deux digits actifs en même temps, pour cela vous devrez en désactiver un AVANT d'activer le suivant.
  2. les changements de valeur pilotant les segments soient réalisés lorsque AUCUN des digits n'est actif.

Programme de départ

Copier coller ce programme à la place de l'ancien. Il contient la définition des variables globales dont vous aurez besoin:

aff7seg.ino
byte numDigits = 4;
byte digitPins[] = {2, 3, 4, 5};
byte numSegments = 8;
byte segmentPins[] = {6, 7, 8, 9, 10, 11, 12, 13};
byte tabDeco7seg[]={0x3f,0x06,0x5b,0x4F,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};
 
void setup() {
  Serial.begin(115200);
  Serial.println("debut");
}
 
void loop() {
}

Initialisations

Dans un premier temps, nous utiliserons les fonctions Arduino digitalWrite(…) et pinMode(…) pour configurer/piloter les broches (en utilisant les tableaux définis en variables globales pour identifier les broches).

Compléter le programme pour configurer toutes les broches utiles dans la bonne direction et à une valeur inactive. Il est très fortement conseillé d'utiliser des boucles car le traitement à produire pour les différentes broches est quasiment le même.

Vérification de la commandabilité

Modifier loop() temporairement juste pour allumer sur l'afficheur des dizaines le segments F et le point décimal.

Faire de même cette fois-ci pour allumer les segments A et E de l'afficheur des milliers.

Une fois que vous avez vérifié en simulation que vous êtes bien capables de piloter les segments, commenter ce code dans loop().

Fonction de pilotage d'un digit

Implémenter la fonction void setDigit(unsigned char nDigitActif,unsigned char nSegsActif) dont les paramètres sont:

Cette fonction devra successivement (copier coller ces 3 items dans votre code en tant que commentaires, et écrire votre code sous chaque commentaire):

  1. désactiver tous les digits avant de changer les segments
  2. piloter les segments en utilisant les valeurs des bits de nSegsActif
  3. activer le bon digit

Tester votre fonction en utilisant ce sous programme loop():

aff7seg5.ino
void loop() {
setDigit(0,0x10);
setDigit(1,0x20);
setDigit(2,0x40);
setDigit(3,0x80);
}

Vérifier que l'affichage est correct. Faire de même pour cet autre programme:

Tester votre fonction en utilisant ce sous programme loop():

aff7seg7.ino
void loop() {
setDigit(0,1);
setDigit(1,2);
setDigit(2,3);
setDigit(3,4);
}

Décodage 7 segments

Nous avons vu en TD l'utilisation d'une table de transcodage (Look-Ut Table) pour réaliser le décodage 7 segments. Cette table est déclarée dans votre programme dans le tableau tabDeco7seg.

Adapter loop() pour afficher les chiffres présents dans les cases du tableau byte digits[4]; en réalisant le décodage. Vous aurez pris soin d'initialiser digit[] pour que chaque case contienne un chiffre différent à afficher sur le digit correspondant. Vous veillerez aussi à ce qu'une valeur supérieure à 15 dans une case de digit[] ne provoque pas une fuite mémoire lors de la recherche de la valeur correspondante dans la table tabDeco7seg. Pour l'instant vous ne vous occuperez pas du point décimal. Vous ne devez pas modifier la fonction void setDigit(unsigned char nDigitActif,unsigned char nSegsActif)!

Gestion du point décimal

Toutes les valeurs stockées dans le tableau tabDeco7seg ont le bit 7 à la valeur 0. Donc votre programme à l'exercice précédent doit avoir éteint tous les points décimaux.

Nous allons maintenant utiliser la variable globale byte dots; pour indiquer quels points décimaux afficher. Pour cela le bit i de dots à 1 indique qu'il faut allumer le point décimal de l'afficheur i.

Adapter le programme précédent pour activer correctement les points décimaux. Pour cela, utiliser les opérateurs logiques et de décalage vus en TD. Vous ne devez toujours pas modifier la fonction void setDigit(unsigned char nDigitActif,unsigned char nSegsActif)!

Conversion binaire 16 bits vers BCD 4 digits

Vous devez maintenant implémenter une fonction void setNumber(unsigned int val) qui va remplir les 4 cases du tableau digits à partir d'une valeur numérique sur 16 bits non signée passée via le paramètre val. Pour cela, vous pourrez utiliser notamment l'opérateur modulo (% en C).

Tester votre programme pour afficher la valeur “789.5”. Pour cela appelez setNumber(7895); et dots=4;

Gestion du temps

Observez pour l'exercice précédent sur les chronogrammes la fréquence à laquelle les digits sont balayés et relevez la durée pendant laquelle chacun d'eux est allumé à chaque affichage. Un rapport cyclique différent se traduit par une intensité lumineuse perçue différente. Pour éviter cela, nous allons mettre en place 2 tâches pseudo parallèles:

La structure du sous programme loop() est fournie et vous devez implémenter les 2 taches dans les fonctions correspondantes.

aff7seg11.ino
///////////////////////////
void tache1(){
 
}
///////////////////////////
void tache2(){
 
}
///////////////////////////
void loop() {
  unsigned int periodiciteTache1=100; //100ms entre chaque incrémentation de la valeur à afficher
  unsigned int periodiciteTache2=4;  //4ms pour l'affichage de chaque digit
  static unsigned long timerTache1 = millis();
  static unsigned long timerTache2 = millis();
  if (millis() - timerTache1 >= periodiciteTache1) {
    timerTache1 += periodiciteTache1;
    tache1();
  }
  if (millis() - timerTache2 >= periodiciteTache2) {
    timerTache2 += periodiciteTache2;
    tache2();
  }
}
///////////////////////////
 
}

Vérifier à l'aide des chronogrammes que chaque digit est bien piloté pendant approximativement 4ms et donc que l'affichage est rafraîchi à une cadence de 62.5Hz. Vérifier que la valeur affichée sur l'afficheur est bien cohérente avec le temps simulé (affiché en haut à droite de la schématique pendant la simulation).

bvdp.inetdoc.net_files_imageschiffres_chiffre-1.jpg}

Appeler un enseignant pour valider votre travail.

Gestion du temps par Interruption Timer

Vous avez peut être relevé des déviations par rapport à la valeur idéal de 4ms pour l'affichage sur les digits. Nous pouvons aggraver ce phénomène en rendant la tâche 1 bloquante pendant plus longtemps. Pour cela, ajouter à la fin de la tâche 1 un appel à delay(25); et relever les chronogrammes. Dans ce cas, on observe que la tâche 2 ne pourra pas être exécutée toutes les 4ms, le processeur restant bloqué dans l'exécution de la tâche 1 pendant plus de 25ms. Nous allons maintenant utiliser un mécanisme appelé Interruption pour que la tâche 2 soit appelée lorsque nécessaire, en interrompant la tâche 1 si besoin.

Avec les interruptions, il n'est plus nécessaire de venir scruter régulièrement la valeur du timer pour exécuter la tâche si besoin. Au lieu de cela, une configuration de l'interruption est effectuée au début du programme afin que la tâche 2 s'exécute à une cadence prédéterminée.

Retirer l'appel de la tâche 2 dans loop(), et appeler la fonction void setupTimer2() une fois dans setup(). Ainsi le sous programme ISR(TIMER2_COMPA_vect) est appelé automatiquement toutes les 4ms.

aff7seg13.ino
//Timer 2 : https://www.aranacorp.com/fr/utilisation-des-timers-de-larduino/
// timer2 (8 bits) qui est utilisé par la fonction Tone() et la génération de la PWM sur les broches 3 et 11.
void setupTimer2(){
  cli();                                   // disable all interrupts
  TCCR2A = (1<<WGM21)|(0<<WGM20);          // Mode CTC
  TIMSK2 = (1<<OCIE2A);                    // Local interruption OCIE2A
  TCCR2B = (0<<WGM22)|(1<<CS22)|(1<<CS21); // prediviser /256 
  OCR2A = 250;                             //250*256*1/16000000 = 4ms
  sei();                                   // enable all interrupts
}
 
//appelée toutes les 4ms:
ISR(TIMER2_COMPA_vect){                    // timer compare interrupt service routine  
    tache2();
}

Lorsque nous utilisons le mécanisme d'interruption, il est nécessaire de prendre des précautions: il faut mettre en place un verrou sur les données et périphériques utilisés en commun par les différentes tâches pour éviter par exemple que l'interruption timer affiche des valeurs en cours de réglage par la tâche 1. Pour cela, vous veillerez à ajouter avant toute modification des variables digits[] ou dots par la tache 1, l'instruction suivante pour éviter l'exécution du programme d'interruption timer pendant la modification de variable partagée:

cli();                                   // disable all interrupts

Une fois la variable modifiée, insérer l'instruction suivante pour autoriser à nouveau l'interruption timer:

sei();                                   // enable all interrupts

Observer à nouveau les chronogrammes et vérifier que les durées d'alternance des digits sont maintenant respectées.

bvdp.inetdoc.net_files_imageschiffres_chiffre-2.jpg}

Appeler un enseignant pour valider votre travail.

Pilotage des broches à bas niveau

Nous avons utilisé jusqu'à maintenant la fonction digitalWrite(…) pour piloter individuellement les broches de l'afficheur. Nous allons maintenant mettre en place un pilotage bas niveau permettant d'accéder simultanément à plusieurs bits en écrivant une valeur 8 bits dans un registre associé au port de sortie.

Nous allons commencer par évaluer le temps nécessaire à la commande de l'afficheur 7 segments par votre fonction void setDigit(void setDigit(…). Pour cela, nous allons utiliser une broche (A3, pilotée par le bit 3 du port C) qui va être mise à 1 pendant l'exécution de la fonction et à 0 le reste du temps. Configurer la broche A3 en sortie et à l'état bas dans setup(). Au début de la fonction void setDigit(…), modifier le registre PORTC pour mettre son bit 3 à la valeur 1, puis le remettre à la valeur 0 à la fin de la fonction (utiliser les opérateurs & et | ainsi que des masques).

Défaire la connexion du point décimal à l'entrée D7 de l'analyseur logique et y connecter A3 de l'Arduino pour pouvoir observer ce signal et relever la durée pendant laquelle le signal est à l'état haut pour quelques digits.

Implémentation bas niveau

Nous allons conserver cette implémentation de votre fonction void setDigit(…) en la renommant void setDigitHAL(…) et vous allez maintenant devoir ré-implémenter une fonction void setDigit(…) réalisant le même travail mais sans utiliser la fonction digitalWrite(…) de la HAL Arduino.

Veillez à ne pas écrire inutilement plusieurs valeurs à la suite dans un registre de PORT, car chaque valeur écrite pilote effectivement la broche. Éventuellement passer par une variable temporaire adéquate, dont la valeur sera finalement affectée au registre de port.

Pour réaliser la nouvelle implémentation de void setDigit(…), vous devrez manipuler les différents registres PORTB, PORTC et PORTD pour successivement (copier coller ces items dans votre code en tant que commentaires, et écrire votre code sous chaque commentaire):

  1. activer la broche A3 pour début de mesure de la durée d'exécution: TIC
  2. régler toutes les cathodes inactives
  3. régler les segments (poids faible), en maintenant toutes les cathodes inactives
  4. régler les segments (poids fort)
  5. régler la cathode active
  6. désactiver la broche A3 pour fin de mesure de la durée d'exécution:TOC

Pour cela vous devrez utiliser des opérateurs logiques, de décalage, des valeurs constantes ainsi que les paramètres nDigitActif et nSegsActif. Avant de coder, vous devriez dessiner chaque registre modifié pour chaque action et les valeurs modifiées pour chacun des bits.

Une fois la fonction codée et le fonctionnement étant correct, relever sa durée d'exécution sur le chronogramme. La durée relevée par votre professeur est de 2.5 us, ce qui est bien plus rapide que l'implémentation utilisant la HAL Arduino.

Organisation des fichiers pour la librairie

En vous inspirant de la librairie utilisée dans le TD1 cesitd1, créer 2 fichiers:

Vous déplacerez les initialisations liées à l'afficheur 7 segments de la fonction setup() à une fonction setup7seg() qui sera elle même appelée par setup() et rangée dans la librairie.

Vous devrez également ajouter à votre librairie une fonction void setDots(unsigned char val) permettant de régler la valeur de la variable dots et donc de configurer quels points décimaux doivent être allumés.

Vous devrez également ajouter à votre librairie une fonction void refresh() permettant de gérer le balayage des digits. Vous y déplacerez le code de la fonction tache2(), et vous veillerez à appeler refresh() à la place de tache2() dans la routine d'interruption timer.

bvdp.inetdoc.net_files_imageschiffres_chiffre-3.jpg}

Appeler un enseignant pour valider votre travail.

Application 1

Nous proposons maintenant d'utiliser la librairie que vous venez de faire pour réaliser une application de monitoring. Connecter 4 potentiomètres aux entrées A0, A1, A2 et A4 de l'Arduino pour reproduire le schéma suivant:

Au besoin, le fichier de schématique est disponible sur: https://bvdp.inetdoc.net/files/cesi/tp1/diagram3.json

Ecrire un programme permettant de réaliser les 4 taches suivantes en parallèles:

  1. Une première tâche réalise l'acquisition des mesures sur ces 4 entrées en permanence dans une tache, chaque 100ms. Les valeurs lues devront être stockées dans un tableau unsigned int datain[4].
  2. Dans une seconde tâche, exécutée chaque deux secondes, le numéro de l'entrée dont la valeur est affichée sur l'afficheur 7 segments sera changée, de sorte que l'on balaye les 4 entrées en 8 secondes. Cette tache remplie le rôle de choix d'aiguillage. Elle devra également indiquer sur l'afficheur quelle est la valeur en cours d'affichage, cette tache devra régler la valeur de commande des points décimaux (avec la fonction setDots(…)) pour allumer le point décimal i lors de l'affichage de la valeur datain[i].
  3. Une troisième tâche, exécutée à la cadence maximale doit utiliser la valeur de l'entrée sélectionnée par la seconde tâche pour qu'elle soit affichée par la routine d'interruption timer de votre librairie.
  4. Une quatrième tâche gérant le balayage des différents digits est appelée par interruption Timer.

Affichage des mesures

Nous allons maintenant tracer les valeurs lues sur les 4 entrées analogiques dans un plotter comme indiqué sur https://docs.wokwi.com/guides/serial-monitor#configuring-the-serial-monitor . Pour cela, dans diagram.json, après la ligne:

"editor": "wokwi",

ajouter:

"serialMonitor": {
"display": "plotter",
"newline": "lf"
},

et dans la tache 1, après la collecte des mesures sur les entrées analogiques, ajouter:

fintache1.ino
for (int i=0;i<4;i++){
  Serial.print(datain[i]);
  Serial.print(" ");
 }
Serial.println();

En lançant la simulation et en jouant sur les potentiomètres, vous devriez voir un tracé similaire à:

bvdp.inetdoc.net_files_imageschiffres_chiffre-4.jpg}

Appeler un enseignant pour valider votre travail.

Application 2

Nous proposons maintenant d'intégrer la librairie objet permettant d'utiliser l'encodeur incrémental vu dans cesitd2 à ce projet pour afficher la position angulaire et la vitesse de rotation sur l'afficheur 7 segments.

Modifier la schématique pour reproduire le schéma suivant:

Au besoin, le fichier de schématique est disponible sur: https://bvdp.inetdoc.net/files/cesi/tp1/diagram4.json

Sur ce schéma, vous retrouvez l'encodeur incrémental ainsi que l'afficheur 7 segments multiplexé à 4 digits. Une LED connectée à la sortie A5 de l'Arduino fait office de signe, en s'allumant pour indiquer le signe négatif. Un bouton de sélection connecté ) l'entrée A4 est utilisé pour permettre l'affichage soit de la position angulaire soit de la vitesse. L'affichage devra être actualisé cinq fois par seconde.

Pour l'affichage de la vitesse, vous pourrez ajouter une fonction d'affichage d'une valeur flottante positive à la librairie d'affichage. Cette fonction devra convertir la valeur flottante en un entier pour occuper au mieux les 4 digits et piloter correctement l'affichage du point. Dans le cas d'une valeur trop grande pour être afficher, il faudra afficher EEEE pour indiquer une erreur.

bvdp.inetdoc.net_files_imageschiffres_chiffre-5.jpg}

Appeler un enseignant pour valider votre travail.

Rendre la librairie de pilotage de l'afficheur 7 segments "Orientée Objet"

Visionner la vidéo de cours présentant les concepts de la Programmation Orientée Objet: https://youtu.be/5Y9P4MIkTIs

Polycopié du cours POO: https://bvdp.inetdoc.net/files/iut/cours_POO_intro_complet_2021_numbered.pdf

La classe suivante est proposée pour la librairie d'affichage:

lib7seg.h
#include <Arduino.h>
/*! Clib7Seg Classe pour la gestion de l'afficheur 7 segments multiplexé */
class Clib7Seg
{
public:
  /*!
      Clib7Seg() constructeur sans paramètre qui utilise des broches par défaut et  
      une taille d'afficheur fixe
  */
  Clib7Seg(); 
  /*!
      Clib7Seg(byte numDigitsInit,byte * digitPinsInit, byte numSegmentsInit, byte * 
      segmentPinsInit);
      constructeur avec des paramètres qui permet de configurer les broches utilisées 
      ainsi que le nombre de digits
  */
  Clib7Seg(byte numDigitsInit,byte * digitPinsInit, byte numSegmentsInit, byte * segmentPinsInit);
  /*!
      void setNumber(unsigned int val); 
      demande de mise à jour de la valeur numérique affichée à partir du paramètre
      entier val.
  */
  void setNumber(unsigned int val);
  /*!
      void setDots(unsigned char val);
      demande de mise à jour de la valeur affichée pour les points. 
      val est une valeur dont le bit 0 pilote le point de digit de gauche, et chacun 
      des bits suivants pilote le point du digit suivant.
  */
  void setDots(unsigned char val);
  /*!
      void refresh();
      demande de rafaichissement de l'affichage pour effectuer le balayage. Cette 
      méthode doit être appelée suffisament fréquemment pour que le balayage ne soit 
      pas perçu par l'oeil. Elle peut être appelée dans une tache périodique utilisant 
      un timer par scrutation ou dans une routine d'interruption timer matériel
      val est une valeur dont le bit 0 pilote le point de digit de gauche, et chacun 
      des bits suivants pilote le point du digit suivant.
  */
  void refresh();
   /*!
      setNumberFloatAbs(float floatAbs); IMPLEMENTATION SUR 4 DIGITS SEULEMENT
      demande de mise à jour de la valeur numérique affichée à partir du paramètre
      entier floatAbs. C'est la valeur absolue de floatAbs qui est affichée. Le point
      est positionné automatiquement et en cas de dépassement de la valeur par rapport
      à la capacité d'affichage, des chiffres E sont affichés.
  */ 
  void setNumberFloatAbs(float floatAbs);
 
private:
  //! nombre de digits de l'afficheur
  byte numDigits;
  /*! liste des broches utilisées pour les digits
      pointeur vers un tableau alloué dans le constructeur
      plutot qu'un tableau, utilise un pointeur pour gérer une taille variable*/
  byte *digitPins; 
  //! nombre de segments de l'afficheur (doit être 8)
  byte numSegments;
  /*! liste des broches utilisées pour les segments
      pointeur vers un tableau alloué dans le constructeur
      plutot qu'un tableau, utilise un pointeur pour gérer une taille variable*/
  byte *segmentPins;
  //! masque de bits pour gérer jusqu'à 8 points
  byte dots;
  /*! stockage des chiffre à afficher sur les digits de l'afficheur
      pointeur vers un tableau alloué dans le constructeur*/
  byte *digits;
  //! méthode de pilotage individuel des digits, appelée par refresh()
  void setDigitHAL(unsigned char nDigitActif,unsigned char nSegsActif);
  //! méthode contenant les initialisations communes aux différents constructeurs
  void init();
};

Adapter votre libraire pour qu'elle implémente cette classe. Le code de configuration du timer et de gestion de l'interruption devront être hors de la classe et le programme d'interruption timer devra juste appeler la méthode refresh(). Le plus simple est de mettre tout le code timer dans le fichier du programme principal.

Le code de votre librairie utilisant un accès bas niveau aux broches via les registres ne sera pas repris dans cette librairie objet car il ne permet pas la modularité (changer le nombre de digits et les broches).

Dans la classe, au lieu d'utiliser des tableaux pour stocker les broches et les digits, les membres déclarés sont des pointeurs. Pour pouvoir les utiliser comme des tableaux, il vous faudra procéder à l'allocation dynamique de mémoire dans les constructeurs. Par exemple, pour allouer le tableau digitPins avec numDigitsInit éléments, il faut faire:

allocation7seg.cpp
  numDigits = numDigitsInit;
  digitPins=new byte[numDigits];

L'instanciation de l'afficheur dans le programme principal se fera par:

instanciation7seg.cpp
byte digitPins[] = {2, 3, 4, 5};
byte segmentPins[] = {6, 7, 8, 9, 10, 11, 12, 13};
Clib7Seg aff7seg(4,digitPins,8,segmentPins); //Objet en variable globale car utilisé dans l'interruption

bvdp.inetdoc.net_files_imageschiffres_chiffre-6.jpg}

Appeler un enseignant pour valider votre travail.

Si vous êtes arrivé jusqu'ici, demander à l'enseignant quoi faire ensuite.