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: