Problème récupération état interrupteurs multiples Arduino Uno

Bonjour à tous.

Je rencontre un nouveau problème dans mon projet.
J'ai besoin de connecter 4 interrupteurs ON/OFF à mon arduino UNO et de récupérer leur état.
Suite à mes tests avec un interrupteur, aucun problème pour récupérer l'état LOW et HIGH.

Par contre, je rencontre malheureusement un soucis lorsque j'en branche plusieurs.
Quel que soit le bouton sur lequel j'appuie, tous les IO ont l'air de recevoir le changement de signal, car mon output est toujours "Interrupteur 1 appuyé" ou "Interrupteur 1 relâché".

J'utilise le mode "INPUT_PULLUP" afin d'utiliser les résistances internes et ne pas avoir à en ajouter en externe.

Le câblage appliqué à tous mes boutons sont basés sur ce schéma :

J'utilise respectivement les broches I/O D2, D3, D4 et D5 pour mes interrupteurs.

J'ai vu que la longueur des câbles pouvait être un problème, mais pour ma part, ils font 15cm grand maximum.

J'ai aussi lu que la librairie bounce2.h demandait d'instancier un objet "bounce" par interrupteur afin d'éviter les problèmes, donc j'ai écris mon code en ce sens :

#include <Bounce2.h>
#include <Adafruit_PWMServoDriver.h>

//Déclarations pour les interrupteurs
const byte buttonPins[] = {2,3,4,5};
Bounce interrupteurs[sizeof(buttonPins)];

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

  int cpt = 0;
  for (byte i = 0; i < sizeof(buttonPins); i++) {
    pinMode(buttonPins[i], INPUT_PULLUP);  // Configure la broche avec la résistance de tirage
    interrupteurs[cpt].attach(buttonPins[i]);  // Attache l'objet 'inter' à la même broche
    interrupteurs[cpt].interval(5); // temps de latence entre deux mesures d'état
    cpt = cpt + 1;
  }

}

// Variable qui va contenir l'état courant du bouton
// On commence avec -1 qui est un état inconnu...
int courant[] = {-1,-1,-1,-1};

void loop() 
{
    for (int i = 0; i < sizeof(buttonPins); i++) {

        // Mise à jour de l'état de inter : bouton pressé ou non ?
        interrupteurs[i].update();

        // Récupération de l'état du bouton
        int valeur = interrupteurs[i].read();

        // Si la valeur n'a pas changé depuis la dernière fois, ne rien faire.
        if (valeur == courant[i])
            return;

        // Agir en fonction de l'état du bouton
        if ( valeur == HIGH ) {
            Serial.print("Interrupteur ");
            Serial.print(i + 1);
            Serial.println(" relaché");
        }
        else {
            Serial.print("Interrupteur ");
            Serial.print(i + 1);
            Serial.println(" appuyé");
        }

        courant[i] = valeur;
    }


}


Pour autre test, avec un code ou j'instancie uniquement un interrupteur avec un objet bounce sur un I/O (D2 par exemple) tout en laissant mes autres interrupteurs câblés sur les I/O D3, D4 et D5, même si j'appuie sur un bouton se trouvant sur un I/O non instancié (D3, D4 ou D5), et bien ma fonction "broche_d2.read()" détecte un changement d'état...

Sauriez-vous ce que j'ai pu mal comprendre dans tout cela, car je sèche avec mon faible niveau en électronique encore un fois :frowning:

Merci par avance pour vos retours :slight_smile:

Veuillez utiliser la langue anglaise dans les sections anglaises du forum. Votre sujet a été déplacé vers la section française du forum.

Bonjour,

Moi je creuserai de ce côté

return

Est-ce que le "return" ne mettrait pas fin à votre boucle dés

interrupteurs[0]

est "stable" et du coup ne testerait pas les autres?

Ce n'est pas return qu'il faut utiliser car cela fait sortir de loop().
Il faut utiliser continue

Bonjour,

Merci pour vos retours.

Effectivement, vous avez raison. Etant donné que j'ai adapté mon code pour les 4 interrupteurs, j'ai convertis mes valeurs en tableau et j'ai omis ce détail qui mettait fin à la boucle au lieu de passer à l'itération suivante. Mais ce n'est malheureusement pas le soucis. J'ai le même problème après correction, et dans tous les cas, le code unitaire suivant que j'avais testé (en laissant connecté les 4 boutons mais en initialisant uniquement que l'I/O D2 dans mon code), et bien il me ressort un output même lors de l'appui sur un autre bouton (D3, D4 ou D5). Voici mon code :

#include <Bounce2.h>

#define INTER 2

// Créer (instancier) un objet Bounce
Bounce inter; 

void setup() 
{
  Serial.begin(9600);
  // Configure la broche avec la résistance de tirage
  pinMode(INTER, INPUT_PULLUP);
  pinMode(3, INPUT_PULLUP);
  pinMode(4, INPUT_PULLUP);
  pinMode(5, INPUT_PULLUP);
  // Attache l'objet 'inter' à la même broche
  inter.attach(INTER);
  inter.interval(5); // temps de latence entre deux mesures d'état
}

// Variable qui va contenir l'état courant du bouton
// On commence avec -1 qui est un état inconnu...
int courant = -1;

void loop() 
{
  // Mise à jour de l'état de inter : bouton pressé ou non ?
  inter.update();

  // Récupération de l'état du bouton
  int valeur = inter.read();
  //Serial.println(valeur);
  // Si la valeur n'a pas changé depuis la dernière fois, ne rien faire.
  if (valeur == courant)
    return;

  // Agir en fonction de l'état du bouton
  if ( valeur == LOW)
    Serial.println("Bouton relaché");
  else
    Serial.println("Bouton appuyé");

  courant = valeur;
  delay(50);
}

Et je fais tout de même un "pinMode()" sur les 4 I/O car j'ai lu que cela pouvait générer des valeurs "flottantes" avec bounce2.h si les 4 interrupteurs étaient branchés sans être initialisés (j'ai testé avec, et sans bien entendu).

Merci par avance pour vos retours :slight_smile:

Re

Cela n'a oeut-être aucun rapport, mais quels sont ces inter à 4 broches avec un VCC?

Que se passe t'il sans le VCC?

Il sagit d'interrupteurs lumineux, le vcc sert à l'allumage de la led de l'interrupteur :

https://a.aliexpress.com/_Ezz27sc

On peut voir le câblage dans le détail du produit. Je ne pense pas qu'il y ait de lien à titre personnel. Tu penses que cela peut poser problème ?

Pour autre information, j'utilise un GRND commun et un +5v commun pour tous les interrupteurs.

En principe ça ne devrait pas gêner!

Si j'ai bien compris, tes voyants sont allumés en permanence et s'alimentent indifférement (sans résistance) de 3 à 220V AC?

Tout à fait, comme tu peux le voir :

Bonjour,
il existe 2 modeles 3-6V et 110-220V

Bonjour,

oui, c'est exact, j'ai pris ceux-ci pour ma part :
Green Ring, 12mm, 3-6V, Latching

J'ai des BP, je vais tester le code par curiosité, et je vous "dis quoi", comme on dit par ici...

Bonjour nono44413

Normalement, lors de l'usage d'une bibliothèque comme Bounce2 pour gérer des boutons, on ne "s'occupe pas" des pin concernées, c'est la bibliothèque qui les initialise.
C'est indiqué dans l'un des exemples:

  // SELECT ONE OF THE FOLLOWING :
  // 1) IF YOUR INPUT HAS AN INTERNAL PULL-UP
  bounce.attach( BOUNCE_PIN ,  INPUT_PULLUP ); // USE INTERNAL PULL-UP
  // 2) IF YOUR INPUT USES AN EXTERNAL PULL-UP
  //bounce.attach( BOUNCE_PIN, INPUT ); // USE EXTERNAL PULL-UP

En résumé, tu dois désactiver celle ligne:
//pinMode(INTER, INPUT_PULLUP);
et initialiser inter ainsi:
inter.attach(INTER, INPUT_PULLUP);

Comme on est en mode PULLUP, donc la valeur du bouton pressé est LOW, il faut inverser ton affichage:

	if ( valeur == LOW)
	Serial.println("Bouton appuyé");
	else
	Serial.println("Bouton relaché");

PS: Si tu veux une façon plus "évoluée" de traiter tes boutons avec cette bibliothèque, regardes cet exemple qui te montre l'événement pressed().

Cordialement
jpbbricole

Hello,

J'ai testé ta version 1, avec la modif proposée par @fdufnews ça ne marche pas.
Et j'ai testé cela sans pullup INTERNE, mais avec un PULLUP externe de 5k, et ça marche

#include <Bounce2.h>
//#include <Adafruit_PWMServoDriver.h>

//Déclarations pour les interrupteurs
const byte buttonPins[] = {2,3,4,5};
Bounce interrupteurs[sizeof(buttonPins)];

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

  int cpt = 0;
  for (byte i = 0; i < sizeof(buttonPins); i++) {
    pinMode(buttonPins[i], INPUT);  // Configure la broche sans la résistance de tirage
    interrupteurs[cpt].attach(buttonPins[i]);  // Attache l'objet 'inter' à la même broche
    interrupteurs[cpt].interval(5); // temps de latence entre deux mesures d'état
    cpt = cpt + 1;
  }

}

// Variable qui va contenir l'état courant du bouton
// On commence avec -1 qui est un état inconnu...
int courant[] = {-1,-1,-1,-1};

void loop() 
{
    for (int i = 0; i < sizeof(buttonPins); i++) {

        // Mise à jour de l'état de inter : bouton pressé ou non ?
        interrupteurs[i].update();

        // Récupération de l'état du bouton
        int valeur = interrupteurs[i].read();

        // Si la valeur n'a pas changé depuis la dernière fois, ne rien faire.
        if (valeur == courant[i])
          continue;
        

        // Agir en fonction de l'état du bouton
        if ( valeur == HIGH ) {
            Serial.print("Interrupteur ");
            Serial.print(i + 1);
            Serial.println(" relaché");
        }
        else {
            Serial.print("Interrupteur ");
            Serial.print(i + 1);
            Serial.println(" appuyé");
        }

        courant[i] = valeur;
    }


}

Ca aussi ça marche avec un PULLUP externe mais pas avec un INPUT_PULLUP

for (byte i = 0; i < sizeof(buttonPins); i++) {
    //pinMode(buttonPins[i], INPUT_PULLUP);
    //pinMode(buttonPins[i], INPUT);  // Configure la broche sans la résistance de tirage
    interrupteurs[cpt].attach(buttonPins[i],INPUT);  // Attache l'objet 'inter' à la même broche
    //interrupteurs[cpt].attach(buttonPins[i]);
    interrupteurs[cpt].interval(5); // temps de latence entre deux mesures d'état
    cpt = cpt + 1;
  }

Par contre, ça ce n'est pas utile,

c'était juste comme @nono44413 l'a écrit.

Merci pour vos retours, et merci pour ton test @jef59 !

Qu'entends tu lorsque tu dis "ca ne fonctionne pas en mode INPUT_PULLUP" ?

Tu veux dire que tu as le meme comportement que moi lors de tes tests et qu'il faut que je passe avec une resistance externe de 5k ?

Merci encore !

Dans les exemples de la librairie Bounce2, il y a celui-ci bounceMore.ino qui fait voir comment initialiser plusieurs boutons et comment les gérer par la suite.

En fait, j'ai fais un dernier test, c'est trés particulier.

A/ Si tu déclare tes entrées en INPUT, et que tu ne mets pas des PULLUP EXTERNES, effectivement,
-BP non appuyé, tu mesure un potentiel +/- flottant.
-BP appuyé, tu mesures 0V
CA NE MARCHE PAS ET C'EST NORMAL

B/ Si tu déclare tes entrées en INPUT, et que tu mets des PULLUP EXTERNES, effectivement,
-BP non appuyé, tu mesure un potentiel +5V.
-BP appuyé, tu mesures 0V
CA MARCHE ET C'EST NORMAL

C/ Si tu déclare tes entrées en INPUT_PULLUP, et que tu ne mets pas des PULLUP EXTERNES
effectivement,
-BP non appuyé, tu mesure un potentiel +5V.
-BP appuyé, tu mesures 0V
CA NE MARCHE PAS ET CE N'EST PAS NORMAL voir E

D/ Si tu déclare tes entrées en INPUT_PULLUP, et que tu mets des PULLUP EXTERNES,
effectivement,
-BP non appuyé, tu mesure un potentiel +5V.
-BP appuyé, tu mesures 0V
CA MARCHE voir E

E/ Si j'approfondis mes mesures, si je déclare tes entrées en INPUT_PULLUP, quand j'appuie sur un BP, mon 5V s'écroule à 1.42V, sauf si en + du PULLUP INTERNE j'ajoute un PULLUP externe.

Trés bizare ce truc, bref
il vaut mieux alors déclarer les entrées en INPUT et mettre un PULLUP EXTERNE, au moins c'est clair.

PS quand j'écris "CA NE MARCHE PAS" je veut dire que le sketch ne marche pas et affiche des résultats éronnés

Hello,

Ce que j'ai constaté se passe aussi avec l'exemple que tu site avec bounceMore.ino

N'hésitez pas à me demander plus de précisions.

Pour initialiser les boutons avec Debounce2:
inter.attach(INTER, INPUT_PULLUP); // Pour PULLUP interne
et
inter.attach(INTER, INPUT); // Pour PULLUP externe

Il a écrit:

  // Agir en fonction de l'état du bouton
  if ( valeur == LOW)
    Serial.println("Bouton relaché");
  else
    Serial.println("Bouton appuyé");

Si c'est des boutons poussoir NO, en mode PULLUP, c'est bien l'inverse, c'est d'ailleurs ce que tu fais dans ton programme:

        // Agir en fonction de l'état du bouton
        if ( valeur == HIGH ) {
            Serial.print("Interrupteur ");
            Serial.print(i + 1);
            Serial.println(" relaché");
        }
        else {
            Serial.print("Interrupteur ");
            Serial.print(i + 1);
            Serial.println(" appuyé");
        }