Codage boutons poussoirs

Bonjour à toutes et à tous,

Problème qui semble enfantin mais s'avère désespérant pour le débutant que je suis : x boutons poussoirs, autant de led, chaque bouton en mode interrupteur commande une led. Jusqu'ici, tout va bien. Lorsque j'appuie sur le bouton 1, la led 1 s'allume, lorsque j'appuie à nouveau, elle s'éteint, et il en va de même pour les autres.
Là où ça coince, c'est que je voudrais que chaque changement de bouton provoque non seulement l'allumage de la led correspondante, mais également qu'il éteigne la led précédemment allumée, c'est-à-dire qu'il agisse comme un commutateur. J'appuie sur le bouton 1, la led 1 s'allume, j'appuie sur le bouton 2, la led 2 s'allume ET la led 1 s'éteint, j'appuie sur le bouton 5, la led 5 s'allume ET la led 2 s'éteint.

Entre autres solutions (naïves, foireuses et vouées à l'échec), j'ai pensé affecter une valeur à la dernière led allumée, (PIN_newLed dans mon code), mais ça ne fonctionne pas, les led restent allumées et refusent obstinément de s'éteindre.

// déclaration des variables

int PIN_led1 = 10;
int PIN_led2 = 11;
int PIN_led3 = 12;
int PIN_bp1 = 2;
int PIN_bp2 = 3;
int PIN_bp3 = 4;
int PIN_newLed;

void setup() {
  pinMode(PIN_led1, OUTPUT);
  pinMode(PIN_led2, OUTPUT);
  pinMode(PIN_led3, OUTPUT);
  pinMode(PIN_bp1, INPUT_PULLUP);
  pinMode(PIN_bp2, INPUT_PULLUP);
  pinMode(PIN_bp3, INPUT_PULLUP);
}

void loop() {

  // on determine la position des boutons
  static uint8_t dernierBp1 = HIGH;
  static uint8_t dernierBp2 = HIGH;
  static uint8_t dernierBp3 = HIGH;
  uint8_t PIN_bp1 = digitalRead(2);
  uint8_t PIN_bp2 = digitalRead(3);
  uint8_t PIN_bp3 = digitalRead(4);

  // premier bouton
  if ((dernierBp1 != PIN_bp1) && (PIN_bp1 == LOW)) // detection d'un changement d'état du bouton
  {
    delay(20); // rebond
    digitalWrite(PIN_led1, !digitalRead(PIN_led1)); // on allume la led 1
    digitalWrite(PIN_newLed, !PIN_newLed); // on éteint la dernière led allumée
    PIN_led1 = PIN_newLed; // la led1 devient newLed
  }

  // deuxième bouton
  if ((dernierBp2 != PIN_bp2) && (PIN_bp2 == LOW)) //détection d'un changement d'état du bouton
  {
    delay(20); // rebond
    digitalWrite(PIN_led2, !digitalRead(PIN_led2)); // on allume la led 2
    digitalWrite(PIN_newLed, !digitalRead(PIN_newLed)); //  on éteint la dernière led allumée
    PIN_led2 = PIN_newLed; // la led 2 devient newLed
  }

  // troisième bouton
  if ((dernierBp3 != PIN_bp3) && (PIN_bp3 == LOW)) // détection d'un changement d'état du bouton
  {
    delay(20); // rebond
    digitalWrite(PIN_led3, !digitalRead(PIN_led3)); // on allume la led 3
    digitalWrite(PIN_newLed, !digitalRead(PIN_newLed)); // on éteint la dernière led allumée
    PIN_led3 = PIN_newLed; // la led 3 devient newLed
  }
}

Il y a évidemment une erreur de codage, peut-être une erreur de raisonnement (ce qui serait plus grave), peut-être la fonction if... else est mal choisie, peut-être...

Merci pour vos remarques et vos solutions.

Cordialement.

Oui, je confirme.

pinMode(PIN_bp1, INPUT_PULLUP);

uint8_t PIN_bp1 = digitalRead(2);

Dans le premier cas, PIN_bp1 est une variable globale et elle contient le numéro de la broche utilisée.
Dans le second cas, PIN_bp1est une variable locale à laquelle tu affectes l'état de la broche 2.

Je pense qu'il faudrait être un peu plus carré. Donner un même nom à 2 variables différentes est source d'embrouille.
PIN_bp1, de par son nom, je pense que c'est logique de l'utiliser pour y mémoriser la PIN à laquelle est affecté un bouton.
Dans le second cas, tu veux mémoriser l'état de la broche il serait donc plus logique de nommer cette variable ETAT_bp1. Ce qui donnerait

ETAT_bp1 = digitalRead(PIN_bp1);

Ensuite, il y a un problème de raisonnement.

  • Tu vérifies si dernierBp1 != PIN_bp1. Le problème c'est que tu ne changes jamais la valeur de dernierBp1.
  • Cette affectation est je pense à l'envers

PIN_led1 = PIN_newLed; // la led1 devient newLed

et devrait plutôt être

PIN_newLed = PIN_led1; // la led1 devient newLed

Si tu dois gérer un nombre plus important de boutons je pense qu'il serait plus propre de passer par un tableau contenant la liste des broches des boutons et un autre contenant la liste des broches des LEDs. Ce qui permettrait de balayer tous les boutons et de tester leur état en utilisant une boucle for plutôt que multiplier les lignes de code avec un if pour chaque bouton..

Bonjour pmvpmv

Le plus simple, pour éviter toute complication est de créer une routine pour tout éteindre avant d'allumer la LED concernée par le bouton pressé, c'est un peu "bourrin" mais très efficace.

	// premier bouton
	if ((dernierBp1 != PIN_bp1) && (PIN_bp1 == LOW)) // detection d'un changement d'état du bouton
	{
		delay(20); // rebond
		toutEteindre();
		digitalWrite(PIN_led1, !digitalRead(PIN_led1)); // on allume la led 1
		//digitalWrite(PIN_newLed, !PIN_newLed); // on éteint la dernière led allumée
		//PIN_led1 = PIN_newLed; // la led1 devient newLed
	}
void toutEteindre()
{
	digitalWrite(PIN_led1, digitalRead(PIN_led1));
	digitalWrite(PIN_led2, digitalRead(PIN_led2));
	digitalWrite(PIN_led3, digitalRead(PIN_led3));
}

Ce n'est pas testé "en vrai"!

Pour faciliter ce genre de programmation répétitive avec plusieurs boutons/LED, c'est très utile d'utiliser les tableaux.

Cordialement
jpbbricole

Bonsoir pmvpmv

J'ai revu, un peu, mon exemple.
Pour autant que tes LED s'allument avec un HIGH si non, inverser.

en fin de setup()

	toutEteindre();

ensuite

	if ((dernierBp1 != PIN_bp1) && (PIN_bp1 == LOW)) // detection d'un changement d'état du bouton
	{
		delay(20); // rebond
		toutEteindre();
		digitalWrite(PIN_led1, HIGH); //!digitalRead(PIN_led1)); // on allume la led 1
		//digitalWrite(PIN_newLed, !PIN_newLed); // on éteint la dernière led allumée
		//PIN_led1 = PIN_newLed; // la led1 devient newLed
	}

Et la fonction:

void toutEteindre()
{
	digitalWrite(PIN_led1, LOW);
	digitalWrite(PIN_led2, LOW);
	digitalWrite(PIN_led3, LOW);
}

Cordialement
jpbbricole

Merci pour vos réponses.

J'ai essayé la solution de fdufnews. Il suffit effectivement de remplacer [PIN_led1 = PIN_newLed;] par [PIN_newLed = PIN_led1;], et cela fonctionne parfaitement. Ceci posé, il me reste à comprendre en quoi a = b diffère de b = a...

J'ai également essayé la solution de jpbbricole, qui solutionne parfaitement le problème, d'une manière qui me paraît plus radicale, - très efficace, mais peut-être moins élégante. Je vais à présent me creuser les méninges sur les tableaux, c'est en codant qu'on devient coderon...

Encore merci.
Cordialement.

a = b affecte à a la valeur de b
b = a affecte à b la valeur de a

J'ai l'esprit déformé par trop d'années passées sur les bancs des écoles. En fait, si j'ai bien compris, il ne faut pas lire "a ÉGALE b", mais "a DEVIENT b". Pour illustrer par un exemple d'actualité, en cette période où l'on s'intéresse particulièrement aux transgenres, "Monsieur = Madame" donne une femme, alors que "Madame = Monsieur" donne un homme. Ce qui, effectivement, n'est pas la même chose.
J'ai bon ?
Cordialement.

tu as bon.
je me souviens d'un langage de programmation où on écrivait a <= b
pour bien illustrer le sens de transit de l'information.
Ceci compris tu ne devrais plus t'émouvoir d'expressions telles que :
a = a + 1

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.