C'est quoi ce code

bool button(byte pin) {
  if(!digitalRead(pin)) {
    delay(30);
      if(!digitalRead(pin)){
        while(!digitalRead(pin));
        return 1;
      }
      else {return 0;}
  }return 0;
}

pouvez vous m'eclaircir ce code svp!!!

Post mis dans la mauvaise section, on parle anglais dans les forums généraux. ➜ déplacé vers le forum francophone.

Merci de prendre en compte les recommandations listées dans "Les bonnes pratiques du Forum Francophone".

c'est une fonction qui répond true au relâchement (elle est bloquante en attendant) si un bouton en mode INPUT_PULLUP connecté à la broche dont le numéro est donné en paramètre est enfoncé. sinon ça répond false

ce code essaye de déjouer un éventuel rebond du bouton.

PS: le code est très moche :slight_smile:

Pour simplifier votre gestion des boutons, éventuellement utilisez la bibliothèque Button dans easyRun de @bricoleau ou OneButton de Matthias Hertel ou encore Toggle de @dlloyd.

@merili
Cf mon tuto sur OneButton :

Bon code :slight_smile:

Maintenant, il parait que ce n'est plus comme cela qu'il faut faire.

J'ai appris la logique avec des relais, donc avec 1 qui correspond à la valeur logique "vrai" si le contact est fermé et 0 à la valeur logique "faux" si le contact est ouvert.
Je ne suis pas du tout choqué par ce code.

Mais il faut bien comprendre ce que l'on fait, ce n'est pas exceptionnel, il est toujours préférable de comprendre ce que l'on fait.

Explications sur le code :

Quand le micro lit un niveau sur une entrée, il inscrit dans le registre de l'entrée :

  • un 1 si le niveau est supérieur à son seuil correspond à un niveau haut
  • un 0 si le niveau est inférieur à son seuil correspond à un niveau bas.

Il faut savoir que le résultat de la quantité qui est dans les parenthèses du "if" est un booléen.
Voir un tuto de C/C++.

Un microcontrôleur ne fait pas de la littérature, il ne sait gérer que des 1 et des 0.
Le C attribue :

  • 1 à la valeur "vrai",
  • 0 à la valeur "faux".

Ce qui, dans le programme que tu cites, permet de faire un raccourci :
Niveau "haut"== valeur logique "vrai".
Niveau "bas" == valeur logique "faux".

If (!digitalRead(pin) :
le point d'exclamation est "l'inversion" (des plus doués que moi proposerons un meilleur terme)

Si le niveau est un niveau haut
→ digitalRead sera égal à 1
→ !digitalRead sera égal à l'inverse soit, 0.

Idem pour While

J'en profite pour faire une digression sur les niveaux logiques.
Le micro avr des cartes Uno, nano (V3) est particulier dans le sens où le point de basculement niveau bas/niveau haut est proche de Vcc/2.

En règle générale les niveaux sont définis comme suis :
Niveau haut : tension supérieure ou égale à 0,7*Vcc ou 0,8*Vcc
Niveau bas : tension inférieure ou égale à 0,3*Vcc ou 0,2* Vcc

La zone entre ces deux limites est interdite.
Ça peut fonctionner, ou pas à quelques degrés de température près. Le fabricant décline toute responsabilité dans cette zone.

Ce terme est, à mon sens, tout à fait approprié.

Robert:
inverser , verbe transitif:

Mettre dans un sens différent, contraire.
Synonyme : changer, intervertir, permuter, déplacer, renverser

Larousse:
inverser verbe transitif Conjugaison (de inverse)

  1. Changer la position relative de deux choses, de façon que chacune prenne la place de l'autre : Inverser l'ordre des deux facteurs d'un produit.
    Synonymes : intervertir - permuter - renverser
  2. Réaliser l'inversion d'un film ou d'un papier photographique.

vrai et faux sont deux valeurs possibles, comme gauche et droite, les deux sens de rotation d'un moteur ou des aiguilles d'une montre.


Pour certains esprit mathématiques, l'inverse de X est 1/X ce qui les conduit à dire que l'inverse de 1 est 1 et que l'inverse de 0 est l'infini. Mais dans ce cas, on n'a pas le droit de dire que vrai et 1 sont identiques.
Nous ne parlons pas toujours avec les mêmes mots:
− pour moi, la tension délivrée par une pile est une tension continue, alors que le mathématicien dira constante.
− le secteur a une tension constante de 230V, mais le matheux dira qu'elle est continue (pas de discontinuité dans une fonction sinusoïdale) mais pas du tout constante.

En algèbre de Boole, on parle de négation.

La négation en algèbre Booléenne (une porte inverseuse en électronique je suppose).


Édit j’avais pas vu la réponse déjà mise…

Il existe différents types d’algèbres que les mathématiques définissent (Algèbre élémentaire, Algèbre linéaire, Algèbre abstraite, Algèbre booléenne, Algèbre universelle, Algèbre commutative, Algèbre homologique, Algèbre de Lie, Algèbre de Boole, Algèbre tensorielle...)

L'algèbre de Boole est une forme plus générale d'algèbre qui peut inclure des éléments autres que les valeurs booléennes (Vrai ou Faux). En revanche, l'algèbre booléenne se réfère spécifiquement à l'algèbre qui utilise des valeurs booléennes et les opérations logiques telles que ET, OU et NON. Le ! Représente ce NON

1 Like

J’avais bien dit que ”certains plus doués que moi trouveraient un meilleur terme”,
c’est fait. :grinning: :rofl: :joy:

Nous sommes d’accord sur le concept (enfin il me semble).
Je pense que mon explication était compréhensible par le demandeur :

et collait bien au sujet puisque le but final était d'avoir une valeur booléenne Faux dans les parenthèses du if.

Je reste très perplexe sur la nécessité d’utiliser une bibliothèque dans le cadre de l’exemple de code présenté.
Partir directement sur l'utilisation d'une bibliothèque sans même analyser les conditions d'emploi revient à utiliser un marteau-pilon pour enfoncer une punaise.

Je pense que mes explications avec leur mauvais vocabulaire auront permis au demandeur de mieux comprendre le fonctionnement du if ( ) et du digitalWrite(), même si la sémantique est un peu "secouée".

La question provenait visiblement d'un débutant et je crains que vos copieuses explications très techniques l'auront plus désorienté qu'aidé.
Je sais j'ai le même travers en électronique. :sneezing_face:

si on s'en tient à la documentation (et on devrait) digitalRead retourne HIGH si le niveau est haut et LOW si le niveau est bas. La documentation ne précise pas vraiment le type exact de ces deux constantes (mais on sait qu'il y a une promotion vers un entier qui est possible) et encore moins leur valeur.

autant respecter les types aussi et si la fonction est booléenne, alors autant mettre un type de valeur de vérité au lieu d'un type numérique dans les return

on devrait donc toujours écire

bool button(const byte pin) {
  if (digitalRead(pin) == LOW) {       // si le bouton est appuyé
    delay(30);                         // on attend pour laisser passer les rebonds
    if (digitalRead(pin) == LOW) {     // s'il est toujours appuyé après la phase de rebond 
      while (digitalRead(pin) == LOW); // on attend (bloquant) le relâchement
      return true;                     // et on confirme que le bouton a bien été appuyé
    } else return false;               // sinon c'était juste un rebond du relâchement
  }
  return false;                        // le bouton n'est pas appuyé
}

On peut aussi se rappeler que le matériel n'est pas de la sémantique, mais bien du réel.
Que ce que traite le microcontrôleur n'est pas du HAUT et du BAS, mais des 1 et des 0.
Les manipulations de bits sont bien prévues il me semble ?

Et puis on peut conseiller, signaler les choix à problèmes potentiels, mais "il est interdit d'interdire". :rofl:

oui mais dans ce cas il faut travailler au niveau des APIs du matériel. Lire le registre, extraire le bit qui correspond et dans ce cas là effectivement vous aurez un 0 ou un 1.

Si vous travaillez à plus haut niveau avec les APIs d'Arduino (digitalRead ou digitalWrite) il faut tenir compte de leur documentation.

De même vous codez en C++, donc il faut tenir compte des règles (syntaxe, grammaire, règles implicites ou explicites) du C++

Un code qui fonctionne "un peu par hasard" risque de poser problème plus tard. Autant écrire donc correctement dès le début.

C'est basé sur les propriétés du matériel, c'est l'opposé du hasard.......sauf à dire que le matériel est conçu par hasard.

Le correctement des uns ne sera pas celui des autres.
Le correctement d'aujourd'hui n'est plus celui d'hier et ne sera pas celui de demain.

Si on veut aller jusqu'au bout dans ton raisonnement, il ne faut pas passer sous silence qu'il existe des boutons avec des contacts Travail et d'autres avec des contacts Repos.

Ce qui est important ce n'est pas que le micro voit un état HIGH ou LOW, mais le fait que le bouton ait été enfoncé.
En conséquence,
if (digitalRead(5) == HIGH)
n'est pas (avis personnel) sémantiquement correct, il faudrait écrire

#define BOUTONAPPUYE 1
if (digitalReadRead(5) == BOUTONAPPUYE)

puisque nul n'est sensé ignorer que ce qui est entre les parenthèses du if est un booléen.
ou même écrire une macro qui permette d'écrire directement :
if (BOUTONAPPUYE)

On ne s'en sortirait plus, il faut des limites.
Les limites sont celles de celui qui écrit le programme.
Elles sont valables par principe dans la mesure où il sait ce qu'il fait.

On peut toujours le mettre en garde.

Les demandeurs viennent ici pour des petits projets, ridiculement petits par rapport aux projets gigantesque où certains d'entre vous ont participé et où il fallait des règles strictes.

Je n'ai jamais fait de logiciel professionnellement, j'en ai compris les impératifs, ayant travaillé sur un projet réunissant plus de 100 personnes, la répartition matériel/logiciel était 50/50. Le "programme " faisait plus d'un million de lignes.
J'ai bien compris l'importance de la rigueur.

Mais là, nous avons affaire à des amateurs, je pars du principe qu'il faut rester raisonnable.
Au début, j'intervenais trop sur les montages électroniques, c'était une erreur. Les demandeurs ne demandaient pas à faire du mieux possible, ils demandaient à ce que cela fonctionne. Maintenant si le montage convient au demandeur, même si je reste persuadé qu'il pourrait être meilleur, je laisse faire.

Je crois que le sujet a suffisamment été pollué, j'arrête là.

Non pas à ce niveau de code (en utilisant digitalRead)

Ce code fonctionne parce que Arduino a décidé que HIGH était de type entier et valait 1 et LOW c'était 0 et grace aux règles C++ sur la promotion des entiers en valeur de vérité et inversement.

Il pourrait en être autrement, par exemple avec des valeur ayant un type C++ formel. C'est exactement ce qu'il s'est passé quand Arduino a voulu remplacer les #define de HIGH et LOW par

typedef enum { 
   LOW     = 0, 
   HIGH    = 1, 
   CHANGE  = 2, 
   FALLING = 3, 
   RISING  = 4, 
 } PinStatus; 

les valeurs étaient bien toujours 0 et 1 mais tout d'un coup, pour le C++, ce n'était plus un entier mais un type formel PinStatus.

ça a fait planter toutes les bibliothèques mal écrites parce que justement les développeurs avaient pris des raccourcis ➜ Breakage caused by PinStatus and PinMode types · Issue #25 · arduino/ArduinoCore-API · GitHub


non. la spec dit que digitalRead retourne HIGH ou LOW, donc si on utilise digitalRead() et que l'on veut respecter la documentation on utilise HIGH et LOW. Si on ne le fait pas, c'est comme utiliser un composant en dehors des spécifications données dans sa datasheet. On prend un risque même si ça a l'air de marcher...

oui, mais c'est de la spécification fonctionnelle. Ensuite il faut coder. Effectivement soit on code pour le bouton que l'on a tous, soit on prévoit le coup mais surtout pas avec

#define BOUTONAPPUYE 1

si on veut faire

if (digitalReadRead(5) == BOUTONAPPUYE)

➜ il faut que BOUTONAPPUYE soit HIGH ou LOW pour respecter la documentation.


on est bien d'accord, mais ne pensez vous pas qu'il est plus raisonnable et lisible d'utiliser HIGH et LOW que d'avoir à expliquer

  • le fait qu'en C++ les entiers bénéficient d'une promotion implicite en valeur de vérité
  • l'algèbre booléenne et la négation
  • le fait que bien que ce ne soit pas dans la doc, en fait HIGH c'est 1 et LOW c'est 0

je trouve donc

bool button(const byte pin) {
  if (digitalRead(pin) == LOW) {       // si le bouton est appuyé
    delay(30);                         // on attend pour laisser passer les rebonds
    if (digitalRead(pin) == LOW) {     // s'il est toujours appuyé après la phase de rebond 
      while (digitalRead(pin) == LOW); // on attend (bloquant) le relâchement
      return true;                     // et on confirme que le bouton a bien été appuyé
    } else return false;               // sinon c'était juste un rebond du relâchement
  }
  return false;                        // le bouton n'est pas appuyé
}

beaucoup plus lisible que

bool button(byte pin) {
  if(!digitalRead(pin)) {
    delay(30);
      if(!digitalRead(pin)){
        while(!digitalRead(pin));
        return 1;
      }
      else {return 0;}
  }return 0;
}

J'en ai fait de l'algèbre de Boole, mais je ne me souviens pas de ce terme de négation.

Ca oui! on utilisait le Non et le barre...

Ce jeu à qui veut avoir raison me lasse.

Chez moi, dans le Sud Ouest on parle de "Cap bourut" (-> le cap n'est pas celui de bonne espérance et le "t" final se prononce -> bourutE).
Donc inutile de chercher à me convaincre, en bon "Cap bourut" je ne changerais pas d'avis.

Bonsoir @68tjs

image

(Vu dans les Landes, en Béarn et au delà ecrit capborrut :wink:)

Merci j'apprécie.
Une langue principalement non écrite à obligatoirement des variantes, moi c'est le Pays de Born près de l'océan.
Pays de Born, J'en vois déjà avec un large sourire.

C'est tout à fait ça, j'assume.
Ma mère disait que les landais n'étaient pas têtus, ils savaient ce qu'ils voulaient.