/* Gestion Piscine */
// Ecran LCD
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 20, 4); // adresse I2C, 20 caractères, 4 lignes
/* Paramètres gestion du temps */ // https://www.locoduino.org/spip.php?article6 //
unsigned long date = 0;
unsigned long date_derniere_mesure = 0; // mémoire date dernière mesure
unsigned long intervalle_mesure = 0;
unsigned long date_dernier_affichage = 0; // mémoire date dernier affichage
unsigned long intervalle_affichage = 0;
unsigned int minute = 1e3; // 1 minute = 60 000 ms
unsigned int seconde = 1e3; // 1 seconde = 1000 ms
uint8_t N = 0; // compteur des 10 mesures
/* Paramètres bouton poussoir */
volatile uint8_t compteur_bouton = 0; //compteur de changement d'état bouton // https://arduinogetstarted.com/fr/reference/arduino-volatile
uint8_t dernier_compteur_bouton = 0; //mémoire dernier état compteur
/* Paramètres débimetres */
const uint8_t Pins_Debit[] = {3, 4, 5, 6, 7}; // Pins entrées débitmetres (signal impulsion)
const float K_capteur[] = {0.2, 0.2, 0.2, 0.45, 0.717}; // Constante capteur 0.2 (buse), 0.45 (Chlore-Brome) et 0.717 (sonde)
float Debit[10][6]; // Liste des 10 dernièresvaleurs des débits des 5 capteurs avec le total à la fin (position 6)
/* Paramètres électrovannes & pompe */
const uint8_t Pins_Vannes_Pompe[] = {8, 9, 10, 11, 12}; // Pins sorties électrovannes (8-Cl 9-pH+ 10-pH- 11-eau) et pompe (12)
uint8_t mode_pompe = 0; // OFF (0), Cl (1), pH+ (2), pH- (3)
const uint8_t intervalle_cycle[] = {10, 10, 10, 2}; // gestion des intervalles de fonctionnement cycle pour Cl, pH+, pH-, eau (en minute)
unsigned long date_debut_cycle = 0;
bool gestion_pH = 0; // mémoire d'un cycle pH (= 1 si effectué)
bool gestion_Cl = 0; // mémoire d'un cycle Chlore (= 1 si effectué)
uint8_t date_cycle_pH = 10; // date début possible de cycle pH en minute
uint8_t date_cycle_Cl = 30; // date début obligatoire (ou commandé par ORP) de cycle Cl/Br en minute
/* Paramètres pHmètre & ORP */
uint8_t pin_ph = A0; //Pin pH
float pH[10]; // Liste des 10 dernières mesures de pH
const float KpH = 5.55; // Coeff à déterminer expérimentalement avec 2 solutions tampons(de l'ordre de 5.55 ... 5.7 suivant doc)
uint8_t pin_redox = A1; // Pin Redox (ORP)
float Uredox[10]; // Liste des 10 dernières mesures de potentiel redox
const int8_t Offset_Redox = 0; // Offset en mV
/* Paramètres température */
#include <OneWire.h> // Sonde de température DS18B20
#include <DallasTemperature.h>
OneWire oneWire(A2); //Pin Température
DallasTemperature Sonde_T(&oneWire);
float Temperature[10]; // Liste des 10 dernières mesures de température
/* Paramètres pression */
float Pression[10]; // Liste des 10 dernières mesures de pression
uint8_t pin_p = A3; // Pin Pression
/* Moyenne d'un tableau 1D */
float moyenne_1D(float tableau[10]) {
float somme = 0.0;
for (uint8_t n = 0; n < 10; n++)
{
somme += tableau[n];
}
return somme/10.0;
}
/* Moyenne de la colonne c d'un tableau 2D */
float moyenne_2D(float tableau[10][6], uint8_t c) {
float somme = 0.0;
for (uint8_t n = 0; n < 10; n++)
{
somme += tableau[n][c];
}
return somme/10.0;
}
/* Fonction de mesure des débits */
void mesure_debits(uint8_t i) {
unsigned long T; float D[] = {0, 0, 0, 0, 0, 0};
Debit[i][5] = 0;
for (uint8_t n = 0; n < 5; n = n + 1) {
T = 0; // temps de l'impulsion haut => 1/2 période du signal
noInterrupts();
T = (pulseIn(Pins_Debit[n], HIGH, 1e5)); // mesure du temps d'impulsion haut en µs (temps maxi pour commencer la mesure, ici 0,1 s = 100000 µs)
interrupts();
if (T<1) {
D[n] = 0;
} else {
D[n] = 3e4/(K_capteur[n]*T); // f(Hz)=K*D(L/min) => D(m3/h) = 60/1000 * f/K avec f = 5e5/T => D(m3/h) = 60/1000 * 5e5/(K*T1) = 3e4/(K*T)
}
Debit[i][n] = 100*(D[n]/100-floor(D[n]/100)); // Débit (m3/h) et max 2 chiffre avant virgule
Debit[i][5] += Debit[i][n];
if (n==4) {
Debit[i][n] = 10*(D[n]*10/6-floor(D[n]*10/6)); // Débit sonde (L/min) et max 1 chiffre avant la virgule *1000/(60*10)
}
}
}
/* Fonction de mesure pH et potentiel Redox */
void mesure_pH_Redox(uint8_t i) {
float Uph = 0.0; float Uorp = 0.0;
Uph = analogRead(pin_ph)*5.0/1023.0; // 0 si 0V et 1023 si 5V - lecture de la broche pin_ph
Uorp = analogRead(pin_redox)*5.0/1023.0; // 0 si 0V et 1023 si 5V - lecture de la broche A1
pH[i] = 7.0 - KpH*(Uph - 2.5); // pH = 7 si Uph = 2,5 V (ajuster potentiomètre pour avoir 2,5V en sortie Po en courcircuitant l'entrée BNC car 0V de la sonde à pH 7)
if (pH[i] < 0){ // On fixe le pH entre 0 et 14
pH[i] = 0.0;
}
if (pH[i] > 14){
pH[i] = 14.0;
}
Uredox[i] = 1e3*(2-Uorp)-Offset_Redox; // fonction (en mV) y = (2 - x)*1000
}
/* Fonction de mesure de température */
void mesure_temperature(uint8_t i) {
Sonde_T.requestTemperatures();
Temperature[i] = Sonde_T.getTempCByIndex(0);
}
/* Fonction de mesure de pression */
void mesure_pression(uint8_t i) {
float Up = 0.0;
Up = analogRead(pin_p)*5.0/1023.0; // 0 si 0V et 1023 si 5V - lecture de la broche pin_p
Pression[i] = 3.0*Up - 1.5; // pression en bar
}
void affichage_pH_Redox() {
lcd.setCursor(2, 0); lcd.print("pH et Pot Redox");
lcd.setCursor(0, 1); lcd.print("pH = ") ; lcd.print(moyenne_1D(pH),1); lcd.print(" ");
lcd.setCursor(0, 2); lcd.print("ORP = ") ; lcd.print(int(moyenne_1D(Uredox))); lcd.print(" mV ");
lcd.setCursor(0, 3); lcd.print("T = ") ; lcd.print(moyenne_1D(Temperature),2); lcd.print((char)223); lcd.print("C ");
}
void affichage_debits() {
lcd.setCursor(0, 0); lcd.print("Dtot (m3/h): "); lcd.print(moyenne_2D(Debit,5),1); lcd.print(" ");
lcd.setCursor(0, 1); lcd.print("(1): "); lcd.print(moyenne_2D(Debit,0),1); lcd.print(" ");
lcd.setCursor(0, 2); lcd.print("(2): "); lcd.print(moyenne_2D(Debit,1),1); lcd.print(" ");
lcd.setCursor(10, 1); lcd.print("(3): "); lcd.print(moyenne_2D(Debit,2),1); lcd.print(" ");
lcd.setCursor(10, 2); lcd.print("Dcl: "); lcd.print(moyenne_2D(Debit,3),1); lcd.print(" ");
lcd.setCursor(0, 3); lcd.print("Dsonde (L/min): "); lcd.print(moyenne_2D(Debit,4),2);
}
void affichage_global() {
lcd.setCursor(0, 0); lcd.print(" Dtot = "); lcd.print(moyenne_2D(Debit,5),1); lcd.print(" m3/h ");
lcd.setCursor(0, 1); lcd.print("pH = ") ; lcd.print(moyenne_1D(pH),1); lcd.print(" ");
lcd.setCursor(0, 2); lcd.print("ORP = ") ; lcd.print(int(moyenne_1D(Uredox))); lcd.print(" mV ");
lcd.setCursor(0, 3); lcd.print("T:") ; lcd.print(moyenne_1D(Temperature),1); lcd.print((char)223); lcd.print("C ");
lcd.setCursor(10, 3); lcd.print("P:") ; lcd.print(moyenne_1D(Pression),1); lcd.print(" bar ");
}
/* Fonction compteur d'impulsion bouton avec 3 valeurs (0,1,2) */
void bouton() {
compteur_bouton ++;
if (compteur_bouton > 2) {
compteur_bouton = 0;
}
Serial.println(compteur_bouton);
}
void setup() {
for (uint8_t i = 0; i < 5; i = i + 1) {
pinMode(Pins_Debit[i], INPUT);
}
for (uint8_t i = 0; i < 5; i = i + 1) {
pinMode(Pins_Vannes_Pompe[i], OUTPUT);
digitalWrite(Pins_Vannes_Pompe[i],0); // Vannes et pompe sur 'OFF' (0 ou LOW)
}
lcd.init(); lcd.backlight();
attachInterrupt(digitalPinToInterrupt(2), bouton, RISING); // détection de front montant bouton (borne D2) https://www.locoduino.org/spip.php?article64
Sonde_T.begin(); // Initialisation sonde de température
Serial.begin(9600); // définie le taux de transfert de donnée à 9600 bauds
}
void loop() {
date = millis();
intervalle_mesure = date - date_derniere_mesure;
intervalle_affichage = date - date_dernier_affichage;
// Mesures
if (intervalle_mesure > 0.1*seconde) {
mesure_pH_Redox(N);
mesure_debits(N);
mesure_temperature(N);
mesure_pression(N);
date_derniere_mesure = millis();
if (N < 9) {
N += 1;
}
else {
N = 0;
}
Serial.println(N);
}
// Affichage
if (intervalle_affichage > 1*seconde) {
date_dernier_affichage = millis();
if (compteur_bouton != dernier_compteur_bouton) {
lcd.clear();
dernier_compteur_bouton = compteur_bouton;
}
if (compteur_bouton == 0) {
affichage_global();
}
if (compteur_bouton == 1) {
affichage_debits();
}
if (compteur_bouton == 2) {
affichage_pH_Redox();
}
// Affichage moniteur série
Serial.print(moyenne_2D(Debit,5),1); Serial.print(" m3/h ");
Serial.print("pH = ") ; Serial.print(moyenne_1D(pH),1); Serial.print(" ");
Serial.print(int(moyenne_1D(Uredox))); Serial.print(" mV ");
Serial.print(moyenne_1D(Pression),1); Serial.print(" bar ");
Serial.print(moyenne_1D(Temperature),1); Serial.println("°C ");
Serial.println(date);
}
// Electrovannes & Pompe
if (date > date_cycle_pH*minute & gestion_pH == 0) {
if (moyenne_1D(pH) < 7.2) {
mode_pompe = 2; // mode pH+
date_debut_cycle = millis();
}
if (moyenne_1D(pH) > 7.8) {
mode_pompe = 3; // mode pH-
date_debut_cycle = millis();
}
gestion_pH = 1;
}
if (date > date_cycle_Cl*minute & gestion_Cl == 0) {
mode_pompe = 1; // mode Cl
date_debut_cycle = millis();
gestion_Cl = 1;
}
if (mode_pompe != 0) {
cycle_pompe(mode_pompe-1);
}
}
/* Fonction cycle pompe */
void cycle_pompe(uint8_t mode) {
if (date >= date_debut_cycle & date <= date_debut_cycle + 2*seconde) {
digitalWrite(Pins_Vannes_Pompe[mode],1); // Ouverture vanne produit
}
if (date >= date_debut_cycle + 2*seconde & date <= date_debut_cycle + intervalle_cycle[mode]*minute) {
digitalWrite(Pins_Vannes_Pompe[4],1); // Démarrage pompe
}
if (date >= date_debut_cycle + intervalle_cycle[mode]*minute & date <= date_debut_cycle + (intervalle_cycle[mode]+intervalle_cycle[3])*minute) {
digitalWrite(Pins_Vannes_Pompe[mode],0); // Fermeture vanne produit
digitalWrite(Pins_Vannes_Pompe[3],1); // Ouverture vanne eau
}
if (date >= date_debut_cycle + (intervalle_cycle[mode]+intervalle_cycle[3])*minute) {
digitalWrite(Pins_Vannes_Pompe[4],0); // Arrêt pompe
digitalWrite(Pins_Vannes_Pompe[3],0); // Fermeture vanne eau
mode_pompe = 0; // Fin de cycle avec mise à 0 du mode_pompe
}
}