Problème démarrage programme avec 1 inter et 2 leds

Bonjour,
Tout d'abord merci à tous ceux qui enrichissent ce forum par leur réponses/commentaires.
Je fais actuellement mes premiers pas dans la programmation Arduino uno et j'ai passé beaucoup de temps à lire ce qui est ici.
Mais je n'ai pas trouvé d'explication à mon problème...
.
Voilà mon code :
.

//////Déclaration des variables

//identifier LED et broches
const int LED1 = 8;   //LED1 sur broche 8, renommée en "LED1"
const int LED2 = 9;   //LED2 sur broche 9, renommée en "LED2"
const int LED3 = 10;  //LED3 sur broche 10, renommée en "LED3", pour visualiser action sur Inter1

//identifier boutons et broches
const int Inter1 = 2;      //Inter branché entre 2 et GND, renommé en "Inter1"
int stateInter1;           //Variable pour l'état actuel d'Inter1
int lastStateInter1 = LOW; //Variable pour l'état précédent d'Inter1

//antirebond
long DebounceDelay = 2000; //durée du filtre anti-rebond
long lastDebounceTime  = 0; //mémoriser le dernier changement d'état Inter1

//variable pour visualiser changement d'état Inter1
int Commut = LOW;

//////initialisation et déclaration des entrées-sorties
void setup()
{
pinMode(LED1, OUTPUT);  //LED1 est une sortie
pinMode(LED2, OUTPUT);  //LED2 est une sortie
pinMode(LED3, OUTPUT);  //LED3 est une sortie
pinMode(Inter1, INPUT); //Inter1 est une entree
digitalWrite(Inter1,HIGH); //actionne la resistance pullup intégrée de l'Arduino sur Inter1
}

////// programme en boucle
void loop(){
int readInter1 = digitalRead(Inter1); //lit état de Inter1 et mémorise sous "readInter1"

//Inter1 vient d'être appuyé ?
if(readInter1 != lastStateInter1){ 
lastDebounceTime  = millis();  //mémorise l'instant du chgt état Inter1 avec "millis"
Commut = HIGH;
digitalWrite(LED3,Commut); //montre si détection du chgt état Inter1, sans filtre antirebond
delay(200); //delay pour voir la détection du chgt état Inter1 (s'éteind en bas de boucle)
}
//antirebond : valide le changement seulement après la durée du DebounceDelay
if ((millis() - lastDebounceTime ) > DebounceDelay){
if(readInter1 != stateInter1){
stateInter1 = readInter1;  
}
}
digitalWrite(LED1,stateInter1); //allume ou éteind la LED1 suivant état de Inter1
digitalWrite(LED2,!stateInter1); //l'inverse de LED1 
digitalWrite(LED3,LOW); //eteind la LED3, pour prochaine visualisation d'action sur Inter1
lastStateInter1 = readInter1; //mémorise état Inter1 pour prochaine boucle
}

.
Mon montage :
1 Arduino Uno
1 inter
3 LEDs (avec résistances de limitation).

Ce que je voudrais faire :
Quand inter = 1, LED1 = 1, LED2 = 0
Quand inter = 0, LED1 = 0, LED2 = 1
Avec gestion Debounce et récupérer une variable (détection changement d'état de l'inter) pour plus tard (pour rajouter 2 boutons poussoirs, pour commander les mêmes LEDs)
.
Mon problème est au démarrage (mise sous tension, juste après download ou après un reset de la carte) :
Inter = 1, mais LED1=0 et LED2=1 pendant 2s (temps du Debounce important pour voir le problème).
Ensuite tout rentre dans l'ordre, sans aucune action sur l'inter...
J'ai un souci - je pense - lors de l'exécution du tout premier loop.

J'ai cherché et testé beaucoup de choses depuis 2 jours, mais là je cale...

Avant de partir dans une autre direction (utiliser un tableau ou autre), j'aimerai bien comprendre mon erreur dans ce code...
.
Si quelqu'un a une idée, ou commentaire, ou correctif ??
Merci merci.
Bonne soirée.

PS : l'idée plus tard est de gérer la rotation d'un motoréducteur DC.
Inter=1 : moteur tourne droite (simulé par LED1 ici)
Inter=0 : moteur tourne gauche (simulé par LED2 ici)
Bouton poussoir 1 : force la rotation à droite
Bouton poussoir 2 : force la rotation à gauche
Avec une tempo (delay) entre les 2 sens de rotation, évidemment...
=> d'où mon besoin de variable "Commut", histoire d'avoir pendant 6s LED1 et LED2=0 (pour freinage moteur avant de repartir dans l'autre sens)
Enfin c'est la voie choisie pour débuter et apprendre... Snif...

Bonjour et félicitations

Voici quelqu'un qui poste pour la première fois sur ce forum, dans la bonne section, en mettant son code entre les balises qui vont bien, et qui ne ménage pas sa peine pour expliquer son problème dans un français impeccable.

Ca donne tout de suite envie d'aider :slight_smile:

Là ton problème vient de plusieurs points :

lastStateInter1 initialisé à LOW alors qu'à la première lecture ton BP est à HIGH, ce qui donne immédiatement un changement fictif

Ton lastDebounceTime est initialisé à zéro, ce qui interdit un appui pendant 2 secondes après démarrage.
Il vaudrait mieux l'initialiser à -2000.
Ou ajouter dans le setup() "lastDebounceTime -= DebounceDelay;"

"readInter1 != lastStateInter1" indique seulement que l'état du bouton a changé.
Pour savoir si c'est un enfoncement ou un relâchement il faut en plus tester la valeur de readInter1

Autres considérations :

Ton code est abondamment commenté. C'est très bien continue comme ça.

Prends l'habitude d'indenter ton code : cela consiste à insérer des caractères blancs au début de chaque ligne, de manière proportionnelle au niveau du bloc dans laquelle elle se trouve.
On y gagne beaucoup en lisibilité et en appréhension des niveaux logiques.

Apprends à utiliser les types de données adéquats par rapport à leur plage de valeur.
Stockage de millis() => "unsigned long" ou bien uint32_t

Oublie DEFINITIVEMENT l'instruction delay() :smiley:

Par exemple (partiel) :

void loop() {

  //Variables d'état de la LED3, conservées entre deux loop() grâce au mot clé "static"
  static uint8_t etat_LED3 = LOW;
  static uint32_t millis_LED3 = 0;

  int readInter1 = digitalRead(Inter1); //lit état de Inter1 et mémorise sous "readInter1"

  //Inter1 vient d'être enfoncé ou relaché
  if(readInter1 != lastStateInter1){

    //tenir compte du changement seulement après expiration du délai de debounce
    if (millis() - lastDebounceTime > DebounceDelay) {

      if (readInter1 == LOW) { //C'est un appui
        digitalWrite(LED1,HIGH);
        digitalWrite(LED2,LOW); 
      }
      else { //C'est un relachement
        digitalWrite(LED1,LOW);
        digitalWrite(LED2,HIGH); 
      }

      //Pour tout changement, on allume la LED3 pendant 200 ms
      digitalWrite(LED3, HIGH);
      etat_LED3 = HIGH;
      millis_LED3 = millis();

      //Mettre à jour les variables d'état
      lastStateInter1 = readInter1;
      lastDebounceTime = millis();
    }
  }

  //Eteindre la LED3 si nécessaire
  if (etat_LED3 == HIGH && millis() - millis_LED3 > 200)
  {
    digitalWrite(LED3, LOW);
    etat_LED3 = LOW;
  }
}

Bonsoir Bricoleau,

Super, merci pour tes commentaires et conseils.

J'ai fait un copier/coller de ton code sous le Void loop (en écrasant ma version), mais ça ne prenait pas en compte le délai Debounce.
C'est à dire que le changement de LED se faisait dès que l'Inter était touché.
Mais pas grave, j'ai repris la partie test du bouton pour "en plus tester la valeur de readInter1"...
Ca marche nickel, tout comme je voulais.

Donc mon erreur venait de la croyance que "if(readInter1 != lastStateInter1)" voulais dire :
Si "readInter1" est différente de "lastStateInter1", alors...action...
Ben non / suffit pas !
Pas que je sois fainéant, mais moins y'a de lignes... moins y'a de lignes. :slight_smile:

Je vais me pencher sur les autres astuces de ton code.
Oui, j'avais bien vu que DELAY était à banir...

Je posterai la version avec mes 2 autres boutons poussoirs pour ceux que ça pourrait intéresser.
D'ici quelques jours avec [résolu] dans le titre, si je ne me trompe...

Encore merci
et bonne soirée.

Bonjour,
Je conclus ce sujet :
L'objectif était de piloter un moteur DC avec inversion du sens de rotation par 2 boutons poussoirs.
Comme mon moteur est assez gros, il me fallait une tempo pour lui laisser le temps de s’arrêter avant de tourner dans l'autre sens (donc sans système de frein).
Le PWM ne me semble pas adapté à mon besoin (aucun besoin de gérer la vitesse / juste l'inertie lors de l'inversion de sens) , mais étant débutant, je laisse les pros me contredire...
Voilà le code qui fonctionne à merveille, très largement commenté (ben oui, je n'y mets pas les doigts souvent et p'tite mémoire).
Bonne continuation.

//Piloter le sens de rotation d'un moteur DC avec :
//1 interrupteur (Inter1) et 2 boutons poussoirs (BP1 et BP2).
//Programme avec antirebond des boutons + evite de prendre en compte un appui furtif sur un bouton,
//Temporisation incluse (temps plus long que l'antirebond)pour laisser le temps
//au moteur de s'arreter(inertie) avant de repartir dans l'autre sens.
//--Fonctionnement :
//A la mise sous tension, le moteur tourne à droite.
//Si Inter1=HIGH : moteur tourne à droite après tempo (ne tient pas compte d'actions sur BP1)
//Si Inter1=HIGH mais appui sur BP2 : arrete moteur et, après tempo, force la rotation à gauche.
//Si Inter1=HIGH et BP2 relaché : arrete moteur et, après tempo, reprend rotation à droite.
//Si Inter1=LOW : moteur tourne à gauche après tempo  (ne tient pas compte d'actions sur BP2)
//Si Inter1=LOW  mais appui sur BP1 : arrete moteur et, après tempo, force la rotation à droite.
//Si Inter1=LOW et BP1 relaché : arrete moteur et, après tempo, reprend rotation à gauche.
//
//Phase test : simulation des sorties rotations moteur avec 2 LEDs
//LED1 = moteur tourne à droite, LED2 = moteur tourne à gauche.
//
//ajout d'une LED3 pour visualiser un appui sur un des 3 boutons (à supprimer si inutile)
//
//de fruitNono, juin 2016.
//

//-----Déclaration des variables-----

//identifier LED et broches
const int LED1 = 8;   //LED1 sur broche 8, renommée en "LED1"
const int LED2 = 9;   //LED2 sur broche 9, renommée en "LED2"
//
//pour visualiser un appui sur un des 3 boutons (à supprimer si inutile)
const int LED3 = 10;  //LED3 sur broche 10, renommée en "LED3"


//identifier boutons et broches
const int Inter1 = 2; //bouton interrupteur branché entre 2 et GND, renommé en "Inter1"
int stateInter1;      //Variable pour l'état actuel d'Inter1
int lastStateInter1;  //Variable pour l'état précédent d'Inter1
//BP1
const int BP1 = 3;    // bouton poussoir BP1 branché entre 3 et GND, renommé en "BP1"
int stateBP1;         //Variable pour l'état actuel de BP1
int lastStateBP1;     // Variable pour l'état précédent de BP1
//BP2
const int BP2 = 4;    // bouton poussoir BP2 branché entre 4 et GND, renommé en "BP2"
int stateBP2;         //Variable pour l'état actuel de BP2
int lastStateBP2;     // Variable pour l'état précédent de BP2

//temps antirebond
const long DebounceDelay = 300;
//mémorise l'instant du dernier changement d'état de boutons (pour antirebond)
unsigned long lastDebounceTime  = 0;

//Temporisation de 2s avant allumage autre LED (temps inversion sens rotation moteur)
const long TEMPO = 2000;

//-----initialisation et déclaration des entrées-sorties-----
void setup()
{
pinMode(LED1, OUTPUT);  //LED1 est une sortie
pinMode(LED2, OUTPUT);  //LED2 est une sortie
pinMode(LED3, OUTPUT);  //LED3 est une sortie (à supprimer si inutile)
pinMode(Inter1, INPUT); //Inter1 est une entree
digitalWrite(Inter1,HIGH); //actionne la resistance pullup intégrée de l'Arduino sur Inter1
pinMode(BP1, INPUT); // BP1 est une broche d'entree
digitalWrite(BP1,HIGH); //actionne la resistance pullup intégrée de l'Arduino sur le BP1
pinMode(BP2, INPUT); // BP2 est une broche d'entree
digitalWrite(BP2,HIGH); //actionne la resistance pullup intégrée de l'Arduino sur le BP2
}

//-----programme en boucle-----
void loop(){

//mémorise le temps au départ de la boucle
unsigned long currentTime = millis();
  
//Variables d'état de la LED3, conservées entre deux loop() grâce au mot clé "static"
  static uint8_t etat_LED3 = LOW;
  static uint32_t millis_LED3 = 0;

//Lecture et stockage des états des boutons
int readInter1 = digitalRead(Inter1); //état de Inter1 stocké dans "readInter1"
int readBP1 = digitalRead(BP1); //état de Inter1 stocké dans "readBP1"
int readBP2 = digitalRead(BP2); //état de Inter1 stocké dans "readBP2"

//un des boutons vient d'être appuyé ?
if((readInter1 != lastStateInter1) || (readBP1 != lastStateBP1)|| (readBP2 != lastStateBP2)){
    lastDebounceTime  = currentTime;  //mémorise l'instant du chgt état d'un des boutons
    //allume la LED3 (à supprimer si inutile)
    digitalWrite(LED3, HIGH);
    etat_LED3 = HIGH;
    millis_LED3 = currentTime;
}
//Eteindre LED3 après 100ms (à supprimer si inutile)
if (etat_LED3 == HIGH && currentTime - millis_LED3 > 300){
    digitalWrite(LED3, LOW);
    etat_LED3 = LOW;
}
//antirebond : valide le changement d'état de boutons seulement après la durée du DebounceDelay
if ((currentTime - lastDebounceTime ) > DebounceDelay){
    //test états boutons et éteind LEDx correspondante et allume LEDy après la tempo 
    if ((readInter1 == HIGH) && (readBP2 == HIGH)){
        digitalWrite(LED2,LOW);
        if ((currentTime - lastDebounceTime ) > TEMPO){
            digitalWrite(LED1,HIGH);
        }
    }
    else if ((readInter1 == HIGH) && (readBP2 == LOW)){ 
        digitalWrite(LED1,LOW);
        if ((currentTime - lastDebounceTime ) > TEMPO){
            digitalWrite(LED2,HIGH);
        }
    }
    else if ((readInter1 == LOW) && (readBP1 == HIGH)){ 
        digitalWrite(LED1,LOW);
        if ((currentTime - lastDebounceTime ) > TEMPO){
            digitalWrite(LED2,HIGH);
        }
    }
    else if ((readInter1 == LOW) && (readBP1 == LOW)){ 
        digitalWrite(LED2,LOW);
        if ((currentTime - lastDebounceTime ) > TEMPO){
            digitalWrite(LED1,HIGH);
        }
    }
}
//mémorise état des boutons pour prochaine boucle (laisser le moteur tourner dans le sens choisi)
lastStateInter1 = readInter1;
lastStateBP1 = readBP1;
lastStateBP2 = readBP2;

//Fin de boucle, retour au début du Loop
}