Trappe automatique poulallier à servomoteur (maj210810.ino)

Alimenté par batterie et panneau solaire.

Ouverture dans la paroi : 200 X 200 mm
Trappe en tôle galva 250 X 300 mm, poids ~300 gr
Bras de levier alu de ~250 mm
Contrepoids du même poids que la trappe ~300 gr
Tige d'acier galva 2 mm, longueur en fonction des emplacements.

Le centre de gravité du contrepoids est désaxé pour que la trappe
guillotine reste bien en position haute quand elle est ouverte et
qu'elle ne puisse être remontée quand elle est fermée, blocage
par une vis en butée.
Principe visible sur cette vieille vidéo

Batterie 2Ah 4.8 V (4 éléments LR14) pas essayé autres formats
Résistance 10 ohms limitant le courant de charge à C/30
charge terminée : 68 mA en plein soleil
Charge mesurée par temps couvert : 5 mA
consommation en veille (led power et régulateur enlevés) : 7 µA

La résistance de 4,7 ohm en série avec le servo moteur limite la puissance
et évite le reboot en cas de blocage mécanique.

installer la librairie LowPowerLab/LowPower

actions du bouton :
appui bref :

  • affiche le niveau de batterie
    1 flash : faible, 2 flashs : normal; 3 flashs : chargé au max 5.6 V
  • ouverture ou fermeture forcée en alternance, activé le jour.
  • La fermeture forcée ( variable closDeForce) est annulée au
    crépuscule suivant .
  • appui long > 3 secondes enregistre la valeur "crepuscule"
    en EEPROM 0.
  • pour régler "crepuscule" sur PC : mettre en mode debug et
    régler le potentiommètre de la "bread board" pour obtenir la valeur
    souhaitée sur le moniteur série.

visuRetard : à l'aube et au crépuscule le retard est visualisé
par des flashs de la led à chaque réveil, tout les 8 secondes.
Le nombre de retards est déterminé par la vaariable nbCycle

même trajet pour l'ouverture que fermeture :
150° de trajet d'angle de sermoteur commandé par
150 impulsions espacées de 20 ms = 3 secondes

Le temps de travail du servo-moteur est compté :
arrêt automatique au bout de 4 secondes en cas d'avarie.

Estimation de consommation du servo-moteur
vu sur oscilloscope :
0.75 V sur résistance de 0.5 ohm, 150 impulsions de 3 ms environ,
donne 1.5 A pendant 0,5 secondes = 0.2 mAh(max)
matin et soir = 0.4 mAh/jour + 0.2 mAh de mode veille = 0.6 mAh/jour

10 mn de ciel voilé suffit logiquement à recharger 1 journée de conso.

analogReference(INTERNAL);// 1.1 V coeff 0.00105
permet une mesure sure de la tension de batterie.
La pin 11 en entrée pendant la veille permet d'effacer la consommation
du pont de mesure alimentation batterie.
Résistance de charge à 10 ohm, permet une charge plus rapide
sans surcharge pour applications futures


#include <EEPROM.h>
#include <Servo.h>
#include <LowPower.h>
//#define Debug  // mode test et moniteur série

//* noms des broches entrées/sorties */
const byte pinBouton = 2;
const byte AlimServo = 3;
Servo monServo;// pin 4
const byte led = 10; //
const byte pinPont = 11;
const byte pinPV = A0; // tension panneau
const byte bat = A1; // tension batterie
//const byte pinILS = A2; // ILS 1 = trappe fermée

/* variables */
int addr = 0;
byte val; // crépuscule en EEPROM
int vBat;// 1 M/ 220 k rapport 0,00593
byte batLed;
bool afBat = true;
// résistane 100 k  à UPV; 22 k au moins
byte seuilNuit = 31; // seuil nuit 0.2 v;
int seuilJour = 320; //  seuil jour 1.9 v;
int UPV; // mesure de tension sur le panneau
byte retard = 0; // pour éviter les ouvertures ou fermetures intempestives
byte nbCycle = 4; // fois 8 secondes
bool ouvert; // 1 : trappe ouverte
volatile bool appuiBref = false;
bool closDeForce = false; // état fermeture manuelle forcée
unsigned long chrono = 0; // bouton, appui long
int dureeTravail = 4000; // fermeture normale 3 secondes
unsigned long chronoTravail = 0 ;

void setup()
{
  // initialisation entree/sortie
  pinMode(pinBouton, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(pinBouton), bouton, FALLING);
  pinMode(AlimServo, OUTPUT);
  monServo.attach(4);
  pinMode(led, OUTPUT);
  pinMode(pinPV, INPUT);
  pinMode(bat, INPUT);
  //pinMode(pinILS, INPUT_PULLUP);
  pinMode(pinPont, OUTPUT);// active le pont batterie

 analogReference(INTERNAL);// 1.1 V coeff 0.00105
  //initialisation trappe :
  seuilNuit = EEPROM.read(addr);
  if (seuilNuit == 255)seuilNuit = 35; //
  UPV = analogRead(pinPV);
#ifdef Debug
  Serial.begin(115200);
  Serial.println ("Moniteur série validé") ;
  Serial.print ("seuilNuit = ") ; Serial.print (seuilNuit) ;
  Serial.print (" UPV = ") ; Serial.print (UPV) ;
  Serial.print (" ouvert = ") ; Serial.print (ouvert) ;
  vBat = analogRead(bat); // valeur / 1.15 / 0.049
  Serial.print (" vBat = ") ;  Serial.println (vBat) ;
  delay(10);
#endif // Debug
  // Pour forcer la trappe à se fermer la nuit ou à s'ouvrir le jour.
  if (UPV >= seuilJour) ouvrir(); // jour
  else fermer();
  appuiBref = false;// en dernier sinon ça bug
}

void loop() {
  pinMode(pinPont, INPUT);// coupe le pont batterie
#ifdef Debug
  LowPower.powerDown(SLEEP_1S, ADC_OFF, BOD_OFF); // mise en veille
#else
  LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF); // mise en veille
#endif
  pinMode(pinPont, OUTPUT);// active le pont batterie
  UPV = analogRead(pinPV); // lit la tension aux bornes du PV
#ifdef Debug
  vBat = analogRead(bat);
  Serial.print (" UPV = ") ; Serial.print (UPV) ;
  Serial.print (" vBat = ") ; Serial.print (vBat) ;
  Serial.print (" ouvert = ") ; Serial.print (ouvert) ;
  Serial.print (" closDeForce = ") ; Serial.print (closDeForce) ;
  Serial.print (" appuiBref = ") ; Serial.print (appuiBref) ;
  Serial.print (" retard = ") ; Serial.println (retard) ;
  delay(10);
#endif // Debug

  modemanuel(); // actions du bouton
  if (UPV <= seuilNuit && ouvert)fermeture(); // attends la nuit
  else if (UPV >= seuilJour && !ouvert)ouverture(); // attends le jour
  else retard = 0;//retour en veille
}// fin de loop

void bouton() {// appui bouton déclenche interruption
  chrono = millis();// initialise le compteur
  appuiBref = true; // autorisé si appui bref
}

void modemanuel()
{
  while (!digitalRead(pinBouton))//tant que le bouton est appuyé
  {
    if (millis() - chrono > 3000) // bouton maintenu appuyé 3 secondes
    {
      sauvseuilNuit();
      digitalWrite(led, 1); delay(200);
      digitalWrite(led, 0); // acquit appuiLong
      appuiBref = false; // annule l'appui bref
    }
  }//while

  if (appuiBref) { // le jour, annulé au crépuscule suivante
    testBat();
    if (ouvert && !closDeForce) { // jour
      fermer();
      ouvert = true ; // ne se refermera pas au réveil suivant
      closDeForce = true; // fermé de force
    }
    else if (ouvert && closDeForce) { // désactive le mode
      ouvrir();
      closDeForce = false;
    }
    appuiBref = false;
  }//appuiBref
}

void ouverture() {
  retard++;
  visuRetard();
  if (retard > nbCycle) ouvrir();
}

void fermeture() {
  retard++;
  visuRetard();
  if (retard > nbCycle) {
    if (closDeForce) {  // déjà fermé manuellement
      closDeForce = false;// annule le blocage
      ouvert = false;// rétabli l'état fermé
    }
    else fermer();
  }
}

void ouvrir() {
  chronoTravail = millis();// enregistre le départ
  digitalWrite(AlimServo, 0); // alimente le servomoteur
  for (int i = 175; i >= 20; i--) {// 130°,
    monServo.write(i);
    delay(20);  // trappe fermé en  2.6 secondes
  }
  digitalWrite(AlimServo, 1);
  ouvert = true;
  if (millis() - chronoTravail > dureeTravail) {
    digitalWrite(AlimServo, 1); // sécurité avarie
    ouvert = true;
  }
}

void fermer() {
  chronoTravail = millis();// enregistre le départ
  digitalWrite(AlimServo, 0);
  for (int i = 20; i <= 175; i++) {
    monServo.write(i);
    delay(20);
  }
  digitalWrite(AlimServo, 1);
  ouvert = false; // arrêt normal
  if (millis() - chronoTravail > dureeTravail) {
    digitalWrite(AlimServo, 1); // sécurité avarie
    ouvert = false;
  }
}

void visuRetard() {
  for (int i = 0; i < retard; i ++) {
    digitalWrite(led, 1); delay(25); digitalWrite(led, 0);
    delay(150);
  }
}

void testBat() {
  //  1 M au +, 220 k au - coeff 0.005817
  vBat = analogRead(bat);
#ifdef Debug
  Serial.print ("vBat = ") ;
  Serial.println (vBat) ;
  delay(10);
#endif // Debug
  if (vBat <= 810)batLed = true; // faible < 4.8 V
  else if (vBat > 810 && vBat < 945)
    batLed = 2; // normal entre 4.7 et 5.4 V
  else if (vBat >= 945)batLed = 3; // pleine charge > 5.4 V

  for (int i = 0; i < batLed; i ++) {
    digitalWrite(led, 1); delay(20); digitalWrite(led, 0);
    delay(200);
  }
}

void sauvseuilNuit() { // enregistre le seuil crépuscule
  EEPROM.write(addr, UPV); // 0 à 254 0 à 1.35 V
  seuilNuit = UPV;
}

210810maj.ino (8.9 KB)
servomoteur/695326)


schema
essai

Essais avant implantation :

Le projet initial [Automatisme porte poulailler à servomoteur - Français / Réalisations et Projets Finis - Arduino Forum](https://forum.arduino.cc/t/automatisme-porte-poulailler-a-

Il suffisait de demander. Sujet ré-ouvert.

Merci Henri, mais autant supprimer l'ancien qui n'était pas abouti.