Cours:XR207 tp digicode : Différence entre versions
(→Informations lumineuses) |
|||
| (39 révisions intermédiaires par le même utilisateur non affichées) | |||
| Ligne 1 : | Ligne 1 : | ||
| − | [[Cours:TPs_2103|{{ | + | <big>{{Rouge|******************************************}}</big> |
| + | <big>{{Rouge|*** Apporter la malette d'informatique ***}}</big> | ||
| + | <big>{{Rouge|******************************************}}</big> | ||
| + | |||
| + | [[Cours:CoursM2103|{{Rouge|<big>'''Fiche résumé'''</big>}}]] | ||
| + | |||
| + | [[Cours:TPs_2103|{{Bleu|<big>'''Retour à la liste des Tps'''</big>}}]] | ||
[[Cours:TPS_2103_tp3_corrige|{{Vert|<big>'''Éléments de correction'''</big>}}]] | [[Cours:TPS_2103_tp3_corrige|{{Vert|<big>'''Éléments de correction'''</big>}}]] | ||
| − | [[Fichier: | + | [[Fichier:Arduino-nano-pinout.png|600px|droite]] |
Vous allez développer un système de digicode architecturé autour d'un atmega328p (le µcontrôleur présent sur les cartes arduino). | Vous allez développer un système de digicode architecturé autour d'un atmega328p (le µcontrôleur présent sur les cartes arduino). | ||
| Ligne 9 : | Ligne 15 : | ||
<big>'''Pour ce TP, nous utilisons une carte arduino {{Rouge|sans le shieldinfo}}'''</big> | <big>'''Pour ce TP, nous utilisons une carte arduino {{Rouge|sans le shieldinfo}}'''</big> | ||
| − | = | + | |
| + | =objectifs= | ||
| + | *numération binaire (affichage avec des leds de la valeur d'un entier signé ou non ) | ||
| + | *e/s + pullup | ||
| + | *utilisation de fonctions | ||
| + | *déclaration de fonctions | ||
| + | *algorithme simple et implémentation | ||
| + | |||
| + | =Matériel= | ||
Nous utiliserons : | Nous utiliserons : | ||
| − | *1 carte arduino | + | *1 carte arduino NANO |
*1 plaque à essais | *1 plaque à essais | ||
| − | * | + | *8 leds pour afficher une valeur |
| − | * | + | *1 résistance de 330Ω par led |
| − | |||
*1 clavier matriciel | *1 clavier matriciel | ||
| − | * | + | *fils M-M |
| − | + | *fils M-F | |
| − | * | ||
=Informations lumineuses= | =Informations lumineuses= | ||
| − | + | ==Câblage== | |
| − | + | {{Todo|Câbler sur une plaque à essais les 8 leds :}} | |
| + | *utiliser des résistances de 330Ω pour régler l'intensité lumineuse | ||
| + | *PD0 à PD7 | ||
| + | *mettre les leds dans "l'ordre" des broches | ||
| − | + | ==Utilisation des 8 leds== | |
| − | {{ | + | Nous utiliserons dans nos programmes [[Cours:CoursM2103#Fixed_width_integer_types|les types de variable dont la taille est explicitement donnée]] |
| + | |||
| + | Le {{Rouge|débogage}} d'un programme est fondamental, il existe différentes façons de le faire. Ici nous nous contenterons {{Rouge|d'utiliser des leds}} pour afficher des informations sur l'exécution du programme. | ||
| + | |||
| + | Principe : | ||
<source lang=c> | <source lang=c> | ||
#include <avr/io.h> | #include <avr/io.h> | ||
#include <util/delay.h> | #include <util/delay.h> | ||
| + | |||
| + | void clignote() | ||
| + | { | ||
| + | PORTD=0; | ||
| + | for (uint8_t i=0;i<5;i++) | ||
| + | { | ||
| + | PORTD ^= 0xFF; | ||
| + | _delay_ms(50); | ||
| + | } | ||
| + | } | ||
int main() | int main() | ||
{ | { | ||
// config des sorties | // config des sorties | ||
| + | DDRD = 0xFF; // les 8 broches des leds en sortie | ||
| + | |||
| + | // qques variables | ||
| + | uint8_t val1 = 0; | ||
| + | int8_t val2 = -1; | ||
| + | uint8_t val3 = 255; | ||
| + | uint16_t val4 = 256; | ||
while(1) | while(1) | ||
{ | { | ||
| − | + | PORTD = val1; | |
| − | + | _delay_ms(2000); | |
| − | + | clignote(); | |
| − | + | PORTD = val2; | |
| − | + | _delay_ms(2000); | |
| − | + | clignote(); | |
| − | + | PORTD = val3; | |
| − | + | _delay_ms(2000); | |
| + | clignote(); | ||
| + | PORTD = val4; | ||
| + | _delay_ms(2000); | ||
| + | for (int i=0;i<10;i++) clignote(); | ||
} | } | ||
} | } | ||
</source> | </source> | ||
| − | {{ | + | {{Question|Indiquer l'affichage réalisé par chacune des lignes}} PORTD=valx |
| − | + | Les nombres négatifs sont représentés pas la méthodes des compléments à deux : https://fr.wikipedia.org/wiki/Compl%C3%A9ment_%C3%A0_deux ] | |
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
=Decodage d'un clavier= | =Decodage d'un clavier= | ||
| − | == | + | ==Câblage== |
| − | Le tableau suivant résume la disposition physique du clavier avec la position physique sur le connecteur des lignes ( | + | Le tableau suivant résume la disposition physique du clavier avec la position physique sur le connecteur des lignes (L0 à L3) et colonnes (C0 à C2) en vue de dessus : |
{|align="center" border="1" cellpadding="20" cellspacing="0" | {|align="center" border="1" cellpadding="20" cellspacing="0" | ||
|- | |- | ||
| Ligne 87 : | Ligne 111 : | ||
{|align="center" border="1" cellpadding="3" cellspacing="0" | {|align="center" border="1" cellpadding="3" cellspacing="0" | ||
|- | |- | ||
| − | | | + | | PC2 || PC3 || PC4 || PC5 || PB0 || PB1 || PB2 |
|- | |- | ||
| − | | L1 || L2 || L3 || | + | | L0 || L1 || L2 || L3 || C0 || C1 || C2 |
|} | |} | ||
|- | |- | ||
| Ligne 98 : | Ligne 122 : | ||
{| class="wikitable" | {| class="wikitable" | ||
|- | |- | ||
| − | ! L/C !! C1 !! C2 | + | ! L/C !! C0 !! C1 !! C2 |
|- | |- | ||
| − | ! | + | ! L0 || 1 || 2 || 3 |
|- | |- | ||
| − | ! | + | ! L1 || 4 || 5 || 6 |
|- | |- | ||
| − | ! | + | ! L2 || 7 || 8 || 9 |
|- | |- | ||
| − | ! | + | ! L3 || * || 0 || # |
|} | |} | ||
|| | || | ||
| − | [[Fichier: | + | [[Fichier:ClavierMatricielPrincipe.png|200px]] |
|} | |} | ||
| − | {{Todo|Câbler sur une plaque à essais le clavier 12 touches que l'on vous donne. Les {{Rouge|colonnes}} seront reliées sur le port {{Rouge| | + | {{Todo|Câbler sur une plaque à essais le clavier 12 touches que l'on vous donne. Les {{Rouge|colonnes}} seront reliées sur le port {{Rouge|B}} et les {{Vert|lignes}} sur le port {{Vert|C}} (cf indications ci dessus)}} |
'''Remarque :''' On ne câblera aucune résistance de tirage, on utilisera les résistances internes au µcontrôleur. | '''Remarque :''' On ne câblera aucune résistance de tirage, on utilisera les résistances internes au µcontrôleur. | ||
| Ligne 145 : | Ligne 169 : | ||
*l'état des lignes dépend de l'appui sur un bouton : | *l'état des lignes dépend de l'appui sur un bouton : | ||
**si {{Rouge|aucun bouton}} appuyé, les résistances de tirage donnent {{Rouge|un état 1}} sur les lignes | **si {{Rouge|aucun bouton}} appuyé, les résistances de tirage donnent {{Rouge|un état 1}} sur les lignes | ||
| − | **si on appui sur un bouton de {{Rouge|la | + | **si on appui sur un bouton de {{Rouge|la ligne0}} (key 1/2/3), alors l'entrée ligne PC2 passe à {{Rouge|l'état 0}}. |
**la valeur change suivant la ligne sur laquelle un bouton est appuyé | **la valeur change suivant la ligne sur laquelle un bouton est appuyé | ||
| − | *il suffit donc d'observer les 4 bits | + | *il suffit donc d'observer les 4 bits PC5..PC2 (que l'on note ici etat), et ainsi : |
| − | **si | + | **si PC5..PC2 = 1111 , pas de touche |
| − | **si | + | **si PC5..PC2 = 1110 , au moins une touche parmi 1/2/3 |
| − | **si | + | **si PC5..PC2 = 1101 , au moins une touche parmi 4/5/6 |
**... | **... | ||
| + | ==Indice de ligne== | ||
| − | + | {{Question|Compléter et vérifier le programme lecture_ligne() qui renvoie le numéro de ligne sur laquelle un bouton est appuyé}} | |
| − | |||
| − | {{Question| | ||
*La validation se fera en utilisant des leds connectées sur le port C : | *La validation se fera en utilisant des leds connectées sur le port C : | ||
| − | **On | + | **On utilisera les 8 leds du PORTD pour afficher le résultat |
| − | ** | + | **par ex : PORTD = lecture_ligne(); |
| − | <source lang= | + | <source lang=cpp> |
int8_t lecture_ligne() | int8_t lecture_ligne() | ||
{ | { | ||
| − | int8_t | + | int8_t etatEntrees; |
| − | + | DDRB |= ( (1<<PB2) | ( (1<<PB1) | ( (1<<PB0) ) ; // commençons par lister les sorties sur le port B | |
| − | + | DDRC &=~ ( (1<<PC5) | (1<<PC4) |(1<<PC3) |(1<<PC2) ) ; // puis les entrées sur le port C | |
| − | + | PORTB &=~ ( (1<<PB2) | ( (1<<PB1) | ( (1<<PB0) ) ; // on place les sortie à l'état 0 | |
| − | + | PORTC |= ( (1<<PC5) | (1<<PC4) |(1<<PC3) |(1<<PC2) ) ; // on active les résistances de pull-up sur les entrées | |
| − | _delay_ms(1); // un | + | _delay_ms(1); // un délai est nécessaire pour l'activation des pull-ups |
| − | + | etatEntrees = PINC & 0b00111100; // on récupère ensuite l'état des entrées en cachant les bits non utiles | |
| − | switch ( | + | switch (etatEntrees) |
{ | { | ||
| − | case | + | // PPPPPPPP |
| − | case | + | // CCCCCCCC |
| + | // ..5432.. | ||
| + | case 0b00111000 : return 0; // L0 (appui sur l'une des touches 1/2/3 => {{Rouge|entrée PC2 à 0}} ) | ||
| + | case 0b00110100 : return 1; // L1 => {{Rouge|entrée PC3 à 0}} | ||
case : return 2; // L2 | case : return 2; // L2 | ||
case : return 3; // L3 | case : return 3; // L3 | ||
| − | + | // si autre cas, pas de touches deux touches ou autre | |
| − | // si autre cas, deux touches ou autre | ||
default : return -1; | default : return -1; | ||
} | } | ||
| Ligne 192 : | Ligne 217 : | ||
| − | == | + | ==Touche appuyée== |
Nous souhaitons maintenant écrire une fonction qui renverra une valeur tel que décrit ci dessous : | Nous souhaitons maintenant écrire une fonction qui renverra une valeur tel que décrit ci dessous : | ||
| Ligne 198 : | Ligne 223 : | ||
|- | |- | ||
| <source lang=c> | | <source lang=c> | ||
| − | int8_t touches[4][3] = { // tableau de | + | const int8_t touches[4][3] = { // tableau de int8_t à 2 dimensions |
| − | + | { 1, 2, 3}, | |
| − | + | { 4, 5, 6}, | |
| − | + | { 7, 8, 9}, | |
| − | + | {10, 0,11} | |
| − | }; | + | }; |
int8_t getTouche(); | int8_t getTouche(); | ||
| Ligne 214 : | Ligne 239 : | ||
|} | |} | ||
| − | {{Question|Écrire cette fonction en vous servant bien évidemment des 2 fonctions précédentes et pourquoi pas du tableau "touches" | + | {{Question|Écrire cette fonction en vous servant bien évidemment des 2 fonctions précédentes et pourquoi pas du tableau "touches" :}} |
| + | |||
| + | *c'est un tableau de 4 lignes et 3 colonnes | ||
| + | *la valeur dans la case [0,0] correspond à la valeur de la touche pour ligne=0 et colonne=0 => 1 | ||
| + | *la valeur dans la case [1,2] correspond à la valeur de la touche pour ligne=1 et colonne=2 => 6 | ||
<source lang=c> | <source lang=c> | ||
| Ligne 223 : | Ligne 252 : | ||
</source> | </source> | ||
| − | = | + | =réalisation d'un digicode= |
Nous allons utiliser la fonction {{Rouge|getTouche()}} pour réaliser un programme de digicode. | Nous allons utiliser la fonction {{Rouge|getTouche()}} pour réaliser un programme de digicode. | ||
| − | == | + | ==contraintes== |
| − | |||
Commençons pour définir les contraintes : | Commençons pour définir les contraintes : | ||
| − | *On appuie sur la touche '*' pour démarrer la saisie du code => la led rouge s'allume | + | *On appuie sur la touche '*' pour démarrer la saisie du code => la led rouge s'allume brièvement |
*L'utilisateur doit alors saisir le code sur 4 chiffres | *L'utilisateur doit alors saisir le code sur 4 chiffres | ||
*On valide le code par la touche '#' | *On valide le code par la touche '#' | ||
| − | *Si le code est bon | + | *Si le code est bon une led verte s'allume pendant 10s, sinon une led rouge clignote pendant 10s |
| − | |||
| − | + | ==codez !== | |
| − | + | {{Question|Ecrire un programme répondant au cahier des charges}} | |
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| + | *vous pouvez vous servir d'un LLM | ||
| + | **https://claude.ai/new | ||
| + | **[https://gemini.google.com/app?utm_source=deepmind.google&utm_medium=referral&utm_campaign=gdm&utm_content= gemini] | ||
| + | *il suffit de mémoriser les 6 dernières touches appuyées | ||
| + | **déclarer un tableau | ||
| + | **faire un décalage du tableau | ||
| + | **rentrer la nouvelle valeur | ||
| + | **comparer le tableau par rapport au code | ||
| − | + | ==Améliorations== | |
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| + | {{Question|Ajouter une procédure de changement du code.}} | ||
| − | |||
| − | {{Question| | + | {{Question|Faire en sorte que le temps maximum de saisie du code soit de 4s}} |
Version actuelle datée du 4 février 2026 à 14:53
****************************************** *** Apporter la malette d'informatique *** ******************************************
Vous allez développer un système de digicode architecturé autour d'un atmega328p (le µcontrôleur présent sur les cartes arduino).
Pour ce TP, nous utilisons une carte arduino sans le shieldinfo
Sommaire
objectifs
- numération binaire (affichage avec des leds de la valeur d'un entier signé ou non )
- e/s + pullup
- utilisation de fonctions
- déclaration de fonctions
- algorithme simple et implémentation
Matériel
Nous utiliserons :
- 1 carte arduino NANO
- 1 plaque à essais
- 8 leds pour afficher une valeur
- 1 résistance de 330Ω par led
- 1 clavier matriciel
- fils M-M
- fils M-F
Informations lumineuses
Câblage
Câbler sur une plaque à essais les 8 leds :
- utiliser des résistances de 330Ω pour régler l'intensité lumineuse
- PD0 à PD7
- mettre les leds dans "l'ordre" des broches
Utilisation des 8 leds
Nous utiliserons dans nos programmes les types de variable dont la taille est explicitement donnée
Le débogage d'un programme est fondamental, il existe différentes façons de le faire. Ici nous nous contenterons d'utiliser des leds pour afficher des informations sur l'exécution du programme.
Principe :
#include <avr/io.h>
#include <util/delay.h>
void clignote()
{
PORTD=0;
for (uint8_t i=0;i<5;i++)
{
PORTD ^= 0xFF;
_delay_ms(50);
}
}
int main()
{
// config des sorties
DDRD = 0xFF; // les 8 broches des leds en sortie
// qques variables
uint8_t val1 = 0;
int8_t val2 = -1;
uint8_t val3 = 255;
uint16_t val4 = 256;
while(1)
{
PORTD = val1;
_delay_ms(2000);
clignote();
PORTD = val2;
_delay_ms(2000);
clignote();
PORTD = val3;
_delay_ms(2000);
clignote();
PORTD = val4;
_delay_ms(2000);
for (int i=0;i<10;i++) clignote();
}
}
Indiquer l'affichage réalisé par chacune des lignes PORTD=valx
Les nombres négatifs sont représentés pas la méthodes des compléments à deux : https://fr.wikipedia.org/wiki/Compl%C3%A9ment_%C3%A0_deux ]
Decodage d'un clavier
Câblage
Le tableau suivant résume la disposition physique du clavier avec la position physique sur le connecteur des lignes (L0 à L3) et colonnes (C0 à C2) en vue de dessus :
|
|
Câbler sur une plaque à essais le clavier 12 touches que l'on vous donne. Les colonnes seront reliées sur le port B et les lignes sur le port C (cf indications ci dessus)
Remarque : On ne câblera aucune résistance de tirage, on utilisera les résistances internes au µcontrôleur.
|
|
Principe de décodage
En utilisant un clavier matriciel, chaque touche n'est pas associé à une broche du µcontrôleur. Dans le cas présent, on passe de :
- 12 entrées nécessaires si chaque touche était connectée directement
- 7 broches nécessaires avec le clavier matriciel
L'intérêt évident est donc une réduction du nombre de broches nécessaires à l'utilisation du clavier.
L'inconvénient qui en résulte est la complexité relative du code pour trouver quelle touche est appuyée.
Le principe de décodage est symétrique entre lignes et colonnes. Détaillons donc le fonctionnement pour trouver sur quelle ligne une touche est appuyée :
- On configure les broches colonnes en sortie.
- On configure ces sorties à l'état 0
- Les broches lignes sont en entrée
- l'état des lignes dépend de l'appui sur un bouton :
- si aucun bouton appuyé, les résistances de tirage donnent un état 1 sur les lignes
- si on appui sur un bouton de la ligne0 (key 1/2/3), alors l'entrée ligne PC2 passe à l'état 0.
- la valeur change suivant la ligne sur laquelle un bouton est appuyé
- il suffit donc d'observer les 4 bits PC5..PC2 (que l'on note ici etat), et ainsi :
- si PC5..PC2 = 1111 , pas de touche
- si PC5..PC2 = 1110 , au moins une touche parmi 1/2/3
- si PC5..PC2 = 1101 , au moins une touche parmi 4/5/6
- ...
Indice de ligne
Compléter et vérifier le programme lecture_ligne() qui renvoie le numéro de ligne sur laquelle un bouton est appuyé
- La validation se fera en utilisant des leds connectées sur le port C :
- On utilisera les 8 leds du PORTD pour afficher le résultat
- par ex : PORTD = lecture_ligne();
int8_t lecture_ligne()
{
int8_t etatEntrees;
DDRB |= ( (1<<PB2) | ( (1<<PB1) | ( (1<<PB0) ) ; // commençons par lister les sorties sur le port B
DDRC &=~ ( (1<<PC5) | (1<<PC4) |(1<<PC3) |(1<<PC2) ) ; // puis les entrées sur le port C
PORTB &=~ ( (1<<PB2) | ( (1<<PB1) | ( (1<<PB0) ) ; // on place les sortie à l'état 0
PORTC |= ( (1<<PC5) | (1<<PC4) |(1<<PC3) |(1<<PC2) ) ; // on active les résistances de pull-up sur les entrées
_delay_ms(1); // un délai est nécessaire pour l'activation des pull-ups
etatEntrees = PINC & 0b00111100; // on récupère ensuite l'état des entrées en cachant les bits non utiles
switch (etatEntrees)
{
// PPPPPPPP
// CCCCCCCC
// ..5432..
case 0b00111000 : return 0; // L0 (appui sur l'une des touches 1/2/3 => {{Rouge|entrée PC2 à 0}} )
case 0b00110100 : return 1; // L1 => {{Rouge|entrée PC3 à 0}}
case : return 2; // L2
case : return 3; // L3
// si autre cas, pas de touches deux touches ou autre
default : return -1;
}
}
Indice de colonne
De la même façon, écrire et tester la fonction lecture_colonne() qui permettra d'obtenir le numéro de colonne sur laquelle un bouton est appuyé.
Touche appuyée
Nous souhaitons maintenant écrire une fonction qui renverra une valeur tel que décrit ci dessous :
const int8_t touches[4][3] = { // tableau de int8_t à 2 dimensions
{ 1, 2, 3},
{ 4, 5, 6},
{ 7, 8, 9},
{10, 0,11}
};
int8_t getTouche();
|
La valeur retournée sera :
|
Écrire cette fonction en vous servant bien évidemment des 2 fonctions précédentes et pourquoi pas du tableau "touches" :
- c'est un tableau de 4 lignes et 3 colonnes
- la valeur dans la case [0,0] correspond à la valeur de la touche pour ligne=0 et colonne=0 => 1
- la valeur dans la case [1,2] correspond à la valeur de la touche pour ligne=1 et colonne=2 => 6
int8_t getTouche()
{
....
}
réalisation d'un digicode
Nous allons utiliser la fonction getTouche() pour réaliser un programme de digicode.
contraintes
Commençons pour définir les contraintes :
- On appuie sur la touche '*' pour démarrer la saisie du code => la led rouge s'allume brièvement
- L'utilisateur doit alors saisir le code sur 4 chiffres
- On valide le code par la touche '#'
- Si le code est bon une led verte s'allume pendant 10s, sinon une led rouge clignote pendant 10s
codez !
Ecrire un programme répondant au cahier des charges
- vous pouvez vous servir d'un LLM
- il suffit de mémoriser les 6 dernières touches appuyées
- déclarer un tableau
- faire un décalage du tableau
- rentrer la nouvelle valeur
- comparer le tableau par rapport au code
Améliorations
Ajouter une procédure de changement du code.
Faire en sorte que le temps maximum de saisie du code soit de 4s


