Cours:ArduinoHorloge : Différence entre versions

De troyesGEII
Aller à : navigation, rechercher
(1 segment)
Ligne 42 : Ligne 42 :
 
==1 segment==
 
==1 segment==
  
[[Fichier:7sgts_tinkercad.png|droite|500px]]
+
[[Fichier:7sgts_tinkercad2.png|droite|500px]]
  
 
On validera déjà le principe de câblage en allumant le segment A sur l'afficheur.
 
On validera déjà le principe de câblage en allumant le segment A sur l'afficheur.

Version du 30 septembre 2021 à 17:03

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

1 segment

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-sch.png

Nous relions maintenant les 7 segments à la carte arduino.

On veillera à mettre une résistance de 100Ω 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
  • on pourra ajouter un bouton connecté sur la broche 3 (INT1) qui incrémente n à chaque appui


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éter 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);
  • essayer de faire clignoter les ":" toutes les secondes
  • ou mieux, toutes les 500ms