Ardu? No!Les boutons ≫ Suppression de résistances mono

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:

Montage à suppression de résistances

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:

Montage à suppression de résistances mono à 10 poussoirs

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.