Portier automatique pour poulailler

c'est généralement un pull-up ou pull-down externe (souvent on utilise celui de la carte mais si le bouton est au bout d'un long fil, le pullup interne ne sera peut être pas suffisant)

Unknown

et sans résistance le long du fil, lorsque vous cliquez vous connectez 5V à la masse directement et ça fait un court circuit. :slight_smile:

Quand un potentiel n'est pas bien défini sur une entrée, avec le bruit électrique, l'entrée peut être fluctuante et indiquer aléatoirement des niveaux "1" ou "0".

Pour éviter ce phénomène, qui rend le montage inutilisable, on place des résistances qui "tirent" l'entrée soit à la masse, soit au Vcc.

On met des résistances de valeur suffisamment fortes pour qu'elles ne gênent pas l'activation à "0" ou à "1".

Tu verras aussi sur des schémas des entrées de transistor MosFet avec une résistance de 10k entre la grille et la masse.
Le fonctionnement est différent : l'entrée grille d'un transistor MosFet présente une résistance extrêmement élevée (c'est favorable) et aussi une capacité non négligeable (c'est très défavorable).
Un Mosfet commandé en impulsion reste passant même quand le signal n'est plus présent sur la grille puisque la capacité d'entrée est chargée et reste chargée.
La résistance de 10 k que l'on ajoute permet de décharger cette capacité et de bloquer le transistor.

Je vous remercie pour ces précisions !

J'ai fait la modif de mon code avec l'ajout des interrupteurs. Le tester sur place étant "compliqué", j'aimerai, si vous avez une idée, que vous me disiez si ça vous semble ok...

Les modifs sont dans mes 2 else if ainsi que dans les void closeDoorEnclos() et closeDoorPoulailler()

//***** Portier double poulailler *****//
// Début: Juillet 2022
// Automatisation de l'ouverture/fermeture des portes du poulailler et de l'enclos.
// Matériel: un arduino Nano, une horloge ds3231, un controleur bridge en H L298N, 2 moteurs 12v 50rpm high torque, 4 capteurs magnétiques.
// Mise en service: Août 2022
// MàJ Septembre 2022: ajout de 2 switch verrouillables.

// Bibliothèques inclues:
#include <Dusk2Dawn.h>
#include <EEPROM.h>
#include <Wire.h>
#include <math.h>
#include <RTClib.h>

// Définition switch:
int switchPoulaillerOn  = 3;  // fil jaune
int switchEnclosOn      = 4;  // fil orange

// Définition capteurs:
int downSensorClose1    = 5;  // fil jaune
int upSensorOpen2       = 6;  // fil vert
int downSensorClose3    = 7;  // fil jaune
int upSensorOpen4       = 8;  // fil vert

// Définition moteurs:
int in1Poulailler       = 9;  // fil noir
int in2Poulailler       = 10; // fil blanc
int in3Enclos           = 11; // fil gris
int in4Enclos           = 12; // fil violet

// Définition module heure temps réel:
RTC_DS3231 rtc;

// Locatlisation GPS et fuseau horaire pour la bibliothèque dusk2dawn
Dusk2Dawn Labastide(43.9163881, 1.357439, +1);

// Déclarations variables:
DateTime now;
int sunrise;
int sunset;
int currentTime;

// MàJ du module RTC à chaque nouvelle connexion.
// à mettre sur "false" après avoir téléversé sur "true" pour éviter une maj suite à une coupure de courant.
const bool debug = true;

void setup(){
    Serial.begin(9600);
    pinMode(in1Poulailler, OUTPUT);
    pinMode(in2Poulailler, OUTPUT);
    pinMode(in3Enclos, OUTPUT);
    pinMode(in4Enclos, OUTPUT);
    pinMode(downSensorClose1, INPUT);
    pinMode(upSensorOpen2, INPUT);
    pinMode(downSensorClose3, INPUT);
    pinMode(upSensorOpen4, INPUT);
    pinMode(switchPoulaillerOn, INPUT);
    pinMode(switchEnclosOn, INPUT);

    rtc.begin();
    
    if (debug){
        Serial.println("Démarrage. Ajustement du RTC");
        rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
    }
    else if (!debug){
        Serial.println("Démarrage. Pas d'ajustement du RTC");
    }
}

void loop(){
    delay(1000);
    now = rtc.now();
    sunrise = Labastide.sunrise(now.year(), now.month(), now.day(), true);
    sunset = Labastide.sunset(now.year(), now.month(), now.day(), true);

    currentTime = ((now.hour()) * 60) + (now.minute());

    afficheHeure(now);
    afficheSunsetSunriseCurrentTime(now);
    controlSensor();
    statutPorte();

    if (currentTime >= sunrise - 10 && currentTime <= sunset + 30 && digitalRead(upSensorOpen2) == 0){
        openDoorPoulailler();
    }
    else if (((currentTime < sunrise - 10 || currentTime > sunset + 30) || digitalRead(switchPoulaillerOn) == 1) && digitalRead(downSensorClose1) == 0){
        closeDoorPoulailler();
    }

    if (currentTime >= sunrise && currentTime <= sunset + 20 && digitalRead(upSensorOpen4) == 0){
        openDoorEnclos();
    }
    else if (((currentTime < sunrise || currentTime > sunset + 20) || digitalRead(switchEnclosOn) == 1) && digitalRead(downSensorClose3) == 0){
        closeDoorEnclos();
    }
}

void doorPoulaillerOpen(){
    digitalWrite(in1Poulailler, 0);
    digitalWrite(in2Poulailler, 1);
}
void doorEnclosOpen(){
    digitalWrite(in3Enclos, 0);
    digitalWrite(in4Enclos, 1);
}

void doorPoulaillerClose(){
    digitalWrite(in1Poulailler, 1);
    digitalWrite(in2Poulailler, 0);
}
void doorEnclosClose(){
    digitalWrite(in3Enclos, 1);
    digitalWrite(in4Enclos, 0);
}

void doorPoulaillerStop(){
    digitalWrite(in1Poulailler, 0);
    digitalWrite(in2Poulailler, 0);
}
void doorEnclosStop(){
    digitalWrite(in3Enclos, 0);
    digitalWrite(in4Enclos, 0);
}

void afficheHeure(DateTime now){
    Serial.print("Date: ");
    Serial.print(now.day());
    Serial.print('/');
    Serial.print(now.month());
    Serial.print('/');
    Serial.print(now.year());
    Serial.print(" | Heure: ");
    Serial.print(now.hour());
    Serial.print(':');
    Serial.print(now.minute());
    Serial.print(':');
    Serial.print(now.second());
    Serial.println();
}

void afficheSunsetSunriseCurrentTime(DateTime now){
    Serial.print("Sunrise: ");
    Serial.print(sunrise);
    Serial.print(" - Sunset: ");
    Serial.print(sunset);
    Serial.print(" - currentTime: ");
    Serial.print(currentTime);
    Serial.println();
}

void controlSensor(){
    Serial.print("Poulailler haut/bas: ");
    Serial.print(digitalRead(upSensorOpen2));
    Serial.print(" / ");
    Serial.print(digitalRead(downSensorClose1));
    Serial.print(" | Enclos haut/bas): ");
    Serial.print(digitalRead(upSensorOpen4));
    Serial.print(" / ");
    Serial.print(digitalRead(downSensorClose3));
    Serial.println();
}

void statutPorte(){
    if (digitalRead(upSensorOpen2) == 0){
        Serial.println("La porte du poulailler est fermée, elle s'ouvre");
    }
    else{
        Serial.println("Le poulailler est ouvert");
    }
    if (digitalRead(upSensorOpen4) == 0){
        Serial.println("La porte de l'enclos est fermée, elle s'ouvre");
    }
    else{
        Serial.println("L'enclos est ouvert");
    }
    if (digitalRead(downSensorClose1) == 0){
        Serial.println("La porte du poulailler est ouverte, elle se ferme");
    }
    else{
        Serial.println("Le poulailler est fermé");
    }
    if (digitalRead(downSensorClose3) == 0){
        Serial.println("La porte de l'enclos est ouverte, elle se ferme");
    }
    else{
        Serial.println("L'enclos est fermé");
    }
    delay(1000);
}

void openDoorPoulailler(){
    statutPorte();
    while (digitalRead(upSensorOpen2) == 0){
        doorPoulaillerOpen();
    }
    doorPoulaillerStop();
    statutPorte();
}
void closeDoorPoulailler(){
    statutPorte();
    while (digitalRead(downSensorClose1) == 0){
        doorPoulaillerClose();
    }
    delay(500);
    doorPoulaillerStop();
    statutPorte();
    while (digitalRead(switchPoulaillerOn) == 1){
        delay(1000);
    }
}

void openDoorEnclos(){
    statutPorte();
    while (digitalRead(upSensorOpen4) == 0){
        doorEnclosOpen();
    }
    delay(1000);
    doorEnclosStop();
    statutPorte();
}
void closeDoorEnclos(){
    statutPorte();
    while (digitalRead(downSensorClose3) == 0){
        doorEnclosClose();
    }
    delay(500);
    doorEnclosStop();
    statutPorte();
    while (digitalRead(switchEnclosOn) == 1){
        delay(1000);
    }
}

Ptite mise à jour!

Installation des switch:

Dans les déclarations des entrées, il fallait en fait indiquer INPUT_PULLUP comme suit et non un simple INPUT

pinMode(switchPoulailler, INPUT_PULLUP);
pinMode(switchEnclos, INPUT_PULLUP);

Et déclarer l'état des switch a 1 quand ils sont relachés,

digitalRead(switchPoulailler) == 1)
digitalRead(switchEnclos) == 1)

Et donc la while que j'ai rajouté dans la fonction de fermeture de chaque porte avec un petit délai pour qu'il teste l'état toutes les 3 secondes et qu'il reste dans la boucle, ou en sorte si l'interrupteur vient a être relâché. État a 0 si le switch est appuyé.

while(digitalRead(switchPoulailler) == 0){
Serial.println("Maintien du poulailler fermé à cause de l'interrupteur.");    
delay(3000);
}

while(digitalRead(switchEnclos) == 0){
Serial.println("Maintien de l'enclos fermé à cause de l'interrupteur.");    
delay(3000);
}

J'ai cependant un soucis avec les pins D3 et D4.
Soit mon support est défaillant (c'est le 2nd que je teste), soit c'est le Arduino...
Aux logs dans la console, l'état du switch reste inchangé quelque soit la position de ce dernier. J'ai évidement essayé d'échanger les switchs et même résultat. Ça ne vient donc pas du switch ni du câblage mais bien soit du support, soit du Arduino... Et je n'ai plus de Pin digital de libre. (PD0 & PD1 ne pouvant pas êtres utilisés)

J'ai encore un support tout neuf, il faut que j'essai avec celui ci et je verrai bien, mais c'est relou...

La suite bientôt

Utilisez HIGH plutôt que 1 ou LOW au lieu de 0 pour tester le résultat du digitalRead(), le code sera plus lisible.

Encore plus lisible c’est de définir de nouveaux termes plus adaptés au sens

#define APPUI LOW

Ou ouvert et fermé etc

Pour votre souci quelle est la longueur du fil qui va aux fins de course ? Le PULLUP interne n’est peut être pas adapté

Bonjour ryugami

Quelle valeur est donnée dans le log?
Normalement en mode PULL_UP c'est 1 (HIGH) qui doit être donné quand le contact ouvert.

Tu as, encore, A0, A1...

Cordialement
jpbbricole

Pour répondre a J-M-L

Environ 10cm de fil, montage identique pour les 2.

Pour répondre a jpbbricole

La valeur donnée dans le log est de 1. Donc ouvert...

Concernant les pin analogique, je "débute", je pensais qu'on ne pouvais pas les utiliser. Y'a-t-il un nommage particulier ou une syntaxe particulière pour ces pins?

Toutes(*) les pins sont « numériques », certaines ont des fonctions en plus comme la possibilité d’être raccordées à une fonction matérielle comme l’ADC pour la lecture de tension ou le port série ou le bus SPI / I2C, le PWM etc…

Donc si vous faites

const byte switchEnclos = A0;

Tout le reste de votre code reste fonctionnel

(*) sur UNO ou Mega. Sur la Nano A6 et A7 ne sont qu’analogiques, câblées en dur avec l’ADC

Je vous remercie! J'essaie ça après ma journée de travail et je ferai un retour ici, merci beaucoup !

Bonjour ryugami

As tu bien un GND sur l'autre contact de ton switch?

Cordialement
jpbbricole

Oui oui, au niveau du branchement c'est tout bon.

J'ai profité d'une pause dans mon taff pour aller téléverser le code avec la modif de l'attribution des pins et là, TADAAAAAAAAAA ça marche!

// Définition switch:
int switchPoulailler    = A1;  // fil bleu/bleu
int switchEnclos        = A0;  // fil vert/violet


Appui sur l'inter de l'enclos, on remarque le changement d'état et le déclenchement de la fermeture de la porte puis du maintient de celle ci fermée, puisque switch == 0.


Je relâche le switch, la porte se ré-ouvre.


Je teste la porte du poulailler car je l'ai changé de Pin. Ça marche également


Je relâche également le switch, la porte se ré-ouvre.

Et petite log générale. Tout baigne!

Merci de votre aide! Je reviendrai sûrement quand je déciderai d'y ajouter le LCD 20x4 et que ça fera 4 jours que je cherche haha.

Déclarez les pins en const byte Au lieu de int, c’est mieux.

Il faudra comprendre pourquoi D3 et D4 ne fonctionnent pas…

Bonjour ryugami

Prends l'affichage avec le petit module
image
qui est en i2C (SDA ou A4 et SCL ou A5). Ce petit module peut être ajouté à un affichage sans.

image

Tu n'as plus assez de pin pour l'afficheur sans module i2C
image

Cordialement
jpbbricole

Oui, j'ai déjà le module sur l'écran :wink:


Je comptais brancher l'écran en série avec le RTC DS3231 du coup.

J'ai déjà préparé une grosse partie du code également.

//Bibliothèques inclues:
#include <Dusk2Dawn.h>
#include <EEPROM.h>
#include <Wire.h>
#include <math.h>
#include <RTClib.h>
#include <LiquidCrystal_I2C.h>

// Définition module heure temps réel:
RTC_DS3231 rtc;

// Définition du LCD:
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);

// Déclarations variables:
int annee = 0;
int mois = 0;
int jours = 0;
int heure = 0;
int minutes = 60;
int secondes = 60;
DateTime now;
int sunrise;
int sunset;
int currentTime;

// MàJ du module RTC à chaque nouvelle connexion. 
// à mettre sur "false" après avoir téléversé sur "true" pour éviter une maj suite à une coupure de courant. 
// Déclaration d'une constante
const bool debug = false;

void setup() {
  Serial.begin(9600);
  rtc.begin();
    if (debug){
      Serial.println("Démarrage. Vérification et ajustement du RTC");
      rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
    }
    else if (!debug){
      Serial.println("Démarrage. Vérification mais pas d'ajustement du RTC");
    }
}

void loop() {
  delay(1000);
  lcd.init();
  lcd.backlight();
  horodatage();
}

void horodatage(){
   lcd.setCursor(0, 0);                // curseur sur 1ere colone, 1ere ligne
   lcd.print("Heure");                 // afficher Heure
   lcd.setCursor(8, 0);                // curseur sur 8eme colone ,1ere ligne
   lcd.print(":");                     // etc...
   lcd.setCursor(11, 0);
   lcd.print(":");
   lcd.setCursor(0, 1);
   lcd.print("Date");
   lcd.setCursor(7, 1);
   lcd.print(":");
   lcd.setCursor(10, 1);
   lcd.print(":");
}

void printInfosTime(){
   lcd.setCursor(0, 2);                 // curseur sur 1ere colone, 3eme ligne
   lcd.print("Sunrise");                // afficher Sunrise
   lcd.setCursor(8, 2);                 // curseur sur 8eme colone ,3eme ligne
   lcd.print(":");                      // etc...
   lcd.setCursor(10, 2);
   lcd.print(sunrise);
   delay(1000);                         
   lcd.setCursor(0, 2);                 
   lcd.print("                   ");    // on efface la ligne
   lcd.setCursor(0, 2);
   lcd.print("Sunset");
   lcd.setCursor(7, 2);
   lcd.print(":");
   lcd.setCursor(10, 2);
   lcd.print(sunset);
   delay(1000);                         
   lcd.setCursor(0, 2);                 
   lcd.print("                   ");   
   lcd.setCursor(0, 2);
   lcd.print("CurrentTime");
   lcd.setCursor(12, 2);
   lcd.print(":");
   lcd.setCursor(14, 2);
   lcd.print(currentTime);
   delay(1000);                         
   lcd.setCursor(0, 2);  
   lcd.print("                   ");
   lcd.setCursor(0, 2);
}

void printSensorInfos(){
   lcd.setCursor(0, 3);             // curseur sur 1ere colone, 4eme ligne
   lcd.print("Poulailler");         // afficher Heure
   lcd.setCursor(11, 3);            // curseur sur 8eme colone ,4eme ligne
   lcd.print(":");                  // etc...
   lcd.setCursor(13, 3);
   lcd.print(statutPoulailler());
   delay(1000);
   lcd.setCursor(0, 3);
   lcd.print("                   ");
   lcd.setCursor(0, 3);             
   lcd.print("Enclos");             
   lcd.setCursor(7, 3);
   lcd.print(":");
   lcd.setCursor(9, 3);
   lcd.print(statutEnclos());
   delay(1000);
   lcd.setCursor(0, 3);
   lcd.print("                   ");
}

void getHeureDate(){
    if (heure != now.hour()){
        lcd.setCursor(6, 0);    // curseur à droite de Heure
        heure = now.hour();     // on verrouille ajuste heure pour que lors du prochaine appel on passe à la suite sans afficher l'heure
        if (heure <10){         // si on on reste en dessous de 10 , l'heure utilise qu'une colone 
            lcd.print("0");     // on met un 0 dans la premiere des deux colone prévue pour l'heure
        }
        lcd.print(heure);
    }

    if (minutes != now.minute()){
        lcd.setCursor(9, 0);
        minutes = now.minute();
        if (minutes <10){
            lcd.print("0");
        }
        lcd.print(minute);
    }
        
    if (secondes != now.second()){
        lcd.setCursor(12, 0);
        secondes = now.second();
        if (secondes <10){
            lcd.print("0");
        }
        lcd.print(secondes);
        }
        
    if (jours != now.day())
        jours = now.day();
        {
        lcd.setCursor(5, 1);
        if (jours <10){
            lcd.print("0");
        }
        lcd.print(jours);
    }

    if (mois != now.month())
        mois = now.month();
        {
        lcd.setCursor(8, 1);
        if (mois <10){
            lcd.print("0");
        }
        lcd.print(mois);
    }
 
    if (annee != now.year())
        annee = now.year();{
            lcd.setCursor(11, 1);
            lcd.print(annee);
    }
} 

J'ignore si ça va marcher, j'ai encore rien testé !

Bonjour ryugami

Ca n'est pas exactement en série, i2C est un bus, c'est à dire que tout les utilisateurs (LCD, RTC...) se connectent sur les mêmes fils, respectivement SDA ou A4 et SCL ou A5 (Pour un UNO).

Quand on fait de l'i2C, l'outil indispensable est le scanner i2C qui permet de voir l'adresses des utilisateurs connectés.

Cordialement
jpbbricole

Je ne comprend pas le schéma...

Mon ds3231 est branché sans résistance...

Ce sont des résistances de pullup internes à l'arduino, ils sont activées par la bibliothèque Wire.

Cf ArduinoCore-avr/twi.c at 2ff00ae7d4e85fa422b7918ee12baf56a1f3006e · arduino/ArduinoCore-avr · GitHub

 // activate internal pullups for twi.
  digitalWrite(SDA, 1);
  digitalWrite(SCL, 1);

Le schéma du post #36, est plus un schéma de principe, le bus i2C étant dit à collecteur ouvert donc nécessitant des résistances de charges. Dans les faits, souvent, sur des modules i2C comme la DS3231 ou l'affichage i2C, ces résiatances sont incluses. Pour "prouver" ceci, il faudrait en étudier le schéma.
Pour ce qui est du couple LCD i2C et DS3231, j'ai fait des essais avec (1.5k) et sans résistances, sans différence quand au fonctionnement.

Sans résistances

TIME	DEC	HEX		 50	100	200	250	400	500	800	[KHz]
------------------------------------------------------------------------------------------------
76312	39	0x27		V	V	V	V	V	V	V
76370	87	0x57		V	V	V	V	V	V	V
76392	104	0x68		V	V	V	V	V	V	V

Avec résistances, 1.5k

TIME	DEC	HEX		50	100	200	250	400	500	800	[KHz]
------------------------------------------------------------------------------------------------
23608	39	0x27		V	V	V	V	V	V	V
23701	87	0x57		V	V	V	V	V	V	V
23757	104	0x68		V	V	V	V	V	V	V

Cordialement
jpbbricole

Merci pour ces précisions!
Je prend notes pour le jour de l'installation du matériel.