2 Poussoirs appuis long pour activer Led et maintien

Bonjour tout le monde,

Mon niveau Arduino comporte essentiellement la lecture d'entrée et activation de sortie basique.
Mais ici, j'ai un projet de machine demandant un minimum de sécurité lors de la fermeture des mâchoires de test.
Voici la démarche:

  • Appuis sur 2 BP en même temps
    • Les mâchoires se ferment (temps de fermeture 2 secondes )
  • Tant que les 2 BP sont enfoncé, décompte du temps (millis)
    • Les mâchoires se ferment toujours (temps de fermeture 2 secondes )
  • Si les 2 secondes sont écoulés, on peut relâcher les BP
    • les mâchoires restent fermées

Je galère complètement!
J'ai fais quelques tests avec des morceaux de programme trouvé un peu partout (notamment sur ce forum je pense)
Mais je ne parviens pas a lui faire faire ce que je souhaite
Premiers essais avec un seul BP
Lors du maintient, la sortie est inactive, je la voudrais active

Voici le code actuel :

const byte Ferm = 24;           // Poussoir Fermeture           
const byte V10 = 16;            // Vanne electrique 10 pour machoire
const byte Ouv = 25;            // Poussoir Ouverture  
const unsigned long duree = 2000ul;
unsigned long chrono = 0;
bool etatPrecedent = HIGH;

void setup()  {
  pinMode(Ferm,INPUT_PULLUP);     
  pinMode(V10,OUTPUT);               
  pinMode(Ouv, INPUT_PULLUP);
}

void loop()  {

  bool etatFerm = digitalRead (Ferm);   // lecture du poussoir Ferm
  if (!etatFerm)  {                     // bouton enfoncé         // condition départ chrono
    if (etatPrecedent)  {               // on vient d'enfoncerle bouton
      chrono = millis();                // on lance le chrono
      delay(30);                        // debounce button
    }  
    if (millis() - chrono > duree){     // condition duréee impulsion
          digitalWrite(V10,HIGH);       // la led de la vanne V10 s'allume
    }
  }
  etatPrecedent = etatFerm ;
  
  bool etatOuv = digitalRead (Ouv);     // lecture du poussoir Ouv
  if (!etatOuv) {                       // bouton enfoncé
    digitalWrite(V10,LOW);              // la led de la vanne V10 s'eteind
  }
}

Je sèche J'avais également essayé avec 2 poussoirs simultané, mais ca ne fonctionnait pas

Un petit coup de main? :slight_smile:

Merci beaucoup,
Luis

Bonjour,

Tu peux gérer ça par une (petite) machine d'état. Par exemple:


Je n'ai pas représenté le traitement anti-rebond. Il peut être fait par une tempo de 20ms.

Pour ouvrir les machoires tu as simplement besoin de couper l'alimentation du vérin?

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

sinon pour simplifier votre gestion des boutons, éventuellement utilisez la librairie de @bricoleau

Salut Kamill,

Merci pour ta réponse rapide!

C'est tout nouveau pour moi ca, cette machine d'état
Je vais regarder un peu comment ca marche et faire quelques tests

Pour répondre a ta question, la réouverture des mâchoires ce fait de la même manière que l'ouverture. question de sécurité a nouveau

Luis

Salut J-M-L,

Top, je suis tombé dessus juste avant ta réponse.
C'est tout nouveau pour moi ce genre de séquence.
Je vais faire quelques test et repasserai pour donner des nouvelles

Merci

Je viens de tester le petit diagramme que je vois beaucoup avec cette méthode de Machine d'Etats.

Voici ce que ca donne:

Par l'état "en cours" je veux représenter le fait que les sorties pilotant mes vérins soient activent (fermeture mâchoires) pendant le temps chronométré.
Si poussoirs lâché trop tôt, les sortis vérins se désactivent.

Est-ce que le diagramme semble bon au moins a votre avis?

A mon avis, il y a des transitions complexes qui ne servent à rien.
Par exemple pourquoi com+ferm enfoncé depuis 2s, il suffit de mettre tempo échue puisque com ou ferm relaché est traité dans une autre transition.
Le diagramme se simplifie:
machine

Peut être que le diagramme est un peu trop simplifié car si on relâche un bouton pendant la fermeture on passe dans l'état "Mâchoire ouverte verrouillée" alors que la mâchoire est à moitié fermée.

Hmm...
Je ne vois plus trop a quoi devrait ressembler le diagramme du coup. Surtout pour le moment de relâchement des poussoirs trop rapide

Que je comprenne bien la maniere de coder une machine d'état:
Le truc c'est de fonctionner qu'avec des "Case" et chaque évènement fait appel a un des case en fonction des conditions remplies ou non pour l'activer

Est-ce que je comprend l'idée ou j'en suis loin?

Merci

pas obligatoirement des case, mais il faut pour un état donné

  • écouter les évènement susceptibles de déclencher une transition
  • réagir quand l'événement se produit et effectuer les actions prévues puis changer (éventuellement) d'état

le switch/case est pratique donc pour lister tous les états possibles, c'est pour cela qu'on l'utilise souvent

Ok ok

Du coup, mes etats possibles sont:

  • Ouvert
  • Fermé

Le plus complexe dans mon application va être:

 si BP1 enfoncé et BP2 enfoncé --> fermer
    début chrono
    si (BP1 relâché ou BP2 relâché) et (chrono < délais voulu) --> ouvrir
       sinon si (BP1 enfoncé et BP2 enfoncé) et (chrono >= délais voulu) --> fermer

Fermer et ouvrir seront activés via le switch
Mais je ne suis pas certain que ca permettra d'ouvrir les mâchoires si je relâche trop tôt

Envisagez aussi "en cours d'ouverture" et "en cours de fermeture" si vous voulez pouvoir réagir au lâcher de bouton pendant ces états

moi je dirais 6 états:

EN_COURS_D_OUVERTURE
OUVERT
OUVERT_VERROUILLE
EN_COURS_DE_FERMETURE
FERME
FERME_VERROUILLE

voire un 7ème état INCONNU (au départ) si vous voulez faire un "homing"

Peut être commencer par des noms de variable plus évocateurs :
pour ferm et ouv j'aurais mis bouton1 bouton2

bool etatFerm;
void setup()  {
  pinMode(pinBTN1,INPUT_PULLUP);     
  pinMode(V10,OUTPUT);               
  pinMode(pinBTN2, INPUT_PULLUP);
}

void loop()  {
  bool bouton1= !digitalRead (pinBTN1);   // lecture du poussoir 1
  bool bouton2= !digitalRead (pinBTN2);   // lecture du poussoir 2

  if (bouton1 && bouton2 || etatFerm) { // les 2 boutons enfoncés  ou etatFerm
      chrono = millis();                // on lance le chrono
      digitalWrite(V10,HIGH);       // la led de la vanne V10 s'allume
    }
  else  { digitalWrite(V10,LOW);       // la led de la vanne V10 s'éteint
      etatFerm = false;
    }
  
  if (millis() - chrono > duree){     // condition durée impulsion
      etatFerm  =  true;       // la led de la vanne V10 est maintenue allumée
    }
 }

La solution de achess me parle plus que les machines a états qui est, pour le moment, plus complexe pour ma compréhension.

J'ai remanié un peu ce code pour inclure l'ouverture sous condition du délais aussi:

int V1 = 13;
bool Etat_Mach = false;
int Com = 31;           // Poussoir Commun
int Ferm = 24;          // Poussoir Fermeture
int Ouv = 25;           // Poussoir Ouverture
unsigned long chrono;   // attention, type unsigned long comme millis()
const unsigned long duree = 15000ul;  // 15 secondes (le ul à la fin pour unsigned long)

void setup()  {
  // Sorties Vannes:
  digitalWrite(V1, LOW); 
  pinMode(V1, OUTPUT);    
  pinMode(Com,INPUT_PULLUP);               
  pinMode(Ferm, INPUT_PULLUP);
}

void loop()  {
  bool Etat_Com= digitalRead (Com);      // lecture du poussoir Com
  bool Etat_Ferm= digitalRead (Ferm);    // lecture du poussoir Ferm
  bool Etat_Ouv= digitalRead (Ouv);      // lecture du poussoir Ouv

// Fermeture
  if (Etat_Com && Etat_Ferm || Etat_Mach) { // les 2 boutons enfoncés  ou etatFerm
      chrono = millis();                    // on lance le chrono
      digitalWrite(V1,HIGH);                // la led de la vanne V1 s'allume
    }
  else  { digitalWrite(V1,LOW);             // la led de la vanne V1 s'éteint
      Etat_Mach = false;
    }  
  if (millis() - chrono > duree){           // condition durée impulsion
      Etat_Mach  =  true;                   // la led de la vanne V10 est maintenue allumée
    }

// Ouverture
  if (Etat_Com && Etat_Ouv || Etat_Mach) { // les 2 boutons enfoncés  ou etatFerm
      chrono = millis();                    // on lance le chrono
      digitalWrite(V1,LOW);                // la led de la vanne V1 s'eteint
    }
  else  { digitalWrite(V1,HIGH);             // la led de la vanne V1 s'allume
      Etat_Mach = true;
    }
  if (millis() - chrono > duree){           // condition durée impulsion
      Etat_Mach  =  false;                   // la led de la vanne V10 est maintenue éteinte
    }  
 }

Mais ma vanne V1 reste active :sweat_smile:

Bonjour,

Perso, j'aurai permuté ces 2 lignes

c'est aussi une machine à état: il écoute les évènements et traite ce qui est nécessaire :slight_smile:

Attention aux rebonds des boutons dans

if (bouton1 && bouton2 || etatFerm) { // les 2 boutons enfoncés  ou etatFerm
  chrono = millis();                // on lance le chrono
  digitalWrite(V10, HIGH);      // la led de la vanne V10 s'allume
}
else  {
  digitalWrite(V10, LOW);      // la led de la vanne V10 s'éteint
  etatFerm = false;
}

qui risquent d'envoyer une rafale d'ordres ON/OFF à votre Vanne electrique. (sur la LED ça ne va pas se voir à l'oeil nu)

Dans votre code vous devez différencier les états (ouverts ou fermés) car sinon le test sur les 2 boutons est le même. (➜ machine à état :wink: )

J'ai essayé de faire fonctionner le programme de achess, mais je ne comprend pas pourquoi celui-ci reste coincé dans le else et valide jamais la condition :

if ((millis() - chrono) > duree)

chrono ne prend pas une photo de millis(), il est en permanence mis a jour et du coup il n'y a pas l'écart suffisent entre millis() et chrono pour valider cette condition

// Vannes:
  int V1 = 13;        // vanne 1 de mise sous pression machine ( pas utilisée dans code )
  int V9 = 15;        // vanne piston
  int V10 = 16;       // vanne retour piston
// Entrées:   
  int Com = 31;           // Poussoir Commun
  int Ferm = 24;          // Poussoir Fermeture
  int Ouv = 25;           // Poussoir Ouverture
// Internes:
  bool Etat_Mach = false;
  unsigned long chrono;                 // attention, type unsigned long comme millis()
  const unsigned long duree = 2000ul;   // 2 secondes (le ul à la fin pour unsigned long)

void setup()  {
// Sorties Vannes:
  digitalWrite(V1, LOW); 
      pinMode(V1, OUTPUT);
  digitalWrite(V9, LOW); 
      pinMode(V9, OUTPUT);
  digitalWrite(V10, LOW); 
      pinMode(V10, OUTPUT);
// Entrées:      
  pinMode(Com,INPUT_PULLUP);               
  pinMode(Ferm, INPUT_PULLUP);
}

void loop()  {
  bool Etat_Com= !digitalRead (Com);          // lecture du poussoir Com
  bool Etat_Ferm= !digitalRead (Ferm);        // lecture du poussoir Ferm
// Fermeture
  if ((Etat_Com && Etat_Ferm) || Etat_Mach) {   // les 2 boutons enfoncés  ou etatFerm
    delay(10);
    chrono = millis();                          // on lance le chrono
    digitalWrite(V1,HIGH);                      // la led de la vanne V1 s'allume     
    if ((millis() - chrono) > duree){           // condition durée impulsion
      Etat_Mach  =  true;                       
      digitalWrite(V9, HIGH);                   // J'allume la led de la V9 comme témoin
    }
  }
  else  { 
    digitalWrite(V1,LOW);                       // la led de la vanne V1 s'éteint
    Etat_Mach = false;  
    digitalWrite(V10, HIGH);                    // J'allume la led de la V10 comme témoin
    }  
}

le comportement de ceci:

  • La V10 est allumée dès le début du programme
  • La V1 s'allume quand j'enfonce Com et Ferm et s'éteint quand je relâche mais après le délais, la V1 n'est pas maintenue active

Je ne vois pas vraiment ce que je rate ici.
Comment faire pour ne pas rester dans ce else

Ne faudrait-il pas plutot controler un changement d'état des poussoirs plutot que si ils sont enfoncés ou relaché?
Tant qu'ils sont enfoncés millis() est enregistré dans chrono
Mais si je passe par un changement d'état des poussoirs, ca devrait regler le problème, non?

vos spécifications ne sont pas claires donc on ne peut pas aboutir à un code propre.

• je suis en position ouverte. J'appuie sur les 2 boutons. la fermeture s'enclenche.

  • Je relâche un des 2 boutons (ou les 2) avant les 2s ➜ que doit-il se passer ?
  • Je ne relâche pas et j'atteint les 2s. ➜ que se passe-t-il si je tiens encore les 2 boutons appuyés ?

• je suis en position fermée. J'appuie sur les 2 boutons. l'ouverture s'enclenche.

  • Je relâche un des 2 boutons (ou les 2) avant les 2s ➜ que doit-il se passer ?
  • Je ne relâche pas et j'atteint les 2s. ➜ que se passe-t-il si je tiens encore les 2 boutons appuyés ?

en gros la machine à état pourrait être cela, mais on n'a pas tout défini.

Salut J-M-L,

Désolé pour les explications pas hyper clair. Pas toujours évident de retranscrire ce qu'on a en tête hahah !

Pour répondre a tes question :

  • désactivation des vannes (les mâchoires ne bougent plus)
  • il ne se passe plus rien de nouveau. Les mâchoires étant déjà fermées, la seule commande qui peut changer cet état est la commande d'ouverture

Inversement pour l'ouverture des mâchoires

Donc si je relâche au bout d’une seconde les mâchoires restent en position. Que se passe t’il ensuite si on appuie sur les 2 boutons ?

Comment déclencher l’ouverture une fois fermées ? (Si ce sont les 2 boutons en même temps - quid de si je ne les ai pas relâchés à la fin des 2s?)

Exactement, elles restent en position.
Si on appuie a nouveau sur les 2 boutons Com et Ferm, on relance la fermeture avec contrôle de délais (même délais de 2s)

Pour ouvrir les mâchoires on aurait exactement les mêmes instructions que la fermeture, mais avec les boutons Com et Ouv
Le comportement a l'ouverture sera le même que pour l'ouverture

J'espère que la problématique est un peu plus claire :sweat_smile: