[RESOLU] Commander moteur en fonction de l'heure

Bonjour,
Pour un système de trappe d'un poulailler. Je souhaite actionner un moteur en fonction de l'heure. J'ai cherché et trouvé plusieurs programmes déjà existants, mais étant novice je n'ai pas tout compris... Du coup j'ai essayé de faire quelque chose de simple par rapport à mon besoin.
J'utilise une carte nano et un DS3231, la partie horloge semble bien fonctionner vu l'affichage du moniteur de série (c'est de la récup). Le programme se compile (c'est déjà ça...) mais je pense que je n'arrive pas a lire et/ou comparer les variables et donc ne pas remplir les bonnes conditions.
Merci d'avance pour votre aide :slight_smile:

// Appel des bibliothèques
#include <Wire.h>
#define ADRESSE_I2C_RTC 0x68
// Déclaration des variables

const int vitesse = 9; // pin PWM permet de régler la vitesse du moteur
const int capteur_bas = 4;
const int capteur_haut = 5;
int cde_moteur_A = 7;
int cde_moteur_B = 8;
int mode = 11;// high = mode manuel
int manuel = 12;

byte seconde, minute, heure, numJourSemaine, numJourMois, mois, annee;
String jourDeLaSemaine[8] = {"","Dim", "Lun", "Mar", "Mer", "Jeu", "Ven", "Sam"};
byte heure_ouverture;
byte minute_ouverture;
byte heure_fermeture;
byte minute_fermeture;

void setup() {
Wire.begin();
Serial.begin(9600);
pinMode (capteur_bas, INPUT);
pinMode (capteur_haut, INPUT);
pinMode (vitesse, OUTPUT);
pinMode (cde_moteur_A, OUTPUT);
pinMode (cde_moteur_B, OUTPUT);
pinMode (mode, INPUT);
pinMode (manuel, INPUT);
}

void loop() {
// Réception de l'heure et de la date
Wire.beginTransmission(ADRESSE_I2C_RTC);
Wire.write(0); // Positionner le pointeur de registre sur 00h
Wire.endTransmission();
Wire.requestFrom(ADRESSE_I2C_RTC, 7);
// Accède aux données de l'horloge (à partir du registre 00h)
seconde = bcdToDec(Wire.read() & 0x7f);
minute = bcdToDec(Wire.read());
heure = bcdToDec(Wire.read() & 0x3f);
numJourSemaine = bcdToDec(Wire.read());
numJourMois = bcdToDec(Wire.read());
mois = bcdToDec(Wire.read());
annee = bcdToDec(Wire.read());

// Affichage de l'heure (moniteur série)
if (heure<10){Serial.print("0");}
Serial.print(heure, DEC);
Serial.print(":");
if (minute<10){Serial.print("0");}
Serial.print(minute, DEC);
Serial.print(":");
if (seconde<10){Serial.print("0");}
Serial.println(seconde, DEC);
// Affichage de la date (moniteur série)
Serial.print(jourDeLaSemaine[numJourSemaine]);
Serial.print(" ");
if (numJourMois<10){Serial.print("0");}
Serial.print(numJourMois, DEC);
Serial.print("/");
if (mois<10){Serial.print("0");}
Serial.print(mois, DEC);
Serial.print("/");
Serial.println(annee, DEC);
delay(1000);


  // parametrage des heures en fonction du mois de l'année (heure au soleil, sans +1 ou +2 heures)
switch (mois){
  case 1:
  case 12:
  heure_ouverture=7;
  minute_ouverture=45;
  heure_fermeture=17;
  minute_fermeture=45;
  break;
  case 2:
  case 11:
  heure_ouverture=7;
  minute_ouverture=30;
  heure_fermeture=18;
  minute_fermeture=15;
  break;
  case 3:
  case 10:
  heure_ouverture=6;
  minute_ouverture=30;
  heure_fermeture=19;
  minute_fermeture=00;
  break;
  case 4:
  case 9:
  heure_ouverture=5;
  minute_ouverture=30;
  heure_fermeture=19;
  minute_fermeture=50;
  break;
  case 5:
  case 8:
  heure_ouverture=5;
  minute_ouverture=00;
  heure_fermeture=20;
  minute_fermeture=30;
  break;
  case 6:
  case 7:
  heure_ouverture=5;
  minute_ouverture=00;
  heure_fermeture=20;
  minute_fermeture=45;
  break;
}
// lecture des capteurs et lancement des cycles de porte
digitalRead(capteur_bas);
digitalRead(capteur_haut);
digitalRead(mode);
digitalRead(manuel);
// mode manuel
if ((mode==HIGH)&&(manuel==HIGH)&&(capteur_bas==HIGH)){
  Serial.print("mode manuel ouverture");// affichage pour test
do{
ouverture();
digitalRead(capteur_haut);
}while (capteur_haut==HIGH);
}
if ((mode==HIGH)&&(manuel==HIGH)&&(capteur_haut==HIGH)){
    Serial.print("mode manuel fermeture");// affichage pour test
do{
fermeture();
digitalRead(capteur_bas);
}while (capteur_bas==HIGH);
}
// mode auto
if ((mode==LOW)&&(heure==heure_ouverture)&&(minute==minute_ouverture)&&(capteur_haut!=HIGH)){
ouverture();
}
if ((mode==LOW)&&(heure==heure_fermeture)&&(minute==minute_fermeture)&&(capteur_bas!=HIGH)){
fermeture();
}
else{
  arret();
}
}
// Convertir les nombres décimaux codés binaires en décimaux normaux
byte bcdToDec(byte val){return( (val/16*10) + (val%16));}


// sous programmes de cycles de portes
void ouverture(){
digitalWrite (cde_moteur_A,HIGH);
digitalWrite (cde_moteur_B,LOW);
analogWrite (vitesse,50);
}
void fermeture(){
digitalWrite (cde_moteur_A,LOW);
digitalWrite (cde_moteur_B,HIGH);
analogWrite (vitesse,50);
}
void arret(){
digitalWrite (cde_moteur_A,LOW);
digitalWrite (cde_moteur_B,LOW);
analogWrite (vitesse,0);
}

Salut.
Je vois bien ce qui est fait : avoir une heure d'ouverture fermeture en fonction de la saison.

Il y a plus simple, avec les fonctions sun_set() et sun_rise() ce que j'ai fait sur mon propre système :
https://bitbucket.org/henri_bachetti/mysensors-gate/src/master/arduino/mysensors-gate/timedate.cpp

voir la méthode GateScheduler::isDay()

https://bitbucket.org/henri_bachetti/mysensors-gate/src/master/arduino/mysensors-gate/timedate.h

Par contre cela suppose plusieurs choses :
Je travaille avec la librairie RTClib.
Dans mon cas, l'heure est stockée dans la RTC en heure locale, mais les fonctions sun_set() et sun_rise() travaillent en temps universel, donc il y a pas mal de code pour gérer les aspects fuseau horaire et heure d'été / hiver.
L'autre solution est de régler le RTC en heure UTC, la gestion sera beaucoup plus simple.

Salut,
Merci beaucoup pour ton retour et le partage. J'ai regardé tes liens et je suis perdu, je suis loin de ce niveau pour pouvoir les utiliser. J'avoue aussi que j'aimerais bien comprendre ce qui ne fonctionne pas sur ce que j'ai fait.
J'ai refait des tests et j'ai déjà un problème sur la déclaration des broches. Si je prend l'exemple de la broche 4, voici ce que j'ai fait:

const int capteur_bas = 4;
pinMode (capteur_bas, INPUT);

Avec ceci je pensais déclarer ma broche 4 comme une entrée portant le nom de "capteur_bas", donc avoir une valeur de 0 ou 1 en fonction de l'état du bouton.
Mais cela me renvoie la valeur 4 , le numéro de la broche...

Bonjour,

capteur_bas c'est le nom de la pin. Pour lire la pin c'est digitalRead(capteur_bas)

Ce qui est sûr est que cette ligne ne sert pas à grand chose :

digitalRead(capteur_bas);

digitalRead() retourne une valeur. Si tu te contentes de tester la valeur de capteur_bas cela ne peut pas fonctionner.

Bonjour,
J'utilisais le digitalRead() mais je ne faisais pas de sauvegarde de l'état de la pin... vos remarques m'ont permis de voir cela, merci. Du coup j'ai bien avancé sur le programme, il n'est pas parfait mais après avoir corrigé quelques erreurs dans les instructions, il fonctionne :slight_smile:
Il me reste encore à traiter le temps de réaction lorsque les capteurs de fin de course sont atteints. Ils sont trop long et le câble risque de se détendre en butée basse et de forcer en butée haute.
Voici ou j'en suis et encore merci à vous deux.

// Appel des bibliothèques
#include <Wire.h>
#define ADRESSE_I2C_RTC 0x68

// Déclaration des variables

const int vitesse = 9; // pin PWM permet de régler la vitesse du moteur
const int capteur_bas = 4;
const int capteur_haut = 5;
const int cde_moteur_A = 7;
const int cde_moteur_B = 8;
const int bouton_mode = 11;// high = mode manuel
const int bouton_manuel = 12;

int bas = 0;
int haut = 0;
int mode = 0;
int manuel = 0;

byte seconde, minute, heure, numJourSemaine, numJourMois, mois, annee;
String jourDeLaSemaine[8] = {"","Dim", "Lun", "Mar", "Mer", "Jeu", "Ven", "Sam"};
byte heure_ouverture;
byte minute_ouverture;
byte heure_fermeture;
byte minute_fermeture;

void setup() {
pinMode(capteur_bas, INPUT); //capteur bas
pinMode(capteur_haut, INPUT);
pinMode(vitesse, OUTPUT);
pinMode(cde_moteur_A, OUTPUT);
pinMode(cde_moteur_B, OUTPUT);
pinMode(mode, INPUT);
pinMode(manuel, INPUT);
Wire.begin();
Serial.begin(9600);

}

void loop() {
// Réception de l'heure et de la date
Wire.beginTransmission(ADRESSE_I2C_RTC);
Wire.write(0); // Positionner le pointeur de registre sur 00h
Wire.endTransmission();
Wire.requestFrom(ADRESSE_I2C_RTC, 7);
// Accède aux données de l'horloge (à partir du registre 00h)
seconde = bcdToDec(Wire.read() & 0x7f);
minute = bcdToDec(Wire.read());
heure = bcdToDec(Wire.read() & 0x3f);
numJourSemaine = bcdToDec(Wire.read());
numJourMois = bcdToDec(Wire.read());
mois = bcdToDec(Wire.read());
annee = bcdToDec(Wire.read());

// Affichage de l'heure (moniteur série)
if (heure<10){Serial.print("0");}
Serial.print(heure, DEC);
Serial.print(":");
if (minute<10){Serial.print("0");}
Serial.print(minute, DEC);
Serial.print(":");
if (seconde<10){Serial.print("0");}
Serial.println(seconde, DEC);
// Affichage de la date (moniteur série)
Serial.print(jourDeLaSemaine[numJourSemaine]);
Serial.print(" ");
if (numJourMois<10){Serial.print("0");}
Serial.print(numJourMois, DEC);
Serial.print("/");
if (mois<10){Serial.print("0");}
Serial.print(mois, DEC);
Serial.print("/");
Serial.println(annee, DEC);
delay(1000);


  // parametrage des heures en fonction du mois de l'année (heure au soleil, sans +1 ou +2 heures)
switch (mois){
  case 1:
  case 12:
  heure_ouverture=7;
  minute_ouverture=45;
  heure_fermeture=17;
  minute_fermeture=45;
  break;
  case 2:
  case 11:
  heure_ouverture=7;
  minute_ouverture=30;
  heure_fermeture=18;
  minute_fermeture=15;
  break;
  case 3:
  case 10:
  heure_ouverture=6;
  minute_ouverture=30;
  heure_fermeture=19;
  minute_fermeture=1;
  break;
  case 4:
  case 9:
  heure_ouverture=5;
  minute_ouverture=30;
  heure_fermeture=19;
  minute_fermeture=50;
  break;
  case 5:
  case 8:
  heure_ouverture=5;
  minute_ouverture=1;
  heure_fermeture=20;
  minute_fermeture=30;
   Serial.println("test prise en charge du mois");// affichage pour test
   Serial.println(mois);
  break;
  case 6:
  case 7:
  heure_ouverture=5;
  minute_ouverture=1;
  heure_fermeture=20;
  minute_fermeture=45;
  break;
}
// lecture des capteurs et lancement des cycles de porte
bas = digitalRead(capteur_bas);
haut = digitalRead(capteur_haut);
mode = digitalRead(bouton_mode);
manuel = digitalRead(bouton_manuel);
Serial.println(minute_fermeture);// affichage pour test
Serial.println(mode);// affichage pour test
Serial.println(manuel);// affichage pour test
Serial.println(bas);// affichage pour test
Serial.println(haut);// affichage pour test
Serial.println(vitesse);// affichage pour test
// mode manuel
if ((mode==HIGH)&&(manuel==HIGH)&&(bas==HIGH)){
  Serial.println("mode manuel ouverture");// affichage pour test
while(haut!=HIGH){
ouverture();
haut = digitalRead(capteur_haut);
}
}
if ((mode==HIGH)&&(manuel==HIGH)&&(haut==HIGH)){
    Serial.println("mode manuel fermeture");// affichage pour test
while(bas!=HIGH){
fermeture();
bas = digitalRead(capteur_bas);
}
}
// mode auto
if ((mode==LOW)&&(heure==heure_ouverture)&&(minute==minute_ouverture)&&(haut!=HIGH)){
while(haut!=HIGH){
ouverture();
haut = digitalRead(capteur_haut);
}}

if ((mode==LOW)&&(heure==heure_fermeture)&&(minute==minute_fermeture)&&(bas!=HIGH)){
while(bas!=HIGH){
fermeture();
bas = digitalRead(capteur_bas);
}
}
else{
  arret();
}
}
// Convertir les nombres décimaux codés binaires en décimaux normaux
byte bcdToDec(byte val){return( (val/16*10) + (val%16));}


// sous programmes de cycles de portes
void ouverture(){
  Serial.println("ouverture");// affichage pour test
analogWrite (vitesse,100);
digitalWrite (cde_moteur_A,HIGH);
digitalWrite (cde_moteur_B,LOW);
}
void fermeture(){
analogWrite (vitesse,100);
digitalWrite (cde_moteur_A,LOW);
digitalWrite (cde_moteur_B,HIGH);
}
void arret(){
analogWrite (vitesse,0);
digitalWrite (cde_moteur_A,LOW);
digitalWrite (cde_moteur_B,LOW);
}

Ce soir être le delay (1000) qui rend ton programme peu réactif.

Si ce delay ne sert qu'à ralentir l'affichage de l'heure, il faut utiliser millis pour ça et laisser la loop tourner à pleine vitesse.

Bonjour,
Effectivement le delay ne sert que pour l'affichage. J'ai fait un test sans et c'est nettement mieux.
J'ai réalisé le montage définitif et cela fonctionne.

Merci à tous d'avoir pris le temps de m'aider.

Oui mais ma c'est ton afficheur qui rame à fond, alors qu'il ne devrait être sollicité qu'une fois par seconde.

Bonjour,
Pour l'afficheur, j'utilise le moniteur de série, c'est juste pour m'aider à débugger le programme.