Cours:TPS 2103 2

De troyesGEII
Aller à : navigation, rechercher

Retour à la liste des Tps

Éléments de correction

Vous allez développer un système de digicode architecturé autour d'un atmega328p (le µcontrôleur présent sur les cartes arduino).

ArduinoPinout.png

Informations lumineuses

Le digicode sera équipé de 2 voyants lumineux (rouge et vert). On utilisera des résistances de 330Ω, et vous êtes libre de choisir un montage à anodes ou cathodes communes.

Todo.jpg Câbler sur une plaque à essais les leds sur les pin PC0 et PC1

Question.jpg Écrire une fonction pour éteindre ou allumer une led dont le prototype sera le suivant :

void setEtatLed(unsigned char numLed,unsigned char val);
Bluebg.png
Aidesmall.png
À propos de cette image

Astuce


Vous pourrez vous inspirer du programme suivant permettant de faire clignoter la led "13" de la carte Arduino Uno.

#define led PB5

void setup()
{
  DDRB |= 1 << led;
  
}

void loop()
{
  PORTB |= 1 << led;
  delay(100);
  PORTB &= ~(1 << led);
  delay(100);
}

Buzzer

Objectif

Nous souhaitons utiliser le buzzer afin d'avoir une information sonore sur la touche du clavier appuyée.

Pour ce faire, chaque touche sera associée à une note de musique tel qu'indiqué dans le tableau suivant :

Touche 0 1 2 3 4 5 6 7 8 9 * #
Note Do Do# Ré# Mi Fa Fa# Sol Sol# La La# Si
Fréquence (Hz) 261,63 277,18 293,66 311,13 329,63 349,23 369,99 392 415,3 440 466,16 493,88
Période (µs) 3822 3608 3405 3214 3037 2863 2703 2551 2408 2273 2145 2025

Premier bruit

Todo.jpg Vous connecterez votre buzzer positionné sur la plaque à essais sur les pins PC4 et PC5

Todo.jpg Ne pas oublier de déclarer les sorties supplémentaires

Question.jpg Faire un premier essai en faisant varier l'état de PC4 à une fréquence correspond à un Sol

Bluebg.png
Aidesmall.png
À propos de cette image

Idem qu'une led


Le principe est identique au clignotement d'une led à ceci près qu'il convient d'utiliser la fonction delayMicroseconds() :

const unsigned int TSol = ... ; // constantes
....                            // et variables

void setup()
{
  ....
}

void loop()
{
  PORTC ^= ....;
  delayMicroseconds(TSol/2);
}

2x plus de son !

Il suffit ensuite d'avoir les 2 sortie (PC5 et PC4) opposées pour doubler le volume sonore : Un "ou exclusif" avec les bonnes valeurs initiales et un masque adapté suffisent

Question.jpg Modifier le programme en conséquence

Ajoutons des notes

Pour jouer toute la gamme, il suffit de déclarer un tableau de valeurs avec les périodes des différentes notes.

On souhaite avoir une fonction qui permet de jouer une certaine note (un nombre entre 0 et 11 en relation avec le tableau ci dessus) et qui répète une période un certain nombre de fois (duree). Le prototype de la fonction est donné ci dessous :

void buzz(unsigned char note, unsigned int duree);


Remarque : Il conviendra de vérifier que le numéro de note est valide.

Question.jpg Écrire la fonction répondant au cahier des charges

Todo.jpg Vous vérifierez avec un programme simple le bon fonctionnement de cette fonction

Decodage d'un clavier

Pour mémoire : exercice TD

Énoncé

Sur un PC, le clavier est complètement décodé. C'est à dire que lorsqu'une touche est appuyée, sa position sur le clavier est envoyée sur la liaison PS2. Le fait d'envoyer la position et non le code ASCII permet de gérer les claviers en divers langues.

Clavier 12 touches

Pour de petites applications, on utilise un clavier à 12 touches. Il est composé de simples contacts et le décodage est réalisé par le système informatique. Avec seulement 8 touches, un PORT de 8 bits en entrée suffit. Si le clavier possède plus de 8 touches, il faut:

  • soit utiliser d'avantage d'entrées,
  • soit multiplexer les entrées en deux étapes.

En utilisant 4 fils pour les lignes et 4 fils pour les colonnes, on peut différencier par croisement 16 touches. On utilise donc 8 fils reliés à 8 bits d'un PORT pour 16 touches. Pour nos 12 touches on peut câbler comme indiqué ci-dessus. Il s'agit ensuite de procéder en deux phases, une pour la détection de la colonne et une autre pour la détection de ligne.

Question 1 : détermination du numéro de colonne

#define NOTAKEY 127
// colonne 1 à gauche
char lecture_colonne(){
  char ch;
  DDRB=0xF0; // 1111 0000
  PORTB = 0x00; // B4, B5,B6 et B7  mis à 0 !!! surtout pas 0x0F =>pullup !!!
  ch = PINB & 0x0E; // on ne garde que les bits intéressants B1, B2 et B3
  switch (ch) {
  case 14 : return 0;//aucune touche
  case 6 : return 1;//a gauche
  case 10 : return 2;// au milieu
  case 12 : return 3;//a droite
// si autre cas, deux touches ou autre
  default : return NOTAKEY;
  }
}

Commenter en testant les bonnes valeurs du case.

Question 2 : détermination du numéro de ligne

Programmer les directions avec DDRB (PB7-PB4 en entrée et PB3-PB1 en sortie).

Quel est le code correspondant : sous-programme char lecture_ligne()

Question 3 : détermination du caractère

A partir des deux informations précédentes transformer le numéro de colonne et le numéro de ligne en caractère correspondant sur le clavier : '1' ou '2' ou ... ou '0' ou '#'

Travail à faire en TP

Câblage

Le tableau suivant résume la disposition physique du clavier avec la position physique sur le connecteur des lignes (L1 à L4) et colonnes (C1 à C3) en vue de dessus :

B0 B1 B2 B3 D4 D5 D6
L1 L2 L3 L4 C1 C2 C3

ArduinoClavier.png

L/C C1 C2 C3
L1 1 2 3
L2 4 5 6
L3 7 8 9
L4 * 0 #

Todo.jpg Câbler sur une plaque à essais le clavier 12 touches que l'on vous donne. Les colonnes seront reliées sur le port D et les lignes sur le port B (cf indications ci dessus)

Remarque : Par rapport au schéma de principe du TD, on ne câblera aucune résistance.

Indice de ligne

Question.jpg Modifier le sous-programme de la question 1 pour l'adapter à votre montage réalisé (sur votre plaque à essais). L'adaptation doit se faire en tenant compte du fait qu'il n'y a pas de résistance de tirage externe : c'est votre ATMega328 qui doit les réaliser en interne ! Les tests de cette fonction seront réalisés en utilisant la liaison série.

char lecture_ligne()
{
  char ch;
  DDRD ?= .... ;    // commençons par lister les sorties sur le port D
  DDRB ?= .... ;    // puis les entrées sur le port B
  PORTD?=..... ;    // on place les sortie à l'état 0
  PORTB?= .... ;    // on active les résistances de pull-up sur les entrées

  delay(10);        // un délais est nécessaire pour l'activation des pull-ups

  ch = PINB & 0x??; // on récupère ensuite l'état des entrées
    .........;           // remettre toutes les pattes en entrées.
  switch (ch)
  {
     case  : return 0; // aucune touche
     case  : return 1; // L1
     case  : return 2; // L2
     case  : return 3; // L3
     case  : return 4; // L4
     // si autre cas, deux touches ou autre
   default : return -1;
  }
}

Indice de colonne

Question.jpg Réaliser le sous-programme de la question 2 pour l'adapter à votre montage réalisé (sur votre plaque à essais). L'adaptation doit se faire en tenant compte du fait qu'il n'y a pas de résistance de tirage externe : c'est votre ATMega328 qui doit les réaliser en interne ! Les tests de cette fonction seront aussi réalisés en utilisant la liaison série.

Touche appuyée

Nous souhaitons maintenant écrire une fonction qui renverra une valeur tel que décrit ci dessous :

char touches[LIGNES][COLONNES] = { // tableau de char à 2 dimensions
  {1,,},
  {...},
  {...},
  {,,11}
};

char getTouche();
La valeur retournée sera :
  • -1 si pas de touches (ou plusieurs) appuyées
  • la valeur correspondant à la touche pour les chiffres
  • 11 pour le #
  • 10 pour l' *

Question.jpg Écrire cette fonction en vous servant bien évidemment des 2 fonctions précédentes et pourquoi pas du tableau "touches" complété.

Assemblons le tout

Nous allons utiliser les 3 fonctions buzzer(),toucheClavier() et setEtatLed() pour réaliser un programme de digicode.

Cahier des charges

Commençons pour définir les contraintes :

  • On commencera systématiquement par appuyer sur la touche "*" pour réinitialiser le digicode => les leds s'éteignent
  • L'utilisateur doit alors saisir le code sur 4 chiffres
  • Si le code est bon la led verte s'allume, sinon la led rouge clignote pendant 10s
  • Chaque appui sur une touche génère le son associé à la touche tel qu'indiqué dans le tableau de la partie Buzzer

Codez !!

Commencez par concevoir un algorigramme sur une feuille répondant au cahier des charges. Quelques étapes clés pour vous aider :

  • Attendre l'appui sur une touche
  • Si c'est un nombre, mettre la valeur dans un tableau et incrémenter l'indice (La prochaine touche sera le chiffre suivant du code)
  • Si c'est une "*" recommencer la saisie
  • Utiliser un tableau pour mémoriser le code, ex :
     const unsigned char code[4]={1,2,3,4};
    

Améliorations

Il serait intéressant de proposer une procédure de changement du code.