Keypad à lecture analogique
Matrice Carrée
Le keypad à membranes
Quelques keypads à membranes:
Ils sont pré-câblé, par exemple:
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:

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:
Et voici par où passe le courant si on appuie par exemple sur 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:
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:
| rapport | Valeur des résistances |
| 2 | 2/1 22/11 24/12 30/15 36/12 150/75 |
| 3 | 3/1 33/11 36/12 39/13 |
| 4 | 12/3 300/75 |
| 5 | 75/15 10/2 110/22 120/24 15/3 180/36 |
| 6 | 12/2 18/3 |
| 7 | 91/13 |
| 8 | 120/15 16/2 24/3 |
| 9 | 8/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:
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é.