Aide code pour énigme (trop de if imbriqués)

Bonjour à tous !

Jusqu'à présent, j'ai toujours réussi à coder mes énigmes avec la théorie, mais là je sèche ! Je suis sûr que c'est facile en plus ...

Je vous explique le principe !!!

Il y a 16 vis enfoncée au max. Celles-ci appuient sur des boutons. Quand quelqu'un dévisse une vis, le bouton est donc relâché.

Par défaut, j'ai donc 16 bouton en HIGH.

C'est 16 boutons contrôle 16 relais. Quand les boutons sont en HIGH, les relais sont en LOW. Quand les vis bougent, les boutons passent en LOW et les relais en HIGH.

Jusqu'ici c'est simple, mais là où ça se complique, c'est que certains boutons contrôlent le même relais !

Du coup imaginons, le bouton 1 et 2, contrôlent tous les 2 le relais 6, au pif ...

A l'état initial, le relais 6 est LOW. Je dévisse la vis 1, le relais passe en HIGH. Je revisse la vis, il repasse en LOW.

Idem pour la vis 2.

PAR CONTRE, si je dévisse la vis 1, le relais passe en HIGH et si ensuite je dévisse la vis 2, le relais passe en LOW !!!

Et c'est là que je galèèèère !

Je ne peux évidemment pas enchaîner les :

if (etatBouton1 == HIGH) {
digitalWrite(relayPin6,LOW);
}
else
{
digitalWrite(relayPin6,HIGH);
}

if (etatBouton2 == HIGH) {
digitalWrite(relayPin6,LOW);
}
else
{
digitalWrite(relayPin6,HIGH);
}

Je peux enchaîner les if en comparant les boutons qui contrôlent le même relais :

if (etatBouton1 == HIGH) 
{
   if (etatBouton2 == LOW)
   {
   digitalWrite(relayPin1,HIGH);
   }
   else
   {
   digitalWrite(relayPin1,LOW);
   }
}
else
{
   if (etatBouton2 == LOW)
   {
   digitalWrite(relayPin1,LOW);
   }
   else
   {
   digitalWrite(relayPin1,HIGH);
   }
}

Sauf que j'ai certains relais sont contrôlés par 5 boutons !!! Et j'ai pas trop envie d'enchaîner un if dans un if dans un if ...

Je me dis qu'il y a surement un truc plus simple auquel je ne pense pas.

En espérant que ce soit le cas =p

Merci !

il ne faut surtout pas imbriqué les if, autrement c'est bazar

pourquoi ne pas utiliser des if / else if / else if / else

if( etatbouton1 == low && etatbouton2 == low){

// faire quelque chose
}

else if ( etatbouton1 == low  && etatbouton2 == high){
// faire quelque chose
}

else if ( etatbouton1 == high  && etatbouton2 == low){
// faire quelque chose
}
else ( etatbouton1 == high  && etatbouton2 == high)
// faire quelque chose
}

Cela en fonction des priorité...

c'est peut etre lourd, mais plus élégant, c'est sur que si tu as 5 bouton poussoir qui gere un relai ça te fait 32 possibilité.

if ( etatbouton1 == low  && etatbouton2 == high  && etatbouton3 == low  && etatbouton4 == high  && etatboutonN == high){
//faire quelque chose
}

Bonjour

Chaque bouton, qui a deux états possibles, peut être associé à un bit.
Ainsi, la configuration de l'ensemble des boutons peut être codifiée sur un seul entier non signé (=16 bits).

Derrière, la condition d'activation de chaque relais peut aussi être codifée sur 16 bits.
Par exemple, le relais2 conditionné par les boutons 1, 3, 5, 7 9 aura une condition égale à 0b0000001010101010

Un bête xor entre la conf des boutons et la condition du relais, et le tour est joué.

désolé peut-être un peu rapide mais pas le temps de faire mieux :smiley:

bricoleau:
Bonjour

Chaque bouton, qui a deux états possibles, peut être associé à un bit.
Ainsi, la configuration de l'ensemble des boutons peut être codifiée sur un seul entier non signé (=16 bits).

Derrière, la condition d'activation de chaque relais peut aussi être codifée sur 16 bits.
Par exemple, le relais2 conditionné par les boutons 1, 3, 5, 7 9 aura une condition égale à 0b0000001010101010

Un bête xor entre la conf des boutons et la condition du relais, et le tour est joué.

désolé peut-être un peu rapide mais pas le temps de faire mieux :smiley:

Bonsoir

Waouh..........!

Serge .D

Merci hazerty ! C'est déjà mieux, mais je pense qu'on peut encore améliorer le truc =p

Et merci bricoleau, mais je ne comprends pas trop ! Je veux bien un petit exemple quand tu auras le temps merci !

Bonsoir la solution de bricoleau est celle qui convient le mieux sauf si tu veux t ' ennn ( quiquiner ? )

Le probleme c ' est quelle demande des connaissances a profondies globales en C .

Pour faire dans le simple , il y a aussi la possibilité du switch case , mais ca ressemble fortement a un if , else if , else if , else if etc else .

A savoir qu dans un if , tu peux combiné plusieurs condition du style en pseudo code :

if ( bouton1 ou bouton 3 ou bouton 9 relaché ) // le ou c ' est || ( touche alt GR + 6) .
{
alors j ' eclaire ma LED
}

tu peux aussi faire un melange de " ou " et de " et "
if ( bouton7 relaché et bouton 29 enfoncé {
alors je fais ...
}

bref la seule limite est l ' imagination pour peu que l ' on sache manier les conditions , et on n ' est pas limité a une condition dans un if ...

D ' apres la doc ici meme : Arduino - Home

Comparison Operators

== (equal to)
!= (not equal to)
< (less than)

(greater than)
<= (less than or equal to)
= (greater than or equal to)

Boolean Operators

&& (and)
|| (or)
! (not)

Bitwise Operators

& (bitwise and)
| (bitwise or)
^ (bitwise xor) // ce dont parlait bricoleau afin de comparer les bits et agir en consequence le tout avec 3 lignes de codes .
~ (bitwise not)
<< (bitshift left)

(bitshift right)

Merci beaucoup Iznobe, mais les if, les comparateurs etc ... pas de soucis ça je connais plutôt pas mal !

Mais comme le disais Hazerty565, j'ai 4 boutons qui contrôlent le même relais, donc si je dois à chaque fois les comparer avec la technique "classique", ça va être très chiant à coder. Ça fait donc 16 possibilités pour ce boutons. Et en plus, je n'ai pas qu'un seul relais contrôlé par plusieurs boutons. Mais beaucoup plus !!!

Je cherchais donc une méthode plus simple et celle de bricoleau semble bien, mais pour l'instant, j'ai du mal à piger !!!

grosso modo tu peux essayer de voir ca comme 2 tableaux
un globalisant les conditions l ' autre sous forme d ' etats de tes relais boutons ou LED .

si tu lis tout tres bien , il detaille exactement tout ce qu il faut faire pas a pas .

Je pensais à un truc du style

const int pin_boutons[16] =  ... ; // à renseigner;
const int pin_relais[16]  =  ... ; // à renseigner;

//conditions d'activation de chacun des 16 relais
//mettre 1 dans la colonne correspondant au(x) bouton(s) désiré(s)
//il peut y avoir plusieurs 1 par ligne...
const unsigned int conditions[16] = {
  0b1000000000000000, //condition relais  0
  0b0100000000000000, //condition relais  1 
  0b0010000000000000, //condition relais  2
  0b0001000000000000, //condition relais  3
  0b0000100000000000, //condition relais  4
  0b0000010000000000, //condition relais  5
  0b0000001000000000, //condition relais  6
  0b0000000100000000, //condition relais  7
  0b0000000010000000, //condition relais  8
  0b0000000001000000, //condition relais  9
  0b0000000000100000, //condition relais 10
  0b0000000000010000, //condition relais 11
  0b0000000000001000, //condition relais 12
  0b0000000000000100, //condition relais 13
  0b0000000000000010, //condition relais 14
  0b0000000000000001  //condition relais 15
};

...

void loop() {
  //lecture de la configuration des boutons
  unsigned int conf = 0;
  for (int i=0; i<16; i++) {
    conf = (conf << 1) | (digitalRead(pin_boutons[i]) == LOW ? 0 : 1);
  }

  //activation des relais
  for (int i=0; i<16; i++) {
    //si tous les 1 de la condition se retrouvent aussi dans la conf, alors activer le relais
    digitalWrite(pin_relais[i], (conf & conditions[i]) == conditions[i] ? HIGH : LOW);
  }
}

euh.... y a pas un seul if

ça ira quand même ?

:smiling_imp:

:grinning:

Mince alors, le code n'est pas gros et l'exécution pas bien lente .... :slight_smile:

Serge .D

Merci beaucoup, mais je pense que ça n'ira pas, je m'explique !

Imaginons mon relais 1 est contrôlé par le bouton 1 et 5, j'ai donc un bitwise = 0B1000100000000000

Dans ton for, je détecte bien ce bitwise est mon relais est donc en LOW (ou en HIGH peu importe, c'est le changement qui compte).

Si je dévisse le 1, mon bouton passe en LOW et mon bitwise = 0B0000010000000000.

Dans le for, je ne détecte plus ce bitwise, le relais passe en HIGH.

Jusqu'ici tout est ok.

Sauf que si je dévisse mon 5, mon relais est sensé repasser en LOW et là, le bitwise étant 0B0000000000000000, je ne le détecterai pas mon for.

En fait si, ce type de solution peut être adapté à toutes les logiques, car justement on utilise des opérateurs logiques binaires.
A toi d'adapter le code pour coller à ton besoin

Par exemples :

Je veux activer mon relais si tous les boutons qui le commandent sont activés, peu importe l'état des autres boutonsif (condition & conf == condition)

Je veux activer mon relais si tous les boutons qui le commandent sont activés, et que tous les autres boutons sont désactivésif (condition == conf)

Je veux activer mon relais si au moins un bouton qui le commande est activéif (condition & conf != 0)

Je veux activer mon relais si certains boutons sont activés, et certains autres désactivés : dans ce cas il faut définir un masque supplémentaire des boutons à prendre en compte

unsigned int cond = 0b0000110000000000;
unsigned int mask = 0b0011111100000000;
...
  if (cond == conf & mask)

etc.

tu as tous les opérateurs binaires à ta disposition : & | ^ ~ << >>

falsuss:
Sauf que si je dévisse mon 5, mon relais est sensé repasser en LOW et là, le bitwise étant 0B0000000000000000, je ne le détecterai pas mon for.

Ben si. Le digitalWrite(pin_relais[i], (conf & conditions[i]) == conditions[i] ? HIGH : LOW); devient alors digitalWrite(pin_relais[i], LOW);
Faut juste comprendre le fonctionnement de l'opérateur ternaire

hello
tu n'es pas clair. deux messages qui disent le contraire l'un de l'autre
en #1

PAR CONTRE, si je dévisse la vis 1, le relais passe en HIGH et si ensuite je dévisse la vis 2, le relais passe en LOW !!!

Et c'est là que je galèèèère !

en #12

Si je dévisse le 1, mon bouton passe en LOW et mon bitwise = 0B0000010000000000.

Dans le for, je ne détecte plus ce bitwise, le relais passe en HIGH.

Jusqu'ici tout est ok.

Sauf que si je dévisse mon 5, mon relais est sensé repasser en LOW et là, le bitwise étant 0B0000000000000000, je ne le détecterai pas mon for.

il est sensé passer en LOW, ce n'est pas ce qu'il faisait dans le #1 ?

Bonjour, sisi :

en LOW (ou en HIGH peu importe, c'est le changement qui compte).

C'est juste que je n'ai pas encore choisi si mon état initial sera un HIGH ou un LOW.

Mais ça ne change donc rien au fait que je veux changer cet état, donc des H à L ou L à H, mais ça ne change rien à la réflexion en elle même.

RE bonjour , ben justement avec les operateurs ternaires et les explications de bricoleau tu devrais arriver a gerer tous les cas sans problemes majeurs .

Je pense que tu devrais approfondir sur les operateurs ternaires .

Personnellement je ne vois pas ce qui te bloque dans ton explication et j ' ai bien compris que low ou high n ' a pas vraiment d' importance .

Tu devrais peut etre expliquer plus clairement avec des exemples et des mots .

Parfois ecrire tout simplement ce que l' on cherche a faire aide grandement a eclaircir les differentes etapes que l ' on doit coder .

Si j ' ai bien suivi tu as 16 relais ?

enfin peu importe , mais admettons , du coup tu dois coder 16 changements d' etat avec la solution de bricoleau .
donc 16 conditions et 32 etats ( 16 0 ou 16 1 ) .

que la condition soit representé par oui ou non ou 0000000000000000 ou 1111111111111111 et tous les intemediaires importe peu et ce qui permet de faire ca ce sont les operateurs ternaires combiné a ce systeme .

Sinon il reste la possibilité de faire du if else if else c ' est peut etre un peu plus long mais bon au moins ca marchera .

si bouton 1 ou sinon si bouton 5 ou sinon si bouton 12 activés , alors je chnge mon relais d' etat .

ca a ecrire 16 fois , je ne vois pas trop la ou c ' est tres compliqué meme si il faut gerer 16 boutons ( ou vis ) .

il suffit de placer les bonnes conditions .

Merci Iznobe,

oui c'est ok, je commence à comprendre et je vois à peu près comment m'en sortir.

Mais je suis sur une autre piste plus simple (car je connais), les Xor.

Je pense que je vais plutôt partir sur ça, ça m'évitera de devoir apprendre des choses sur les bitwise et cie.

J'ai une deadline et je suis pressé c'est pour ça =p

Et si on dévisse trop, les vis sortent-elles ?