Cours:ClefUSB

De troyesGEII
Aller à : navigation, rechercher
Retour à la liste des Tps
Éléments de correction (page protégée)

Le but de ce projet est de réaliser ce que les anglo-saxons nomment USB EasyLogger et que nous traduisons par clé de connexion USB. L'idée est de pouvoir stocker un certain nombre d'identifiants et de mots de passe et de pouvoir les utiliser. En soi le problème est relativement simple, sauf si l'on désire gérer correctement le changement des mots de passe dans la clé.

Présentation du matériel utilisé

Le matériel utilisé sera une platine Leonardo. Ce projet ne peut pas être réalisé avec une UNO.

Nous disposons d'une clé compatible Leonardo qui pourra être utilisée pour les tests finaux.

Platine Leonardo

La platine Leonardo est architecturée autour d'un processeur ATMega32U4, le U signifiant USB. Cette version de processeur permet de gérer deux protocoles USB clients en même temps, nous voulons dire par la même prise USB. Nous verrons dans le projet de cette section (et dans l'exemple keyboardSerial de la rubrique USB) qu'il est possible d'utiliser ensemble la liaison série et un clavier USB par le même fil USB.


Nous allons examiner les performances de la Leonardo par rapport à cette liaison USB. Pour ce faire, nous allons simuler une clé USB destinée à entrer un identifiant et un mot de passe automatiquement.

Clé USB finale

Voici le schéma de principe retenu :

Clé de connexion USB (Jean-Michel Gérard)

Ce schéma réalisé avec Eagle est de qualité suffisante pour pouvoir être téléchargé et consulté à l'aide de zooms importants.

Les trois boutons (nommés plus loin) sont clairement visibles en haut du schéma où l'on découvre clairement qu'ils sont montés à l'aide d'une pull-up externe (pas forcément utile avec la famille AVR).

Trois LEDs sont aussi visibles en bas à droite du schéma.

Note aux enseignants (et étudiants avec leur propre PC)

Le clavier émulé par défaut par la carte Leonardo est un clavier QWERTY ce qui ne manquera pas de poser des problèmes. Nous donnons ici le moyen de gérer partiellement ce problème.

Tableau de transcodage QWERTY

Chercher le fichier HID.cpp de votre distribution Arduino. Chez nous, sous Linux, il est dans "/usr/share/arduino/hardware/arduino/cores/arduino". Chez vous, sous Windows, il est probablement dans quelque chose comme "Program File\arduino\hardware\arduino\cores\arduino".

Dans le fichier HID.cpp vous trouverez un tableau de transcodage :

#define SHIFT 0x80
const uint8_t _asciimap[128] =
{
	0x00,             // NUL
	0x00,             // SOH
	0x00,             // STX
	0x00,             // ETX
	0x00,             // EOT
	0x00,             // ENQ
	0x00,             // ACK  
	0x00,             // BEL
	0x2a,			// BS	Backspace
	0x2b,			// TAB	Tab
	0x28,			// LF	Enter
	0x00,             // VT 
	0x00,             // FF 
	0x00,             // CR 
	0x00,             // SO 
	0x00,             // SI 
	0x00,             // DEL
	0x00,             // DC1
	0x00,             // DC2
	0x00,             // DC3
	0x00,             // DC4
	0x00,             // NAK
	0x00,             // SYN
	0x00,             // ETB
	0x00,             // CAN
	0x00,             // EM 
	0x00,             // SUB
	0x00,             // ESC
	0x00,             // FS 
	0x00,             // GS 
	0x00,             // RS 
	0x00,             // US 

	0x2c,		   //  ' '
	0x1e|SHIFT,	   // !
	0x34|SHIFT,	   // "
	0x20|SHIFT,    // #
	0x21|SHIFT,    // $
	0x22|SHIFT,    // %
	0x24|SHIFT,    // &
	0x34,          // '
	0x26|SHIFT,    // (
	0x27|SHIFT,    // )
	0x25|SHIFT,    // *
	0x2e|SHIFT,    // +
	0x36,          // ,
	0x2d,          // -
	0x37,          // .
	0x38,          // /
	0x27,          // 0
	0x1e,          // 1
	0x1f,          // 2
	0x20,          // 3
	0x21,          // 4
	0x22,          // 5
	0x23,          // 6
	0x24,          // 7
	0x25,          // 8
	0x26,          // 9
	0x33|SHIFT,      // :
	0x33,          // ;
	0x36|SHIFT,      // <
	0x2e,          // =
	0x37|SHIFT,      // >
	0x38|SHIFT,      // ?
	0x1f|SHIFT,      // @
	0x04|SHIFT,      // A
	0x05|SHIFT,      // B
	0x06|SHIFT,      // C
	0x07|SHIFT,      // D
	0x08|SHIFT,      // E
	0x09|SHIFT,      // F
	0x0a|SHIFT,      // G
	0x0b|SHIFT,      // H
	0x0c|SHIFT,      // I
	0x0d|SHIFT,      // J
	0x0e|SHIFT,      // K
	0x0f|SHIFT,      // L
	0x10|SHIFT,      // M
	0x11|SHIFT,      // N
	0x12|SHIFT,      // O
	0x13|SHIFT,      // P
	0x14|SHIFT,      // Q
	0x15|SHIFT,      // R
	0x16|SHIFT,      // S
	0x17|SHIFT,      // T
	0x18|SHIFT,      // U
	0x19|SHIFT,      // V
	0x1a|SHIFT,      // W
	0x1b|SHIFT,      // X
	0x1c|SHIFT,      // Y
	0x1d|SHIFT,      // Z
	0x2f,          // [
	0x31,          // bslash
	0x30,          // ]
	0x23|SHIFT,    // ^
	0x2d|SHIFT,    // _
	0x35,          // `
	0x04,          // a
	0x05,          // b
	0x06,          // c
	0x07,          // d
	0x08,          // e
	0x09,          // f
	0x0a,          // g
	0x0b,          // h
	0x0c,          // i
	0x0d,          // j
	0x0e,          // k
	0x0f,          // l
	0x10,          // m
	0x11,          // n
	0x12,          // o
	0x13,          // p
	0x14,          // q
	0x15,          // r
	0x16,          // s
	0x17,          // t
	0x18,          // u
	0x19,          // v
	0x1a,          // w
	0x1b,          // x
	0x1c,          // y
	0x1d,          // z
	0x2f|SHIFT,    // 
	0x31|SHIFT,    // |
	0x30|SHIFT,    // }
	0x35|SHIFT,    // ~
	0				// DEL
};

Nous le donnons ici car c'est la version originale du fichier HID.cpp et il vous faut la mettre de côté.

Changer QWERTY en AZERTY

C'est le tableau de transcodage de la section précédente qu'il faut changer. En voici donc la nouvelle version.

#define SHIFT 0x80
const uint8_t _asciimap[128] =
{
	0x00,             // NUL
	0x00,             // SOH
	0x00,             // STX
	0x00,             // ETX
	0x00,             // EOT
	0x00,             // ENQ
	0x00,             // ACK  
	0x00,             // BEL
	0x2a,			// BS	Backspace
	0x2b,			// TAB	Tab
	0x28,			// LF	Enter
	0x00,             // VT 
	0x00,             // FF 
	0x00,             // CR 
	0x00,             // SO 
	0x00,             // SI 
	0x00,             // DEL
	0x00,             // DC1
	0x00,             // DC2
	0x00,             // DC3
	0x00,             // DC4
	0x00,             // NAK
	0x00,             // SYN
	0x00,             // ETB
	0x00,             // CAN
	0x00,             // EM 
	0x00,             // SUB
	0x00,             // ESC
	0x00,             // FS 
	0x00,             // GS 
	0x00,             // RS 
	0x00,             // US 

	0x2c,		   //  ' '
	0x38,	   // ! 
	0x20,    // "
	0x20,    // # :TODO
	0x30,    // $
	0x34|SHIFT,    // %
	0x1E,    // & 
	0x21,          // '
	0x22,    // (
	0x2d,    // )
        0x31,    // * : done
	0x2e|SHIFT,    // +
	0x10,          // , 
	0x23,          // -
	0x36|SHIFT,    // .
	0x37|SHIFT,    // /
	0x27|SHIFT,    // 0
	0x1e|SHIFT,    // 1
	0x1f|SHIFT,    // 2
	0x20|SHIFT,    // 3
	0x21|SHIFT,    // 4
	0x22|SHIFT,    // 5
	0x23|SHIFT,    // 6
	0x24|SHIFT,    // 7
	0x25|SHIFT,    // 8
	0x26|SHIFT,    // 9
	0x37,          // :
	0x36,          // ;
	0x64,      // < Done
	0x2e,          // =
	0x64|SHIFT,      // > Done
	0x10|SHIFT,      // ? 0x38 -> 0x10 OK
	0x1f,      // @ TODO
	0x14|SHIFT,      // A
	0x05|SHIFT,      // B
	0x06|SHIFT,      // C
	0x07|SHIFT,      // D
	0x08|SHIFT,      // E
	0x09|SHIFT,      // F
	0x0a|SHIFT,      // G
	0x0b|SHIFT,      // H
	0x0c|SHIFT,      // I
	0x0d|SHIFT,      // J
	0x0e|SHIFT,      // K
	0x0f|SHIFT,      // L
	0x33|SHIFT,      // M
	0x11|SHIFT,      // N
	0x12|SHIFT,      // O
	0x13|SHIFT,      // P
	0x04|SHIFT,      // Q
	0x15|SHIFT,      // R
	0x16|SHIFT,      // S
	0x17|SHIFT,      // T
	0x18|SHIFT,      // U
	0x19|SHIFT,      // V
	0x1d|SHIFT,      // W
	0x1b|SHIFT,      // X
	0x1c|SHIFT,      // Y
	0x1a|SHIFT,      // Z
	0x0c,          // [ TODO 2F
	0x31,          // bslash
	0x0d,          // ] TODO 30
	0x2F,    // ^
	0x25,    // _
	0x35,          // ` TODO
	0x14,          // a
	0x05,          // b
	0x06,          // c
	0x07,          // d
	0x08,          // e
	0x09,          // f
	0x0a,          // g
	0x0b,          // h
	0x0c,          // i
	0x0d,          // j
	0x0e,          // k
	0x0f,          // l
	0x33,          // m
	0x11,          // n
	0x12,          // o
	0x13,          // p
	0x04,          // q
	0x15,          // r
	0x16,          // s
	0x17,          // t
	0x18,          // u
	0x19,          // v
	0x1d,          // w
	0x1b,          // x
	0x1c,          // y
	0x1a,          // z
	0x2f|SHIFT,    // 
	0x31|SHIFT,    // | TODO
	0x30|SHIFT,    // } TODO
	0x35|SHIFT,    // ~ TODO
	0				// DEL
};

ATTENTION : Seul le tableau de transcodage est à changer. N'échangez pas les les fichiers HID.cpp entre des versions différentes de l'Arduino, ce fichier a évolué au fil des versions.

Pour information

Voici comment procéder techniquement pour le changer.

Essayez de vous procurer une photo d'un clavier QWERTY. Nous en dessinons un (très simplifié) ci-dessous.

Claviers QWERTY et AZERTY simplifiés et leurs scancodes (en rouge)

Le point essentiel est de comprendre que votre tableau de transcodage doit correspondre au clavier du bas alors que celui que vous avez au départ correspond à celui du haut ! Les échanges de codes sont faciles lorsque vous savez à quelle touche QWERTY correspond telle lettre. Vous la cherchez sur le clavier AZERTY et notez le numéro rouge s'il est différent et le placez à l'endroit du commentaire correspondant.

Les choses sont plus délicates lorsque vous n'avez pas la lettre correspondante sur le clavier QWERTY. Prenez le é par exemple, quel est son code ? Ce n'est pas 0X1F comme le laisserait penser le dessin du bas ! ... et de toute façon il n'est même pas en commentaire dans le fichier HID.cpp !!!

Cahier des charges

Première version du cahier des charges

Nous allons donc développer la partie logicielle sur une platine Leonardo. La partie matérielle finale devra être compatible Leonardo. Elle est décrite plus loin. Nous voulons être capable de :

  • stoker plusieurs identifiants et mots de passes en EEPROM par la liaison série/USB
  • effacer certains couples identifiants/mots de passes plus utilisés
  • choisir lequel est actif par défaut
  • choisir la séquence par défaut

Le dernier point mérite quelques explications. Les comptes éloignés nécessitent en général un identifiant et un mot de passe. Les deux sont séparés par une tabulation et après le mot de passe on valide par un ENTER. Mais sur votre ordinateur local, le bon utilisateur est parfois choisi par défaut et donc seul le mot de passe est demandé. C'est cela que nous appelons séquence et qui pourra être choisi.

Notre description de cette clé de connexion USB nécessitera une utilisation fréquente des expressions :

  • Mot de Passe que nous résumerons le plus possible par MdP
  • Utilisateur (ou mieux identifiant) que nous appellerons aussi par l'anglicisme login
  • couple "Identifiant/Mot de passe" sera souvent appelé login/MdP

Pour respecter ce cahier des charges, nous envisageons d'utiliser quatre boutons :

  • un bouton appelé ENTER pour envoyer le couple login/MdP,
  • un bouton appelé MODIF qui devra permettre d'entrer dans un mode modification à l'aide d'un hyperterminal,
  • un bouton appelé CHOIX qui devra aussi permettre des modifications en utilisant uniquement les trois LEDs présentes.
  • un reset comme il y a sur le Leonardo

Seuls ENTER et MODIF seront utilisés dans ce projet (avec le reset bien sûr !).

La séquence de choix pour modifier sera imposée par le programme et les choix se feront par la liaison série en fait :

  • où fait-on une modification (ajout/changement de mot de passe) Vous remarquez que rien n'est prévu pour effacer un mot de passe à part écrire par-dessus.
  • choix du login par défaut (et ce même si vous n'avez pas besoin de changer !)
  • choix de la séquence par défaut (et ce même si vous n'avez pas besoin de changer !)

Modifications du cahier des charges

Les jeunes étudiants étant plus à même d'utiliser ce genre de produit, nous avons l'intention d'animer une discussion pour éventuellement modifier ce cahier des charges. Cette section sera donc le fruit de cette discussion.

Une question au hasard : comment changer le mot de passe par défaut avec les boutons et les LEDs sans connecter de moniteur série ?

Travail à réaliser

Le travail à réaliser va se diviser en deux parties :

  • utilisation d'une liaison série pour gérer une communication avec un PC tournant sous n'importe quel OS pour la saisie et le stockage des logins et mots de passes
  • utilisation de la liaison clavier USB pour les tests finaux.

Introduction pour comprendre

Pour présenter la problématique, nous vous proposons directement un travail avec clavier

Mon premier programme qui simule un clavier

Pour tester le bon fonctionnement correct du clavier en AZERTY, on vous propose le programme suivant.

void setup() {
  pinMode(2,INPUT); // bouton A sur shield IUT
}
void loop() {
  static char new_button,old_button;
  new_button=digitalRead(2);
  if ((old_button==0)&&(new_button==1)) { //detection front montant
   Keyboard.begin();   Keyboard.println("DEBUT AUTORISE");
   Keyboard.println("abcdefghijklmnopqrstuvwxyz");
   Keyboard.println("ABCDEFGHIJKLMNOPQRSTUVWXYZ");
   Keyboard.println("0123456789");
   Keyboard.println(" !\"$%&'()");
   Keyboard.println("%,;:!?./+=");
   Keyboard.println("FIN AUTORISE");
   Keyboard.println("DEBUT NON AUTORISE");
   Keyboard.println("<>*#{[|`\^@]}");
   Keyboard.println("FIN NON AUTORISE");
   Keyboard.end();
  }
  old_button = new_button;
  delay(100);
}

Essayer ce programme (en faisant un copier-coller). Il vous montrera la limite des caractères utilisables dans vos mots de passe.

Rappel : Le tableau suivant donne les caractéristiques utiles des 4 boutons du shield de l'IUT:

Bouton Position Arduino Pin Port Interruption Niveau logique si bouton appuyé
A Bas Gauche 2 PD2 int0 1
D Haut Gauche 3 PD3 int1 1
B Bas Droite A0 PC0 0
C Haut Droite A1 PC1 0

Travail 1

Modifier le programme d'exemple précédent pour qu'il envoie un identifiant (celui de votre bureau virtuel par exemple) suivi d'une tabulation et votre mot de passe suivi du retour chariot et ceci seulement si vous appuyez sur le bouton A.

INDICATION :

  • L'écriture du caractère tabulation se fait par :
Keyboard.write(0x09);//tabulation
  • L'écriture du retour chariot est automatique avec le Keyboard.println(), c'est le "ln" derrière le print qui fait le travail.

Remarque importante pour la suite

Comme on vient de le voir, il est possible d'envoyer simplement un identifiant/mot de passe avec un simple programme d'une dizaine de lignes... le tout en une demi-heure !

Que va-ton faire maintenant dans les heures qui restent ? Tout simplement gérer la possibilité de mémoriser plusieurs mots de passe ainsi que leur modifications/ajouts. Ce que vous venez de faire est très bien mais changer de mot de passe nécessite de changer de programme, autrement dit d'avoir des compétences en programmation Arduino. Si l'on veut réaliser une clé USB utilisable par tous, il nous faut aller plus loin.

Travail sur la liaison série

Nous avons décidé d'utiliser la liaison série pour gérer le stockage des "identifiants/mots de passe". Ces valeurs seront destinées à finir en EEPROM pour ne pas les perdre à chaque fois que l'on débranche l'USB. L'EEPROM est cependant une ressource qui a un nombre d'écritures limité !!! Pour ne pas gaspiller, nous avons décidé de faire la mise au point de cette partie en RAM (Travail 2 à 5). Une fois au point, nous passerons en EEPROM (Travail 6).

Mémoriser en mémoire RAM

Un tableau pour le grand gaspillage

Un tableau de caractères sera déclaré en RAM. Il comportera 256 caractères, même si nous n'en utilisons que très peu (d'où le mot gaspillage utilisé dans le titre de la section). Le travail essentiel se fera sur les indices de tableau qui rappelons-le deviendront des adresses mémoire EEPROM en travail 6. Ainsi, à partir de maintenant, nous utiliserons indistinctement les mots adresses ou indices pour les désigner.

Comment sont organisées les données en RAM ?

Nous allons utiliser l'abréviation MdP pour désigner les mots de passe dans la suite.

L'organisation mémoire est la suivante :

  • les mots de passe comme les identifiants seront des mots de 15 caractères maximum terminés systématiquement par un zéro (de fin de chaîne).
  • Le premier octet du tableau désigne le mot de passe par défaut : 0 est le premier mot de passe, 1 le deuxième etc ... d'où la flèche rouge de la figure ci-dessous.
  • Le deuxième octet du tableau désigne le nombre maximum de mots de passe enregistrés dans le tableau (ce nombre ne devra pas dépasser 7) et il est de 2 dans la figure ci-dessous.
  • Le troisième octet désigne le type de séquence utilisée : soit "Login TAB MdP ENTER", soit "MdP ENTER" pour le moment. Il est de 0 dans la figure ci-dessous. L'utilisation de ce troisième octet n'est pas obligatoire pour une première approche.
  • Le premier identifiant se trouve en adresse 0x10 (il s'agit de "toto01" suivi de son 0 de fin de chaîne), le deuxième en 0x30 (il s'agit de "tata02" suivi de son 0 de fin de chaîne), ....
  • Le premier mot de passe se trouve en adresse 0x20 (il s'agit de "titi?27" suivi de son 0 de fin de chaîne), le deuxième en 0x40 (quel est-il ?), ....

Voici la figure correspondante aux explications.

Comment les mots de passe et identifiants sont stockés en EEPROM

Les X dans le tableau désignent des valeurs qui n'ont pas d'importance (et qui sont gaspillées).

Vous y voyez deux paires identifiants/MdP stockées dans une EEPROM (ou dans le tableau RAM correspondant). Le fait que l'on aligne le début de ces chaînes de caractères simplifie les calculs correspondants. Il est ainsi facile de construire une boucle d'affichage par exemple (demandé en travail 3 plus loin)

Travail 2

On vous demande de réaliser un sous-programme capable de mettre à jour la RAM avec des couples "identifiants/mots de passe" qui respectent l'organisation précisée en section précédente.

char fakeEEPROM[256]; // c'est ici qu'on simule l'EEPROM
void init_ram()

On pourra utiliser des tableaux intermédiaires du genre :

char eeprom1[]={'t','w','X','z','o','u','9','1',0};
char eeprom2[]={'X','b','=','7','8','?',0};
char eeprom3[]={'z','t','o','t','r','o','w',0};
char eeprom4[]={'d','E','w','a','Z','d','t','=','M','y',0};

qui sont à adapter avec un de vos "identifiants/mots de passe" pour un test ultérieur.

Vous ne pourrez rien faire de très spectaculaire tant que Travail 3 n'est pas réalisé. Seulement vérifier la syntaxe et c'est déjà pas mal !!!

Indications : Une boucle for peut être utilisée pour chaque recopie mais elle débordera forcément et écrira donc un peu n'importe quoi à la place des X de la figure ci-dessus. Peut être préférer quelque chose du genre :

//....
  i=0;
  do {
    fakeEEPROM[0x10+i]=eeprom1[i];
    i++;
  }while(eeprom1[i]!=0);
  fakeEEPROM[0x10+i]=0;
//....

Travail 3

On désire maintenant réaliser un sous-programme capable de trouver, à partir de l'organisation du tableau de mémorisation des login/MdP, la séquence qu'il devra envoyer comme Login/MdP.

Écrire un sous-programme

void fakeKeyboard(); //joue le role de clavier par défaut

Le mot anglais "fake" se traduit par "faire comme si".

ATTENTION : Votre fakeKeyboard() se comporte comme un clavier !!! Il peut donc envoyer des choses dans votre environnement Arduino et complètement polluer votre programme source ! Prévoyez un éditeur de texte pour les tests, sous peine de mauvaise surprise !!! fakeKeyboard() doit être déclenché par un appui sur un bouton, et en aucun cas directement dans loop().

INDICATION (Rappel) :

  • L'écriture du caractère tabulation se fait par :
Keyboard.write(0x09);//tabulation
  • L'écriture du retour chariot est automatique avec le Keyboard.println()

A partir de maintenant vous avez deux possibilités :

  • continuer par les exercices 4, 5, 6 et 7 qui nécessitent l'utilisation d'un hyperterminal de type GTKTerm
  • continuer par les exercices 8, 9 et 10 qui nécessitent l'utilisation de Processing.org

Travail 4

On vous demande de réaliser un sous-programme capable d'afficher le contenu de la RAM de manière compréhensible par un utilisateur. Nous avons prévu une option brouillage (des mots de passe = remplacemant des caractères par '*') comme le montre le commentaire suivant, mais vous pouvez la laisser tomber pour simplifier.

// option = 0x01 brouille l'affichage des mots de passe
void afficheContenu(char option)

Bien sûr, l'affichage se réalise dans un moniteur série. Un programme du genre

void setup() {
  delay(5000);
  Serial.begin(9600);
  init_ram();
  afficheContenu(0);
}

void loop() {
}

pourra être utilisé pour tester. Il vous faudra naturellement ouvrir le moniteur série en moins de 5 secondes.

Voici un exemple de ce qui peut être affiché :

****Login / Mots de Passe ******
>> twXzou91 Xb=78?
ztotrow dEwaZdt=My
***** Sequence utilisee :
Login TAB MotPasse ENTER

qui montre comment la séquence identifiant/MdP courante est précisée.

Travail 5

1°) Pour raison de sécurité, mettre au point un sous-programme capable de lire un choix utilisateur à travers la liaison série entre un minimum (4 bits de poids faible) et un maximum (4 bits de poids fort).

// lecture du choix de l'opérateur
 char readChoixSerie(char maxmin)

Ce sous-programme rappelle à l'utilisateur ce qu'il est sensé faire dans le moniteur série. Par exemple readChoixSerie(0x72) doit commencer par afficher :

Entrez votre choix entre 2 et 7 :

et si l'utilisateur entre 1 et bien on lui redemande. L'utilisateur doit se fatiguer avant le programme !!!

Bien sûr, l'appel readChoixSerie(0x72) sera précédé systématiquement par une série de Serial.println() qui explique à l'utilisateur ce qu'il est sensé faire.


2°) Vous allez maintenant écrire la mise au point d'un programme utilisant quelques boutons et la liaison série pour ajouter/supprimer un couple "identifiants/mots de passe" tout en donnant aussi la possibilité de changer de séquence.

INDICATIONS :

  • un seul bouton est nécessaire pour tester cette partie. Commencez par gérer la détection d'un front sur un bouton... et c'est cette détection de front qui doit déclencher la mise à jour. Les choix pendant la mise à jour seront fait par la liaison série, c'est pour cela qu'un bouton suffit.
  • La fonction "Serial.readBytesUntil('\n', login, 15);" permet de lire les caractères provenant de la liaison série jusqu'au retour chariot ('\n') en les mettant dans le tableau login (déclaré comme "char login[16];"). Le 15 est là pour limiter le nombre de caractères à 15.
  • Pour notre shield de mise au point, il s'agit des possibilités suivantes :
Bouton Position Arduino Pin Port Interruption Résistance de tirage Niveau logique de l'entrée arduino si bouton appuyé
A Bas Gauche 2 PD2 int0 Pull Up + inverseur 1
D Haut Gauche 3 PD3 int1 Pull Up + inverseur 1
B Bas Droite A0 PC0 Pull Down + inverseur 0
C Haut Droite A1 PC1 Pull Down + inverseur 0
  • Pour la clé de Monsieur Gérard il s'agit des boutons 8, 9 et 10.
nom des boutons CR = ENTER MODIF CHOIX
PORT PB4 PB5 PB6
Nom Arduino 8 9 10

Ils seront donc gérés avec le code :

// trois boutons avec pullup externe
  pinMode(8,INPUT); // ENTER
  pinMode(9,INPUT); // MODIF
  pinMode(10,INPUT); // CHOIX

Trois LEDs sont présentes et doivent, elles-aussi, être associées à un nom Arduino.

PORT PF5 PF6 PF7
Nom Arduino A2 A1 A0
  • Le bouton ENTER sert à envoyer le "identifiants/mots de passe" comme on le ferait avec un clavier
  • le bouton MODIF sert à ajouter un "identifiants/mots de passe" et à modifier le "identifiants/mots de passe" par défaut et la séquence à l'aide d'un hyperterminal
  • le bouton CHOIX fait la même chose que MODIF mais sans hyperterminal mais avec les trois LEDs (non encore réalisé en logiciel à ce jour)


RAPPEL : la séquence de choix pour modifier sera imposée par le programme et les choix se feront par la liaison série en fait :

  • où fait-on une modification (ajout/changement de "identifiants/mots de passe") Vous remarquez que rien n'est prévu pour effacer un "identifiants/mots de passe" à part écrire par-dessus.
  • choix de "identifiants/mots de passe" par défaut (et ce même si vous n'avez pas besoin de changer !)
  • choix de la séquence par défaut (et ce même si vous n'avez pas besoin de changer !)
  • un dernier choix demandant l'éventuel sauvegarde ou pas.

INDICATION 2 : un programme simple du genre :

void setup() {
  pinMode(2,INPUT); // bouton A
  delay(5000);
  Serial.begin(9600);
  init_ram();
  afficheContenu(0x80);
}

void loop() {
  static unsigned char AButtonPast=0,AButtonPresent=0;
  AButtonPresent=digitalRead(2);
  if ((AButtonPresent == 1) && (AButtonPast == 0)) {
    updateRAM();
    afficheContenu(0x00);
  }
  AButtonPast = AButtonPresent;
  delay(100);
}

vous montre que le programme demandé ici a été appelé updateRAM() et surtout vous montre une manière simple de faire le test.


Faites constater avant de passer à l'écriture en EEPROM.

Mémoriser en mémoire EEPROM

Le travail en EEPROM est assez similaire à celui de la RAM. Son utilisation nécessite l'inclusion :

#include <EEPROM.h>

La lecture d'une donnée en EEPROM se fait avec :

nbDefaut = EEPROM.read(0x00); // au lieu de nbDefaut=fakeEEPROM[0x00];

qui lit l'adresse 0 pour la stocker dans "nbDefaut", tandis qu'une écriture se fait avec :

EEPROM.write(0x01,2); // au lieu fakeEEPROM[0x01]=2;

qui écrit simplement le nombre 2 en adresse 0x01.

Travail 6

MdP est encore l'abréviation de "Mot de Passe".

On vous demande de porter le programme du Travail 5 pour un usage non plus de la RAM mais de l'EEPROM. On gardera l'organisation mémoire EEPROM suivante :

  • les mots de passe comme les identifiants seront des mots de 15 caractères maximum terminés systématiquement par un zéro (de fin de chaîne).
  • Le premier octet de l'EEPROM désigne le mot de passe par défaut : 0 est le premier mot de passe, 1 le deuxième etc ...
  • Le deuxième octet de l'EEPROM désigne le nombre maximum de mots de passe enregistrés dans l'EEPROM (ce nombre ne devra pas dépasser 7)
  • Le troisième octet désigne le type de séquence utilisée : soit "Login TAB MdP ENTER", soit "MdP ENTER" pour le moment
  • Le premier identifiant se trouve en adresse 0x10, le deuxième en 0x30 ....
  • Le premier mot de passe se trouve en adresse 0x20, le deuxième en 0x40 ....

Travail avec le clavier : l'apothéose finale

Travail 7

Porter le sous-programme

void fakeKeyboard(); //joue le role de clavier par défaut

de l'exercice 4 pour qu'il fonctionne avec l'EEPROM au lieu du tableau.

Travail avec Processing

La mise à jour des mots de passe et des identifiants se fait maintenant à l'aide de processing. Le gros intérêt par rapport à un hyperterminal c'est que l'on peut travailler sur tous les mots de passe en même temps et une fois que tout est rempli correctement on envoie à l'Arduino.

Processing est un environnement pas très adapté à ce qu'on va lui demander. Mais on peut faire des choses importantes si l'on installe une librairie particulière controlP5. La Librairie controlP5 a une installation très simple à choisir parmi les deux possibilités suivantes :

  • Télécharger et décompacter dans le répertoire "libraries" de votre répertoire de sketchs ou
  • sketch->import library->chercher controlP5

Travail 8

On désire maintenant que votre programme processing soit capable d'envoyer à votre Arduino l'ensemble du contenu de la mémoire. Pour cela, vous allez utiliser des boîtes de texte (voir l'exemple ControlP5textfield).

Il serait normal d'utiliser des boutons radio qui permettent un choix exclusif (voir l'exemple ControlP5radiButton) mais nous allons simplifier au maximum cette partie processing en nous limitant aux boîtes de texte.

Travail 9

Travail 10

Voir aussi

  • Projet de clé USB
  • Librairie controlP5 Installation très simple :
    • Télécharger et décompacter dans le répertoire "libraries" de votre répertoire de sketchs ou
    • sketch->import library->chercher controlP5