Suppression de résistances mono
L'idée
En mélangeant des boutons et des résistances, on peut obtenir un dipole dont la résistance va varier en fonction de l'appui sur les boutons. En mesurant cette résistance, on peut en déduire quel(s) bouton(s) est(sont) appuyé(s). Pour la lecture on n'a pas vraiment le choix si on veut rester simple (sans circuit supplémentaire), on fera un pont diviseur à partir du 5V. Ici, l'idée est de court-circuiter des résistances.
Voici le câblage de cette résistance variable:
Ce montage permet une lecture mono ou poly.
L'intérêt de ce montage est un câblage plus simple si les résistances sont soudées directement sur les boutons.
Lecture mono
On peut parfaitement garder le montage poly si on sait que l'on appuiera que sur un seul bouton à la fois, mais avec N boutons, il faut être capable de différencier 2N états alors qu'une lecture mono n'a que N états à différencier. En utilisant une lecture mono, on peut mettre beaucoup plus de boutons ou avoir plus d'écart entre les valeurs, ce qui permet des erreurs plus importantes sur les valeurs. C'est pour cela qu'en lecture mono, le schéma suivant est plus intéressant:
Le choix de 1,1V comme tension de référence semble être meilleur que le choix des 5V. Pour 10 boutons, l'écart des valeur semble être deux fois plus grand. Je vais donc garder pour la suite la référence du CAN à 1,1V.
La valeur de P est choisie telle que l'entrée de l'Arduino soit à 1,1V si aucun bouton n'est appuyé. Si N est le nombre de boutons (ou de résistances) la valeur de P est donné par la formule:
N.(N + 1) 5V - 1,1V P = ───────── . ──────── 2 1,1V
Les 5V c'est la tension de la carte et les 1,1V est la référence. Ces valeurs peuvent être mesurées (ou pas!).
L'étude détaillée est un peu complexe, je vais me contenter de donner les principaux résultats. Dans ce montage, plus le nombre de boutons est important, plus il y aura de résistances et moins il y aura de variations de résistance. Ceci ne facilitera pas la lecture.
A vide (sans presser les boutons), la tension sur le CAN sera de 1,1V. Mais on ne pourra jamais avoir du 0V, car on n'appuie que sur un seul bouton. On ne va donc pas utiliser les 1024 poins du CAN, mais une partie seulement. Les formules approximatives de Martin donnent:
1500 ΔCAN = ──── N
Pour 5 boutons, ΔCAN = 300, on va donc de 1023-300 à 1023. Pour 20 boutons, on va de 1023-75 à 1023...
L'écart entre deux mesures est de l'ordre de:
1500 Écart = ──── N2
Si l'on veut un écart de 10 points minimum, N doit être au maximum de √150 soit 12 boutons.
Enfin la courbe n'est pas vraiment une droite, mais l'erreur par rapport à la droite est voisine du dixième de l'écart. Par exemple pour 12 boutons, l'erreur de non linéarité du montage est d'environ 1 point. Comme on en a 10 fois plus, la correction est inutile.
Le montage ainsi n'est pas terrible, on peut dons aller jusqu'à 10 boutons environ par broche.
Voici les données pour 13 boutons (je garde l'espacement entre les valeurs de 8 minimum comme pour la lecture poly à 6 boutons):
- résistance de pull-up de 323kΩ
- écart minimum théorique 8,8 points
- erreur de linéarité de 0,94 point
Pour un programme de test, je dois lire la valeur CNA0 obtenue quand aucun bouton n'est appuyé. Cette valeur doit être au plus égale à 1022, si ce n'est pas le cas, il faut augmenter la valeur de la résistance de pull-up. Il faut lire également la valeur CNA13 obtenue quand le treizième bouton est appuyé (valeur théorique attendue: 906). Les autres mesures s'obtiennent en supposant que les valeurs sont réparties linéairement.
// Suppression de résistances mono, 13 boutons // VCC // │ // 162kΩ // │ // ├─────┬─── vers A0 // │ │ // 500Ω SW1 // │ │ // ├─────┤ // │ │ // 1kΩ SW2 // │ │ // ├─────┤ // │ │ // 1,5kΩ SW3 // │ │ // ├─────┤ // │ │ // 2kΩ SW4 // │ │ // ├─────┤ // ● // ● // ● // │ │ // ├─────┤ // │ │ // 6,5kΩ SW13 // │ │ // ├─────┘ // GND const float N = 13; // Nombre de boutons; A ajuster const byte BOUTONS = A0; // Broche de lecture; A ajuster // Valeurs à mesurer et à ajuster const int CAN_0 = 1016; // Pas plus de 1022 sinon augmenter la pull-up const int CAN_N = 911; // Valeur théorique pour 13 boutons: 906 // Donnée calculée fixe const float intervalle = (CAN_0 - CAN_N) / N; void setup() { Serial.begin(115200); // Régler aussi la console à 115200 bauds! analogReference(INTERNAL); // Pour passer à 1,1V } int valeurLue, // Résultat de la conversion brute puis corrigée oldValeurLue, // Mémorisation pour permettre deux lectures consécutives identiques touche, // Numéro de la touche oldTouche; // Touche précédente appuyé pour ne pas l'afficher plusieurs fois void loop() { do // Lecture brute { oldValeurLue = valeurLue; // Sauvegarde de la mesure précédente valeurLue = analogRead(BOUTONS); // Nouvelle lecture } while (valeurLue!=oldValeurLue); // On recommence jusqu'à avoir deux lectures identiques // Serial.println(valeurLue); // Mesure de CAN_0 et CAN_N // Pas de correction de la valeur //Extraction touche= round((CAN_0-valeurLue)/intervalle); // Cela donne le N° de la touche 1..N // Affichage if (touche!=oldTouche) // Si changement { if (touche) // C'est une nouvelle touche { Serial.print("Bouton SW"); Serial.print(touche); // Boutons numérotés à partir de 0 Serial.print(" (erreur:"); Serial.print(valeurLue-CAN_0+touche*intervalle,0); // Valeur de l'erreur Serial.print("/"); Serial.print(intervalle,0); // On a le droit d'une erreur de "intervalle" environ Serial.println(")"); delay(100); // Anti-rebond } oldTouche=touche; // Mémorisation pour ne pas afficher plusieurs fois } delay(1000); // Pas trop souvent }
Et l'affichage donne:
Bouton SW1 (erreur:-1/8) Bouton SW2 (erreur:1/8) Bouton SW3 (erreur:2/8) Bouton SW4 (erreur:3/8) Bouton SW5 (erreur:1/8) Bouton SW6 (erreur:0/8) Bouton SW7 (erreur:1/8) Bouton SW8 (erreur:3/8) Bouton SW9 (erreur:-0/8) Bouton SW10 (erreur:-0/8) Bouton SW11 (erreur:1/8) Bouton SW12 (erreur:1/8) Bouton SW13 (erreur:1/8)
Les erreurs sont acceptables. On remarque que c'est la résistance R8 qui procure l'erreur la plus grande. Sa mesure donne 3,93kΩ alors qu'il aurait fallu une 4,00kΩ.
Bilan
- lecture simple, sans correction de linéarité
- câblage simplifié si on soude directement les résistances sur les boutons
MAIS
- lecture mono
- résistances non identiques ne compensant pas les erreurs
- les boutons n'ont pas de borne commune
- une résistance par bouton en plus
- je ne connais pas de bibliothèques pour ce montage
- utilisation d'interruption impossible
Intéressant, mais peu utilisé. On peut peut être aller jusqu'à 7 boutons.