Bonjour à tous,
Nouveau dans le monde Arduino, j'aimerai automatiser la gestion de mon aquarium
-
Contrôle de la température
-
Contrôle du pH
-
Contrôle de la conductivité de l eau
-
Contrôle de la hauteur d'eau
Je n'ai pas encore reçu l'ensemble des capteurs et éléments constituants le circuit mais je me suis mis au code.
Il se compile sans erreur mais je ne peux pas encore le tester.
Pouvez vous m'aider en m'indiquant les possibles erreurs de conception ainsi que les optimisations possibles si vous en voyez.
Merci à vous tous pour votre aide
#include "OneWire.h"
#include "DallasTemperature.h"
#include "Ultrasonic.h"
#include "LiquidCrystal_I2C.h"
#include "Wire.h"
#include "DS3231.h"
// ************************************************
//
// DECLARATION DES PINS A UTLISER
//
// ************************************************
//
// 0 -> sonde pH
// 2 -> interrupteur Marche Arret
// 3 -> PWM pour Lumiere (relais 100% / MOSFET PWM pour v2) - 12V
// 4 -> Relais chauffage - 220V
// 5 -> Relais Ventilateur - 12V
// 6 -> Relais pompe remplissage - 12V voir 6V après test
// 8 -> ECHO capteur Ultrason
// 9 -> TRIG capteur Ultrason
// A0 -> Sonde temperature DS18B20
// A1 -> Sonde TDS
// A4 et A5 -> SDA et SCL pour Communication I2C pour ecran LCD et DS3231
// vcc -> Alimentation 12V du circuit (Arduino et relais / mosfet)
// GND
// 5V -> Alimentation des capteurs et I2C
//
// Definition donnees de temps
RTClib monTemps;
// définition du type d'ecran lcd 20 x 4
LiquidCrystal_I2C LCD(0x27,20,4);
// Definition capteur ultrason
Ultrasonic ultrasonic(9, 8); // Trig et Echo
int dist = 0;
// Definition sonde DS18B20
OneWire oneWire(A0);
DallasTemperature ds(&oneWire);
// Definition bouton Marche/Arret
#define BoutonMarche 2
boolean Marche = 0;
// Definition sonde TDS
#define TdsSensorPin A1
#define VREF 5.0 // Voltage de reference de ADC
#define SCOUNT 20 // Nombre d'echantillons
int analogBuffer[SCOUNT]; // Tableau pour les donnees analogique de ADC
int analogBufferTemp[SCOUNT];
int analogBufferIndex = 0, copyIndex = 0, temperature = 25;
float averageVoltage = 0, tdsValue = 0;
//Definition sonde PH
#define PHSensorPin 0 //pH meter Analog output to Arduino Analog Input 0
unsigned long int avgValue; //Store the average value of the sensor feedback
float b, pH;
int buf[SCOUNT], temp;
// Definition relais
#define relaisLumiere 3
#define relaisChauffage 4
#define relaisVentilateur 5
#define relaisPompe 6
void setup()
{
Serial.begin(115200);
Wire.begin(); // initialisation i2c
pinMode(TdsSensorPin, INPUT); // sonde TDS sur pin TdsSensorPin - input
pinMode(PHSensorPin, INPUT); // sonde PH sur pin PHSensorPin
ds.begin(); // sonde temperature activée
LCD.init(); // initialisation de l'afficheur
LCD.backlight();
pinMode(BoutonMarche, INPUT); // initialisation du bouton Marche/Arret
attachInterrupt(digitalPinToInterrupt(BoutonMarche), changementEtat, CHANGE);
pinMode(relaisLumiere, OUTPUT);
pinMode(relaisChauffage, OUTPUT);
pinMode(relaisVentilateur, OUTPUT);
pinMode(relaisPompe, OUTPUT); // definition des pins des relais
}
void loop()
{
// Acquisition des donnees : temperature, TDS, PH, hauteur d'eau, temps
temperature = getTemper();
tdsValue = getTDS(temperature);
pH = getPH();
dist = ultrasonic.read();
DateTime now = monTemps.now();
// Affichage des donnees : temperature, TDS, PH, Niveau d'eau, focntionnement
affichage(temperature, tdsValue, pH, dist, now, Marche);
// Traitement de la lumiere
// Version 1 : si l'heure est comprise entre 10 et 20h -> activation du relais 1 pour la lumiere
// Version 2 : activation de la lumiere via PWM et MOSFET pour lever et coucher de soleil
// Version 1 : Allumage à 10h extinction à 20h
if ((now.hour()>=10) && (now.hour()<20))
digitalWrite (relaisLumiere, HIGH);
else
digitalWrite(relaisLumiere, LOW);
// Version 2 : A ecrire : Allumage 20% a 10h, +20% toutes les 10mn , -20% toutes les 10mn a partir de 19h jusqu'a extinction à 20h
// Traitement Chauffage / Refroiddissement
// si temperature < 25°C -> activation relai 2 pour le chauffage
// si temperature > 28°C -> activation relai 3 pour la ventilation
if (temperature <25)
digitalWrite(relaisChauffage, HIGH);
else
digitalWrite(relaisChauffage, LOW);
if (temperature >=28)
digitalWrite(relaisVentilateur, HIGH);
else
digitalWrite(relaisVentilateur, LOW);
// Traitement niveau d'eau
// si niveau d'eau > 3cm ET systeme en marche -> activation relais 4 pour la pompe de remplissage
if ((dist > 3) && Marche)
{
digitalWrite(relaisPompe, HIGH); // Activation de la pompe
while (dist >= 3) // Tant que le niveau d'eau est > 3cm
{
dist = ultrasonic.read(); // Mesure du niveau car la pompe tourne
}
digitalWrite(relaisPompe, LOW); // Extinction de la pompe qd le niveau est atteint
}
}
// *******************************************
//
// DECLARATION DES FONCTIONS
//
// *******************************************
//
// Acquisition de la temperature
// Parametre : aucun
// Renvoi : temperature sous forme d'entier
//
int getTemper()
{
ds.requestTemperatures();
int t = ds.getTempCByIndex(0);
return t;
}
//
// Acquisition TDS
// Parametre : T° sous forme d'entier
// Renvoi : valeur TDS en ppm sous forme de float
//
float getTDS(int temp)
{
static unsigned long analogSampleTimepoint = millis();
if (millis() - analogSampleTimepoint > 40U) //every 40 milliseconds,read the analog value from the ADC
{
analogSampleTimepoint = millis();
analogBuffer[analogBufferIndex] = analogRead(TdsSensorPin); // read the analog value and store into the buffer
analogBufferIndex++;
if (analogBufferIndex == SCOUNT)
analogBufferIndex = 0;
}
static unsigned long printTimepoint = millis();
if (millis() - printTimepoint > 800U)
{
printTimepoint = millis();
for (copyIndex = 0; copyIndex < SCOUNT; copyIndex++)
analogBufferTemp[copyIndex] = analogBuffer[copyIndex];
averageVoltage = getMedianNum(analogBufferTemp, SCOUNT) * (float)VREF / 1024.0; // read the analog value more stable by the median filtering algorithm, and convert to voltage value
float compensationCoefficient = 1.0 + 0.02 * (temp - 25.0); //temperature compensation formula: fFinalResult(25^C) = fFinalResult(current)/(1.0+0.02*(fTP-25.0));
float compensationVolatge = averageVoltage / compensationCoefficient; //temperature compensation
tdsValue = (133.42 * compensationVolatge * compensationVolatge * compensationVolatge - 255.86 * compensationVolatge * compensationVolatge + 857.39 * compensationVolatge) * 0.5; //convert voltage value to tds value
return tdsValue;
}
}
//
// Acquisition pH
// Parametre : aucun
// Renvoi : valeur du PH sous forme de float
//
float getPH()
{
for(int i=0; i<SCOUNT; i++) //for(int i=0;i<10;i++) //Get SCOUNT sample value from the sensor for smooth the value every 40 ms
{
buf[i]=analogRead(PHSensorPin);
delay(10);
}
avgValue = getMedianNum (buf, SCOUNT);
float phValue = (float)avgValue*5.0/1024;
phValue = 3.5*phValue;
return phValue;
}
//
// Renvoie la valeur median d'un tableau d'entier
// Parametres : Tableau de valeurs sous forme d'entier
// Nombre de valeurs dans le tableau sous forme d'entier
// Renvoi : Valeur median du tableau sous forme d'entier
//
int getMedianNum(int bArray[], int iFilterLen)
{
int bTab[iFilterLen];
for (byte i = 0; i < iFilterLen; i++)
bTab[i] = bArray[i];
int i, j, bTemp;
for (j = 0; j < iFilterLen - 1; j++)
{
for (i = 0; i < iFilterLen - j - 1; i++)
{
if (bTab[i] > bTab[i + 1])
{
bTemp = bTab[i];
bTab[i] = bTab[i + 1];
bTab[i + 1] = bTemp;
}
}
}
if ((iFilterLen & 1) > 0)
bTemp = bTab[(iFilterLen - 1) / 2];
else
bTemp = (bTab[iFilterLen / 2] + bTab[iFilterLen / 2 - 1]) / 2;
return bTemp;
}
//
// Affichage sur ecran LCD
// Parametres : Valeur de la temperature sous forme d'entier
// Valeur TDS sous forme de float
// Valeur pH sous forme de float
// Valeur de la hauteur d'eau sous forme d'entier
// Etat du system (ON/OFF) sous forme de booleen
// Renvoi : rien - Affichage
//
void affichage(int dataTemp, float dataTDS, float dataPH, int dataHauteurH2O, DateTime temps, boolean fonctionnement)
{
LCD.clear ();
LCD.setCursor (0,0);
LCD.print(temps.hour(), DEC);
LCD.print(':');
LCD.print(temps.minute(), DEC);
LCD.print(':');
LCD.print(temps.second(), DEC);
LCD.print(' ');
LCD.print(temps.day(), DEC);
LCD.print('/');
LCD.print(temps.month(), DEC);
LCD.print('/');
LCD.print(temps.year(), DEC);
// LCD.print ("HH:MM;SS JJ/MM/YYYY"); // Affichage DATE et Heure ligne 1
LCD.setCursor (0, 1);
LCD.print ("Temp : ");
LCD.print (dataTemp, 1);
LCD.print ("°"); // Affichage TEMPERATURE ligne 2
LCD.setCursor (0, 2);
LCD.print ("pH : ");
LCD.print (dataPH, 1); // Affichage PH au debut de la ligne 3
LCD.setCursor (10, 2);
LCD.print ("TDS : ");
LCD.print (dataTDS, 0);
LCD.print (" ppm"); // Affichage TDS au milieu de la ligne 3
LCD.setCursor (0, 3);
LCD.print ("-");
LCD.print (dataHauteurH2O);
LCD.print (" cm"); // Affichage niveau manque d'eau
LCD.setCursor (17, 3);
if (fonctionnement)
LCD.print ("ON");
else
LCD.print ("OFF"); // Affichage de l'etat en bas a droite
LCD.display ();
}
//
// Change l'etat de la variable Marche selon la position de l'interrupteur Marche/Arret
// Parametres : aucun
// Renvoi : rien
//
void changementEtat()
{
Marche = !Marche;
}