Calcul d'un Keypad
à lecture analogique
Montage
Voici le 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 lira sans aucune erreur la valeur 1023 (aucun bouton appuyé) car c'est le résultat d'une lecture de 5V avec une référence de 1,1V. Les autres lectures peuvent être entachées d'une erreur. Si on veut pouvoir avoir une erreur possible la plus grande (sécurité maximale), on essaiera d'approcher le graphe suivant:
Pour un AVR, MAX vaut 1024, qui correspond à une tension de Vref de 1,1V. Mais on lira au maximum 1023.
Calcul de la résistance P
Voici en résumé comment cela se présente si on appuie sur la touche n:
Appelons:
- VCC la tension d'alimentation (5V pour une Uno)
- Vref la tension de référence (1,1V pour une Uno)
- MAX la valeur qui correspondrait à Vref (1024 pour une Uno)
- N le nombre de boutons
- ΣR la résistance R lorsque le dernier bouton est appuyé (c'est aussi la somme de toutes les résistances)
- ε l'écart possible (qui dépend de tous les paramètres précédents)
- Vin,n la tension d'entrée de l'Arduino si on appuie sur le bouton n
- CANn la valeur numérique lue si le bouton n est appuyé
L'idéal bien sûr est d'avoir des résistances R et des résistances C*R, mais en fonction des restes du tiroir, on peut être amené à avoir des résistances légèrement différentes, par exemple si R=500Ω avoir les 4*R de 2,2kΩ.
Calculons Vin,N-1 par le pont diviseur:
ΣR (1) Vin,N-1 = ────── VCC P + ΣR
Puis avec le graphe:
MAX - 1 (2) ε = ──────── 2N - 1
Et d'autre part:
MAX - 1 - ε Vin,N-1 (3) ─────────── = ─────── MAX Vref
Extrayons P/ΣR: mettre l'ε de (2) dans l'expression (3), puis écrire l'égalité des Vin,N-1 entre les expressions (1) et (3). On obtient alors:
MAX (2N-1) VCC (4) P/ΣR = ──────────── . ──── - 1 2(MAX-1)(N-1) Vref
Changer la valeur de P (pour avoir une valeur normalisée) va changer CANN-1 et les écarts ε. Si on diminue un peu la valeur de P, cela va diminuer beaucoup l'erreur acceptable pour le dernier bouton εN:
Les autes valeurs des erreurs ε seront réparties régulièrement. Mais c'est la valeur minimale des différents ε qui est limitant. Il ne faut donc pas prendre P plus petite que la valeur idéale. Si on prend maintenant P un peu plus grand, cela va donner:
La dernière erreur maximale εN va augmenter, et cela va diminuer les autres erreurs mais 2N-2 fois moins. C'est donc plus acceptable.
On prendra une résistance légèrement supérieure à la valeur calculée.
MAX (2N-1) VCC (5) P ⩾ ( ──────────── . ──── - 1 ) . ΣR 2(MAX-1)(N-1) Vref
Linéarisation
Malheureusement si n varie de 0 à N la tension en entrée du convertisseur ne va pas varier linéairement! On obtient pour 16 touches:
La courbe rouge est la courbe idéale (linéaire) et la courbe bleue est celle que l'on a réellement. Pour un pavé de 9 touches l'erreur entre les deux courbes atteint quasiment l'erreur ε autorisé, et pour peut que l'on ait une dispersion sur la valeur des résistances, la lecture serait fausse. Sans correction, on peut espérer pouvoir utiliser un maximum de 6 touches (erreur de lecture possible partagée pour moitié par les erreurs sur les valeurs et par moitié par la non linéarité).
Il peut être nécessaire de corriger la valeur lue pour la linéariser. Je conçois trois possibilités:
- on ne corriger rien si on a moins de 6 boutons
- on corrige la courbe avec l'expression mathématique exacte en utilisant plutôt des entiers (calculs plus rapides, mais cela introduit une
erreur supplémentaire, mais qui est petite). On obtient alors une courbe linéaire... si les résistances sont parfaites!
- on mesure les valeurs pour les N boutons et on fait une table. Cela veut dire que si une résistance n'avait pas la bonne valeur, ce
serait pris en compte. C'est la méthode qui va maximaliser le nombre de boutons. Mais si on a peu de boutons, une correction suffit et si
on a beaucoup de boutons il faut une grande table et une lecture de la table est plus complexe.
Il n'y a pas de solution universelle, par la suite je vais m'intéresser à la correction exacte. La solution avec table sera étudiée dans une autre page car elle n'est pas spécifique à la lecture d'un keypad, mais fonctionne avec quasi tous les ensembles de boutons lus en analogique.
Extraction du numéro du bouton
Appelons:
- VCC la tension d'alimentation (5V pour une Uno)
- Vref la tension de référence (1,1V pour une Uno)
- MAX la valeur qui correspondrait à Vref (1024 pour une Uno)
- N le nombre de boutons
- CANn la valeur numérique réelle pour le bouton n
- P la résistance fixe entre l'entrée et VCC
- R les résistances que l'on insère pour chaque bouton
- ΣR la somme de toutes les résistances R. Cela vaut (N-1)R si toutes les résistances sont identiques.
On a pris pour P une valeur différente de la valeur idéale, ne serait-ce que pour prendre une valeur existante. D'autre part, il peut y avoir des écarts de VCC, de Vref ainsi que sur la valeur des résistances. Il vaut donc mieux s'affranchir des valeurs de VCC Vref et P.
Mon choix est de calculer d'abord la valeur du convertisseur pour le dernier bouton CANN-1 et d'utiliser ce résultat pour trouver la valeur n. Ce serait bien de remplacer la valeur théorique CANN-1 par la valeur réellement lue.
Calculons tout de même la valeur que l'on devrait avoir pour CANN-1.
ΣR (1) Vin,N-1 = ────── VCC P + ΣR MAX ΣR.VCC MAX (5) CANN-1 = Vin,N-1 ────── = ────── . ─── Vref P + ΣR Vref
Si tout était parfait, on devrait trouver (voir le premier graphique):
MAX - 1 2N - 2 (6) CANN-1 = MAX - 1 - ε = MAX - 1 - ─────── = (MAX -1) ────── 2N - 1 2N - 1
Par la suite, on va supposer que l'on mesure CANN-1.
On a pour la lecture réelle un pont diviseur:
n.R.VCC (7) CANn = ───────────── (P + n.R).Vref
Éliminons tout d'abord Vref et VCC entre (5) et (7):
VCC (P + ΣR).CANN-1 (8) (5) ⟹ ───── = ─────────────── Vref ΣR.MAX
Et remplaçons le dans (7):
n.R.VCC n.R.(P + ΣR).CANN-1 (9) CANn = ───────────── = ───────────────── (P + n.R).Vref (P + n.R).ΣR.MAX
C'est n que l'on cherche, multiplions par le dénominateur des deux côtés, regroupons ce qui contient n à droite puis exprimons n:
(10) CANn.(P + n.R).ΣR.MAX = n.R.(P + ΣR).CANN-1 CANn.P.ΣR.MAX = n.R.(P + ΣR).CANN-1 - CANn.n.R.ΣR.MAX = n . [R.(P + ΣR).CANN-1 - CANn.R.ΣR.MAX] CANn.P.ΣR.MAX (11) n = ───────────────────────────────── R.(P + ΣR).CANN-1 - CANn.R.ΣR.MAX P/R.CANn (12) n = ──────────────────────── (P/ΣR + 1).CANN-1 - CANn
C'est de la forme:
a.CANn (13) n = ──────── avec a = P/R.CANn et b = (P/ΣR + 1).CANN-1 b - CANn
Compte tenu des erreurs de lecture du convertisseur et des arrondis éventuels (on peut travailler avec des entiers), n ne sera pas entier. Il faut prendre le plus proche entier, l'arrondi. Si on travaille avec des entiers, la division entière fait une troncature. On rajoutera 0,5 car:
(14) round(x) = trunc(x + 0,5)
Si on veut utiliser la troncature:
a.CANn 1 (14) n = trunc( ──────── + ─ ) b - CANn 2
Si on travaille avec des entiers, 1/2 vaut zéro, pour en tenir compte, il faut réduire au même dénominateur et faire la division à la fin:
a.CANn b/2 - CANn/2 (15) n = trunc( ──────── + ──────────── ) b - CANn b - CANn b/2 + (a-1/2).CANn (16) n = trunc( ──────────────────── ) b - CANn
Avec un AVR, si (b/2), (a-1/2) et (b) sont des entiers, la division se fera avec des entiers et trunc est inutile.