Automatisation arrosage et eclairage pour semi

Bonjour la comunautée,

Voici mon projet, je veux automatisé la gestion de mes semis car je ne peux pas toujours etre chez moi et je viens de perdre 200 semi de beterave par manque de lumiere. Pour ca je veux pouvoir programer une plage horaire d'eclairage UV et une detection d'humidité avec arosage automatique en actionnant une pompe si il y à manque d'eau.

Je debute et ces mon premier projet.

J'ai donc appris des choses et bidouiller un code qui me permet de faire un controle de l'humidité de toute les deux heure et actionner ma pompe un certain temps et de garder la lumiere allumé 6h ( 3 cycle de 2h ) car je me suis rendu compte que l'on ne pouvais pas programer de tache en fond du style " lampe allumé 6h lampe etteinte 18h " et " controle de l'humidite toutes les heure" en même temps, car des que l'on met des notion delay () ces tache par tache.

Donc ca sa fonctionne. Et bien et j'actione ma lampe et pompe avec un relais 220V. Voici mon code. Si vous voyez a le simplifier je suis preneur j'aime apprendre.

int PinHumidite = 0; // redefini le nom de la borne A0 en PinHumidite
int humid;           // Nom donné au relevé de valeur

void setup() {
Serial.begin(9600); // Fixe le débit de communication en nombre de caractères par seconde
pinMode(PinHumidite, INPUT); // capteur
pinMode(5, OUTPUT); // relais POMPE
pinMode(4, OUTPUT); // relais LAMPE
digitalWrite(5, HIGH); // pompe off valeur inversé car le relais est en secuityLOW
digitalWrite(4, HIGH); // lampe off valeur inversé car le relais est en secuityLOW
 }


void loop(){
  pompe();
    lampe_A();
  pompe();
    lampe_A();
  pompe();
    lampe_A();
  pompe();
    lampe_E();
  pompe();
    lampe_E();
  }

void lampe_A (){
  digitalWrite (4, LOW);
  delay (7200000);
}
void lampe_E (){
  digitalWrite (4, HIGH);
  delay (32400000);
}

void pompe (){
humid= analogRead(PinHumidite); // lecture capteur humidité
Serial.println(humid); //affichage humidité

if (humid<400) // if = si sol sec (dans l'eau : 1023, dans l'air 0)
  {
 digitalWrite(5, LOW); // allumage pompe
  Serial.println("pompe on");
  delay(2500); // arrosage 1 secondes
 digitalWrite(5, HIGH); // arret pompe
  Serial.println("pompe off");
  }
}

Seul probleme, si il y a une coupure de courant, et bien la loop se relance et du coup la plante pourait avoir 12h d'UV se qui n'est pas bon.

J'ai donc acheté une puce avec pile DS3231 qui permetrais que si il y a une coupure de courant mon code soit lui basé sur un truc du genre " tu eclaire de 10h à 16h" comme ca meme si ca coupe bien je suis sur qu'il n'y ai pas un sur eclérage.

je les configuré elle m'affiche bien l'heure.

 #include <Wire.h>
 #include <ds3231.h>
 struct ts temps;

void setup() {
  Serial.begin (9600);
Wire.begin ();
DS3231_init (DS3231_INTCN);
}

void loop() {
DS3231_get(&temps);
Serial.print(temps.hour);
Serial.print(":");
Serial.print(temps.min);
Serial.print(".");
Serial.print(temps.sec);
Serial.print("    ");
delay(6000);

}

Mais maintenant j'aimerais savoir allumer et eteindre une led selon un plage horaire.
Puis arriver à combiner mes deux codes pour que tout soit géré en même temps.

je precise, ca fait une semaine que j'ai commencé à " coder " donc toutes les notions que j'aborde son fragile j'ai tout à pprendre.

Merci par avance ^^'

:warning:
Post mis dans la mauvaise section, on parle anglais dans les forums généraux. déplacé vers le forum francophone.

Merci de prendre en compte les recommandations listées dans Les bonnes pratiques du Forum Francophone

Je répond d'abord à ta première question : comment optimiser le code ?
Il y a de nombreuses façons de le faire, en voici une :

#define SECONDE 1000ul
#define HEURE   (3600 * SECONDE)

const int PinHumidite = 0; // redefini le nom de la borne A0 en PinHumidite
const int PinLampe = 4;
const int PinPompe = 5;

const unsigned long dureeA = 2 * HEURE;
const unsigned long dureeE = 9 * HEURE;
char programmation[] = "AAAEE";

void setup() {
  Serial.begin(9600); // Fixe le débit de communication en nombre de caractères par seconde
  pinMode(PinHumidite, INPUT); // capteur
  pinMode(PinPompe, OUTPUT); // relais POMPE
  pinMode(PinLampe, OUTPUT); // relais LAMPE
  digitalWrite(PinPompe, HIGH); // pompe off valeur inversé car le relais est en securityLOW
  digitalWrite(PinLampe, HIGH); // lampe off valeur inversé car le relais est en securityLOW
}


void loop() {
  int longueur = sizeof(programmation) / sizeof(char);
  for (int i = 0; i < longueur; ++i) {
    pompe();
    lampe(programmation[i]);
  }
}

void lampe (char lampe) {
  switch (lampe) {
    case 'A':
      digitalWrite (PinLampe, LOW);
      delay (dureeA);
      break;
    case 'E':
      digitalWrite (PinLampe, HIGH);
      delay (dureeE);
      break;
    default:
      break;
  }
}

void pompe () {
  int humid = analogRead(PinHumidite); // lecture capteur humidité
  Serial.println(humid); //affichage humidité

  if (humid < 400) // if = si sol sec (dans l'eau : 1023, dans l'air 0)
  {
    digitalWrite(PinPompe, LOW); // allumage pompe
    Serial.println("pompe on");
    delay(2500); // arrosage 1 secondes
    digitalWrite(PinPompe, HIGH); // arret pompe
    Serial.println("pompe off");
  }
}

Le principe n'a pas changé, j'ai surtout mis des paramètres pour définir les pins, les durées, et grouper tes deux fonctions d'éclairage en une seule. J'ai aussi automatisé le "programme" d'éclairage grâce à un tableau de caractères, ce qui permet de le changer plus facilement par la suite si nécessaire.
Par exemple, si tu veux modifier les durées et le nombre de phases d'éclairage, il suffit de changer les lignes

const unsigned long dureeA = 2 * HEURE;
const unsigned long dureeE = 9 * HEURE;

qui sont faciles à comprendre, et le code du programme par exemple (ici AAAEE fait 3 phases A (allumage pendant 2 heures) puis 2 phases E (extinction pendant 9 heures)). Tu peux alterner les phases et changer leurs durées, voire faire d'autres types de phases avec d'autres durées : il suffit d'ajouter des durées genre :
const unsigned long dureeB = 1 * HEURE;
de changer le programme (par exemple "ABABAAEE") et d'ajouter un case dans la fonction lampe()

... Mais peut-être que ça ne sert à rien !!! ... :grin:

Edit : ajouté ul dans le premier define

Pour la seconde question : il est souvent pratique de représenter les heures selon un format différent de celui qu'on connait. Par exemple pour 16h12, au lieu de le mettre au format décimal 16.2 on l'écrira 16.12, ce qui est plus facile à lire. On fait comme s'il y avait 100 minutes dans une heure et on ne tient pas compte des 40 dernières. On peut faire pareil pour les secondes, mais je pense que tu n'as pas besoin de cette précision...

Donc, lorsque tu as temps.hour et temps.min, tu peux créer une variable comme ceci :
int now = temps.hour + temps.min / 100;
int now = temps.hour * 100 + temps.min;
Cette valeur, tu peux la comparer avec celles de ta plage horaire. Si tu veux faire quelque chose entre 14h15 et 18h30, il te suffit de faire un test :
if ((1415 < now) && (now < 1830)) { ... }

Si tu as plusieurs plages horaires, tu peux les définir dans des tableaux :

int begin[5] = { 830, 1200, 1530, 1900, 2230};
int end[5]   = {1015, 1345, 1700, 2130, 2355};

Dans ta loop, tu lis l'heure comme tu le fais déjà, tu crées ta valeur now et tu la compares dans une boucle sur l'indice des tableaux :

for (int i = 0; i < 5; ++i) {
  if ((begin[i] < now) && (now < end[i])) {
     // action numéro i ...
   }
}

Le problème qui va se poser c'est si tu as une plage autour de minuit. Dans ce cas, deux solutions :

  • tu fais deux plages : la première s'arrête à minuit, la seconde commence à 0 heure 00
  • tu ajoutes 2400 à la fin de la plage, et tu ajoutes 2400 à l'heure courante pour comparer au début de la plage (un peu plus subtil à faire)

WoW ok, dans les fais j'ai pas l'impression que ca simplifie le code XD En tout cas, ca ma bien cramé le cerveau ^^'

J'aime le concepte du progamme, c'est vraie que si le programe doit etre lomg alors avoir juste a marquer des lettres doit bien simplifié l'ecriture et la lectur. Merci

Alors je ne suis pas sur de tout cesire

int begin[5] = { 830, 1200, 1530, 1900, 2230};
int end[5]   = {1015, 1345, 1700, 2130, 2355};

Cette partit la ma perdu, je ne suiis pas sur de bien la lire. Je comprend pas le code. Pourrais tu m l'expliquer ou me donner un lien pour le comprendre ?

Merci

C'est juste la définition de cinq plages horaires. La première va de 8h30 à 10h15.
Elles sont définies par deux tableaux d'entiers de dimension 5, un pour le début et un pour la fin.

Au temps pour moi, cette formule est fausse. Il faut faire
int now = temps.hour * 100 + temps.min;

Ok la suivente est de 12h00 à 13h45 etc.. Ok merci

je tente de taper le code cette aujourd'hui je reviens vers vous en tout cas merci pour le suivi et le partage

Slaut, je viens de tester ce code la.

 #include <Wire.h>
 #include <ds3231.h>
 struct ts temps;
int now = temps.hour + temps.min / 100;


void setup() {

  Serial.begin (9600);
Wire.begin ();
DS3231_init (DS3231_INTCN);
pinMode( 4, OUTPUT);

}

void loop() {
if ((1415 < now) && (now < 1840)) { 
  digitalWrite (4, HIGH); 
  delay (500);}


DS3231_get(&temps);
Serial.print(temps.hour);
Serial.print(":");
Serial.print(temps.min);
Serial.print(".");
Serial.print(temps.sec);
Serial.print("    ");
delay(6000);

}

Je ne comprend pas pourquoi ma led en pin 4 ne sallume pas à 18h37. J'ai fais tester le code par arduino. Pas d'erreure apparente.

Qu'aurais je fais de mal ?

Le calcul de now doit être au début de la loop.
Tu dois faire

void loop () {
DS3231_get(&temps);
int now = temps.hour * 100 + temps.min;

// Et le reste...

}

Ok, mais je dois louper un truc la XD


 #include <Wire.h>
 #include <ds3231.h>
 struct ts temps;



void setup() {

  Serial.begin (9600);
Wire.begin ();
DS3231_init (DS3231_INTCN);
pinMode( 4, OUTPUT);

}

void loop() {
  
DS3231_get(&temps);
 int now = temps.hour + temps.min / 100;


if ((830 < now) && (now < 1840)) { 
  digitalWrite (4, HIGH); 
  delay (500);}


DS3231_get(&temps);
Serial.print(temps.hour);
Serial.print(":");
Serial.print(temps.min);
Serial.print(".");
Serial.print(temps.sec);
Serial.print("    ");
delay(6000);

}

Le Print se passe bien j'ai bien l'heure qui s'affiche dans le moniteur. Par contre ma led ne s'allume pas. J'ai commencé a me dire que cetait mon branchement qui posais probleme donc j'ai tapé un simple code pinMode et digitalWrite et j'ai bien ma Led allimenté en par la pin 4 qui s'allume.

Et arduino ne detecte pas d'erreure dans mon code. Juste qu'il ne se passe rien ^^

Ohhh Grand LESEPT viens a mon secour XD

Bonjour,

Il ne faut pas diviser par 100. Voir la formule de @lesept au post #11

Reprend ton code pour allumer ta led.
Tu veux l'allumer si now est entre 830 et 1840.
Si elle ne s'allume pas c'est donc que now ne correspond pas à cet intervalle.
Si maintenant on regard l'affectation d'une valeur à now, si on prend au hasard 24:59, cela donne 24+59 /100 = 24,59 arrondi à l'entier le plus près.

Dans ce genre de cas, il serait intéressant que tu affiche d'abord la valeur de now, si tu veux pouvoir debugger ton programme.

Oui, c'est une erreur que j'ai corrigée au post 8 puis encore au post 11 (j'ai aussi corrigé le post 4). Ca va fonctionner avec
int now = temps.hour * 100 + temps.min;

Merci pour cette réponse. @lesept avais corrigé par :

int now = temps.hour * 100 + temps.min;

mais j'ai copier coller la mauvaise formule. Maintenant ma led est allumé. Parcontre j'ai mis

Tif ((830 < now) && (now < 942)) {

Et à 9h43 elle etait toujours allumé. J'ai donc essayé de comprendre et d'appliquer ce qu'a dis @terwal et metre 9,42 mais la nomplus ca reste allumé.

Je me dis que soit je n'ai pas compris l'histoire de divion et conversion d'heure et que donc c'est normal que ca ne se passe pac comme prevu ou soit il manque une ligne de code qui complete la premeire. La premiere dit si il est entre 8h30 et 9h42 tu t'allume et une autre ligne qui dit "passé ça tu t'etteind.

Voila, encore merci à tous !

Un ordinateur ne sait faire que ce qu'on lui dit de faire : tant que tu ne lui dit pas d'éteindre, il ne le fera pas.

if ((830 < now) && (now < 1003)) { 
  digitalWrite (4, HIGH); 
  delay (500);
} else {
  digitalWrite (4, LOW); 
}

Voila le code avec les plages horaires d'allumage de la LED :

#define SECONDE 1000ul
#define MINUTE  (60 * SECONDE)
#define HEURE   (3600 * SECONDE)
#include <Wire.h>
#include <ds3231.h>

const int PinHumidite = 0; // redefinit le nom de la borne A0 en PinHumidite
const int PinLampe = 4;
const int PinPompe = 5;
struct ts temps;

// Définition des plages horaires
const int nbPlages = 5;
int debut[nbPlages] = { 830, 1200, 1530, 1900, 2230};
int fin[nbPlages]   = {1015, 1345, 1700, 2130, 2355};

void setup() {
  Serial.begin (9600);
  Wire.begin ();
  DS3231_init (DS3231_INTCN);
  pinMode(PinHumidite, INPUT); // capteur
  pinMode(PinPompe, OUTPUT); // relais POMPE
  pinMode(PinLampe, OUTPUT); // relais LAMPE
  digitalWrite(PinPompe, HIGH); // pompe off valeur inversé car le relais est en securityLOW
  digitalWrite(PinLampe, LOW); 

void loop() {
  DS3231_get(&temps);
  int now = temps.hour * 100 + temps.min;
  bool allumer = false;

  for (int i = 0; i < nbPlages; ++i) {
    if ((debut[i] < now) && (now < fin[i])) {
      digitalWrite (PinLampe, HIGH);
      allumer = true;
    }
  }
  if (!allumer) digitalWrite (PinLampe, LOW);

  Serial.print(temps.hour);
  Serial.print(":");
  Serial.print(temps.min);
  Serial.print(".");
  Serial.println(temps.sec);
  delay(1 * MINUTE);
}

Tu peux les modifier dans les lignes

int debut[nbPlages] = { 830, 1200, 1530, 1900, 2230};
int fin[nbPlages]   = {1015, 1345, 1700, 2130, 2355};

pour voir la LED s'allumer et s'éteindre comme tu le veux. J'ai mis un délai d'une minute pour l'affichage de l'heure, ça économise l'écran... :stuck_out_tongue_winking_eye:

Ah ouais ! Tu mas fait mon code quoi :sweat_smile:

Merci, je m'en servirais pour apprendre. Je l'essaie et je reviens vers vous.

J'ai juste incorporé tout ce qui s'est dit dans le fil de discussion. Tu peux changer le nombre de plages horaires à la ligne
const int nbPlages = 5;
et bien sûr il faut changer ensuite les lignes suivantes.

Le délai d'une minute risque de faire que l'allumage et l'extinction ne se font pas à hh:mm:00 (à 0 secondes), mais aléatoirement selon le moment où tu lances le code sur l'Arduino. Au pire tu devras attendre 59 secondes pour voir la LED changer...