Cours:ArduinoHorloge : Différence entre versions

De troyesGEII
Aller à : navigation, rechercher
(7 segments)
(7 segments)
Ligne 114 : Ligne 114 :
  
 
==7 segments==
 
==7 segments==
<div style="float:right; width:350px;">
+
<div style="float:right; width:250px;">
 
   <div style="display:block;">
 
   <div style="display:block;">
 
     [[Fichier:7segments-sch1.png|250px]]
 
     [[Fichier:7segments-sch1.png|250px]]

Version du 20 septembre 2024 à 13:38

Retour à la liste des Tps

Éléments de correction

Documentation


Nous utiliserons une carte arduino nano ainsi que divers composants que nous relierons ensemble sur une plaque à essais.

Utilisation de la plaque à essais

191px-Seven segment display-animated.gif

On utilisera dans un premier temps juste un seul digit (un seul chiffre)

dgt_M A F dgt_C dgt_D
pin 12 pin 11 pin 10 pin 9 pin 8
Afficheur4dgts.png
pin 1 pin 2 pin 3 pin 4 pin 5 pin 6 pin 7
E D DP C G dgt_U B
7seg segments.jpg
B G A C Cat L1 et L2 F NC NC
pin 16 pin 15 pin 14 pin 13 pin 12 pin 11 pin 10 pin 9
Afficheur4dgts2.png
pin 1 pin 2 pin 3 pin 4 pin 5 pin 6 pin 7 pin 8
dgt_M dgt_C D Ano L1 et L2 E dgt_D DP dgt_U
7seg segments.jpg

1 segment

   7sgts tinkercad.png

Afficheur 12 pins

   7sgts tinkercad2.PNG

Afficheur 16 pins


On validera déjà le principe de câblage en allumant le segment A sur l'afficheur.

L'afficheur utilisé est de type cathode commune :

Afficheurs 7seg ac cc 001 5.gif

Comme indiqué sur la figure précédente, pour allumer un segment il faut :

  • relier une résistance 100Ω pour nous sur la broche du segment
  • avec un fil, relier l'autre patte de la résistance à l'alimentation (5V ici)
  • relier la cathode commune ( broche digit_U ou digit_D ou digit_C ou digit_M) à la masse

Todo.jpg Vérifier que le segment s'allume et déplacer votre résistance pour allumer les différents segments


Question.jpg Déplacer maintenant le fil relié à la résistance du segment A pour le mettre sur la broche arduino D0 (Rx)

Question.jpg Ecrire un programme permettant de faire clignoter ce segment

void setup()
{
  // mettre la broche en sortie !
}

void loop()
{
  // mettre la sortie à l'état 1
  // attendre un peu
  // ...ensuite éteindre le segment et bien évidemment attendre encore !
}

7 segments

   7segments-sch1.png

Afficheur 12 pins

   7segments-sch2.png

Afficheur 16 pins

Nous relions maintenant les 7 segments à la carte arduino.

On veillera à mettre une résistance de 100Ω (270Ω) en série pour chaque segment.

Les segments seront connectés de la façon suivante :

Segment a b c d e f g
Broche arduino D0 (Rx) D1 (Tx) D3 D4 D5 D6 D7

Remarque, nous n'utilisons pas la broche arduino n°2 qui servira pour un bouton poussoir par la suite.

Question.jpg Faire le câblage

Premier affichage

Question.jpg En utilisant les fonctions pinMode et digitalWrite, représentez le chiffre 2 sur l'afficheur

Question.jpg Modifiez votre programme pour représentez le chiffre 3

Question.jpg Puis affichez successivement 2 puis 3

... ça devient vite pénible !!!

tableau et PORT

PORTD

Notion de port

ArduinoNanoPinout.png

En observant attentivement la figure ci-contre, on constate que les pattes utilisées pour commander les leds n'ont pas été choisies au hasard.

En effet, nous utilisons les pattes 0 à 7, qui correspondent pour le µcontrôleur au PORTD (PD0, PD1, PD2, ...).

Info.jpg Ainsi, il devient possible de modifier l'état de toutes ces sorties/leds, en une seule instruction :

void setup()
{
   // déclarer toutes les pattes en sortie :

}

void loop()
{
   //mettre toutes les sorties à '1'
   PORTD = 0b11111011;  // nous n'utilisons pas PD2, la broche 2
   delay(200);
   //mettre toutes les sorties à '0'
   PORTD = 0b00000000;  // ou PORTD = 0x00; ou encore PORTD = 0;
   delay(200);
}

Utilisation

Question.jpg Reprenez la question précédente, c'est à dire afficher 2 puis 3

Question.jpg Puis complétez pour afficher en boucle tous les chiffres

Tableau

Simplifions encore en utilisant un tableau dont le principe est donné si dessous :

// déclaration d'un tableau de 3 cases
// avec des valeurs initiales dans chaque case
uint8_t tableau[3] = {0b00000000,0b11001100,0b11110000};
//uint8_t est un type de variable sur 8 bits pour des nombres entiers positifs : unsigned int => uint
//[3] est le nombre de cases du tableau

void loop()
{
   // pour modifier une case :
   tableau[0] = 0b01010101; // modification de la première case
   
   // utilisation d'une case :
   x = tableau[2]; // dernière case du tableau de dimension 3

   // parcourir le tableau
   for (int i=0;i<3;i++)
   {
      .... = tableau[i] ....;
   }
}

Question.jpg Reprendre la question précédente en utilisant un tableau

  • Dans un premier temps, il suffit de remplacer PORTD=0b11111011; par PORTD=tableau[0]; ....
  • vous pouvez ensuite utiliser une boucle comme indiqué ci dessus
  • Ou mieux, se servir de la boucle pour changer de nombre :
uint8_t tableau[3] = {0b00000000,0b11001100,0b11110000};
int i=0;

void setup()
{
  ...
}

void loop()
{
      PORTD = tableau[i];
      if (i==2)
      {
         i=0;
      }
      else
      {
         i++;
      }
      // qu'on peut comprimer en supprimant les lignes inutiles if (i==2) i=0; else i++;
}

Terminé ? ... ajoutons l'afficheur des dizaines, centaines et le petit dernier les milliers !

Câblage

Nous allons réaliser un multiplexage des afficheurs, c'est à dire que l'on affichera successivement unité puis dizaine puis .... Du coup ça va clignoter, à moins de faire ça très vite.

Il faut alors modifier le schéma en reliant les cathodes communes (dig_U, dig_D, dig_C et dig_M) sur les broches du µcontrôleur.

Todo.jpg Utiliser les broches A0 à A3 pour connecter les cathodes communes.

Premier programme

Question.jpg Écrire un programme qui affiche la valeur 2 sur chacun des digits.

void setup()
{
  // pas mal de sorties !
}
void loop()
{
  PORTD=quelqueChosePourAfficher2;
  // mettre la sortie dig_U à 0 pour afficher les unités (attention seulement le dig_U !)
  digitalWrite...
  delay(100);
  // ... la même chose pour les 3 autres digits

}

Remarque :

  • changer la durée et vérifier que si cela est fait assez rapidement (tous les digits en 20ms), on aura l'impression que les 4 afficheurs sont allumés simultanément !
  • on peut éventuellement modifier les sorties des 4 digits d'un seul coup, par ex : PORTC=0b00001111;

Compteur modulo 9999

On va réaliser un compteur modulo 9999 : un compteur qui s'incrémente jusqu'à 9999 et le coup d'après retourne à 0.

Alors on commence par faire en sorte que le compteur s'incrémente toutes les 100ms :

  • installer la librairie TimerOne
  • on indique dans notre programme que l'on va l'utiliser : #include <TimerOne.h>
  • indiquons ensuite la périodicité de notre action (en µs) Timer1.initialize(100000);
  • il reste à indiquer la fonction à exécuter : Timer1.attachInterrupt(blinkLED);
  • pour récupérer la valeur :
    • des unités : u = n%10;
    • des dizaines : d = (n/10)%10;
    • des centaines : c = (n/100)%10;
    • des mil.....
  • alterner rapidement (mais pas trop) entre l'affichage des unités et des dizaines


Question.jpg En vous servant de la base suivante et de vos programmes précédents, faire en sorte d'afficher la valeur du compteur qui s'incrémente sur votre afficheur 4 digits

#include <TimerOne.h>
//sans doute d'autres variables :

volatile int compteur=0; // volatile est nécessaire lorsqu'on utilise attachInterrupt

void incrementeCompteur(void)
{
  // si compteur vaut 9999
  // alors le remettre à 0
  // sinon incrémenter le compteur
}

void setup() {
  //initialiser les choses à initialiser !

  //mise en place de l'action périodique
  Timer1.initialize(100000);
  Timer1.attachInterrupt(incrementeCompteur);
}

void loop()
{
  //répéter en permanence afficher sur les 4 digits :
  
  //sélectionner le digit des unités : PORTC=0b00001110;
  //afficher le chiffre des unité : PORTD=tab7sgt[compteur%10];
  //attendre un peu

  //même chose ou presque pour les dizaines

  //les centaines

  //et les milliers

  //that's all folks !
}


Réalisation d'une horloge

Todo.jpg Terminez le câblage en ajoutant la gestion des ":" qui permettront de séparer minutes et heures.

Vous utiliserez la broche 12 arduino.


#include <TimerOne.h>

const unsigned int tab7Sgt[10]={0b01111011,0b00001010,0b10110011,0b10011011,0b11001010,0b11011001,0b11111001,0b00001011,0b11111011,0b11011011};
volatile uint8_t secondes=40;
volatile uint8_t minutes=59;
volatile uint8_t heures=23;

void nextSecond(void)
{
  // un petit peu de travail par ici !
}

void setup() {
  // broches des segments
  pinMode(0,OUTPUT);
  pinMode(1,OUTPUT);
  pinMode(3,OUTPUT);
  pinMode(4,OUTPUT);
  pinMode(5,OUTPUT);
  pinMode(6,OUTPUT);
  pinMode(7,OUTPUT);
  // broche du :
  pinMode(12,OUTPUT);
  // broches des cathodes communes (digits)
  pinMode(A0,OUTPUT);
  pinMode(A1,OUTPUT);
  pinMode(A2,OUTPUT);
  pinMode(A3,OUTPUT);
  // éteindre tous les digits
  PORTC=0x0F;
  // 
  Timer1.initialize(1000000);
  Timer1.attachInterrupt(nextSecond); // blinkLED to run every 0.15 seconds
}



void loop()
{
  PORTC=0b1110;
  PORTD=tab7Sgt[minutes%10];
  delay(5);

  PORTC=0b1101;
  PORTD=tab7Sgt[(minutes/10)%10];
  delay(5);

  PORTC=0b1011;
  PORTD=tab7Sgt[(heures)%10];
  delay(5);

  PORTC=0b0111;
  PORTD=tab7Sgt[(heures/10)%10];
  delay(5);
}


Le programme précédent permet d'afficher 23H59 sur l'afficheur.

Question.jpg la fonction nextSecond s'exécute toutes les secondes, complétez là pour incrémenter de façon adéquat le temps (heures/minutes/secondes)

Remarque : pour vérifier le fonctionnement vous pouvez accélérer le temps en modifiant Timer1.initialize(1000000);

Améliorations

affichage des secondes

Question.jpg Utilisez les points de l'afficheur pour indiquer les secondes : ils doivent s'allumer chaque seconde et non pas changer d'état toutes les secondes

réglage de l'heure

Question.jpg Ajoutez un bouton connecté sur la broche arduino 2 (ne pas oublier la résistance de tirage), et faire en sorte que l'on puisse régler l'heure avec ce bouton

Bluebg.png
Aidesmall.png
À propos de cette image

Une possibilité :




La fonction loop se répète toutes les 20 ms.

Vous pouvez faire en sorte qu'à chaque fois qu'on recommence la "loop", si le bouton est appuyé, alors on exécute la fonction nextSecond.

Si c'est trop lent, il est bien évidemment possible d'exécuter plusieurs fois la fonction nextSecond.