Ardu? No!Les boutons ≫ Sommateur de courants à lecture poly

Sommateur de courants à lecture poly

Schéma de base

Voici le schéma de principe:

Principe pour un sommateur de courants à lecture poly

Dans ce principe, pour 5 boutons, on a 5 générateurs de courant, et la résistance R est dimensionnée de façon à avoir une tension à ses bornes égale à la tension de référence du CAN de l'Arduino quand elle est traversée par le courant 32I.

L'intérêt de ce montage est de permettre la lecture de l'état de tous les boutons. La lecture est poly. Si par exemple la tension aux bornes de R vaut 22RI, on en déduit que les boutons SW4 (laisse passer 16I), SW2 (laisse passer 4I) et SW1 (lisse passer 2I) sont enfoncés.

J'ai numéroté les boutons en fonction du poids SWn laisse passer un courant de 2nI. Lors de la lecture, on peut obtenir un mot binaire, chaque bit correspondant à un bouton, le bit de poids 2n correspondra au bouton SWn.

Ce serait trop compliqué d'utiliser de vrais générateurs de courant, nous allons utiliser de simples résistances. Le schéma devient alors:

Base pour un sommateur de courants à lecture poly

Pour que cela fonctionne au mieux, il faudrait que la tension aux bornes des résistances soit fixe, ce qui donnerait un courant constant. Mais la tension aux bornes de la résistance R va varier, faisant varier les autres tensions. Pour en minimiser l'effet, on pourrait alimenter les résistances avec une tension élevée, mais dans la pratique c'est compliqué car il faudrait une deuxième alimentation, genre 12V, et une erreur pourrait s'avérer fatale. De plus cela compliquerait le schéma et cela deviendrait moins intéressant. Par contre, on peut diminuer la tension maximale de R en utilisant la référence de 1,1V au lieu des 5V par défaut.

Il y a quand même un problème de tension qui n'est pas fixe aux bornes des résistances et cela va fausser les mesures et décaler les lectures. Je pense que l'erreur par défaut est d'environ 35 points sur les 1024 si tous les composants étaient parfaits. Si on utilise 4 boutons, l'écart théorique minimum de lecture entre boutons est de 1024/16 (le convertisseur à 1024 points et avec 4 boutons il y a 16 possibilités) soit de 64. Cela devrait passer. Pour 5 boutons l'écart entre lecture est de 1024/32 soit 32, cela ne peut théoriquement pas fonctionner sans correction (on en reparlera plus bas).

Avec 4 boutons

Je choisis arbitrairement une résistance R de 1kΩ, et si le bouton SW4 est seul appuyé, il y aura 1,1V/2 aux bornes de R qui sera donc parcouru par un courant voisin de 1mA. Il y aura au maximum 2mA si on appuie sur tous les boutons.

Le courant I est tel que l'on a VREF=1,1V (tension de référence du CAN) si R est traversé par 16I. I vaut donc VREF/16R. Les résistances R0 à R3 ont à leur bornes en moyenne VCC-VREF/2, on va se baser sur ce nombre.
R0 vaudra donc 16R(VCC-VREF/2)/VREF = 16.1000Ω.(5V-0,55V)/1,1V = 64000Ω = 64kΩ.
R1 laisse passer deux fois plus de courant, sa valeur est moitié soit 32kΩ
R2 laisse passer quatre fois plus de courant, sa valeur est 4 fois moins soit 16kΩ
R3 laisse passer huit fois plus de courant, sa valeur est 8 fois plus faible soit 8kΩ
R a été choisie à 1kΩ

Pour minimiser l'erreur et arriver à une erreur maximale des 35 points, il faut en fait choisir des résistances R0 à R3 légèrement plus petites, ou une résistance R légèrement plus grande. Le schéma est alors:

Sommateur de courants à lecture poly pour 4 boutons

Bien entendu, on peut multiplier ou diviser toutes les valeurs des résistances par le même nombre. Si on a des résistances en pagaille de 33kΩ venant du même lot, on peut l'utiliser pour R1, R0 sera faite avec deux de ces résistances en série, R2 avec deux résistances en parallèle et R3 avec 4 résistances en parallèle. Pour R il faut donc prendre une résistance théorique de 33x1057/32 soit1090Ω. En mettant une 1kΩ cela va donner une lecture un peu plus faible et le programme peut en tenir compte (au lieu de 1024, on mettra 939).

Le programme en dessous fonctionne. Éventuellement pour 4 boutons on pourrait économiser la correction.

Pour plus de sécurité, on peut corriger la lecture, comme on le fait pour 5 boutons

Avec 5 boutons

On a vu que l'écart de lecture dû à la variation de la tension sur les résistance était de 35 points environ. Si on veut pouvoir mettre 5 boutons, il faut absolument corriger la lecture pour diminuer cet écart.

Dans un premier temps, recalculons R pour que 32I fasse 1,1V. Cela correspond à une résistance "en haut" de 4kΩ. La tension de 1,1V vaut donc (pont diviseur avec R et 4kΩ) 1,1V=5V.R/(4kΩ+R) soit R=1,13kΩ. En utilisant la correction de Martin:

valeurLue = analogRead(A0);
valeurLue += 0.00024 * (valeurLue - 522.0)*(valeurLue - 522.0) - 64.1;

Cela ramène l'erreur de lecture à environ 2 points, et si tous les composants était parfaits, on pourrait même mettre 9 boutons. Avec 5 boutons cela passe, et cela devrait aussi passer pour 6 boutons avec des résistances correctes (pas les miennes!).

Pas de mystère pour le schéma:

Sommateur de courants à lecture poly pour 5 boutons

Si on prend une valeur plus faible pour R par exemple 1,1kΩ, au lieu d'aller de 0 à 1024, on n'ira que de 0 à 997 (1024*1.1/1.13) et cela peut facilement se corriger dans le soft, par exemple en faisant la correction:

valeurLue = analogRead(A0) * 1.13 / 1.1;
valeurLue += 0.00024 * (valeurLue - 522.0)*(valeurLue - 522.0) - 64.1;

A partir de ces valeurs, on peut toutes les multiplier ou les diviser par un même coefficient, cela ne change ni le programme ni le résultat.

Exemple de programme de lecture

// Sommateur de courant à lecture poly

//  VCC   VCC   VCC   VCC   VCC
//   │     │     │     │     │
// 128kΩ  64kΩ  32kΩ  16kΩ  8kΩ
//   │     │     │     │     │
//  SW0   SW1   SW2   SW3   SW4
//   │     │     │     │     │
//   ├─────┴─────┴─────┴─────┴─── vers A0
//   │
// 1,1kΩ
//   │
//  GND


const byte N = 5; // Nombre de boutons; A ajuster 
const byte BOUTONS = A0; // Broche de lecture; A ajuster

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, // Mot de 5 bits contenant les touches (SW4.SW3.SW2.SW1.SW0)
    oldTouche; // Mot précédent 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

  // Correction de la valeur
  valeurLue *= 1.13 / 1.1;
  valeurLue += 0.00024 * (valeurLue - 522.0)*(valeurLue - 522.0) - 64.1;

  //Extraction
  touche=((valeurLue+(512>>N)) >> (10-N)); // Cela donne un mot SW4.SW3.SW2.SW1.SW0
  
  // Affichage
  if (touche!=oldTouche) // Si changement
  {
    if (touche) // Il y a au moins une touche appuyée
    {
      // Affichage type "   SW4     SW3     SW2     SW1     SW0"
      for (int8_t bouton=N-1; bouton>=0; bouton--)
      {
        Serial.print("   SW");  
        Serial.print(bouton);  
        Serial.print("  ");  
      }
      Serial.println();
      // Affichage des boutons
      for (int8_t bouton=N-1; bouton>=0; bouton--) // Pour chaque bouton
        if (touche & (1<<bouton)) Serial.print(" appuyé ");
        else Serial.print("   --   "); // Non appuyé
      Serial.print("  écart=");
      Serial.print(valeurLue-touche*(1<<(10-N)));
      Serial.print("/");
      Serial.print(512/(1<<N));
      Serial.println(")\n"); // Retour chariot et saut d'une ligne en plus
      delay(100); // Anti-rebond
    }
    oldTouche=touche; // Mémorisation pour ne pas afficher plusieurs fois
    delay(1000); // Pas trop souvent
  }
}

Le programme affiche le ou les boutons appuyés et l'écart entre la valeur lue et corrigée et la valeur théorique attendue:

   SW4     SW3     SW2     SW1     SW0
   --      --      --      --    appuyé   écart=0/16)
   --      --      --    appuyé    --     écart=-7/16)
   --      --      --    appuyé  appuyé   écart=-4/16)
   --      --    appuyé    --      --     écart=-8/16)
   --      --    appuyé    --    appuyé   écart=-6/16)
   --      --    appuyé  appuyé    --     écart=-12/16)
   --      --    appuyé  appuyé  appuyé   écart=-9/16)
   --    appuyé    --      --      --     écart=-7/16)
   --    appuyé    --      --    appuyé   écart=-2/16)
   --    appuyé    --    appuyé    --     écart=-9/16)
   --    appuyé    --    appuyé  appuyé   écart=-5/16)
   --    appuyé  appuyé    --      --     écart=-8/16)
   --    appuyé  appuyé    --    appuyé   écart=-4/16)
   --    appuyé  appuyé  appuyé    --     écart=-10/16)
   --    appuyé  appuyé  appuyé  appuyé   écart=-7/16)
 appuyé    --      --      --      --     écart=-1/16)
 appuyé    --      --      --    appuyé   écart=2/16)
 appuyé    --      --    appuyé    --     écart=-5/16)
 appuyé    --      --    appuyé  appuyé   écart=-1/16)
 appuyé    --    appuyé    --      --     écart=-2/16)
 appuyé    --    appuyé    --    appuyé   écart=2/16)
 appuyé    --    appuyé  appuyé    --     écart=-5/16)
 appuyé    --    appuyé  appuyé  appuyé   écart=-1/16)
 appuyé  appuyé    --      --      --     écart=2/16)
 appuyé  appuyé    --      --    appuyé   écart=5/16)
 appuyé  appuyé    --    appuyé    --     écart=-3/16)
 appuyé  appuyé    --    appuyé  appuyé   écart=3/16)
 appuyé  appuyé  appuyé    --      --     écart=0/16)
 appuyé  appuyé  appuyé    --    appuyé   écart=3/16)
 appuyé  appuyé  appuyé  appuyé    --     écart=-4/16)
 appuyé  appuyé  appuyé  appuyé  appuyé   écart=-1/16)

Avec mes résistances un peu triées, les écarts vont jusqu'à 12/16, il est donc impossible avec ces composants d'avoir un bit de plus (6 boutons). Mais en utilisant des résistances métalliques à 1%, on devrait sans doute pouvoir utiliser 6 boutons.

Le programme ci-dessus est bon quelque soit le nombre de boutons (changer la valeur de N). Il ne fonctionne que si les erreurs ne sont pas trop importantes. Si avec des composants il fonctionne, on peut retirer un ou des boutons, cela fonctionnera aussi

Bilan

- lecture simple, mais avec correction indispensable pour plus de 4 boutons
- lecture poly
- les boutons ont une borne commune
- utilisation d'interruption possible
MAIS
- résistances non identiques ne compensant pas les erreurs
- une résistance par bouton en plus
- je ne connais pas de bibliothèques pour ce montage

Intéressant, mais peu utilisé. On peut peut être aller jusqu'à 6 boutons.