Arduino : Bouton poussoir comme interrupteur

J’ai fait ce programme pour faire fonctionner un bouton poussoir comme interrupteur pour commander une simple led, et ça marche normalement :

boolean etatAllumage=0;

void setup() 
{
  Serial.begin(9600);
  pinMode(28,INPUT_PULLUP);
  pinMode(32,OUTPUT);
}

void loop() 
{
  
  if (etatAllumage==1)
  {
    digitalWrite(32,HIGH);
  }
  
  else
  {
    digitalWrite(32,LOW);
  }

  boolean etat=digitalRead(28);
  Serial.println(etat);
  if (etat==0)
  {
    if(etatAllumage==1)
    {
      etatAllumage=0;
    }
    else
    {
      etatAllumage=1;
    }
  }
    delay(200);
}

Mais quand je l’ai intégré dans mon projet (un robot controlé par vocal via bluetooth), la led commence à clignoter sans que je ne fasse rien :

#include <AFMotor.h> 
boolean etatAllumage=0;

AF_DCMotor motor1 (1, MOTOR12_1KHZ);
AF_DCMotor motor2 (2, MOTOR12_1KHZ);
AF_DCMotor motor3 (3, MOTOR34_1KHZ);
AF_DCMotor motor4 (4, MOTOR34_1KHZ);


String readString;
String voice;

void setup() {
  //set all the motor control pins to output

  Serial.begin(9600);
  pinMode(28,INPUT_PULLUP);
  pinMode(32,OUTPUT);
}

void loop() 
{
  Serial.println(etatAllumage);
  if(etatAllumage==1)
  {
    digitalWrite(32,HIGH);
    while(Serial.available())
  {
    delay(10);
    char c = Serial.read();
    readString+=c;
  }

  if(readString.length() > 0) 
  {

    if(readString == "FORWARD")
    {
      Avancer();
    }
    
    if(readString == "BACK")
    {
      Reculer();
    }

    if(readString == "LEFT")
    {
      Gauche();
    }

    if(readString == "RIGHT")
    {
      Droite();
    }

    if(readString == "STOP")
    {
      Stop();
    }

    readString = "";
  }

  }

  else
  {
    digitalWrite(32,LOW);
    while (Serial.available())
  { 
    delay(10); 
    char v = Serial.read(); 
    if (v == '#') 
    {
      break;
    } 
    voice += v; 
  }
  if (voice.length() > 0){
    if(voice == "*avancer"){
      Avancer();
      }
    else if(voice == "*reculer"){
      Reculer();
      }
    else if(voice == "*droite") {
      Droite();
    }
    else if(voice == "*gauche") {
      Gauche();
    }
    else if(voice == "*stop") {
      Stop();
    }
    
  voice=""; 
  }
  }

  boolean etat=digitalRead(28);
  if (etat==0);
  {
    if(etatAllumage==1)
    {
      etatAllumage=0;
    }
    else
    {
      etatAllumage=1;
    }
  }
  delay(200);
  
}

  

void Avancer()
{
  motor1.run(FORWARD);
  motor1.setSpeed(700);
  motor2.run(FORWARD);
  motor2.setSpeed(700);
  motor3.run(FORWARD);
  motor3.setSpeed(700);
  motor4.run(FORWARD);
  motor4.setSpeed(700);
  delay(2000);
  motor1.run(RELEASE);
  motor2.run(RELEASE);
  motor3.run(RELEASE);
  motor4.run(RELEASE);
}
  
void Reculer()
{
  motor1.run(BACKWARD);
  motor1.setSpeed(700);
  motor2.run(BACKWARD);
  motor2.setSpeed(700);
  motor3.run(BACKWARD);
  motor3.setSpeed(700);
  motor4.run(BACKWARD);
  motor4.setSpeed(700);
  delay(2000);
  motor1.run(RELEASE);
  motor2.run(RELEASE);
  motor3.run(RELEASE);
  motor4.run(RELEASE);
}
  
void Droite()
{
  motor1.run(FORWARD);
  motor1.setSpeed(190);
  motor4.run(FORWARD);
  motor4.setSpeed(190);
  motor2.run(BACKWARD);
  motor2.setSpeed(190);
  motor3.run(BACKWARD);
  motor3.setSpeed(190);
  delay(1000);
  motor1.run(RELEASE);
  motor2.run(RELEASE);
  motor3.run(RELEASE);
  motor4.run(RELEASE);
}
  
void Gauche()
{
  motor2.run(FORWARD);
  motor2.setSpeed(190);
  motor3.run(FORWARD);
  motor3.setSpeed(190);
  motor1.run(BACKWARD);
  motor1.setSpeed(190);
  motor4.run(BACKWARD);
  motor4.setSpeed(190);
  delay(1000);
  motor1.run(RELEASE);
  motor2.run(RELEASE);
  motor3.run(RELEASE);
  motor4.run(RELEASE);
}

void Stop()
{
  motor3.run(RELEASE);
  motor4.run(RELEASE);
}

Vous avez posté deux fois le même code...

conceptuellement digitalRead() retourne HIGH ou LOW, pas 0 ou 1, ni true or false (pas un booléen).

J-M-L:
conceptuellement digitalRead() retourne HIGH ou LOW, pas 0 ou 1, ni true or false (pas un booléen).

C'est pas pareil?

Si, mais Le mot clé est « conceptuellement » :slight_smile:

Quand on programme c’est bien d’être clair dans son intention. Avec HIGH et LOW on parle de valeur de tension pour une broche, true ou false on parle de valeur de vérité pour une condition, et 0 ou 1 c’est pour faire des maths.

Si vous continuez dans la programmation vous verrez des langages plus évolués qui vous imposeront d’utiliser le bon type de données pour la cohérence du code. Le compilateur refusera de compiler. Le C est plus permissif de par son origine et ça permet quelques optimisations malines mais faut être conscient du « hack » et quand on peut s’en passer c’est mieux

Arzou:
C'est pas pareil?

Pour certains non, pour moi si.
Nous avons déjà eu une discussion a ce sujet avec J-M-L, pour moi 1 ou 0 ne sont pas des booléens mais des niveaux logiques comme on en utilise en logique combinatoire, HIGH et LOW font, toujours pour moi, référence à un niveau de tension.
C'est dans le choix intitial du choix de la logique qu'on affecte HIGH à 0 ou à 1 selon qu'on choisi la logique positive ou la logique négative, une fois ce choix décidé on déroule

J'irai plus loin dans le choix d'utiliser HIGH ou 1 : tout dépend de la suite des opérations :

  • si c'est pour allumer une del alors HIGH qui est plus pres du matériel peut être mieux adapté
  • si c'est pour tester si une condition comme voir si un inter est bien positionné alors 0 ou 1 est plus adapté.
    En fait l'impportant est se comprendre, je veux dire se comprendre soi même :grin:.

Pour revenir au sujet il y a t-il une résistance reliée avec l'interupteur ? Il me semble que non et ce serait explicable que cela fonctionne sur maquette avec des fils courts et plus en site avec un câblage différents.
S'il n'y a pas de résistance en série avec l'interrupteur pour imposer un potentiel quand l'inter est ouvert, le fil de liaison entre inter et entrée de micro se retrouve "en l'air" et se comporte comme une antenne.
Il faut soit une résistance extérieure de tirage au Vcc ou à la masse selon le câblage du bouton interrupteur, soit utiliser les résistances internes au micro (option INPUT_PULLUP) mais dans ce cas l'interupteur est obligatoirement à la masse.

Ne pas oublier l'anti-rebond pour l'interupteur. Soit un condensateur de 100 nF en parallèle sur les contacts (pour le mec qui vient du matériel c'est le mieux), soit par solution logicielle comme les programmeurs préfèrent le faire.
Les deux solutions fonctionnent.

Je trouve que ça ne mange pas de pain d’être précis, ça facilite la lecture et clarifie les intentions donc aide au debug - mais ensuite chacun fait comme il veut bien sûr car en C ou dans l’univers Arduino true HIGH et 1 c’est pareil au niveau binaire (un booléen sera sur 1 octet alors que 1, HIGH ou true seront promus en int sur 2 octets)

Ha ok, c'est bien ce que je pensais.
Mais effectivement, ca éclairci le code.
Merci

Oui mais ce n'est pas applicable à la réalisation de modules I2C qui fonctionnent en logique inverse, dans ce cas HIGH devrait être égal à 0.
Ce ne serait pas applicable si plusieurs signaux logiques devaient être traités dans des tableaux de Karnaugh.

Si vous continuez dans la programmation vous verrez des langages plus évolués qui vous imposeront d'utiliser le bon type de données

HIGH ou LOW n'ont rien à voir avec un langage de programmation et ce ne sont pas des types de données : c'est un choix Wiring.
Tout est figé dans Wiring.h ou Arduino.h
#define HIGH 1
#define LOW 0
C'est un choix exclusif de logique positive matérielle

NB les auteurs de Wiring auraient très bien pu choisir d'écrire :
#define VCC 1
#define GND 0
Ce n'est qu'une question de convention.

Mais comme d'habitude : parfaitement éclairé, chacun choisi la méthode où il se sent le plus à l'aise.

68tjs:
HIGH ou LOW n'ont rien à voir avec un langage de programmation et ce ne sont pas des types de données : c'est un choix Wiring.

Pas avec le langage mais avec l'environnement qui a documenté que la fonction digitalWrite() prenait en paramètre HIGH or LOW, c'est tout et que c'est aussi ce que retournait digitalRead()

Alors oui je chipote mais c'est pour être structuré et conforme aux spécifications.

Alors je vais dire deux choses :
Un peu avant la fin des années 60 j'ai reçu mes premiers cours de logique, à l'époque on enseignait encore la logique à relais vu que les semi-conducteurs étaient rare et chers et l'équivalent d'un PC tenait dans un immeuble entier.
C'était très simple : un relai fermé c'était 1_Logique et un relai ouvert c'était 0_Logique.
Comme le but final était de résoudre des équations logiques c'était parfaitement adapté.

L'autre chose c'est pendant mon année de terminale j'ai du "subir" des cours de philo.
Il ne m'en est resté qu'un seul et unique enseignement c'est quand le professeur a abordé le sujet de la liberté de penser et de la pensée libre (ce n'est pas la même chose).

  1. Ne croyez jamais sur parole.
  2. Renseignez vous, cherchez des avis contradictoires, analysez les, confrontez les.
  3. Seulement après faites votre propre opinion.

Et mon opinion est que 0 ou 1 est plus proche du raisonnement logique que les indications niveaux Haut et Bas et qu'un programme c'est aussi du raisonnement logique.
Les auteurs de Wiring n'étaient pas des programmeurs professionnels mais des "artistes" éclairés. Ils ont fait des choix critiquables comme redéfinir le type boolean qui existait déjà en C..
Autant je ne chercherai pas à remettre en question les bases du C de Kernigham et Ritchie, autant je ne me sens absolument pas obligé de suivre les choix Wiring surtout que dans le cas présent la compréhension du programme n'est pas affectée.

Je sais je suis encore un 68.... attardé.

Mon point d'origine c'est que dans l'idée, certains débutant ici feront carrière dans l'informatique, et donc dans un but didcactif (comme les langages de programmation deviennent plus fortement typés pour éviter des erreurs bêtes, par exemple il faut vraiment une expression qui renvoie un booléen dans un test), il n'est pas inutile de prendre de bonnes habitudes.

68tjs:
Je sais je suis encore un 68.... attardé.

:wink:
Ensuite quand on sait ce qu'on fait (ce qui est votre cas) et qu'on se fiche de la cohérence sémantique ou qu'on cherche à gratter un octet, j'ai pas de souci avec l'idée de faire plus direct.

J-M-L:
Vous avez posté deux fois le même code…

conceptuellement digitalRead() retourne HIGH ou LOW, pas 0 ou 1, ni true or false (pas un booléen).

Je suis désolé, j’avais remarqué que j’ai mis le même code, j’ai corrigé, si vous pouvez m’aider c’est très urgent. Merci.

Si vous voulez comprendre comment bien écouter le port série vous pouvez jeter un oeil à mon petit tuto sur le sujet

Tel quel nous n’êtes pas garanti de bien lire vos messages (et assurez vous de virer les éventuels \r ou \n en entrée

Mais moi mon problème n'est pas dans la communication, le véhicule fonctionne normalement, par contre la Led que je voudrais contrôler par le bouton poussoir comme interrupteur n'a pas marché, je voudrais quand j'appuie une fois sur le bouton poussoir la Led s'allume et reste allumée, et quand j'appuie à nouveau la Led s'eteint et reste éteinte.

C’est typiquement une définition de programme qui se prête bien à la programmation par machine à états (cf mon tuto éventuellement)