"Rebonds" dans une lecture analogique

Bonjour,

Je viens d'écrire une bibliothèque permettant de lire un ensemble de boutons avec une broche analogique et de lire un touchpad résistif d'écran. Je me suis pas mal intéresser par la lecture analogique car je cherchais une méthode pour lire notamment un keypad analogique sans avoir de lectures fantômes (je ne veux pas avoir des lectures d'appui de touches non pressées).

Le sujet Multi-boutons sur PinAnalogique initié par @theoy est arrivé trop tôt pour moi, je n'avais pas fait tous mes essais.

@jpbbricole a notamment donner un lien sur la bibliothèque ezAnalogKeypad que j'ai testée.

Voici le programme que j'ai utilisé:

/*
   Created by ArduinoGetStarted.com

   This example code is in the public domain

   Tutorial page: https://arduinogetstarted.com/library/arduino-analog-keypad-example

   This example reads the pressed key from analog keypad and prints it to Serial Monitor.
*/

#include "ezAnalogKeypad.h"

ezAnalogKeypad keypad(A5);  // create ezAnalogKeypad object that attach to pin A0

void setup() {
  Serial.begin(115200);

  // MUST READ: You MUST run the calibration example, press key one-by-one to get the analog values
  // The below values is just an example, your keypad's value may be different
  keypad.setNoPressValue(1024);  // analog value when no key is pressed
  keypad.registerKey('1', 0); // analog value when the key '1' is pressed
  keypad.registerKey('2', 11); // analog value when the key '2' is pressed
  keypad.registerKey('3', 24); // analog value when the key '3' is pressed
  keypad.registerKey('4', 37); // analog value when the key '4' is pressed
  keypad.registerKey('5', 49); // analog value when the key '*' is pressed
  keypad.registerKey('6', 62); // analog value when the key '0' is pressed
  keypad.registerKey('7', 74); // analog value when the key '#' is pressed
  keypad.registerKey('8', 85); // analog value when the key '#' is pressed
  keypad.registerKey('9', 97); // analog value when the key '#' is pressed
  keypad.registerKey('A', 108); // analog value when the key '#' is pressed
  // ADD MORE IF YOUR KEYPAD HAS MORE
  //keypad.setDebounceTime(2000);
}

char key;
void loop() {
  //key = analogRead(A0);
  key = keypad.getKey();
  if (key)
  {
    Serial.print(key);
  }
}

Quand j'appuie plusieurs fois uniquement sur le bouton 1, j'ai l'affichage:

11811A11311112131A121111A111511211113116121121121211

Les touches fantômes apparaissent quasiment tout le temps au relâchement, un appui sur la touche 1 met l'entrée A5 à 0V et au relâchement la tension remonte lentement à cause de la résistance de rappel au 5V de 15kΩ.

C'est génial pour faire une serrure codée!!!

C'est un peu comme les rebonds en digital, mais ici c'est plutôt que si on fait une lecture n'importe quand, on peut être dans une zone non encore stabilisée:


Il ne faut pas faire comme en digital, garder une lecture et si elle à changée, on attend bounce avant de lire la suivante, la solution que j'utilise est d'attendre que la valeur se stabilise avant d'en faire la lecture. Avec ce principe ma bibliothèque MTobjets me permet de faire une serrure codée analogique sans que j'ai eu jusqu'à présent une fausse touche en plus au milieu de mon code.

Pour plus information sur mes recherches sur les "rebonds" analogique c'est ici.

Ce message ne pose pas de questions, mais est présent pour donner des pistes pour des lectures analogique. Et pour ne plus voir de bounce dans les programmes avec cette lecture analogique. La méthode qui consiste à lire une moyenne de plusieurs lecture, ou une médiane... ne fonctionne pas. Celle que j'utilise en attendant d'en avoir une meilleure est la double lecture:

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

Je n'ai pas d'experience particulière sur ce domaine, donc une interrogation de ma part ➜ on constate souvent avoir un léger mouvement sur le bit de poids faible par l'ADC (stabilité de l'alim) et on risque d'être coincé dans le do-while pendant longtemps si c'est le cas.

est-ce qu'une approche comme

do
{
  oldValeurLue = valeurLue;
  valeurLue = analogRead(A5);
} while ((valeurLue & ~1) != (oldValeurLue & ~1)); // ou >> 1

ne serait pas plus sure - on ignore le bit de poids faible ?

Le plus bruité que j'ai eu c'est la lecture du touchpad d'un écran, surtout qu'il faut lire deux fois pour avoir les coordonnée, et qu'une instabilité de la lecture traduit une trace du stylet en un nuage de points. J'utilise cette méthode mais par sécurité, j'abandonne au bout de 15 valeurs lues. J'ai affiché le nombre de boucles et la plus part du temps il n'y a que deux lectures. C'est extrêmement rare de dépasser les 5 lectures.

On ne peut pas ignorer les bits de poids faibles car on pourrait avoir deux nombres entre
0b00001111 et 0b00010000.

MTobjets ne faisant qu'une lecture toutes les 16ms, je teste
while (abs(valeurLue - oldValeurLue) < erreur);
Avec erreur = 3 Je ne constate pas de retard entre l'appui et la prise en compte de la touche.
L'intérêt aussi de cette méthode est que si je veux cliquer sur des boutons d'un écran (touchpad) et ignorer les déplacements, je prends erreur = 1000. Je n'ai alors que appuyé ou pas (bien entendu lors du premier appui, j'ai les coordonnés du point).

Pour éviter le bruit et la dispersion au maximum dans un programme d'apprentissage qui doit voir les différentes valeurs pour les différents boutons, j'utilise une triple lecture identique:

   do // Tant que l'on ne lit pas une bonne valeur du CAN
    {
      oldOldValeurLue = oldValeurLue; // Sauvegarde des mesures précédentes du CAN
      oldValeurLue = valeurLue;
      valeurLue = analogRead(PIN); // Nouvelle lecture
    } while ((valeurLue!=oldValeurLue) || (valeurLue!=oldOldValeurLue)); // On recommence jusqu'à avoir trois lectures identiques

Et en appuyant sur tous les boutons environ 1/2 seconde, je n'ai jamais constaté que j'en ai oublié un seul.

OK oui c'est sûr que ça revient à diviser par 2...