Aide amélioration code ouverture trappe

Bonjour à tous,

j'aurais besoin de votre aide pour améliorer un code mais je ne sais pas quoi et comment faire.

Le principe :

J'ai une trappe qui est fixé par une corde à un moteur avec une poulie, et il y à 2 capteur de fin de course, 1 en haut et 1 en bas. J'ai également un capteur de luminosité et si il fait jour la trappe s'ouvre jusque au capteur haut et quand il fait nuit elle ce ferme jusqu'en bas.

Le problème :

Il arrive que lors de la descente de la trappe elle ce bloque ce qui ne fait pas contact sur le fin de course bas et provoque un enroulement de la corde dans l'autre sens, ce qui a pour effet de remonter la trappe et ma poulie en impression 3d casse.

Les solutions proposées :
1- Soit il faut mettre un timer et quand les temps est dépasser il arrête le moteur pour empêcher la casse.
2- Soit il faut que quand la trappe remonte le capteur du haut arrête la trappe même s'il fait nuit.
3- Soit vous avez d'autre idée je suis preneur.

Le code :

const int in1 = 2; // moteur tourne dans le sens des aiguilles
const int in2 = 3; // moteur tourne dans le sens inverse des aiguilles
const int fdch = 5; // Fin de course Haut
const int fdcb = 6; // Fin de course Bas
const int soleil = 7; // Capteur de luminosité

void setup() 
{
pinMode(in1, OUTPUT); // Tension de sortie pour moteur sens 1
pinMode(in2, OUTPUT); // Tension de sortie pour moteur sens 2
pinMode(fdch, INPUT); // Tension d'entrée pour fin de course Haut
pinMode(fdcb, INPUT); // Tension d'entrée pour fin de course Bas
pinMode(soleil, INPUT); // Tension d'entrée pour capteur de luminosité
}

void loop() 
{
int capteurh = digitalRead(fdch); // Lecture de la valeur du fin de course haut et intégrer à capteurh
int capteurb = digitalRead(fdcb); // Lecture de la valeur du fin de course bas et intégrer à capteurb
int luminosite = digitalRead(soleil); // Lecture de la valeur du capteur de luminosité et intégrer à luminosite

if(capteurh==LOW && luminosite==HIGH) //Si capteurh = 0 et luminosité = 1 alors 
{
  digitalWrite(in1, HIGH);                 // La tension de sortie de in1 = 1
  digitalWrite(in2, LOW);                  // La tension de sortie de in2 = 0
}

else if (luminosite==LOW && capteurb==LOW) //Sinon Si capteurb = 0 et luminosité = 0 alors 
 {
  digitalWrite(in1, LOW);                 // La tension de sortie de in1 = 0
  digitalWrite(in2, HIGH);                // La tension de sortie de in2 = 1
   }
   
 else //Sinon 
{
  digitalWrite(in1, LOW);                 // La tension de sortie de in1 = 0
  digitalWrite(in2, LOW);                 // La tension de sortie de in2 = 0
}
}

image :

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

Bonjour
le tuto pour utiliser la bibliothèque OneButton, complémentaire à celui sur les machines à état :

Bonne journée

Cordialement
Pandaroux007

C'est aussi typiquement un problème mécanique.
La trappe arc-boute car elle est pratiquement carré. Elle faudrait qu'elle soit plus haute que large ce qui lui éviterait de se mettre en travers et réduirait le risque de rencontrer ce problème.

certes :slight_smile:

Je vous remercie de vos réponse mais ce n'est pas la question, en terme de mécanique je m'en occupe mais c'est améliorer le code pour une sécurité qu'il me faudrait.
Si quelqu'un peut me dire quelle ligne de code je doit ajouté je suis preneur.
Merci

une machine à états de ce genre:

il y aurait la gestion du time out.

vous pourriez aussi rajouter (mais le timeout interviendrait sans doute avant) un OU avec un test sur le mauvais capteur déclenché dans la partie qui détecte les erreurs

ss

Ta solution d'un "Timer" me parait le plus simple non?
Quel problème cela te pose t-il ?

Merci pour ta réponse.
peux-tu m'écrire la ligne de code qu'il faut que je rajoute ?
Merci

comment sont câblés les boutons ? vous avez un pullup externe ?

Pour améliorer, tu peux essayer de mettre des commentaires utiles. En effet, ceux que tu as mis répètent le code et n'amènent absolument rien comme information !

voici un exemple de l'implémentation de la machine à états décrite dans le schéma précédent

J'utilise la bibliothèque Toggle qu'il faut donc installer

vous verrez que pour que le code soit plus compréhensible j'ai écrit quelques fonctions avec des noms parlants.

je ne sais pas comment sont câblés vos capteurs donc c'est peut être à l'envers
➜ ici j'ai mis

  • un pullup sur les FdC donc LOW = appui
  • in2 doit être HIGH et in1 LOW pour fermer
  • in2 doit être LOW et in1 HIGH pour ouvrir
  • s'il fait nuit le capteur de soleil retourne HIGH

j'ai rajouté une LED (celle interne) qui clignote en cas de détection d'erreur.

j'ai caché des fils dans le simulateur pour que ça reste lisible

#include <Toggle.h> // https://github.com/Dlloydev/Toggle/blob/main/src/Toggle.h

const int in1 = 2;      // moteur tourne dans le sens des aiguilles
const int in2 = 3;      // moteur tourne dans le sens inverse des aiguilles
const int fdch = 5;     // Fin de course Haut
const int fdcb = 6;     // Fin de course Bas
const int soleil = 7;   // Capteur de luminosité HIGH == nuit

const unsigned long ATTENTE_MAX = 20000; // 20 secondes max pour ouvrir ou fermer

Toggle btnFdch(fdch);
Toggle btnFdcb(fdcb);

enum {DEBUT, EN_OUVERTURE, OUVERTE, EN_FERMETURE, FERMEE, ERREUR} etat = DEBUT;
unsigned long chronoDebutAction;

// ====================================
// ========= Fonctions d'aide =========
// ====================================
void ouvrir() {
  Serial.println(F("En ouverture"));
  digitalWrite(in1, LOW);
  digitalWrite(in2, HIGH);
  chronoDebutAction = millis();
  etat = EN_OUVERTURE;
}

void fermer() {
  Serial.println(F("En fermeture"));
  digitalWrite(in2, LOW);
  digitalWrite(in1, HIGH);
  chronoDebutAction = millis();
  etat = EN_FERMETURE;
}

void stop() {
  Serial.println(F("stop"));
  digitalWrite(in1, LOW);
  digitalWrite(in2, LOW);
}

void erreur() {
  static unsigned long chrono = millis();
  etat = ERREUR;
  // on clignotte 1Hz
  if (millis() - chrono >= 500) {
    digitalWrite(LED_BUILTIN, digitalRead(LED_BUILTIN) == HIGH ? LOW : HIGH);
    chrono = millis();
  }
}

bool ilFaitNuit() {
  return digitalRead(soleil) == HIGH;
}

bool ilFaitJour() {
  return digitalRead(soleil) == LOW;
}


// ====================================
// ========== CODE PRINCIPAL ==========
// ====================================

void setup() {
  Serial.begin(115200);
  pinMode(LED_BUILTIN, OUTPUT);
  pinMode(in1, OUTPUT); // Tension de sortie pour moteur sens 1
  pinMode(in2, OUTPUT); // Tension de sortie pour moteur sens 2
  stop();
  digitalWrite(LED_BUILTIN, LOW);
  btnFdch.begin(fdch);
  btnFdcb.begin(fdcb);
}

void loop() {

  // on met à jour l'état des FdC
  btnFdch.poll();
  btnFdcb.poll();

  // en fonction de notre état on décide quoi faire
  switch (etat) {
    case DEBUT:
      if (ilFaitJour()) {
        ouvrir();
      } else {
        fermer();
      }
      break;

    case EN_OUVERTURE:
      if (btnFdch.onPress()) {
        // on a touché le Fdc Haut
        stop();
        etat = OUVERTE;
      } else if (millis() - chronoDebutAction >= ATTENTE_MAX) {
        // erreur : le temps est dépassé
        stop();
        Serial.println(F("Erreur ouverure - Temps moteur dépassé"));
        erreur();
      } else if (btnFdcb.onPress()) {
        // erreur : on a touché l'autre FdC
        stop();
        Serial.println(F("Erreur ouverure - le moteur s'est inversé"));
        erreur();
      }
      break;

    case OUVERTE:
      if (ilFaitNuit()) fermer();
      break;

    case EN_FERMETURE:
      if (btnFdcb.onPress()) {
        // on a touché le Fdc Bas
        stop();
        etat = FERMEE;
      } else if (millis() - chronoDebutAction >= ATTENTE_MAX) {
        // erreur : le temps est dépassé
        stop();
        Serial.println(F("Erreur fermeture - Temps moteur dépassé"));
        erreur();
      } else if (btnFdch.onPress()) {
        // erreur : on a touché l'autre FdC
        stop();
        Serial.println(F("Erreur fermeture - le moteur s'est inversé"));
        erreur();
      }
      break;

    case FERMEE:
      if (ilFaitJour()) ouvrir();
      break;

    case ERREUR:
      erreur();
      break;
  }
}

Salut.
En supposant qu'il s'agit d'un poulailler :
Je pense sincèrement que le principe mécanique retenu n'est pas le bon.

La ficelle qui s'enroule autour d'une poulie, en cas de problème, s'enroule dans l'autre sens et provoque l'ouverture de la porte, ce qui ne posera pas de problème en été, vu que le renard est occupé ailleurs, mais en hiver l'histoire risque de mal se terminer.

La glissière doit être d'une qualité irréprochable. Or, le glissement sur du bois est loin d'être optimal. Pour mon poulailler j'ai choisi des crémaillères en U, en acier, et une porte en plastique (un bout de gaine GTL).

Les fins de course sont plutôt mal placés. La moindre saleté qui traîne au sol a toutes les chances d'empêcher la porte de se fermer complètement et le FDC bas ne sera pas actionné.

EDIT :

comme on ne connaît pas le type de FDC que tu utilises, on ne connaît pas leur degré de qualité, étanches ou pas ?
Pour ma part, j'utilise une mesure du courant moteur, donc pas de FDC, mais on peut utiliser ceci (capteur ILS ou REED) :

Ma solution est celle-ci : une courroie crantée.

Voir ici :

Avec une courroie, si le FDC bas n'est pas actionné, la porte ne remonte pas, au contraire elle est plaquée au sol.

Bien entendu un timeout est toujours nécessaire, à l'ouverture comme à la fermeture. Tu peux t'inspirer de l'exemple suivant :
Mais il faudra avant tout mémoriser l'état de la porte dans une variable.

#define MOTOR_MAX_ONTIME  15000
int porte = -1;     // état indéterminé au départ

void ouverture(void)
{
  unsigned long start = millis();
  digitalWrite(in1, HIGH);
  digitalWrite(in2, LOW);
  while (1) {
    if (digitalRead(fdch) == HIGH) {
      Serial.println("FDCH, STOP");
      break;
    }
    if (millis() - start > MOTOR_MAX_ONTIME) {
      Serial.println("TIMEOUT, STOP");
      break;
    }
  }
  porte = HIGH;
}

Ensuite dans loop() il suffit de remplacer :

if(capteurh==LOW && luminosite==HIGH) //Si capteurh = 0 et luminosité = 1 alors 
{
  digitalWrite(in1, HIGH);                 // La tension de sortie de in1 = 1
  digitalWrite(in2, LOW);                  // La tension de sortie de in2 = 0
}

Par :

if(capteurh==LOW && luminosite==HIGH) //Si capteurh = 0 et luminosité = 1 alors 
{
  if (porte != HIGH) {
    ouverture();
  }
}

Même chose pour la fermeture.
Les 15 secondes sont à ajuster en fonction du temps d'ouverture / fermeture réels.

J'espère que des résistances de pulldown sont présentes, si ce sont des FDC NO, pullup pour des FDC NF.
Si tu avais donné le schéma, ce serait mieux.

Tu veux dire les lignes à rajouter pour que ton code puisse gérer un pseudo "Timer"
Malheureusement avec la structure de ton programme, il faut rajouter pas mal de ligne de code pour pouvoir gérer le réarmement du timer.
Pour te donner une idée voici un code que je n'ai pas testé, qui devrait marcher une fois, donc sans réarmement du timer.

const int in1 = 2; // moteur tourne dans le sens des aiguilles
const int in2 = 3; // moteur tourne dans le sens inverse des aiguilles
const int fdch = 5; // Fin de course Haut
const int fdcb = 6; // Fin de course Bas
const int soleil = 7; // Capteur de luminosité
const unsigned int timerTime = 3000;
unsigned int timer1 = 0;

void setup() {
  pinMode(in1, OUTPUT); // Tension de sortie pour moteur sens 1
  pinMode(in2, OUTPUT); // Tension de sortie pour moteur sens 2
  pinMode(fdch, INPUT); // Tension d'entrée pour fin de course Haut
  pinMode(fdcb, INPUT); // Tension d'entrée pour fin de course Bas
  pinMode(soleil, INPUT); // Tension d'entrée pour capteur de luminosité
}

void loop() {
  int capteurh = digitalRead(fdch); // Lecture de la valeur du fin de course haut et intégrer à capteurh
  int capteurb = digitalRead(fdcb); // Lecture de la valeur du fin de course bas et intégrer à capteurb
  int luminosite = digitalRead(soleil); // Lecture de la valeur du capteur de luminosité et intégrer à luminosite

  if(capteurh==LOW && luminosite==HIGH && (timer1 == 0 || millis() - timer1 < timerTime)) /*Si capteurh = 0 et luminosité = 1 alors*/ {
    digitalWrite(in1, HIGH);                 // La tension de sortie de in1 = 1
    digitalWrite(in2, LOW);                  // La tension de sortie de in2 = 0
    if (timer1 == 0) timer1 = millis();
  } else if (luminosite==LOW && capteurb==LOW && (timer1 == 0 || millis() - timer1 < timerTime)) /* Sinon Si capteurb = 0 et luminosité = 0 alors */ {
    digitalWrite(in1, LOW);                 // La tension de sortie de in1 = 0
    digitalWrite(in2, HIGH);                // La tension de sortie de in2 = 1
    if (timer1 == 0) timer1 = millis();
  } else /*Sinon*/  {
    digitalWrite(in1, LOW);                 // La tension de sortie de in1 = 0
    digitalWrite(in2, LOW);                 // La tension de sortie de in2 = 0
  }
}

Dans les choses à améliorer en plus de ce que décrit @biggil , il faudrait que tu indente ton code.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.