Poulailler avec servo Moteur

Bonjour,
il y a deux mois j’ai fabriqué une porte coulissante façon « guillotine » pour mon poulailler. Le but c’était d’utiliser le plus possible le matériel déjà en ma possession. Je me suis inspiré de plusieurs projets vus sur le net et j’ai créé le mien, bien entendu sans prétention aucune (car plutôt bricoleur du dimanche, pour le code aussi). J’ai utilisé un servo moteur 360 degrés connecté à deux poulies. Un capteur de lumière donne la commande pour la fermeture et l’ouverture. Afin d’arrêter le servo moteur au bon moment, j’ai rajouté deux fins de course. Le système marche, mais parfois, lors de la fermeture, la porte ne touche pas le fin de course en bas. Cela à cause soit d’une poule (conne) qui traine devant la porte, soit de la paille qui se déplace, un grand :poop: bien pile à l’entrée … Donc le moteur continue à tourner, mais se s’arrêtant pas, il embobine le câble dans le sens inverse, donc la porte remonte (mais l’Arduino pense qu’il est en train toujours de la baisser). Ne trouvant pas le fin de course, la porte reste coincée et le moteur se bloque à cause de la force contraire (et heureusement ne grille pas). Le moteur est alimenté par une alimentation 5V externe et l’Arduino Nano par 12V. Pour résoudre ce problème j’ai essayé d’imaginer de coupler une temporalité au fin de course, c’est à dire que si après un certain temps le fin de course n’est pas trouvé, le moteur s’arrête quand même.
Voici déjà mon code à ce jour:


#include <Servo.h>
int Val_Photo ;  //Lecture valeurs capteur lumière
int photo = A0; // PIN capteur lumière
int Val_luce = 30; // Valeur  luminosité


const int Fin_Course_Bas = 4;     // Numéro de la broche à laquelle est connecté le fin de course
const int Fin_Course_Haut = 5;  // Numéro de la broche à laquelle est connecté le fin de coursE

Servo myservo;  

void setup() {
  
  pinMode(Fin_Course_Bas, INPUT);
  pinMode(Fin_Course_Haut, INPUT);

  myservo.attach(9);  
  
  Serial.begin (9600); // initaialisation port série

}

void Montee (){
  while ( digitalRead (Fin_Course_Haut) == HIGH) {
  myservo.write(180);  
    delay(15); 
  }
}

void Descente (){
 
  
  while ( digitalRead (Fin_Course_Bas) == HIGH ) {
  myservo.write(0); 
    delay(15);  
  }
}
void OFF (){
   myservo.write (90); 
     delay(15);  
     
}
      


void loop() {
  
  
  Val_Photo = analogRead (photo); // valeur capteur lumière
  Serial.print("Val_Photo");
  Serial.println(Val_Photo);
  

  if (Val_Photo > Val_luce) {
    {
      Montee();
    }
    if( digitalRead (Fin_Course_Haut) == LOW)
    {
      OFF();
   }
}

  if (Val_Photo < Val_luce) {
  {
     Descente();
   
     if( digitalRead (Fin_Course_Bas) == LOW)
    {
      OFF();
    }
     
  }     
   }
  
  
delay (60000);

}




Est-ce que je dois travailler plutôt dans le while du Void Descente en rajoutant un « or » ?

Merci d’avance de vos retours.

Claudio

Moi je mettrais un or dans ce if.
Lorsque tu lances la descente tu initialises un chrono (en variable globale c'est le plus simple)

chrono = millis();
Juste avant l'appel de la fonction descente

Et dans ton test tu ajoutes

|| (millis()-chrono>dureemax)

Et tu définis dureemax pour la durée de descente maximale en millisecondes.

Bonsoir Lesept,
et merci beaucoup pour la réponse !
Comme je disais je suis un "codeur" du dimanche ...
J'imagine que je dois me tromper quelque part:


#include <Servo.h>
int Val_Photo ;  //Lecture valeurs capteur lumière
int photo = A0; // PIN capteur lumière
int Val_luce = 950; // Valeur  luminosité
int dureemax = 2000; // temps de descente


const int Fin_Course_Bas = 4;     // Numéro de la broche à laquelle est connecté le fin de course
const int Fin_Course_Haut = 5;  // Numéro de la broche à laquelle est connecté le fin de coursE

Servo myservo;  

void setup() {
  
  pinMode(Fin_Course_Bas, INPUT);
  pinMode(Fin_Course_Haut, INPUT);

  myservo.attach(9);  
  
  Serial.begin (9600); // initaialisation port série

}

void Montee (){
  while ( digitalRead (Fin_Course_Haut) == HIGH) {
  myservo.write(180);  
    delay(15); 
  }
}

void Descente (){
 
  
  while ( digitalRead (Fin_Course_Bas) == HIGH ) {
  myservo.write(0); 
    delay(15);  
  }
}
void OFF (){
   myservo.write (90); 
     delay(15);  
     
}
      


void loop() {
  
  
  Val_Photo = analogRead (photo); // valeur capteur lumière
  Serial.print("Val_Photo");
  Serial.println(Val_Photo);
  

  if (Val_Photo > Val_luce) {
    {
      Montee();
    }
    if( digitalRead (Fin_Course_Haut) == LOW)
    {
      OFF();
   }
}

  if (Val_Photo < Val_luce) {
     int chrono = millis();
  {
     Descente();
   
     if( digitalRead (Fin_Course_Bas) == LOW || (millis()-chrono>dureemax))
    {
      OFF();
    }
     
  }     
   }
  
  
delay (60000);

}

Merci pour ta patience :expressionless: 



Un servo 180° avec un bras de levier aurai été plus adapté, et les FDC seraient inutiles.

... surement, mais le but c'était, comme j'ai expliqué, d'utiliser du matériel déjà à disposition.
Par contre ça ne résolue pas mon problème ... :expressionless:
Après conseil de lesept j'ai modifié mon code, mais ça ne marche toujours pas. Je poste mon dernier code ici:


#include <Servo.h>
int Val_Photo ;  //Lecture valeurs capteur lumière
int photo = A0; // PIN capteur lumière
int Val_luce = 950; // Valeur  luminosité
int dureemax = 2000; // temps de descente


const int Fin_Course_Bas = 4;     // Numéro de la broche à laquelle est connecté le fin de course
const int Fin_Course_Haut = 5;  // Numéro de la broche à laquelle est connecté le fin de coursE

Servo myservo;  

void setup() {
  
  pinMode(Fin_Course_Bas, INPUT);
  pinMode(Fin_Course_Haut, INPUT);

  myservo.attach(9);  
  
  Serial.begin (9600); // initaialisation port série

}

void Montee (){
  while ( digitalRead (Fin_Course_Haut) == HIGH) {
  myservo.write(180);  
    delay(15); 
  }
}

void Descente (){
 
  
  while ( digitalRead (Fin_Course_Bas) == HIGH ) {
  myservo.write(0); 
    delay(15);  
  }
}
void OFF (){
   myservo.write (90); 
     delay(15);  
     
}
      


void loop() {
  
  
  Val_Photo = analogRead (photo); // valeur capteur lumière
  Serial.print("Val_Photo");
  Serial.println(Val_Photo);
  

  if (Val_Photo > Val_luce) {
    {
      Montee();
    }
    if( digitalRead (Fin_Course_Haut) == LOW)
    {
      OFF();
   }
}

  if (Val_Photo < Val_luce) {
     int chrono = millis();
  {
     Descente();
   
     if( digitalRead (Fin_Course_Bas) == LOW || (millis()-chrono>dureemax))
    {
      OFF();
    }
     
  }     
   }
  
  
delay (60000);

}




Où je me trompe ... ?
Merci pour votre patience.

Claudio

Bonjour Vinchiappetto

Je tournerai Montee () Descente() ainsi:


void Montee (){
	myservo.write(180);     // Servo dans le sens montée
	while ( digitalRead (Fin_Course_Haut) == HIGH) {
	}
	OFF ();
}

void Descente (){
	
	myservo.write(0);     // Servo dans le sens descente	
	while ( digitalRead (Fin_Course_Bas) == HIGH ) {
	}
	OFF ();
}

Je n'ai pas essayé "en vrai" mais s'il faut, j'ai le nécessaire.

Cordialement
jpbbricole

Bonjour Jpbbricole,
merci pour ta réponse.
Mais le problème c'est plutôt de rajouter une temporalité au cas où le fin de course n'est pas enclenché à la descente. J'ai bien eu une piste par lesept, mais ça ne marche pas.
:face_with_raised_eyebrow:

Parfois il faut savoir investir quelques euros plutôt que de s'engager dans une voie logicielle sans issue.
Il y a de multiples problèmes :

  • servo 360° : équivalent à un moteur continu. Pas de contrôle de position.
  • ficelle : la porte n'est pas plaquée au sol. Un prédateur rusé pourra la soulever.

Bonjour Vinchiappetto

Peut-être mettre le fin de course sur la tension du fil de levage, quand détendu, arrivé en bas ou sur une poule ou sur un grand :poop: bien pile à l’entrée.

Cordialement
jpbbricole

Bien entendu tu as raison hbachetti, mais c'était le principe de récupération qui a été mis en avant. Le poulailler a été construit aussi avec de la récupération. Il est installé dans un enclos et j'ai un chien dans le terrain, donc pas trop de chance que les poules soient attaquées. Mais c'est le code qui me perturbe: normalement ça devrait être facile de rajouter une temporalité couplée au fin de course, mais je n'y arrive pas. Des idées ... ?

Bonjour Vinchiappetto

Doubler un fin de course d'une temporisation, cela veut dire que l'on sait au bout de combien de temps on estime que le fin de course (FDC) "n'a pas fait son travail".
A ce moment, pourquoi ne pas supprimer le FDC et envoyer l'ordre de descente le temps nécessaire à la fermeture, le fil risque, au pire, d'être détendu?
Ou se baser uniquement sur la tension du fil.
Avec la surveillance du fil, si un obstacle temporaire, comme une poule, disparaît, le tension reviendrait et on pourrait continuer le processus de fermeture.

Cordialement
jpbbricole

Quand on utilise millis() ou micros(), il faut déclarer des variables unsigned long :
unsigned long chrono = millis();

Ca donnerait ça :

  if (Val_Photo < Val_luce) {
    unsigned long chrono = millis();
    Descente();

    if ((digitalRead (Fin_Course_Bas) == LOW) || (millis() - chrono > dureemax)) OFF();
  }

Il faut expliquer ce qui ne marche pas, j'ai un peu de mal à voir d'ici... Que se passe t-il ou t-il pas ?

Effectivement je trouve plus censé d'agir de telle façon. Mais vu que le FDC est déjà installé, pourquoi m'en priver ? C'est juste une question de sécurité (ça plante environs 1 fois sur 10) Merci beaucoup !

Merci beaucoup lesept. Demain je vais changer cela dans mon code et je vais tester. J'ai appris des nouvelles choses ...

Le plantage est donc fréquent. Les FDC sont probablement mal placés.
D'autre part, en extérieur les FDC classiques et bon marché, non étanches, peuvent poser des problèmes à plus ou moins long terme.
Pour ma part j'utilise des ampoules REED :

Bonjour Vinchiappetto

C'est quel type de FDC, si c'est un mécanique du genre
image
Pourquoi ne pas le déplacer sur le chemin du fil de façon que, le fil tendu, donc porte pendue, il soit "fermé"?

Cordialement
jpbbricole

Bonjour à tous,
déjà désolé pour le long silence mais un départ soudain m'a obligé de mettre en stand bye mon projet.
Merci beaucoup pour tous vos suggestions.
De retour je voudrais clôturer mon petit post et ne plus vous embêter.

C'est bien ce type de FDC que j'ai installé. Voici une petite photo pour vous montrer mon installation (désolé pour la qualité)


Je ne voudrais pas changer ce système mais juste rajouter un timing couplé au FDC (oui, je pourrais laisser tomber le FDC en bas, mais au final j'ai vraiment envie de comprendre niveau code ce qu'il faut faire).
Donc voici le code à ce jour:


#include <Servo.h>
int Val_Photo ;  //Lecture valeurs capteur lumière
int photo = A0; // PIN capteur lumière
int Val_luce = 30; // Valeur  luminosité
int dureemax = 2000; // temps de descente


const int Fin_Course_Bas = 4;     // Numéro de la broche à laquelle est connecté le fin de course
const int Fin_Course_Haut = 5;  // Numéro de la broche à laquelle est connecté le fin de coursE

Servo myservo;  

void setup() {
  
  pinMode(Fin_Course_Bas, INPUT);
  pinMode(Fin_Course_Haut, INPUT);

  myservo.attach(9);  
  
  Serial.begin (9600); // initaialisation port série

}

void Montee (){
  while ( digitalRead (Fin_Course_Haut) == HIGH) {
  myservo.write(180);  
    delay(15); 
  }
}

void Descente (){
 
  
  while ( digitalRead (Fin_Course_Bas) == HIGH ) {
  myservo.write(0); 
    delay(15);  
  }
}
void OFF (){
   myservo.write (90); 
     delay(15);  
     
}
      


void loop() {
  
  
  Val_Photo = analogRead (photo); // valeur capteur lumière
  Serial.print("Val_Photo");
  Serial.println(Val_Photo);
  

  if (Val_Photo > Val_luce) {
    {
      Montee();
    }
    if( digitalRead (Fin_Course_Haut) == LOW)
    {
      OFF();
   }    
}

 if (Val_Photo < Val_luce) {
    unsigned long chrono = millis();
    Descente();

   
     if( digitalRead (Fin_Course_Bas) == LOW || (millis()-chrono>dureemax))
    {
      OFF();
    }
     
  }     
   
  
  
delay (60000);

}




Malheureusement avec ce code le temps de descente n'est pas pris en compte et le FDC n'ont plus. Le servo moteur ne s'arrête pas.
Auriez-vous la patience de me dire ce qui va pas dans mon code ? Si c'est trop compliqué j'opterais pour enlever au moins le FDC en bas.
Merci d'avance pour votre aide.

Bonjour,
Ne lancer les actions qu'une seule fois avec l'aide de variables bool :

#include <Servo.h>
int Val_Photo ;  //Lecture valeurs capteur lumière
int photo = A0; // PIN capteur lumière
int Val_luce = 30; // Valeur  luminosité
unsigned long topDepart = 0;
int dureemax = 2000; // temps de descente
bool porteClose, porteOuverte, ouvert;

const int Fin_Course_Bas = 4;     // Numéro de la broche à laquelle est connecté le fin de course
const int Fin_Course_Haut = 5;  // Numéro de la broche à laquelle est connecté le fin de coursE
Servo myservo;

void setup() {
  pinMode(Fin_Course_Bas, INPUT);
  pinMode(Fin_Course_Haut, INPUT);
  myservo.attach(9);
  Serial.begin (9600); // initaialisation port série
}

void Montee () {
  topDepart = millis();
  myservo.write(180);
}

void Descente () {
  topDepart = millis();
  myservo.write(0);
}

void OFF () {
  myservo.write (90);
}

void loop() {
  Val_Photo = analogRead (photo); // valeur capteur lumière
  porteOuverte = !digitalRead (Fin_Course_Haut);
  porteClose = !digitalRead (Fin_Course_Bas);
  ouvert = porteClose ? false : true;// suppose la porte en fin de course
  Serial.print("Val_Photo");
  Serial.println(Val_Photo);

  if (!ouvert && Val_Photo > Val_luce) {
    if (porteClose)Montee();
    if (porteOuverte || millis() - topDepart > dureemax) {
      OFF();
      ouvert = true;
    }
  }

  if (ouvert && Val_Photo < Val_luce) {
    if (porteOuverte)Descente();
    if (porteClose || millis() - topDepart > dureemax) {
      OFF();
      ouvert = false;
    }
  }
}

Le code ci dessus n'a pas été essayé.
Si je peut me permettre quelques conseils :

2 secondes de fermeture c'est rapide, voir si myservo.write(80); ou autre valeur intermédiaire permet de ralentir ?
Un seuil de luminosité pour le lever quand le jour est déjà bien présent permettrai d'éviter le yoyo qui risque d'arriver si la luminosité est variable au moment du seuil(nuages).
Un délai de retard avant ouverture est souhaitable pour éviter les déclenchements intempestifs en cas de flash de lumière.

Bonjour Achess,
merci beaucoup d'avoir pris le temps d'éditer le code, mais malheureusement ça ne marche pas avec mon dispositif. Les FDC ne sont pas pris en compte et le temps non plus.

j'avais mis 2 secondes juste pour les tests.

Du coup je suis un peu perdu ...

Dans ce cas, mets d'abord int dureemax = 20000; dans un premier temps, que tu modifieras par la suite.

J'ai repensé à un truc if (porteOuverte)Descente(); ne va pas fonctionner si le fin de course est défectueux, du coups j'ai ajouté une variable "moteur"

Essaies ce code :

#include <Servo.h>
int Val_Photo ;  //Lecture valeurs capteur lumière
int photo = A0; // PIN capteur lumière
int Val_luce = 30; // Valeur  luminosité
unsigned long topDepart = 0;
int dureemax = 20000; // temps de descente
bool porteClose, porteOuverte, ouvert, moteur;

const int Fin_Course_Bas = 4;     // Numéro de la broche à laquelle est connecté le fin de course
const int Fin_Course_Haut = 5;  // Numéro de la broche à laquelle est connecté le fin de coursE
Servo myservo;

void setup() {
  pinMode(Fin_Course_Bas, INPUT);
  pinMode(Fin_Course_Haut, INPUT);
  moteur = false; // à l'arrêt
  myservo.attach(9);
  Serial.begin (9600); // initaialisation port série
}

void Montee () {
  topDepart = millis();
  myservo.write(180);
  moteur = true; // moteur tourne
}

void Descente () {
  topDepart = millis();
  myservo.write(0);
  moteur = true;
}

void OFF () {
  myservo.write (90);
  moteur = false;
}

void loop() {
  Val_Photo = analogRead (photo); // valeur capteur lumière
  porteOuverte = !digitalRead (Fin_Course_Haut);
  porteClose = !digitalRead (Fin_Course_Bas);
  ouvert = porteClose ? false : true;
  Serial.print("Val_Photo");
  Serial.println(Val_Photo);

  if (!ouvert && Val_Photo > Val_luce) { // jour
    if (!moteur)Montee();// si le moteur ne tourne pas
    if (porteOuverte || millis() - topDepart > dureemax) {
      OFF();
      ouvert = true;
    }
  }

  if (ouvert && Val_Photo < Val_luce) { // nuit
    if (!moteur)Descente();
    if (porteClose || millis() - topDepart > dureemax) {
      OFF();
      ouvert = false;
    }
  }
}