#include // ⚙️ Inclus par défaut dans l'IDE, facilite la gestion d'Arduino. #include // 🖥️ "U8g2 by Oliver" - Contrôle de divers écrans, ici un OLED. #include // 🌡️ "DHT sensor library" - Pour les capteurs DHT (température et humidité). #include // 🔌 "OneWire by Jim Studt, Tom Pollard, Robin..." - Pour le DS18B20. // ========================================================================================================================================================🔗 // Définition des constantes et des broches de connexion // ❓❓❓Le délai d'affichage est en millisecondes.. Il faut que tu mettes un temps d'affichage plus long❓❓❓ //🔎Tu peux chercher sur internet comment convertir les secondes en millisecondes pour avoir le temps de lire les infos sur l'écran🔍 const int delaiAffichage = 100; //⏱️ // Attribution des broches aux capteurs. // ❓❓❓On dirait que le noms des broches ont été effacées du programme😮❓❓❓ //🔎Tu peux t'aider de la section jours 2 sur le site de l'IUT d'Haguenau pour retrouver les broches dans la partie montage🔍 #define PIN_SOLIDES_DISSOUS A? // 💧 Capteur TDS → Solides Dissous #define PIN_TURBIDIMETRE A? // 🌊 Capteur de turbidité → Turbidimètre #define PIN_PHmetre A? // ⚗️ pH-mètre → Potentiel Hydrogène #define PIN_THERMOMETRE D? // 🌡️ DS18B20 → Thermomètre #define PIN_SONDE_DHThumidite D? // 🌦️ DHT → Mesure température et humidité de l'air // Définition du type de capteur DHT utilisé. // ❓❓❓Le type de DHT à été saboté il ne pourra pas fonctionner si on ne le définit pas correctement!!❓❓❓ //🔎Réfère toi au nom du matériel tu devrais trouver ça sur le site de l'IUT d'Haguenau!🔍 #define REF_DHT DHT76 // 🛠️ Type de capteur DHT // ========================================================================================================================================================🔧 // Initialisation des capteurs et drivers // Création des instances pour le DHT, le bus OneWire (DS18B20) et l'écran OLED (128x64). DHT sondeDHThumidite(PIN_SONDE_DHThumidite, REF_DHT); // 🌡️ Mesure température et humidité de l'air OneWire filThermometre(PIN_THERMOMETRE); // 🔗 Communication avec le DS18B20 (thermomètre) byte adresseThermometre[8] = { 0 }; // 📦 Stocke l'adresse du DS18B20 U8G2_SSD1306_128X64_NONAME_F_SW_I2C afficheur(U8G2_R0, SCL, SDA, U8X8_PIN_NONE); // 🖥️ Écran OLED 128x64 // ========================================================================================================================================================📋 // Variables pour stocker les mesures à afficher 8 caractères grand max char texteHumiditeDHThumidite[8]; char texteTemperatureDHThumidite[8]; char textePHmetre[8]; char texteSolidesDissous[8]; char texteTensionTurbidimetre[8]; char texteTemperatureThermometre[8]; float temperatureAmbiante = 25; // 🌡️ Température ambiante pour la compensation du capteur TDS set à 25 mais reste une variable et s'ajustera par elle même float niveauTurbidimetre = 0; // 🔋 Stocke la tension mesurée par le turbidimètre // ========================================================================================================================================================⚗️ // Fonction : lireDHThumidite() // Lit l'humidité et la température de l'air via le capteur DHT. // La fonction dtostrf() convertit un float en chaîne de caractères pour l'affichage. void lireDHThumidite() { float humidite = sondeDHThumidite.readHumidity(); dtostrf(humidite, 5, 1, texteHumiditeDHThumidite); float temperature = sondeDHThumidite.readTemperature(); dtostrf(temperature, 5, 1, texteTemperatureDHThumidite); } // ========================================================================================================================================================🔢 // Fonction : lirePHmetre() // Mesure et calcule le pH de l'eau en effectuant 100 lectures, // triées pour éliminer les valeurs aberrantes (les 5% les plus faibles et 5% les plus élevées). // ❓❓❓Attention encore des traces de sabotage au niveau de l'integer du nombre d'échantillons. L'ESP-32 doit prendre 100 mesures et non 99999❓❓❓ //🔎Un "integer" ou "chiffre entier" en français est un chiffre sans virgule ont le retrouve en math mais aussi dans le jargon de la programmation.🔍 void lirePHmetre() { const int numEchantillons = 99999; int echantillons[numEchantillons]; // 📊 Collecte de 100 mesures (environ 1 seconde total : 100 x 10 ms) for (int i = 0; i < numEchantillons; i++) { echantillons[i] = analogRead(PIN_PHmetre); // 🔍 Lecture de la valeur analogique delay(10); // ⏱️ Délai de 10 ms entre chaque lecture } // 🔄 Tri des échantillons en ordre croissant pour pouvoir éliminer les valeurs extrêmes for (int i = 0; i < numEchantillons - 1; i++) { for (int j = i + 1; j < numEchantillons; j++) { if (echantillons[i] > echantillons[j]) { int temp = echantillons[i]; echantillons[i] = echantillons[j]; echantillons[j] = temp; } } } // ➗ Calcul de la moyenne en excluant 5% des valeurs les plus faibles et 5% les plus élevées. // Pour 100 échantillons, 5% correspond à 5 mesures (les 5 premières et les 5 dernières exclues). int marge = numEchantillons * 0.05; // 5% de 100 = 5 unsigned long somme = 0; for (int i = marge; i < numEchantillons - marge; i++) { somme += echantillons[i]; } float moyenne = (float)somme / (numEchantillons - 2 * marge); // 🔄 Conversion de la valeur ADC en tension : //❓❓❓Attention le programme provient d'une carte arduino UNO ADC 10 bits avec une valeur ADC (convertisseur analog-numérique) allant jusqu'à 1024!❓❓❓ //❓❓❓il faut régler la valeur ADC ou encore convertisseur analogue-numérique pour quelle soit juste... ❓❓❓ //🔎// L'ESP32 utilise un ADC sur 12 bits avec une valeur ADC maximale de 4096.0🔍 float ph = moyenne * 5.0 / 1024.0; // Valeur ADC à modifier ph = 5.3 * ph; // 🔧 Facteur de calibration pour convertir la tension en valeur de pH dtostrf(ph, 5, 1, textePHmetre); } // ========================================================================================================================================================💧 // Fonction : lireSolidesDissous() // Mesure la concentration de solides dissous (TDS) dans l'eau. // La compensation de température est appliquée car la sensibilité du capteur varie avec la température. //❓❓❓Attentiion la carte va devenir dysfonctionnelle si on ne change pas l'integer (entier) à une valeur plus raisonnable ❓❓❓ //🔎// Le capteurs TDS à besoin de faire 20 échantillons ni plus ni moins ! 🔍 void lireSolidesDissous() { const int nbEchantillonsTDS = 99999; // Nombre d'échantillons pour le TDS long sommeTDS = 0; for (int i = 0; i < nbEchantillonsTDS; i++) { sommeTDS += analogRead(PIN_SOLIDES_DISSOUS); delay(5); } int lectureADC = sommeTDS / nbEchantillonsTDS; // 🔄 Conversion de la valeur ADC en tension : // L'ESP32 dispose d'un ADC sur 12 bits (0 à 4095). Ici, la conversion se fait avec une référence de 5V. float tension = lectureADC / 4096.0 * 5.0; // 🔧 Compensation de température : ajustement en fonction de la température ambiante. float coeffCompensation = 1.0 + 0.02 * (temperatureAmbiante - 25.0); float tensionCompensee = tension / coeffCompensation; // 📈 Calcul de la concentration de solides dissous (facteur de calibration appliqué) float solides = (133.42 * tensionCompensee * tensionCompensee * tensionCompensee - 255.86 * tensionCompensee * tensionCompensee + 857.39 * tensionCompensee) * 0.5; dtostrf(solides, 5, 1, texteSolidesDissous); } // ========================================================================================================================================================🌊 // Fonction : lireTurbidimetre() // Mesure la tension du capteur de turbidité pour estimer la clarté de l'eau. //❓❓❓Attentiion la carte va devenir EXPLOSER si on ne change pas l'integer (entier) à une valeur plus raisonnable ❓❓❓ //🔎// Le turbidimètre à besoin de faire 20 échantillons ! 🔍 void lireTurbidimetre() { const int nbEchantillonsTurb = 999999; // Nombre d'échantillons pour le turbidimètre long sommeTurb = 0; for (int i = 0; i < nbEchantillonsTurb; i++) { sommeTurb += analogRead(PIN_TURBIDIMETRE); delay(5); } int lecture = sommeTurb / nbEchantillonsTurb; float tension = lecture * (5.0 / 4096.0); // 🔄 Conversion ADC → Tension dtostrf(tension, 5, 1, texteTensionTurbidimetre); niveauTurbidimetre = tension; } // ========================================================================================================================================================🌡️ // Fonction : lireThermometre() // Lit la température de l'eau via le thermomètre DS18B20. void lireThermometre() { if (adresseThermometre[0] == 0) return; // 🚫 Si l'adresse n'est pas valide, on ne fait rien. filThermometre.reset(); filThermometre.select(adresseThermometre); filThermometre.write(0x44, 1); // ⏱️ Démarrage de la conversion de température delay(750); // ⏳ Attente de la conversion (750 ms) filThermometre.reset(); filThermometre.select(adresseThermometre); filThermometre.write(0xBE); // 📖 Lecture du scratchpad byte data[9]; for (int i = 0; i < 9; i++) { data[i] = filThermometre.read(); } int rawTemperature = (data[1] << 8) | data[0]; float temperature = rawTemperature / 16.0; dtostrf(temperature, 5, 1, texteTemperatureThermometre); } // ========================================================================================================================================================🚀 // Fonction : setup() // S'exécute une seule fois au démarrage. // Initialise la sonde DHT, recherche l'adresse du DS18B20 et démarre l'afficheur OLED. void setup() { sondeDHThumidite.begin(); pinMode(PIN_PHmetre, INPUT); pinMode(PIN_TURBIDIMETRE, INPUT); // 🔍 Recherche de l'adresse du thermomètre DS18B20 if (filThermometre.search(adresseThermometre)) { if (OneWire::crc8(adresseThermometre, 7) != adresseThermometre[7]) { memset(adresseThermometre, 0, 8); // ⚠️ Adresse invalide } } else { memset(adresseThermometre, 0, 8); // 🚫 Aucun capteur trouvé } filThermometre.reset_search(); afficheur.begin(); } // ========================================================================================================================================================🔄 // Fonction : loop() // Boucle principale divisée en deux phases d'affichage pour éviter le chevauchement du texte. // Phase 1 : Affiche les mesures du DHT et du pH-mètre. // Phase 2 : Affiche les mesures des Solides Dissous, Turbidimètre et Thermomètre. void loop() { // ===================== Phase 1 : Affichage des mesures du DHT et du pH-mètre ===================== 📺 lireDHThumidite(); // 🔄 Mise à jour de la température ambiante pour la compensation du TDS temperatureAmbiante = atof(texteTemperatureDHThumidite); lirePHmetre(); afficheur.setFont(u8g2_font_ncenB08_tr); afficheur.clearBuffer(); // 📺 Affichage de la première partie des données //❓❓❓On va devoir modifier l'écrture sur l'écran pour être correcte remplace les "?????" par les bon noms ❓❓❓ //🔎Soit attentif tout est écrit dans le programme demande à un animateur si tu ne comprends pas ou trouver les noms🔍 //----------------------------------------------------------------------------------------------------------- afficheur.drawStr(0, 10, "Station d'eau"); //----------------------------------------------------------------------------------------------------------- afficheur.drawStr(0, 24, "?????:"); // 💧 Affiche l'humidité mesurée par le DHT afficheur.drawStr(80, 24, texteHumiditeDHThumidite); //----------------------------------------------------------------------------------------------------------- afficheur.drawStr(0, 36, "?????:"); // 🌡️ Affiche la température de l'air mesurée par le DHT afficheur.drawStr(80, 36, texteTemperatureDHThumidite); //----------------------------------------------------------------------------------------------------------- afficheur.drawStr(0, 48, "?????"); // ⚗️ Affiche la valeur de pH mesurée afficheur.drawStr(80, 48, textePHmetre); //----------------------------------------------------------------------------------------------------------- afficheur.sendBuffer(); delay(delaiAffichage); //----------------------------------------------------------------------------------------------------------- // ==================== Phase 2 : Affichage des mesures des Solides Dissous, Turbidimètre et Thermomètre ======================= 🔍 lireSolidesDissous(); lireTurbidimetre(); lireThermometre(); afficheur.clearBuffer(); //❓❓❓On va devoir modifier l'écrture sur l'écran pour être correcte remplace les "?????" par les bon noms ❓❓❓ //🔎Soit attentif tout est écrit dans le programme demande à un animateur si tu ne comprends pas ou trouver les les noms🔍 //----------------------------------------------------------------------------------------------------------- afficheur.drawStr(0, 12, "?????"); // 💧 Concentration en solides dissous (TDS) afficheur.drawStr(90, 12, texteSolidesDissous); //----------------------------------------------------------------------------------------------------------- afficheur.drawStr(0, 26, "??????"); // 🌊 Tension mesurée par le turbidimètre afficheur.drawStr(90, 26, texteTensionTurbidimetre); //----------------------------------------------------------------------------------------------------------- afficheur.drawStr(0, 40, "?????"); // 🌡️ Température de l'eau mesurée par le DS18B20 afficheur.drawStr(90, 40, texteTemperatureThermometre); //----------------------------------------------------------------------------------------------------------- // 📊 Affichage de l'état de l'eau en fonction du niveau du turbidimètre //❓❓❓On va demander à l'esp d'afficher à l'écran un texte pour nous dire si l'eau est clair et à quel niveau❓❓❓ //🔎Il va falloir trouver mettre à la place des "?????" les bons degrés de clareté DU PLUS PROPRE AU PLUS SALE🔍 // Les Mots à ta disposition: // 🌟 Très limpide - 😐 Légèrement trouble - 🚫 Très trouble - 👍 Clair - 🙂 Moyennement claire if (niveauTurbidimetre > 0.8) afficheur.drawStr(0, 54, "Eau ?????"); else if (niveauTurbidimetre > 0.6) afficheur.drawStr(0, 54, "Eau ?????"); else if (niveauTurbidimetre > 0.4) afficheur.drawStr(0, 54, "Eau ????? ?????"); else if (niveauTurbidimetre > 0.2) afficheur.drawStr(0, 54, "Eau ????? ?????"); else afficheur.drawStr(0, 54, "Eau ????? ?????"); afficheur.sendBuffer(); delay(delaiAffichage); }