Gestion Aquarium (température et Niveau Eau)

Bonjour,

Voici mes premiers pas sur ce forum.
Je vais sans doute faire des ajouts ultérieurement, car le projet va évoluer (boitier en 3D, etc...)

N'hésitez pas à me donner vos avis/impressions :wink:

Objectif:
Mon objectif principal était d'automatiser la gestion "de base" de mon aquarium à crevette d'eau douce, soit :
1| Gestion de la température :

  • Si la température dépasse la valeur de consigne (réglable) => Activation d'un ventilateur de PC fixé au dessus de l'eau pour la refroidir
    2| Gestion du niveau d'eau :
  • Si le flotteur est au niveau bas => Activation de la pompe de remplissage

Le tout avec une visualisation des actions sur un écran LCD :wink:

Vidéo :

Matériels:

  • Carte Arduino Uno R3
  • Ecran LCD 2004 I2C
  • Flotteur
  • Sonde température ds18b20
  • Carte 2 x Relais
  • 2 Interrupteurs
  • 5 résistances 220 Ohm
  • 1 résistance 4,7 Ohm

Schéma de câblage :
Voir pièce jointe...

Programme :

#include <Wire.h> 
#include <LiquidCrystal_I2C.h>
#include <OneWire.h> //Librairie du bus OneWire
#include <DallasTemperature.h> //Librairie du capteur
OneWire oneWire(6); //Bus One Wire sur la pin 6 de l'arduino
DallasTemperature sensors(&oneWire); //Utilistion du bus Onewire pour les capteurs
DeviceAddress sensorDeviceAddress; //Vérifie la compatibilité des capteurs avec la librairie

// Déclaration des entrées
int interventil = 2 ; //signal interrupteur Ventil sur la pin 2 de l'arduino
int inter = 3 ; //signal interrupteur Pompe sur la pin 3 de l'arduino
int boutonm = 4; // bouton diminution consigne sur la pin 4 de l'arduino
int boutonp = 5; // bouton augmentation consigne sur la pin 5 de l'arduino
int flotteur = 7;//signal du flotteur sur la pin 7 de l'arduino

// Déclaration des Sorties
int pompe = 12 ;//sortie Pompe sur la pin 12 de l'arduino = Pompe à eau
int ventil = 13 ;//sortie ventilation sur la pin 13 de l'arduino

int etatinter = 0; // variable qui sera utilisée pour stocker l'état de l'inter Pompe
int etatinterventil = 0; // variable qui sera utilisée pour stocker l'état de l'inter Ventil
int etatflotteur = 0; // variable qui sera utilisée pour stocker l'état du flotteur
int etatboutonm = 0; // variable bouton diminution consigne
int etatboutonp = 0; // variable bouton augmentation consigne
int varx=23;// Consigne de température max souhaitée
int cpt=23;// Consigne de température max souhaitée

// création des images spécifiques du LCD (flèche haute, carré vide, etc...)
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);  // Set the LCD I2C address
byte carrevide [8] = {
B11111,
B10001,
B10001,
B10001,
B10001,
B10001,
B10001,
B11111,
};
byte carreplein [8] = {
B11111,
B11111,
B11111,
B11111,
B11111,
B11111,
B11111,
B11111,
};
byte smiley [8] = {
B00000,
B01010,
B00000,
B00000,
B10001,
B01110,
B00000,
B00000,
};
byte flechehaut [8] = {
B00100,
B01110,
B10101,
B00100,
B00100,
B00100,
B00100,
B00100,
};
byte flechebas [8] = {
B00100,
B00100,
B00100,
B00100,
B00100,
B10101,
B01110,
B00100,
};
byte interouv [8] = {
B10000,
B10000,
B10010,
B00100,
B01000,
B10000,
B10000,
B10000,
};
byte interferm [8] = {
B10000,
B10000,
B11110,
B00100,
B01000,
B10000,
B10000,
B10000,
};


/** Fonction setup() */
void setup() {

// Déclaration des entrées/sorties
pinMode(interventil, INPUT); //déclarer l'entrée inter qui est sur pin 2
pinMode(boutonp, INPUT);//déclarer l'entrée bouton+ qui est sur pin 5
pinMode(boutonm, INPUT);//déclarer l'entrée bouton+ qui est sur pin 4
pinMode(flotteur, INPUT); //déclarer l'entrée flotteur qui est sur pin 7
pinMode(ventil, OUTPUT); //déclarer la sortie "ventil" qui est sur pin 13
pinMode(inter, INPUT); //déclarer l'entrée inter qui est sur pin 3
pinMode(pompe,OUTPUT); //déclarer la sortie "pompe" qui est sur pin 12

/*Serial.begin(9600);  // Init connection serie*/

//messages sur LCD démarrage de la solution 
lcd.begin(20,4); 
lcd.setCursor(2,0);
lcd.print("Gestion Aquarium");
lcd.setCursor(7,1);
lcd.print("Tony G");
lcd.setCursor(0,3);
lcd.print("v1.2 - 05 avril 2020");
lcd.setCursor(8,2);
lcd.print("----");
delay (3000);
lcd.begin(20,4); 

// création des images spécifiques du LCD (flèche haute, carré vide, etc...)
lcd.createChar (0,carrevide);
lcd.createChar (1,carreplein);
lcd.createChar (2,smiley);
lcd.createChar (3,flechehaut);
lcd.createChar (4,flechebas);
lcd.createChar (5,interouv);
lcd.createChar (6,interferm);

/*sensors.begin(); //Activation du capteur de temp
sensors.getAddress(sensorDeviceAddress, 0); //Demande l'adresse du capteur à l'index 0 du bus
sensors.setResolution(sensorDeviceAddress, 12); //Résolutions possibles: 9,10,11,12*/

}


void loop() 
{

// Ecriture des messages fixes sur LCD
lcd.setCursor(0,0); //postionne le curseur sur le 1er digit et 1ère ligne du LCD
lcd.print("Niveau :");//ecrit Niveau : sur le LCD
lcd.setCursor(0,1);
lcd.print("I/O :");
lcd.setCursor(9,1);
lcd.print("P:");
lcd.setCursor(14,1);
lcd.print("V:");
lcd.setCursor(0,2);
lcd.print("Temperature :");
lcd.setCursor(0,3);
lcd.print("Consigne :");
lcd.setCursor(11,3);
lcd.print (varx);
lcd.setCursor(13,3);
lcd.print (".00C");

/*// Visu de l'état du flotteur sur connexion série
Serial.print("Etat Flotteur : ");
Serial.println(etatflotteur, BIN); //saut de ligne et en binaire
Serial.print("Etat inter : ");
Serial.println(etatinter, BIN); //saut de ligne et en binaire
Serial.print("Etat inter 2 : ");
Serial.println(interventil, BIN); //saut de ligne et en binaire
delay (20);*/

// lecture des états inter et flotteur
etatflotteur = digitalRead(flotteur);// lit l'état du bouton et stocke le résultat dans etatflotteur
etatinter = digitalRead(inter);// lit l'état de et stocke le résultat dans etatinter
etatinterventil = digitalRead(interventil);// lit l'état de et stocke le résultat dans etatinterventil
etatboutonp = digitalRead(boutonp);
etatboutonm = digitalRead(boutonm);

sensors.requestTemperatures(); //Demande la température au capteur
/* Serial.print("La température est: ");
Serial.print(sensors.getTempCByIndex(0)); //Récupération de la température en celsius du capteur n°0
Serial.println(" C°");*/
lcd.setCursor(14,2);
lcd.print(sensors.getTempCByIndex(0));
lcd.setCursor(19,2);
lcd.print("C");



//GESTION DE LA SORTIE POMPE
// Si inter pompe est à 5V (HIGH) = marche forcee de la pompe
if (etatinter==HIGH) { 
digitalWrite(pompe, HIGH);
lcd.setCursor(12,1);
lcd.write (byte(6)); //affichage sur LCD du symbole 
delay (20);
}
else {
lcd.setCursor(12,1);
lcd.write (byte(5)); //affichage sur LCD du symbole 
delay (20);
}

// Si le flotteur est niveau haut (0V) et que l'inter pompe est désactivée (0V) = Pas de Pompe
if (etatflotteur==LOW && etatinter!=HIGH) { // 
digitalWrite(pompe, LOW);
lcd.setCursor(11,1);
lcd.write (byte(0));
delay (20);
}
else  {   
digitalWrite(pompe, HIGH);
lcd.setCursor(11,1);
lcd.write (byte(1));
delay (20);
}

//conditions en fct du niveau flotteur si 5v = niveau bas et affiche sur LCD Bas et flèche vers le haut
if (etatflotteur==HIGH) { // Si etatflotteur est à 5V (HIGH) c'est que le niveau est bas
lcd.setCursor(9,0);
lcd.print("Bas  ");
lcd.setCursor(19,0);
lcd.write (byte(4));
delay (20);
}
else {
lcd.setCursor(9,0);
lcd.print("Haut  ");
lcd.setCursor(19,0);
lcd.write (byte(3));
delay (20); 
}



//GESTION DE LA TEMPERATURE ET MESSAGES LCD
// Incrementation de la variable consigne temp grace au bouton+
if (etatboutonp==HIGH) { 
cpt++; // Incremantation du compteur
varx = cpt; // memorisation du compteur
delay (20);
}
// Décrementation de la variable consigne temp grace au bouton+
if (etatboutonm==HIGH) { 
cpt--; // Décremantation du compteur
varx = cpt; // memorisation du compteur
delay (20);
}

// Si inter Ventil est à 5V (HIGH) = marche forcee de la ventil
if (etatinterventil==HIGH) { 
digitalWrite(ventil, HIGH);
lcd.setCursor(17,1);
lcd.write (byte(6));
delay (20);
}
else {
lcd.setCursor(17,1);
lcd.write (byte(5));
delay (20);
}

// Si la température mesurée est < à la consigne et que l'inter Ventil est désactivée (0V) = Pas de ventilation
if (sensors.getTempCByIndex(0)<cpt && etatinterventil!=HIGH) { // 
digitalWrite(ventil, LOW);
lcd.setCursor(16,1);
lcd.write (byte(0));
delay (20);
}
else  {   // en revanche, si la température mesurée est > à la consigne = ventilation
digitalWrite(ventil, HIGH);
lcd.setCursor(16,1);
lcd.write (byte(1));
delay (20);
}


}

Schéma cablage.pdf (645 KB)

Salut

Techniquement le coup du ventilo pour refroidir l'eau, j'y crois moyen ... En surface à la rigueur mais pas le fond ..
Tout dépend le volume et la vitesse de régulation souhaitée mais je pense qu'il faut que tu jettes un coup d'oeil des solutions de type watercooling avec des échangeurs , des peltiers etc ..

L'eau c'est une "catastrophe" niveau inertie ... (tout dépend de ce que l'on veut faire avec évidemment).

:wink:

Salut,

Pour ma part, j'utilise cette technique depuis 2 ans sur un nano aquarium de 20 litres.
Sur lequel j'ai installé un ventilateur de PC 120 mm juste au dessus du refoulement de mon filtre.
Ma sonde de température se trouve quasiment dans le fond de l'aquarium et ça fonctionne plutôt bien (suffisant pour mon utilisation).

Après il est sur qu'en fonction du volume...

Je vais tout de même regarder ce que tu évoques (watercooling) :wink:

Merci pour ton retour :wink:

Maj du 12/04/20 :
Ajout d'un capteur de niveau d'eau (carte GZF-12) permettant de ne pas faire fonctionner la pompe de remplissage lorsque le réservoir est vide (niveau bas).

1- Modification de l'affichage LCD
2- Modification de la gestion de la pompe
3- Maj du schéma de câblage

#include <Wire.h> 
#include <LiquidCrystal_I2C.h>
#include <OneWire.h> //Librairie du bus OneWire
#include <DallasTemperature.h> //Librairie du capteur
OneWire oneWire(6); //Bus One Wire sur la pin 6 de l'arduino
DallasTemperature sensors(&oneWire); //Utilistion du bus Onewire pour les capteurs
DeviceAddress sensorDeviceAddress; //Vérifie la compatibilité des capteurs avec la librairie

// Déclaration des entrées
int interventil = 2 ; //signal interrupteur Ventil sur la pin 2 de l'arduino
int inter = 3 ; //signal interrupteur Pompe sur la pin 3 de l'arduino
int boutonm = 4; // bouton diminution consigne sur la pin 4 de l'arduino
int boutonp = 5; // bouton augmentation consigne sur la pin 5 de l'arduino
int flotteur = 7;//signal du flotteur sur la pin 7 de l'arduino
int niv = 8;//signal du niveau réservoir sur la pin 8 de l'arduino

// Déclaration des Sorties
int pompe = 12 ;//sortie Pompe sur la pin 12 de l'arduino = Pompe à eau
int ventil = 13 ;//sortie ventilation sur la pin 13 de l'arduino

int etatinter = 0; // variable qui sera utilisée pour stocker l'état de l'inter Pompe
int a ;
int etatniv = 0; // variable qui sera utilisée pour stocker l'état du capteur de niveau dans le réservoir
int b ;
int etatflotteur = 0; // variable qui sera utilisée pour stocker l'état du flotteur
int c ;
int v;

int etatinterventil = 0; // variable qui sera utilisée pour stocker l'état de l'inter Ventil
int etatboutonm = 0; // variable bouton diminution consigne
int etatboutonp = 0; // variable bouton augmentation consigne
int varx=23;// Consigne de température max souhaitée
int cpt=23;// Consigne de température max souhaitée
int x=0;


// création des images spécifiques du LCD (flèche haute, carré vide, etc...)
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);  // Set the LCD I2C address
byte carrevide [8] = {
  B11111,
  B10001,
  B10001,
  B10001,
  B10001,
  B10001,
  B10001,
  B11111,
};
byte carreplein [8] = {
  B11111,
  B11111,
  B11111,
  B11111,
  B11111,
  B11111,
  B11111,
  B11111,
};
byte smiley [8] = {
  B00000,
  B01010,
  B00000,
  B00000,
  B10001,
  B01110,
  B00000,
  B00000,
};

byte smiley2 [8] = {
  B00000,
  B01010,
  B00000,
  B00000,
  B01110,
  B10001,
  B00000,
  B00000,
};

byte flechehaut [8] = {
  B00100,
  B01110,
  B10101,
  B00100,
  B00100,
  B00100,
  B00100,
  B00100,
};
byte flechebas [8] = {
  B00100,
  B00100,
  B00100,
  B00100,
  B00100,
  B10101,
  B01110,
  B00100,
};
byte interouv [8] = {
  B10000,
  B10000,
  B10010,
  B00100,
  B01000,
  B10000,
  B10000,
  B10000,
};
byte interferm [8] = {
  B10000,
  B10000,
  B11110,
  B00100,
  B01000,
  B10000,
  B10000,
  B10000,
};


/** Fonction setup() */
void setup() {

// Déclaration des entrées/sorties
 pinMode(interventil, INPUT); //déclarer l'entrée inter qui est sur pin 2
 pinMode(inter, INPUT); //déclarer l'entrée inter qui est sur pin 3
 pinMode(boutonp, INPUT);//déclarer l'entrée bouton+ qui est sur pin 5
 pinMode(boutonm, INPUT);//déclarer l'entrée bouton+ qui est sur pin 4
 pinMode(flotteur, INPUT); //déclarer l'entrée flotteur qui est sur pin 7
 pinMode(niv, INPUT); //déclarer l'entrée flotteur qui est sur pin 8
 pinMode(ventil, OUTPUT); //déclarer la sortie "ventil" qui est sur pin 13
 pinMode(pompe,OUTPUT); //déclarer la sortie "pompe" qui est sur pin 12
  
 Serial.begin(9600);  // Init connection serie
 
//messages sur LCD démarrage de la solution 
  lcd.begin(20,4); 
  lcd.setCursor(2,0);
  lcd.print("Gestion Aquarium");
  lcd.setCursor(7,1);
  lcd.print("Tony G");
  lcd.setCursor(0,3);
  lcd.print("v1.3 - 12 avril 2020");
  lcd.setCursor(8,2);
  lcd.print("----");
  delay (3000);
  lcd.begin(20,4); 

  // création des images spécifiques du LCD (flèche haute, carré vide, etc...)
  lcd.createChar (0,carrevide);
  lcd.createChar (1,carreplein);
  lcd.createChar (3,flechehaut);
  lcd.createChar (4,flechebas);
  lcd.createChar (5,interouv);
  lcd.createChar (6,interferm);

}

  
 
void loop() 
{
  
// Ecriture des messages fixes sur LCD
  lcd.setCursor(0,0); //postionne le curseur sur le 1er digit et 1ère ligne du LCD
  lcd.print("Niveaux:");//ecrit Niveau : sur le LCD
  lcd.setCursor(9,0);
  lcd.print("Bac");
  lcd.setCursor(16,0);
  lcd.print("Res");
  lcd.setCursor(0,1);
  lcd.print("I/O :");
  lcd.setCursor(9,1);
  lcd.print("P:");
  lcd.setCursor(16,1);
  lcd.print("V:");
  lcd.setCursor(0,2);
  lcd.print("Temperature :");
  lcd.setCursor(0,3);
  lcd.print("Consigne :");
  lcd.setCursor(14,3);
  lcd.print (varx);
  lcd.setCursor(16,3);
  lcd.print (".00C");

  /*// Visu de l'état du flotteur sur connexion série
  Serial.print("Etat Flotteur : ");
  Serial.println(etatflotteur, BIN); //saut de ligne et en binaire
  Serial.print("Etat inter : ");
  Serial.println(etatinter, BIN); //saut de ligne et en binaire
  Serial.print("Etat inter 2 : ");
  Serial.println(interventil, BIN); //saut de ligne et en binaire
  delay (20);*/

  // lecture des états inter et flotteur
  etatflotteur = digitalRead(flotteur);// lit l'état du bouton et stocke le résultat dans etatflotteur
  etatinter = digitalRead(inter);// lit l'état de et stocke le résultat dans etatinter
  etatinterventil = digitalRead(interventil);// lit l'état de et stocke le résultat dans etatinterventil
  etatboutonp = digitalRead(boutonp);
  etatboutonm = digitalRead(boutonm);
  etatniv = digitalRead(niv);

 sensors.requestTemperatures(); //Demande la température au capteur
 /* Serial.print("La température est: ");
 Serial.print(sensors.getTempCByIndex(0)); //Récupération de la température en celsius du capteur n°0
 Serial.println(" C°");*/
 lcd.setCursor(14,2);
 lcd.print(sensors.getTempCByIndex(0));
 lcd.setCursor(19,2);
 lcd.print("C");

    



//GESTION DE LA SORTIE POMPE
// Serial.println(x); permet d'afficher la valeur de la variable x dans le moniteur série
//les calcul ci-dessous permette de déterminer la valeur de x
a=10;
b=0;
c=1;
//modification de la variable b afin de rendre le résultat v positif
if (b<=0) { //
v=b+5;
}
// conditions de Mise en route et arrêt de la pompe 
x = (etatinter*a) + (etatniv*v) + (etatflotteur*c);
if (x==6 || x>=10){
digitalWrite(pompe, HIGH);
lcd.setCursor(11,1);
lcd.write (byte(1));
delay (20);
}
else {
  digitalWrite(pompe, LOW);
  lcd.setCursor(11,1);
lcd.write (byte(0));
delay (20);
  }

// Affichage du symbole "niveau du réservoir" sur LCD 
if (etatniv==HIGH) {
lcd.setCursor(19,0);
lcd.write (byte(3)); //affichage sur LCD du symbole 3
delay (20);
}
else {
lcd.setCursor(19,0);
lcd.write (byte(4)); //affichage sur LCD du symbole 4
delay (20);
}

// Affichage du symbole interrupteur sur LCD en marche forcée
if (etatinter==HIGH) {
lcd.setCursor(12,1);
lcd.write (byte(6)); //affichage sur LCD du symbole 6
delay (20);
}
else {
lcd.setCursor(12,1);
lcd.write (byte(5)); //affichage sur LCD du symbole 5
delay (20);
}



//Affichage du symbole de niveau (flotteur= niveau bas) et affiche sur LCD Bas et flèche vers le haut
if (etatflotteur==HIGH) { // Si etatflotteur est à 5V (HIGH) c'est que le niveau est bas
lcd.setCursor(12,0);
lcd.write (byte(4));
delay (20);
}
else {
lcd.setCursor(12,0);
lcd.write (byte(3));
delay (20);
}




//GESTION DE LA TEMPERATURE ET MESSAGES LCD
// Incrementation de la variable consigne temp grace au bouton+
if (etatboutonp==HIGH) {
cpt++; // Incremantation du compteur
varx = cpt; // memorisation du compteur
delay (20);
}
// Décrementation de la variable consigne temp grace au bouton+
if (etatboutonm==HIGH) {
cpt--; // Décremantation du compteur
varx = cpt; // memorisation du compteur
delay (20);
}

// Si inter Ventil est à 5V (HIGH) = marche forcee de la ventil
if (etatinterventil==HIGH) {
digitalWrite(ventil, HIGH);
lcd.setCursor(19,1);
lcd.write (byte(6));
delay (20);
}
else {
lcd.setCursor(19,1);
lcd.write (byte(5));
delay (20);
}

// Si la température mesurée est < à la consigne et que l'inter Ventil est désactivée (0V) = Pas de ventilation
if (sensors.getTempCByIndex(0)<cpt && etatinterventil!=HIGH) { //
digitalWrite(ventil, LOW);
lcd.setCursor(18,1);
lcd.write (byte(0));
delay (20);
}
else  {   // en revanche, si la température mesurée est > à la consigne = ventilation
digitalWrite(ventil, HIGH);
lcd.setCursor(18,1);
lcd.write (byte(1));
delay (20);
}


}

Schéma cablage v2.3 (12-04-20).pdf (673 KB)

Maj du 26/04/20: Création d'un boitier 3D