Mon projet d'analyse de l'eau d'une piscine

Bonjour,

Depuis maintenant presque 2 ans, je bricole dans mon coin pour facilité la gestion de ma piscine au chlore.
L'objectif n'est pas d'automatiser le traitement de l'eau mais uniquement de visualiser les données suivantes :

Température de l'eau : En fonctionnement via une carte ESP32 et un capteur DS18B20

La valeur du Ph : En fonction depuis 1 an via une carte Uno Wifi

La valeur de l'ORP : que je galère à gérer via la carte Uno Wifi

Mon programme PH et ORP :

#include <LiquidCrystal_I2C.h> // Librairie pour afficheur LCD

LiquidCrystal_I2C lcd(0x3F, 16, 2); // Déclaration adresse et format afficheur LCD

uint8_t pin_ph = A1;                  //Pin PH
float ph_sensor_value = 0.0;          // Valeur lu en volt(0 et 5)
float ph_value_float = 0.0;           // Valeur du Ph
float ph_offset = -1.90;             // Offset Ph

uint8_t pin_redox = A2;               // Pin Redox 
float redox_sensor_value = 0.0;       // Valeur lu en volt(0 et 5)
float redox_value_float = 0.0;        // Valeur du Redox
float redox_offset = 700;         // Offset Redox 0,2 = 365

void setup()
{
    Serial.begin(9600);
    lcd.init();
    lcd.backlight();  
    delay(100);
    lcd.clear();
    
 }

void loop()
   {
    ph_sensor_value = analogRead(pin_ph)* 5000.0 / 1023.0 / 1000.0; // mise en forme pour 0.0 à 5.0 V
    ph_value_float = (0.0178 * ph_sensor_value * 200.0) -1.889 + ph_offset;       // Calcul du pH 
    if (ph_value_float < 0){                // On fixe le Ph entre 0 et 14
      ph_value_float = 0;
    }
    if (ph_value_float > 14){
      ph_value_float = 14;
    }
  
    redox_sensor_value = analogRead(pin_redox) * 5000.0 / 1023.0 / 1000.0; //  mise en forme pour 0.0 à 5.0 V
    redox_value_float = 0.9 * redox_value_float + 0.1 * ( ((2.5 - redox_sensor_value) / 1.037) * 1000.0 + redox_offset);     // from -2000 to 2000 mV

    Serial.print("{");
    Serial.print("\"PH\":");
    Serial.print(ph_value_float);
    Serial.print(",");
    Serial.print("\"ORP\":");
    Serial.print(redox_value_float);
    Serial.println("}");
    delay(100);

// Affichage sur LCD.
  lcd.backlight();
  lcd.setCursor(0,0);
  lcd.print("PH: ");
  lcd.setCursor(8,0);
  lcd.print(ph_value_float,2);
  lcd.setCursor(0,1);
  lcd.print("ORP: ");
  lcd.setCursor(8,1);
  lcd.print(redox_value_float,0);
  delay(1000);


}

J'utilise :

Une double chambres d'analyse PH+ ORP
UNO R4 WIFI qui gère le PH et l'ORP
ESP32 qui gère la température de l'eau du bassin
Deux afficheurs lcd1602 i2c
une sonde de température DS18B20
2 cartes d'isolation galvanique
2 adaptateur Sonde PH/ORP Phidget 1130 (GOTRONIC)
Une sonde ORP
Une sonde PH
Un piquet de terre spécifique

Mon problème est le suivant, la valeur du ph est stable et correspond à nos mesure avec photomètre. par contre la valeur de désinfection ORP ne correspond pas à la réalité :frowning:

Quand vous dites

la valeur de désinfection ORP ne correspond pas à la réalité
est-ce un biais toujours dans le même sens ou n'importe quoi ?

Quelle sonde ORP utilisez-vous et comment est elle alimentée ?

En flux constant pour une piscine, la sonde doit être installée dans une cellule de passage avec un débit stable, assez faible - 30 et 60 mL/min pour assurer un renouvellement constant de l’eau autour de la sonde sans provoquer de turbulences ni de bulles d’air).

Comme il n’est pas possible de la rincer entre chaque mesure, il faut prévoir un nettoyage périodique manuel ou automatique pour éviter l’encrassement et vérifier régulièrement la dérive avec une solution d’étalonnage et à entretenir la sonde.

L’ORP est sensible à la température, mais dans une piscine où la température varie peu, la compensation est utile mais pas toujours indispensable (on utilise souvent une formule du premier ordre ORP corrigé = ORP mesuré + k × (T - T₀) où k est une constante (coefficient de sensibilité à la température) déterminée par des tests.

La sonde doit être alimentée par une source propre, protégée de l’humidité et des interférences électriques.

Bonsoir et merci pour votre contribution.
Mon problème est que la valeur affichée est par exemple de 650 pour un taux de chlore de 1.4 et de 740 pour un taux de 5.8.
Les valeurs évoluent dans le bon sens mais pour une très faible variation de valeur affichée j’ai une très forte variation de la chloration.
J’utilise un chlorinateur que je règle manuellement. Cet appareil est un récipient dans lequel sont disposés des galets de chlore et un petit robinet permet de régler l’injection de chlore dans le circuit de la piscine.
Concernant le débit, je pense avoir résolu le problème avec mes deux chambres d’analyse. Au début, sans ces chambres la valeur de pH était très instable. Maintenant ce n’est plus de cas donc idem pour l’orp.
Les sondes viennent d’aliexpress et sont alimenté via les Phiget 1130. Entre mon Uno et les Phiget 1130 j’ai deux carte d’isolation galvanique.

J’espère avoir bien répondu à vos questions.

On ne sait pas trop ce que l’on reçoit parfois…

Le problème est que beaucoup de sondes ORP vendues sur différents sites viennent de Chine et c’est pas évident de choisir la bonne.

Concernant mon programme, vous ne voyez pas d’erreurs ?

Je ne ne connais pas votre montage exact / circuit ni le fonctionnement de votre adaptateur ni les alims.

Ce qui me trouble c’est que Sur ESP32, analogRead() donne une valeur sur 12 bits (0–4095) donc vos divisions par 1023 ne sont pas correctes dans les formules et la tension est de 3.3V donc la multiplication par 5000 pas représentative de la réalité.

La précision réelle est souvent limitée à 10–11 bits à cause du bruit et des interférences et la lecture pas très précise aux valeurs extrêmes. Éventuellement utilisez analogReadResolution() pour passer en 10 bits.

Les mesures sur l’ADC2 peuvent être perturbées si le Wi-Fi est actif mais A1 et A2 sont sur l’ADC1 donc OK

Vous avez une formule pour faire un filtre glissant en ne prenant que 10% de la variation mais une lecture très erronée peut fausser longtemps les lectures suivantes (surtout si la première n’est pas bonne). Pour plus de fiabilité, il faut moyenner plusieurs lectures dans la durée (votre processus est lent) ➜ par exemple Lisez 5 fois et conservez la moyenne des 3 valeurs centrales en ignorant la plus forte et la moins forte.

C'est le code de sa Uno, je crois.

Effectivement j’aurais dû relire - ce n’est pas l’ESP32 qui est utilisé.

Le UNO R4 WiFi peut monter à 14 bits de résolution - ça vaut peut être le coup d’essayer ?

Bonjour et merci,

Si j'ai bien compris je dois modifier mon programme comme ci-dessous pour ma carte UNO R4 Wifi :
-------
redox_sensor_value = analogRead(pin_redox) * 5000.0 / 16384.0 / 1000.0; // mise en forme pour 0.0 à 5.0 V
-------

Par contre je ne comprend pas vraiment la ligne de programme ci-dessous :frowning:
Ce programme est une variante de :exemple trouvé sur le net
--------
redox_value_float = 0.9 * redox_value_float + 0.1 * ( ((2.5 - redox_sensor_value) / 1.037) * 1000.0 + redox_offset); // from -2000 to 2000 mV
-------

Merci d'avance pour vos lumières

non 1023 était OK car par défaut sur votre UNO R4 WiFi, la résolution reste à 10 bits.

cette ligne

fait 2 choses qu'on peut décomposer ainsi

float nouveauRedox = (((2.5 - redox_sensor_value) / 1.037) * 1000.0 + redox_offset);
redox_value_float = 0.9 * redox_value_float + 0.1 * nouveauRedox;

La première ligne est le calcul de la nouvelle valeur du redox en fonction de ce qu'à lu le capteur dans redox_sensor_value. j'imagine que cette formule est fournie avec la capteur / interface de votre sonde. Je n'ai aucune idée si elle est adaptée à votre sonde et interface. Normalement si la valeur est centrée sur 2.5 V, on devrait simplement avoir ORP (mV) = (Vmesure - 2.5) × 1000 mais on peut corriger pour étalonner le truc et Le facteur 1.037 que vous avez est une correction du gain appliquée pour compenser une amplification réelle légèrement différente de la théorie. La tension de 2.5 V reste la référence du module Phidget 1130, correspondant à 0 mV. La multiplication par 1000 convertit la tension en volts vers des millivolts. L’offset final permet de corriger le décalage observé en pratique lors de l'étalonnage avec une solution de référence.

La seconde ligne est ce qu'on appelle un filtre passe-bas exponentiel ou filtre de lissage exponentiel. L'idée est de ne pas prendre la valeur brute du nouveau calcul mais de lisser dans le temps la mesure. On prend donc 90% (le 0.9) de la valeur précédente à laquelle on ajoute 10% (le 0.1) de la nouvelle valeur lue. cela minimise les changements brutaux de valeur et minimise aussi l'impact d'une lecture erronée.

Merci beaucoup pour ces explications, qui me permettent enfin de comprendre ces lignes de codes.

Si les exemples sont bien utiles pour des non spécialistes comme moi, ils permettent au moins d'apprendre à coder.

Je pense que mon erreur vient du facteur de 1.037 qui ne correspond pas à ma sonde.
Jusqu'à maintenant je compensais le décalage entre mesure et lecture via l'offset au dépend de la linéarité du résultat obtenu :wink:

Si j'ai bien compris, via ma UNO R4, ma sonde ORP mesure la résistance de l'eau qui sous l'action de la présence de chlore varie, je pense, linéairement.

Je vais tester dans le temps mon ORP et ensuite je ferai la même chose pour le pH ou j'ai aussi recopier le facteur présent dans l'exemple.

Encore merci et je posterai mes résultats dans les jours à venir.

Bonjour,

Après quelques recherches sur le net, j'ai trouvé des courbes qui, pour certaines, démontrent une faible variation de la valeur ORP pour une importante variation du taux de chlore.

Courbe, semble être en relation avec mes mesures
Courbe incidence pH sur la mesure ORP

Ce qui est certain c'est qu'il n'y a pas de linéarité, voir courbe ci-dessous Linéarité

@ suivre ...

la fonction linéaire est pour la correction d'erreur / calibbration. C'est votre module et la sonde qui gèrent la partie non linéaire que vous obtenez dans redox_sensor_value.