[Résolu] Bouton poussoir qui incrémente un compteur

Bonjour

Problème mainte fois posé sur ce forum, mais je n'ai pas trouvé de réponse pour l'instant à ma question.
Donc j'incrémente un compteur avec un montage pull-up comme présenté par Eskimon avec interruption matérielle.

j'ai donc une valeur qui s'incrémente à chaque fois que j'appuie sur le bouton, lorsque je passe de High à Down.
Cependant, à chaque appui sur le bouton, mon compteur s'incrémente de +/- 12 valeurs.
Lorsque j'enlève le condo du circuit, l'incrémentation n'est que de 1, 2 ou 3.

mon condensateur est un 100 nF en céramique et non un 10nF comme indiqué sur le tuto.
Ceci peut-il expliquer cela ?

Voici le code que j'utilise :

const byte interruptPin = 2;  // bouton sur connecteur D2
volatile int state = 1;
int value;

void setup()
{
  pinMode(interruptPin, INPUT);  // configuration en entrée
  attachInterrupt(digitalPinToInterrupt(interruptPin), blink, FALLING);
  Serial.begin(9600); // open the serial port at 9600 bps:
}

void loop()
{
 Serial.print(state);
  Serial.println();
}

void blink(){
  state++;
}

Merci

Il doit y avoir des rebonds
Comment est câblé le bouton. En pull-up externe ?

Il ya t'il une résistance de Pullup externe? si oui de quelle valeur?

j'ai testé les deux méthodes.
La pull-up interne de la carte uno et une pull-up externe de 10 kOhm

comme je l'ai écrit, j'ai copié le tuto d'eskimon pour le montage, à la seule différence de la valeur du condo.
C'est un condo céramique, ça change quelque chose ?

a tester s'affiche uniquement a chaque appui

const byte interruptPin = 2;  // bouton sur connecteur D2
volatile int state = 1;
int value;

void setup()
{
  pinMode(interruptPin, INPUT_PULLUP);  // configuration en entrée
  attachInterrupt(digitalPinToInterrupt(interruptPin), blink, FALLING);
  Serial.begin(9600); // open the serial port at 9600 bps:
}

void loop()
{
}

void blink(){
  state++;
Serial.println(state);
}

Bonjour,

Si l'anti-rebond hard ne suffit pas tu peux essayer un anti rebond soft

const byte interruptPin = 2;  // bouton sur connecteur D2
volatile int state = 1;
int value;
const unsigned long debounceTempo = 20; // ms

void setup()
{
  pinMode(interruptPin, INPUT);  // configuration en entrée
  attachInterrupt(digitalPinToInterrupt(interruptPin), blink, CHANGE);
  Serial.begin(9600); // open the serial port at 9600 bps:
}

void loop()
{
  Serial.print(state);
  Serial.println();
}

void blink()
{
  static unsigned long millisLastChange = millis();
  if (millis() - millisLastChange < debounceTempo)
  {
    // c'est un rebond, on ne le traite pas
    millisLastChange = millis();
    return;
  }
  millisLastChange = millis();
  if (digitalRead(interruptPin) == LOW) // prend en compte uniquement le front descendant
    state++;
}

Cf ce post de @68tjsCondensateur pour anti rebond - #6 by 68tjs

Merci elektrax.
Avec ton code, l'incrémentation devient très régulière. +1 à l'appui, +2 quand je relâche.
C'est bien moins aléatoire et l'incrémentation bien moins forte qu'avant.

Merci Kamill
Avec ton code : l'incrémentation est de +1 à l'appui et +1 au relâchement,
J'ai changé la ligne suivante
attachInterrupt(digitalPinToInterrupt(interruptPin), blink, CHANGE);
pour :
attachInterrupt(digitalPinToInterrupt(interruptPin), blink, FALLING);
Mais ça ne change rien. toujours +2 au final.

j'ai changé le pin pour passer sur le 03, mais même soucis.

Merci J-M-L, bon pour l'info.

Hello pitoucol,

Les solutions que tu as mis en oeuvre sont logicielles.

Côté matériel, il faut ajouter un fitre passe-bas pour filtrer les rebonds.
Pour cela, il te faut un circuit RC en série avec ton entrée.
la résistance doit être placée entre le bouton et l'entrée, puis le condensateur entre l'entrée et la masse 0V.

R=10K C=100nF tu auras un bon filtrage.
Et dans ce cas plus besoin de filtrer dans le code.

Salut

Si je te suis bien, c'est bien ce que j'ai tenté initialement. Sans filtrage logiciel. Cette solution a été proposée par un membre et j'ai donc tenté par la suite, mais à la base, j'étais parti sur un filtre anti-rebond avec C=100 nF et R=10K.
Si j'ai bien fait mon montage, j'ai reproduis le tuto d'Eskimon sans filtrage logiciel, avec pull-up interne ou externe.

Ou alors j'ai pas pigé ton message Sly37

C'est très bizarre, normalement les rebonds au relâchement sont aussi supprimés. Tu peux essayer d'augmenter debounceTempo et mettre 50 voir carrément 100 ms

Il faut absolument CHANGE si on veut traiter aussi les rebonds au relâchement.

Avec FALLING c'est normal, à l'appui il y a détection donc +1 et au relâchement il y a un rebond qui est pris en compte, donc +1 aussi

ça veut dire que votre condensateur ne joue pas son rôle d'amortisseur.

expliquez nous votre montage de filtre et de pull-up externe plus précisément...

Le rebond au relachement ne devrait pas être pris en compte car à la remontée du signal le timeout est initialisé et les transitions rapprochées suivantes ne seront pas prises en compte (c'est pour ça qu'il faut CHANGE dans attachInterrupt)

Oui

un truc comme cela - sans matériel externe - devrait fonctionner (non testé)

const byte interruptPin = 2;  // bouton sur connecteur D2
volatile unsigned long compteur = 0;
const unsigned long debounceTempo = 50; // ms

void appuiBouton() {
  static volatile unsigned long chrono;
  if ((digitalRead(interruptPin) == LOW) && (millis() - chrono >= debounceTempo)) compteur++;
  chrono = millis();
}

void setup() {
  pinMode(interruptPin, INPUT_PULLUP);  // configuration en entrée
  attachInterrupt(digitalPinToInterrupt(interruptPin), appuiBouton, CHANGE);
  Serial.begin(115200);
}

void loop() {
  static unsigned long ancienCompteur = 0;
  // section critique
  noInterrupts();
  unsigned long copieCompteur = compteur;
  interrupts();

  if (copieCompteur != ancienCompteur) {
    Serial.println(copieCompteur);
    ancienCompteur = copieCompteur;
  }
}

le bouton est câblé comme cela; pin 2 --- bouton -- GND
le moniteur série est à 115200 bauds

Oui, j'ai vu par la suite en reprenant ton code qu'il fallait bien CHANGE.
Merci JML, en effet, ton schéma est clair.
Donc je devrais en conclure que mon condo ne fonctionne pas assez bien.

j'ai donc tout débranché, tout remonté (pour la xième fois). J'ai changé le condo, maintenant ça passe et avec le code de kamill, j'ai bien une seule incrémentation.
Donc je me suis dit que c'était le condo qui déconnait (nouille de pas y avoir pensé avant). J'ai donc repris l'ancien condo pour vérifier et ça passe aussi avec l'ancien condo. J'y pige plus grand chose.

j'ai testé avec le nouveau condo et sans filtrage logiciel, ça incrémente +1 en général, mais quelques fois ça incrémente +3

Je pourrais me contenter du filtrage logiciel, mais j'ai bien envie de comprendre pourquoi le filtre matériel ne passe pas.
Merci

faites un schéma clair de comment vous avez branché le matériel.

avez vous testé mon code?

Au mieux la pullup interne est une 50K. Avec 100nF cela donne une constante de temps de 5ms, ce qui peut être insuffisant pour certains boutons.

Je reste certain qu'avec un filtrage approprié ça fonctionne sans anti rebond soft.

Ce qu'il se passe : à la fermeture, ton condensateur se décharge instantanément dans ton bouton.
Il faut un résistance série pour filtrer à la charge et à la décharge.

C= 100nF, R1=10K R2=10K à 100K

Règle ton filtre avec R2.

Bon, j'ai fait pleins de tests différents.
J'ai fait le montage de sly37, avec une résistance de 10 K ou 120K, mais ça ne change rien. Le compteur s'incrémente quand même de +2 +3 au hasard.

Donc j'ai repris le montage initial (qui devrait marcher quand même). j'ai changé mon bouton pour un modèle totalement différent (genre bouton poussoir à deux broches pour grosse installation (pas le petit qu'on met sur les breadboards)) et c'est le même problème.

j'ai replacé mon premier bouton sur la breadboard, j'ai gardé le bouton appuyé et j'ai fait bouger mon doigt, le compteur incrémente. Donc ça serait plutôt un problème de bouton ?

J'ai refait le montage de sly37, j'ai à nouveau écrasé le bouton et fait joué mon doigt, le compteur ne bouge pas à ce moment là, mais il s'incrémente toujours aléatoirement.

Autre chose : sur un appui long (je laisse le doigt assez longtemps dessus genre une demi-seconde), le compteur fait +1 les 3/4 du temps. Si l'appui est très bref, je fais généralement +2 ou +3

Si vous y comprenez quelque chose... Désolé, mes faibles compétences en électronique sont dépassées.

  1. es tu certain des valeurs de résistances et condensateur que tu as câblé ?
    Code des couleurs ...

  2. Pour vérifier la partie soft, connecte une sortie de ton Arduino sur l'entrée en question.
    Fais la basculer toutes les secondes par exemple, et vois ce qu'il se passe sur ton entrée.
    Sans le bouton bien sûr :wink: