Ardu? No!Les boutons ≫ Keypad à lecture analogique

Keypad à lecture analogique
Matrice Carrée

Le keypad à membranes

Quelques keypads à membranes:

Exemples de keypads à membranes

Ils sont pré-câblé, par exemple:

Keypad 12 et 16 touches

Lorsque l'on fait une lecture analogique, un appui sur une touche fera un diviseur de tension entre une résistance qui augmente avec le numéro de la touche et une résistance fixe. Pour un keypad 16 touches, si l'incrément est de 500Ω, la résistance fixe vaut 27kΩ.

Avec un keypad à membranes, l'appui sur une touche va rajouter une résistance supplémentaire car le contact est entre deux pistes et une pastille de caoutchouc conductrice. J'ai testé 4 keypads neufs. Les claviers à membranes rajoutent une résistance qui varie selon la touche de 0Ω à 500Ω. Une lecture en utilisant la courbe théorique n'est alors possible que si chaque touche rajoute une résistance grande devant les 500Ω et cela ferait une impédance en entrée de la broche analogique de l'ordre de 300kΩ. On risque de capter pas mal de bruit. Les keypads à membranes ne sont pas recommandées pour ce genre de lecture expliquée dans la suite de cette page. On peut par contre les lire avec des impédances plus faibles et une lecture au travers d'une table.

Le keypad à interrupteurs

Quelques exemples:

Exemples de keypads avec interupteursExemples de keypads avec interupteurs

Il est pré-câblé, comme les keypads à membranes (L: Line -> ligne, R: Row -> colonnes):

Un keypad pré-câblé ne pourra jamais faire une lecture poly: si on appuie sur les boutons 1, 2 et 4, on ne pourra pas savoir si le bouton 5 est appuyé ou non, car cela ne rajoute pas de connexions. Dans la suite, je ne vais donc m'intéresser qu'à la lecture mono, bien qu'une lecture stéréo serait possible.

Montage

Voici un schéma pour un keypad 16 touches:

Câblage d'un keypad 16 touches pour une lecture mono optimale

Et voici par où passe le courant si on appuie par exemple sur la touche 9:

Passage du courant pour la touche 9

En analysant ce schéma, on comprendra que l'on va diviser la tension VCC avec en haut une résistance P et en bas une résistance comprise entre 0 (si on presse la touche 1) et 15*R (si on presse le D).

Voici le schéma général pour C colonnes et pour L lignes:

Schéma général pour C colones et pour L lignes

On choisira de prendre pour le CNA le 1,1V comme tension de référence. On essaiera d'avoir proche de 1023 pour la touche correspondante à la résistance maximale, de façon à avoir un écart le plus grand possible entre les différentes valeurs lues.

Erreurs sur les valeurs R /C.R

Pour des raisons d'arrondis, de fond de tiroirs... on peut être amené à choisir des couples R/C.R légèrement différents, par exemple pour un clavier à 4 colonnes on pourrait prendre 500Ω/2,2kΩ au lieu de 500Ω/2,0kΩ. Les écarts ε possibles seront alors inégaux, mais cela fonctionne quand même si on n'a pas trop de boutons. Notez que dans la série E24 (24 valeurs par décade) On peut avoir des rapports entiers:

rapportValeur des résistances
22/1 22/11 24/12 30/15 36/12 150/75
33/1 33/11 36/12 39/13
412/3 300/75
575/15 10/2 110/22 120/24 15/3 180/36
612/2 18/3
791/13
8120/15 16/2 24/3
98/2 27/3

Pour 16 touches, il faut des couples R/4R, on peut prendre (1,2kΩ/300Ω) (12kΩ/3kΩ) (3kΩ/75Ω) (30kΩ/750Ω)...

On peut aussi n'utiliser que des résistances identiques pour R et 4R. On peut par exemple utiliser deux résistances de 1kΩ en parallèle pour avoir R=500Ω et en série pour 4R=2kΩ. Cela peut faire par exemple:

Câblage de keyopads avec des 1k

Valeurs et formules

Je ne détaille pas ici les calculs, ils sont donnés dans la page Keypad_analogique_Calculs.

Notez que les valeurs des résistances peuvent toutes être multipliées par un même facteur, cela ne change rien, et les formules d'extraction du numéro du bouton est inchangée. Une impédance trop grande ramène du bruit, une impédance trop faible consomme du courant.

Le montage est le suivant:

Ajustez si besoin la tension VCC
VCC = V

Ajustez si besoin la tension Vref
Vref = V

Modifiez si besoin la valeur maximale du convertisseur
MAX =

Donnez la taille de la matrice:
Nombre de lignes ➩ lignes
Nombre de colonnes ➩ colonnes

Choisissez la valeur de R (100Ω à 500Ω conseillé):
R = Ω

Confirmez ou modifiez la valeur de R2 (il vaut mieux prendre plus grand que plus petit):
R2 = Ω

Choisissez la valeur de P (prendre la valeur immédiatement supérieure):
P = Ω

Que donne la conversion pour le dernier bouton de la dernière ligne (si c'est supérieur au nombre indiqué, il faut prendre P plus grande):
CANN-1 = Ω

Deux formules permettent d'avoir le numéro n du bouton (0..L*C, 0 pour le bouton de la première ligne première colonne, 1 pour le bouton de la deuxième colonne...) en fonction de la valeur CANn du convertisseur:

Notez qu'avec des AVR, si on fait des calculs avec des entiers, la valeur est tronquée. On n'a donc pas besoin de mettre le "trunc". CANn doit être un word ou un uint16_t.

Lecture par table

Comme tous les montages de lecture de boutons par lecture analogique, il est possible de connaitre l'état des boutons par une lecture à l'aide d'une table. Se reporter à la page Lecture analogique avec une table

Exemple de programme de lecture par calcul

// Clavier matriciel 20 touches 

//                                    VCC
//                                     │
//                                    15kΩ
//                                     │
//                                     ├── Vers A0
// ┌─ 220Ω ─┬─ 220Ω ─┬─ 220Ω ─┬─ 220Ω ─┤
// ├─ / ┐   ├─ / ┐   ├─ / ┐   ├─ / ┐   ├─ / ┐
// │    └───│────┴───│────┴───│────┴───│────┴────┐
// ├─ / ┐   ├─ / ┐   ├─ / ┐   ├─ / ┐   ├─ / ┐  1,1kΩ
// │    └───│────┴───│────┴───│────┴───│────┴────┤
// ├─ / ┐   ├─ / ┐   ├─ / ┐   ├─ / ┐   ├─ / ┐  1,1kΩ
// │    └───│────┴───│────┴───│────┴───│────┴────┤
// └─ / ┐   └─ / ┐   └─ / ┐   ├─ / ┐   └─ / ┐  1,1kΩ
//      └────────┴────────┴────────┴────────┴────┤
//                                              GND

void setup()
{
  Serial.begin(115200); // Mettre aussi la console sur 115200 bauds
  analogReference(INTERNAL); // Vref=1,1V; mettre INTERNAL1V1 pour la Mega
}

word valeurLue, // Résultat de la conversion brute puis corrigée puis n° de la touche
     oldValeurLue, // Mémorisation pour permettre deux lectures consécutives identiques
     oldTouche; // Touche précédente appuyé pour ne pas l'afficher plusieurs fois

void loop()
{
  // Mesure
  do
  {
    oldValeurLue = valeurLue; // Sauvegarde de la mesure précédente
    valeurLue = analogRead(A5); // Nouvelle lecture
  } while (valeurLue!=oldValeurLue); // On recommence jusqu'à avoir deux lectures identiques
  if (valeurLue!=1023) // Si une touche est appuyée: correction et extraction
    valeurLue = ((68UL * valeurLue + 2035) / (4070 - valeurLue)); // UL car 68 dépasse 64; cela donne le N° de la touche 0..19

  // Affichage
  if (valeurLue!=oldTouche) // Si changement
  {
    if (valeurLue!=1023) // C'est une nouvelle touche
    {
      Serial.print("Bouton appuyé, ligne ");
      Serial.print(valeurLue / 5 + 1);
      Serial.print(", colonne ");
      Serial.println(valeurLue % 5 +1);
    }
    else Serial.println("Bouton relâché");
    oldTouche=valeurLue; // Mémorisation pour ne pas afficher plusieurs fois
  }
}

Exemple 2, avec interruption

Le keypad analogique se prête bien à une lecture par interruption. Les explications détaillées se trouvent à la page Boutons et interruption

Cet exemple montre juste un programme qui fonctionne et qui affiche le bouton appuyé. Ce n'est pas à suivre, on ne met pas d'affichage dans une routine d'interruption. C'est juste pour le cadre:

// Clavier matriciel 20 touches 

//                                    VCC
//                                     │
//                                    15kΩ
//                                     │
//                                     ├── Vers A0
// ┌─ 220Ω ─┬─ 220Ω ─┬─ 220Ω ─┬─ 220Ω ─┤
// ├─ / ┐   ├─ / ┐   ├─ / ┐   ├─ / ┐   ├─ / ┐
// │    └───│────┴───│────┴───│────┴───│────┴────┐
// ├─ / ┐   ├─ / ┐   ├─ / ┐   ├─ / ┐   ├─ / ┐  1,1kΩ
// │    └───│────┴───│────┴───│────┴───│────┴────┤
// ├─ / ┐   ├─ / ┐   ├─ / ┐   ├─ / ┐   ├─ / ┐  1,1kΩ
// │    └───│────┴───│────┴───│────┴───│────┴────┤
// └─ / ┐   └─ / ┐   └─ / ┐   ├─ / ┐   └─ / ┐  1,1kΩ
//      └────────┴────────┴────────┴────────┴────┤
//                                              GND

void setup()
{
  Serial.begin(115200); // Mettre aussi la console sur 115200 bauds
  analogReference(INTERNAL); // Vref=1,1V; mettre INTERNAL1V1 pour la Mega
  PCICR = 2; // Autorise les interruptions PCINT[14:8]
  PCMSK1 = 32; // Autorise uniquement PCINT13, soit la broche A5 
}

void loop()
{
}


word valeurLue, // Résultat de la conversion brute puis corrigée puis n° de la touche
     oldValeurLue, // Mémorisation pour permettre deux lectures consécutives identiques
     oldTouche; // Touche précédente appuyé pour ne pas l'afficher plusieurs fois


ISR(PCINT1_vect)
{
  // Mesure
  do
  {
    oldValeurLue = valeurLue; // Sauvegarde de la mesure précédente
    valeurLue = analogRead(A5); // Nouvelle lecture
  } while (valeurLue!=oldValeurLue); // On recommence jusqu'à avoir deux lectures identiques
  if (valeurLue!=1023) // Si une touche est appuyée: correction et extraction
    valeurLue = ((68UL * valeurLue + 2035) / (4070 - valeurLue)); // UL car 68 dépasse 64; cela donne le N° de la touche 0..19

  // Affichage
  if (valeurLue!=oldTouche) // Si changement
  {
    if (valeurLue!=1023) // C'est une nouvelle touche
    {
      Serial.print("Bouton appuyé, ligne ");
      Serial.print(valeurLue / 5 + 1);
      Serial.print(", colonne ");
      Serial.println(valeurLue % 5 +1);
    }
    else Serial.println("Bouton relâché");
    oldTouche=valeurLue; // Mémorisation pour ne pas afficher plusieurs fois
  }
}

Vidéos de démonstration

Sur cette vidéo, on peut bien voir que la lecture du clavier se fait bien sur une seule broche. Le programme utilisé est le même que celui qui est au dessus, sauf que l'affichage se fait sur un petit écran au lieu de la console.

On m'a dit qu'il fallait mettre le clavier près de l'arduino. La vidéo suivante montre le même montage, mais en ayant inséré une rallonge de 25m (c'est bien 25, il y a une erreur dans la vidéo). Cala fonctionne aussi.

Bilan

- lecture simple, mais avec correction
- permet d'utiliser les claviers matriciels pré-câblés usuels
- un seule broche pour un keypad
- résistances proches compensant en partie les erreurs
- utilisation d'interruption possible
MAIS
- lecture mono
- des résistances en plus
- je ne connais pas de bibliothèques pour ce montage

Très très intéressant, mais peu utilisé.