Projet ventilateur Grow Box
Dans ce projet on cherche a répondre a un problème qui est la surchauffe de panneau LED dans un Grow Box à l'espace Greenlab. Pour y remédier, le but est de créer un programme sur un Arduino UNO qui va permettre d'activer un ventilateur lorsque la température est trop élevé. Pour l'instant j'ai un schéma de montage avec une carte Arduino UNO branché à un capteur de température qui, en fonction de la température, vas ouvrir ou fermer un relai ce qui aura pour effet d'ouvrir ou de fermer le circuit du ventilateur. Le code que j'ai utilisé est le suivant :
#include <Adafruit_Sensor.h>
#include <DHT.h>
#define DHTpin 2 // pin2 devient le pin du DHT11
#define Relai 3 // pin3 devient le pin du relai
#define DHTTYPE DHT22 // on règle le modèle de capteur
DHT dht(DHTpin, DHTTYPE);
void setup() {
pinMode(DHTpin, INPUT); // règle le pin 2 en input
pinMode(Relai, OUTPUT); // règle le pin 3 en output
Serial.begin(9600); // initialise la comm.
dht.begin(); // allume le capteur
}
void loop() {
delay(2000); //attend un peu entre chaque mesures
float t = dht.readTemperature(); // lit la température exterieur et l'associe à la variable t=température
if ( t >= 25 ) { // si la temérature est au dessus de 35°C
digitalWrite(Relai, HIGH); // le relai se ferme => le ventilateur s'allume
Serial.println("closed");
}
else { // la température est a 35°C ou moins
digitalWrite(Relai, LOW); // le relai s'ouvre => le ventilateur s'arrête
Serial.println("open");
}
if (isnan(t)) {
Serial.println("x("); // verifie le bon fonctionnement du capteur
}
Serial.println(t);
}
Maintenant, il ne reste plus qu'a rajouter des fonctionnalités tels qu'un écran LCD avec possibilité de régler la température de déclenchement, mais aussi des moyens de régler l'hygrométrie !!
J'ai ajouté ci-joint les librairies utilisé dans ce code.
Paul SPIRCKEL : J'ai ajouté un LCD (https://learn.adafruit.com/character-lcds/wiring-a-character-lcd). A chaque déclenchement du relais, il est parasité par de nombreux de caractères mais le circuit fonctionne toujours en arrière-plan.
A noter qu'il faudrait ajouter un petit delta de température de façon à ce que le ventilateur ne s'active/désactive pas sans arrêt autour de 25°C (typiquement ventiler jusqu'à 22°C avant de se désactiver).
Voici le code mis à jour :
#include <Adafruit_Sensor.h>
#include <DHT.h>
#include <LiquidCrystal.h>
#define DHTpin 2 // pin2 devient le pin du DHT11
#define Relai 3 // pin3 devient le pin du relai
#define DHTTYPE DHT22 // on règle le modèle de capteur
DHT dht(DHTpin, DHTTYPE);
LiquidCrystal lcd(7, 8, 9, 10, 11, 12); // connexion des ports de l'écran LCD
void setup() {
pinMode(DHTpin, INPUT); // règle le pin 2 en input
pinMode(Relai, OUTPUT); // règle le pin 3 en output
Serial.begin(9600); // initialise la comm.
dht.begin(); // allume le capteur
lcd.begin(16, 2);
lcd.setCursor(1, 0);
lcd.write("Temperature =");
lcd.setCursor(6, 1);
lcd.write(" C");
}
void loop() {
delay(2000); //attend un peu entre chaque mesures
float t = dht.readTemperature(); // lit la température exterieur et l'associe à la variable t=température
lcd.setCursor(0, 1);
lcd.print(dht.readTemperature());
if ( t <= 25 ) { // si la temérature est au dessus de 35°C
digitalWrite(Relai, HIGH); // le relai se ferme => le ventilateur s'allume
Serial.println("closed");
}
else { // la température est a 35°C ou moins
digitalWrite(Relai, LOW); // le relai s'ouvre => le ventilateur s'arrête
Serial.println("open");
}
if (isnan(t)) {
Serial.println("x("); // verifie le bon fonctionnement du capteur
}
Serial.println(t);
}
Paul SPIRCKEL : J'ai finalisé le code pour 1 ventilateur, avec un delta de température de 3°C et un potentiomètre permettant de choisir le seuil de température à ne pas dépasser. Le LCD ne fonctionne toujours pas correctement. Il peut s'agir d'un problème matériel donc je n'ai rien changé tant que le circuit ne sera pas posé sur une platine. Aussi, il faut faire attention à ne pas allumer le circuit avec le potentiomètre réglé pour une température en dessous de la température ambiante sinon le ventilateur ne s'arrêtera jamais de tourner. Si c'est le cas, il faut juste éteindre le circuit, remonté le potentiomètre et tout rallumer.
#include <Adafruit_Sensor.h>
#include <DHT.h>
#include <LiquidCrystal.h>
#define DHTpin 2 // pin2 devient le pin du DHT11
#define Relai 3 // pin3 devient le pin du relai
#define DHTTYPE DHT22 // on règle le modèle de capteur
DHT dht(DHTpin, DHTTYPE);
LiquidCrystal lcd(7, 8, 9, 10, 11, 12); // connexion des ports de l'écran LCD
int adcPin = A0; // attribution du pin analogique A0 comme entrée du signal du potentiomètre
int poten = 0; // poten est la variable modifiée par le potentiomètre
void setup() {
pinMode(DHTpin, INPUT); // règle le pin 2 en input
pinMode(Relai, OUTPUT); // règle le pin 3 en output
pinMode(adcPin, INPUT); // règle le pin A0 (analogique) comme entrée du signal du potentiomètre
Serial.begin(9600); // initialise la comm.
dht.begin(); // allume le capteur
lcd.begin(16, 2);
lcd.setCursor(0, 0);
lcd.println("Temp =");
lcd.setCursor(0, 1);
lcd.println("Set = ");
}
void loop() {
delay(2000); //attend un peu entre chaque mesures
poten = (analogRead(adcPin)/10); // poten prend comme valeur celle envoyée par le potentiomètre, divisée par 10 pour avoir un interval de température entre 0 et 70°C
Serial.println(3+poten); // on fixe une valeur minimum de T à 3°C de façon à créer un delta en additionnant la valeur poten
lcd.setCursor(6, 1);
lcd.println(3+poten);
if ( dht.readTemperature() >= (3+poten) ) { // si la température est au dessus de (3+poten)
while (dht.readTemperature() >= (poten)) { // et tant qu'elle n'est pas repassée en dessous de poten (donc 3°C en dessous de la valeur de déclenchement), on active le ventilateur
delay(2000);
digitalWrite(Relai, LOW); // le relai se ferme => le ventilateur s'allume
Serial.println(dht.readTemperature());
Serial.println("closed");
lcd.setCursor(7, 0);
lcd.write(dht.readTemperature());
}
}
else { // la température est a 35°C ou moins
digitalWrite(Relai, HIGH); // le relai s'ouvre => le ventilateur s'arrête
Serial.println(dht.readTemperature());
Serial.println("open");
lcd.setCursor(7, 0);
lcd.write(dht.readTemperature());
}
}
Avec 2 relais
#include <Adafruit_Sensor.h>
#include <DHT.h>
#include <LiquidCrystal.h>
#define DHTpin 2 // pin2 devient le pin du DHT11
#define Relai_1 3 // pin3 devient le pin du relai 1
#define Relai_2 4 // pin4 devient le pin du relai 2
#define DHTTYPE DHT22 // on règle le modèle de capteur
DHT dht(DHTpin, DHTTYPE);
LiquidCrystal lcd(7, 8, 9, 10, 11, 12); // connexion des ports de l'écran LCD
int adcPin = A0; // attribution du pin analogique A0 comme entrée du signal du potentiomètre
int poten = 0; // poten est la variable modifiée par le potentiomètre
void setup() {
pinMode(DHTpin, INPUT); // règle le pin 2 en input
pinMode(Relai_1, OUTPUT); // règle le pin 3 en output
pinMode(Relai_2, OUTPUT); // règle le pin 4 en output
pinMode(adcPin, INPUT); // règle le pin A0 (analogique) comme entrée du signal du potentiomètre
Serial.begin(9600); // initialise la comm.
dht.begin(); // allume le capteur
lcd.begin(16, 2);
lcd.setCursor(0, 0);
lcd.println("Temp =");
lcd.setCursor(0, 1);
lcd.println("Set = ");
}
void loop() {
delay(2000); //attend un peu entre chaque mesures
poten = (analogRead(adcPin)/10); // poten prend comme valeur celle envoyée par le potentiomètre, divisée par 10 pour avoir un interval de température entre 0 et 70°C
Serial.println(3+poten); // on fixe une valeur minimum de T à 3°C de façon à créer un delta en additionnant la valeur poten
lcd.setCursor(6, 1);
lcd.println(3+poten);
if ( dht.readTemperature() >= (3+poten) ) { // si la température est au dessus de (3+poten)
while (dht.readTemperature() >= (poten)) { // et tant qu'elle n'est pas repassée en dessous de poten (donc 3°C en dessous de la valeur de déclenchement), on active le ventilateur
delay(2000);
digitalWrite(Relai_1, LOW); // le relai se ferme => le ventilateur s'allume
Serial.println(dht.readTemperature());
Serial.println("closed 1");
lcd.setCursor(7, 0);
lcd.write(dht.readTemperature());
while (dht.readTemperature() >= (poten+2)) { // et tant qu'elle n'est pas repassée en dessous de poten (donc 3°C en dessous de la valeur de déclenchement), on active le ventilateur
delay(2000);
digitalWrite(Relai_2, LOW); // le relai se ferme => le ventilateur s'allume
Serial.println(dht.readTemperature());
Serial.println("closed 2");
}
}
}
else { // la température est a 35°C ou moins
digitalWrite(Relai_1, HIGH); // le relai s'ouvre => le ventilateur s'arrête
Serial.println(dht.readTemperature());
Serial.println("open");
lcd.setCursor(7, 0);
lcd.write(dht.readTemperature());
}
}
Miro Von der Borch : J'ai aujourd'hui tenté de résoudre certains problèmes de la version précédente du code et du montage :
-Des bugs d'affichage sur l'écran LDC
-La communication serial qui ne renvoie rien
-La valeur des potentiomètres qui se fige si elle est en dessous de la température
Une première modification que j'ai apporté a été de brancher le file de contraste directement à la masse pour se débarrasser d'un des potentiomètres inutile. Ensuite, j'ai modifier le code à deux relais en ajoutant des espaces à la fin de chaque print du LCD ce qui a corrigé l'un des bugs d'affichage, mais pas le second qui fait que la première valeur de température du capteur DHT est un caractère étrange. J'ai aussi ajouté des actualisation au sein de chaque "while" de la valeur "poten" :
#include <Adafruit_Sensor.h>
#include <DHT.h>
#include <LiquidCrystal.h>
#define DHTpin 2 // pin2 devient le pin du DHT11
#define Relai_1 3 // pin3 devient le pin du relai 1
#define Relai_2 4 // pin4 devient le pin du relai 2
#define DHTTYPE DHT22 // on règle le modèle de capteur
DHT dht(DHTpin, DHTTYPE);
LiquidCrystal lcd(7, 8, 9, 10, 11, 12); // connexion des ports de l'écran LCD
int adcPin = A0; // attribution du pin analogique A0 comme entrée du signal du potentiomètre
int adcPinfine = A1; // attribution du pin analogique A1 comme entrée su signal du potentiomètre de réglage fin
int poten = 0; // poten est la variable modifiée par les potentiomètres
void setup() {
pinMode(DHTpin, INPUT); // règle le pin 2 en input
pinMode(Relai_1, OUTPUT); // règle le pin 3 en output
pinMode(Relai_2, OUTPUT); // règle le pin 4 en output
pinMode(adcPin, INPUT); // règle le pin A0 (analogique) comme entrée du signal du potentiomètre
Serial.begin(9600); // initialise la comm.
dht.begin(); // allume le capteur
lcd.begin(16, 2);
lcd.setCursor(0, 0);
lcd.println("Temp = ");
lcd.setCursor(0, 1);
lcd.println("Set = ");
}
void loop() {
delay(2000); //attend un peu entre chaque mesures
poten = ((7+analogRead(adcPin)/40)+(analogRead(adcPinfine)/125)); // poten prend comme valeur celle envoyée par le potentiomètre, divisée par 10 pour avoir un interval de température entre 0 et 70°C à laquelle on ajoutte celle d'un deuxième potentiomètre divisé par 100 pour avoir plus de précision
Serial.println(3+poten); // on fixe une valeur minimum de T à 3°C de façon à créer un delta en additionnant la valeur poten
lcd.setCursor(7, 0);
lcd.println(dht.readTemperature());
lcd.setCursor (12, 0);
lcd.println(" C ");
lcd.setCursor (7, 1);
lcd.println(3+poten);
lcd.setCursor (9, 1);
lcd.println (" C ");
if ( dht.readTemperature() >= (3+poten) ) { // si la température est au dessus de (3+poten)
while (dht.readTemperature() >= (poten)) { // et tant qu'elle n'est pas repassée en dessous de poten (donc 3°C en dessous de la valeur de déclenchement), on active le ventilateur
delay(2000);
digitalWrite(Relai_1, LOW); // le relai se ferme => le ventilateur s'allume
Serial.println(dht.readTemperature());
Serial.println("closed 1");
lcd.setCursor(7, 0);
lcd.println(dht.readTemperature());
lcd.setCursor (12, 0);
lcd.println(" C "); // après chaque print de l'écran LCD j'ai rajouter une instruction pour afficher d'une part l'unité mais aussi pour se débarrasser les symboles étranges qui apparraissaient à la fin des print
poten = ((7+analogRead(adcPin)/40)+(analogRead(adcPinfine)/125)); // Ici j'ai ajouté une actualisation de la valeure poten afin d'éviter que la valeur ne se fige
lcd.setCursor (7, 1);
lcd.println(3+poten);
lcd.setCursor (9, 1);
lcd.println (" C ");
while (dht.readTemperature() >= (poten+2)) { // et tant qu'elle n'est pas repassée en dessous de poten (donc 3°C en dessous de la valeur de déclenchement), on active le ventilateur
delay(2000);
digitalWrite(Relai_2, LOW); // le relai se ferme => le ventilateur s'allume
Serial.println(dht.readTemperature());
Serial.println("closed 2");
lcd.setCursor(7, 0);
lcd.println(dht.readTemperature());
lcd.setCursor (12, 0);
lcd.println(" C ");
poten = ((7+analogRead(adcPin)/40)+(analogRead(adcPinfine)/125));
lcd.setCursor (7, 1);
lcd.println(3+poten);
lcd.setCursor (9, 1);
lcd.println (" C ");
}
}
}
else { // la température est a 35°C ou moins
digitalWrite(Relai_1, HIGH); // le relai s'ouvre => le ventilateur s'arrête
Serial.println(dht.readTemperature());
Serial.println("open");
lcd.setCursor(7, 0);
lcd.write(dht.readTemperature());
}
}
Je n'ai cependant pas réussi à faire fonctionner la communication sérial.
Pour le bug d'affichage de la valeur de température du DHT, il n'est pas toujours présent, notamment, l'affichage se fait correctement si les relais sont éteint (le circuit est fermé). Je suspect donc que le problème viens du fait que les relais sont sur la même alimentation que l'écran. Piste à creuser...
Paul SPIRCKEL :
J'ai continué à améliorer le code. J'ai notamment essayé de modifier les boucles while car lorsque la condition n'est plus valide, les signaux déclarés en LOW ne repassent pas en HIGH. Pour ce faire il faut écrire quelque part "digitalWrite(Relai_..., HIGH)". Ainsi plutôt que d'imbriquer 2 boucles while, j'ai essayé de faire démarrer les deux ventilateurs tant que la température n'était pas redescendue en dessous de (2+poten) et une fois sorti de la boucle, que le relai 2 s'ouvre mais que le premier reste bien fermé jusqu'à ce que le if ne soit plus vrai. Un deuxième problème s'est alors posé, la sortie d'une boucle while comprise dans un if renvoie immédiatement au else. Même en essayant de mettre un deuxième while dans le if (pour T < (2+poten), les deux ventilateurs s'éteignent immédiatement.
Ce code n'est clairement pas abouti
#include <Adafruit_Sensor.h>
#include <DHT.h>
#include <LiquidCrystal.h>
#define DHTpin 2 // pin2 devient le pin du DHT11
#define Relai_1 4 // pin3 devient le pin du relai 1
#define Relai_2 5 // pin4 devient le pin du relai 2
#define DHTTYPE DHT22 // on règle le modèle de capteur
DHT dht(DHTpin, DHTTYPE);
LiquidCrystal lcd(7, 8, 9, 10, 11, 12); // connexion des ports de l'écran LCD
int adcPin = A0; // attribution du pin analogique A0 comme entrée du signal du potentiomètre
int adcPinfine = A1; // attribution du pin analogique A1 comme entrée su signal du potentiomètre de réglage fin
int poten = 0; // poten est la variable modifiée par les potentiomètres
void setup() {
pinMode(DHTpin, INPUT); // règle le pin 2 en input
pinMode(Relai_1, OUTPUT); // règle le pin 3 en output
pinMode(Relai_2, OUTPUT); // règle le pin 4 en output
pinMode(adcPin, INPUT); // règle le pin A0 (analogique) comme entrée du signal du potentiomètre
Serial.begin(9600); // initialise la comm.
dht.begin(); // allume le capteur
lcd.begin(16, 2);
lcd.setCursor(0, 0);
lcd.println("Temp = ");
lcd.setCursor(0, 1);
lcd.println("Set = ");
}
void loop() {
delay(2000); //attend un peu entre chaque mesures
poten = ((7+analogRead(adcPin)/40)+(analogRead(adcPinfine)/125)); // poten prend comme valeur celle envoyée par le potentiomètre, divisée par 10 pour avoir un interval de température entre 0 et 70°C à laquelle on ajoutte celle d'un deuxième potentiomètre divisé par 100 pour avoir plus de précision
Serial.println(3+poten); // on fixe une valeur minimum de T à 3°C de façon à créer un delta en additionnant la valeur poten
lcd.setCursor(7, 0);
lcd.println(dht.readTemperature());
lcd.setCursor (12, 0);
lcd.println(" C ");
lcd.setCursor (7, 1);
lcd.println(3+poten);
lcd.setCursor (9, 1);
lcd.println (" C ");
if ( dht.readTemperature() >= (3+poten) ) { // si la température est au dessus de (3+poten)
delay(2000);
Serial.println(dht.readTemperature());
Serial.println("closed 1");
lcd.setCursor(7, 0);
lcd.println(dht.readTemperature());
lcd.setCursor (12, 0);
lcd.println(" C ");
poten = ((7+analogRead(adcPin)/40)+(analogRead(adcPinfine)/125));
lcd.setCursor (7, 1);
lcd.println(3+poten);
lcd.setCursor (9, 1);
lcd.println (" C ");
do {
delay(2000);
digitalWrite(Relai_1, LOW);
digitalWrite(Relai_2, LOW);
Serial.println(dht.readTemperature());
Serial.println("closed 1 & 2");
lcd.setCursor(7, 0);
lcd.println(dht.readTemperature());
lcd.setCursor (12, 0);
lcd.println(" C "); // après chaque print de l'écran LCD j'ai rajouter une instruction pour afficher d'une part l'unité mais aussi pour se débarrasser des symboles étranges qui apparraissaient à la fin des print
poten = ((7+analogRead(adcPin)/40)+(analogRead(adcPinfine)/125)); // Ici j'ai ajouté une actualisation de la valeure poten afin d'éviter que la valeur ne se fige
lcd.setCursor (7, 1);
lcd.println(3+poten);
lcd.setCursor (9, 1);
lcd.println (" C ");
}
while (dht.readTemperature() >= (2+poten)); // et tant qu'elle n'est pas repassée en dessous de poten (donc 3°C en dessous de la valeur de déclenchement), on active le ventilateur
do {
delay(2000);
digitalWrite(Relai_2, HIGH);
Serial.println(dht.readTemperature());
Serial.println("closed 1 & open 2");
lcd.setCursor(7, 0);
lcd.println(dht.readTemperature());
lcd.setCursor (12, 0);
lcd.println(" C "); // après chaque print de l'écran LCD j'ai rajouter une instruction pour afficher d'une part l'unité mais aussi pour se débarrasser des symboles étranges qui apparraissaient à la fin des print
poten = ((7+analogRead(adcPin)/40)+(analogRead(adcPinfine)/125)); // Ici j'ai ajouté une actualisation de la valeure poten afin d'éviter que la valeur ne se fige
lcd.setCursor (7, 1);
lcd.println(3+poten);
lcd.setCursor (9, 1);
lcd.println (" C ");
}
while (dht.readTemperature() < (2+poten)); // et tant qu'elle n'est pas repassée en dessous de poten (donc 3°C en dessous de la valeur de déclenchement), on active le ventilateur
}
else { // la température est à (3+poten) ou moins
digitalWrite(Relai_1, HIGH); // le relai 1 s'ouvre => le ventilateur 1 s'arrête
digitalWrite(Relai_2, HIGH); // le relai 2 s'ouvre => le ventilateur 2 s'arrête
Serial.println(dht.readTemperature());
Serial.println("open");
lcd.setCursor(7, 0);
lcd.write(dht.readTemperature());
}
}
Miro VON DER BORCH (24/11/2023) :
J'ai reproduit le circuit à l'identique dans l'espace prototypage pour pouvoir continuer à avancer dessus. J'ai ainsi apporté les modifications suivantes au circuit :
- J'ai abandonné le capteur DHT trop peu précis (plusieurs degrés d'incertitude) pour un capteur SHT31 bien plus précis (incertitude de l'ordre du dixième de degré à présent). Cependant, il n'apparait pas dans le montage ci-dessous car il se branche pour l'instant sur un shield seeeduino via les port I2C. Mais s'il existe un moyen de contourner le shield je suis preneur.
- J'ai échangé les "slide potentiometer" de chez Arduino pour des potentiomètres rotatif plus précis (8 et 10kOHm) et plus esthétique aussi ! Seulement pour cela j'ai dût ajouter quelques résistances pour éviter tout risque de cours circuit.
- J'ai aussi ajouté trois relais supplémentaire.
- Un qui actionnerais une résistance de chauffe afin d'élever la température de la serre au dessus de la température ambiante.
- Un autre qui actionnerais un système de refroidissement (une pompe à eau par exemple).
- Un dernier qui actionnerais un système de brumisation afin de pouvoir contrôler l'hygrométrie à terme !
- J'ai aussi remis un tout petit potentiomètre pour la luminosité (c'est finalement plus agréable).
J'ai aussi fait un premier aperçut du circuit imprimé que l'on pourrais faire pour ce montage avec toute les modifications que j'ai mentionné plus haut incluse dedans :
Le schéma du circuit sur KiCad
La PCB
Pour ce qui est du code :
- Il faudra maintenant apporter quelques modifications pour l'adapter à la librairie du capteur SHT31 (essentiellement changer les "dht.read" par des "sht.get").
- J'ai connecté
- "résistance de chauffe" -----> pin digitale 5
- "cooler" ---------------------> pin digitale 6
- "système d'humidification" -> pin digital 13
- Il faudrait établir des conditions d'allumage des nouveaux système lié à la régulation de la température, à savoir, le chauffage et le refroidissement actif.
- Il faudrait établir un système de régulation de l'humidité (quand allumer le brumisateur pour humidifier et quand allumer les ventilateurs pour sécher l'air).
- Peut-être aussi que centrer le delta d'allumage autour de la valeur demandé serais plus judicieux pour avoir une meilleur précision. Par ça j’entends, au lieu d'allumer les ventilateurs lorsque la température souhaité est atteinte et les éteindre trois degré en dessous, les allumer un degré au dessus de la valeurs souhaité et les éteindre un degré en dessous de la valeur souhaité
Lors de mes essais pour régler le problème d'affichage qui survenait lorsque les relais s'allumait (Le premier chiffre de la valeur de température lut par le capteur était remplacé par un caractère étrange), je pensai d'abords qu'ils en étaient la cause, mais après quelques essais, les boucles "while", pour une raison que j'ignore, semblent être en cause, en effet le problème survient même si les relais sont déconnectés. Cependant peut-être qu'avec la nouvelle version du code il n'est plus présent.