Projet d'Automatisation et régulation de la viscosité
UE MU5CI823-Optimisation, contrôle et digitalisation des procédés
Groupe 2
Noms et Prénoms:
DE LA TAILLE LOLAINVILLE Gregoire (gregoire.de_la_taille_lolainville@etu.sorbonne-université.fr) 21103148
PALAIN Ilies (ilies.palain@etu.sobonne-université.fr) 21400210
HOU Charles (charles.hou@etu.sorbonne-université.fr) 21400213
JIANG Alexandre (alexandre.jiang@etu.sorbonne-université.fr) 21113611
Cursus scolaire : Master 2 de Chimie - Parcours Ingénierie Chimique
Date de commencement du projet : Septembre 2023
Date de fin du projet :
Introduction :
L'objectif de notre projet est de contrôler la concentration d'une solution aqueuse à partir de sa viscosité. Pour cela, nous utiliserons un agent visqueux afin de directement associer la viscosité du mélange à sa concentration en agent visqueux
Matériel utilisés:
Réactifs :
Composants:
- 1 carte Arduino (Carte Arduino UNO Rev 3)
- 3 pompes (LEX-WATER-PUMP2 Pompe miniature à eau 1,1 L/min)
- 1 moteur agitateur pour mélanger (Motoréducteur 37025GM-12130)
- 2 électrovannes (Electrovanne 12 V FDP360L)
- 4 Relais (Module de relais 5 V SRD-05VDC-SL-C)
- 1 capteur ultrason (Capteur de détection ultrasons HC-SR04)
- 1 capteur de température (Capteur de température DS18B20 étanche DFR0198) : TT (Temperature Transmitter)
- 1 capteur de débit (Capteur de débit YFS401) : FT (Flow Transmitter)
- 1 BreadBoard
- 4 récipients
Avancement du projet:
16/10/2025: Lors de la semaine blanche, nous avons entamé une première séance de brainstorming qui nous servait de base préliminaire pour choisir le sujet de notre projet. Nous nous sommes ainsi porté sur un sujet portant sur la régulation du procédé d'une élaboration de biodiesel avec une analyse de sa pureté.
17/10/2025 : Après concertation avec notre tuteur de projet, M. Jérôme PULPYTEL, nous avons décider de modifier notre sujet, tout en gardant l'une des idée de base de l'ancien sujet qui est en rapport avec la viscosité. C'est pour cela que nous sommes donc partis sur l'automatisation de la régulation de la viscosité par une méthode in-situ.
17/10/2025 jusqu'au 28/10/2025 : Réalisation du schéma de notre projet et la préparation de la liste de matériel nécessaire à notre projet.
Figure 1 : P&ID de départ
17/11/2025 : Nous allons chercher les matériaux de la liste pour pouvoir ainsi commencer le projet.
19/11/2025: Sciure pour créer les supports pour les deux réservoir des réactifs de départ.

Figure 2 : Support en bois après modification
24/11/2025 : Nous débutons le montage. Pour cela, on perce des trous dans la plaque en bois pour permettre le maintien des équipements. De plus, nous perçons les récipients pour permettre l'insertion des tuyaux. Nous installons ensuite les premiers éléments qui sont les récipients, une pompe, une électrovanne et un capteur.

Figure 3 : Assemblage des premiers éléments du projet


Figure 4 : Placement des éléments sous différents angles
26/11/2025 : 1er essai de modélisation du montage électrique sur TinkerCad. Modélisation 3D de l'hélice et de la tige à rattacher au moteur pour nous permettre de mélanger nos liquide. Création d'un support pour le moteur.

Figure 5 : 1er essai de modélisation sur TinkerCad
27/11/2025 : Après un premier envoi de notre essai de modélisation, notre tuteur nous explique qu'il manque des composants sur notre modèle TinkerCad et le code est incomplet. Suite à cela, nous nous décidons de modifier notre envoi de modélisation. En parallèle à cela, nous imprimons en 3D les pales de notre agitateur. Puis nous avons fait des trous dans nos planches pour pouvoir installer les derniers pièces manquantes sur le support.

Figure 6 : Pales imprimées en 3D pour l'agitation

Figure 7 : Support comportant tout les emplacements finaux
28/11/2025 : Nous commençons les branchement des modules relais à l'Arduino. Tous les équipements ont d'abord été testé avec le code correspond afin de vérifier leur bon fonctionnement. Ils ont ensuite été placés sur le support avec les différents récipients et les branchements associés.
Figure 8a : Support comportant les équipements, récipients et branchements (face avant)

Figure 8b : Support comportant les équipements, récipients et branchements (face avant)
Du fait d'un débit de sortie de l'eau beaucoup trop faible à cause de la vanne associée, il a été décidé de la remplacer par une pompe. Voici le nouveau P&ID du projet :

Figure 9 : Nouveau P&ID de l'installation
26/01/2025 : Il n'a pas été possible d'obtenir de la glycérine pour le projet. Ainsi, la glycérine est remplacée par un autre liquide visqueux, la grenadine, car disponible à bas coût et en grande quantité, la viscosité a été estimé à environ 1500 CP.
On obtient la courbe d'étalonnage suivante, grâce à des différentes mesures d'eau pure, de grenadine pure, et de mélange 50/50, :


Figure 10 : Graphique montrant l'évolution du débit en fonction de la viscosité
Nous avons également peaufiné le code Arduino :
|
// === MACHINE DE REGULATION DE VISCOSITE === #include "Ultrasonic.h"
// Valeur de viscosité cible en centipoise (MODIFIER ICI) const float VISCOSITE_CIBLE = 500.0; // Entre 1 et 1500 cP
// === PINS === const int pumpWaterPin = 2; // Pompe eau const int pumpGrenadinePin = 3; // Pompe grenadine const int pumpCircuitPin = 4; // Pompe circuit de mesure const int transferPumpPin = 5; // Pompe de transfert const int transferValvePin = 6; // Vanne de transfert const int flowSensorPin = 7; // Capteur de débit const int ultrasonicPin = 8; // Capteur niveau ultrason
// === PARAMETRES === const float TOLERANCE_DEBIT = 0.10; // 10% de tolérance sur le débit const unsigned long minPulseInterval = 50; // Filtre anti-bruit const int NIVEAU_MIN = 6; // Niveau minimum en cm (débordement si < 6cm)
// === VARIABLES MESURE === volatile int pulseCount = 0; int lastState = HIGH; unsigned long lastPulseTime = 0; float flowReadings[10]; Ultrasonic ultrasonic(ultrasonicPin); unsigned long lastLevelCheck = 0;
void setup() { Serial.begin(115200); // Configuration des pins pinMode(pumpWaterPin, OUTPUT); pinMode(pumpGrenadinePin, OUTPUT); pinMode(pumpCircuitPin, OUTPUT); pinMode(transferPumpPin, OUTPUT); pinMode(transferValvePin, OUTPUT); pinMode(flowSensorPin, INPUT_PULLUP); // Tout éteint au départ digitalWrite(pumpWaterPin, LOW); digitalWrite(pumpGrenadinePin, LOW); digitalWrite(pumpCircuitPin, LOW); digitalWrite(transferPumpPin, LOW); digitalWrite(transferValvePin, LOW); Serial.println("========================================"); Serial.println(" REGULATEUR DE VISCOSITE"); Serial.println("========================================"); Serial.print("Viscosité cible: "); Serial.print(VISCOSITE_CIBLE); Serial.println(" cP"); Serial.print("Tolérance débit: +/- "); Serial.print(TOLERANCE_DEBIT * 100); Serial.println("%\n"); // Attente de 3 secondes avant de démarrer Serial.println("Démarrage dans 3 secondes..."); delay(3000); // ETAPE 1: Injection initiale d'eau Serial.println("\n=== INJECTION INITIALE D'EAU ==="); digitalWrite(pumpWaterPin, HIGH); Serial.println("Pompe eau: ON (5 secondes)"); delay(5000); digitalWrite(pumpWaterPin, LOW); Serial.println("Pompe eau: OFF\n"); delay(2000); // Pause pour stabilisation // Boucle de régulation regulateViscosity(); }
void loop() { // Programme terminé, ne fait rien }
void regulateViscosity() { int iteration = 1; while (true) { // Vérification du niveau toutes les 5 secondes if (millis() - lastLevelCheck >= 5000) { checkLevel(); lastLevelCheck = millis(); } Serial.println("========================================"); Serial.print("ITERATION #"); Serial.println(iteration); Serial.println("========================================\n"); // Mesure du débit float avgFlow = measureFlow(); // Calcul de la viscosité mesurée par interpolation // Points d'étalonnage : (1, 0.815), (750, 0.772), (1500, 0.688) float viscositeMesuree; if (avgFlow >= 0.772) { // Entre eau et mélange : interpolation linéaire // De 0.815 L/min (1 cP) à 0.772 L/min (750 cP) viscositeMesuree = 1 + (0.815 - avgFlow) / (0.815 - 0.772) * (750 - 1); } else { // Entre mélange et grenadine : interpolation linéaire // De 0.772 L/min (750 cP) à 0.688 L/min (1500 cP) viscositeMesuree = 750 + (0.772 - avgFlow) / (0.772 - 0.688) * (1500 - 750); } // Limite les valeurs entre 1 et 1500 cP if (viscositeMesuree < 1) { viscositeMesuree = 1; Serial.println(">>> (Débit très élevé, viscosité limitée à 1 cP)"); } if (viscositeMesuree > 1500) { viscositeMesuree = 1500; Serial.println(">>> (Débit très faible, viscosité limitée à 1500 cP)"); } Serial.print("\n>>> Viscosité mesurée: "); Serial.print(viscositeMesuree, 1); Serial.println(" cP"); // Calcul du débit cible par interpolation inverse float debitCible; if (VISCOSITE_CIBLE <= 750) { // Entre eau et mélange debitCible = 0.815 - (VISCOSITE_CIBLE - 1) / (750 - 1) * (0.815 - 0.772); } else { // Entre mélange et grenadine debitCible = 0.772 - (VISCOSITE_CIBLE - 750) / (1500 - 750) * (0.772 - 0.688); } Serial.print(">>> Débit cible: "); Serial.print(debitCible, 2); Serial.print(" L/min | Débit mesuré: "); Serial.print(avgFlow, 2); Serial.println(" L/min"); // Calcul de l'écart sur le débit float ecartDebit = abs(avgFlow - debitCible) / debitCible; Serial.print(">>> Écart débit: "); Serial.print(ecartDebit * 100, 1); Serial.println("%"); // PREMIERE ITERATION : on ignore et on passe à la suivante if (iteration == 1) { Serial.println("\n--> Première itération: aucun ajustement"); Serial.println("Pause de stabilisation (2 sec)...\n"); delay(2000); iteration++; continue; } // Vérification si dans la tolérance (à partir de l'itération 2) if (ecartDebit <= TOLERANCE_DEBIT) { Serial.println("\n*** DEBIT CIBLE ATTEINT! ***\n"); transferMixture(); Serial.println("\n========================================"); Serial.println(" PROCESSUS TERMINE AVEC SUCCES"); Serial.println("========================================\n"); break; } // Ajustement nécessaire if (avgFlow > debitCible) { // Débit trop élevé (trop fluide) => Ajouter grenadine Serial.println("\n--> Débit trop élevé: Ajout de GRENADINE (3 sec)"); digitalWrite(pumpGrenadinePin, HIGH); delay(3000); digitalWrite(pumpGrenadinePin, LOW); } else { // Débit trop faible (trop visqueux) => Ajouter eau Serial.println("\n--> Débit trop faible: Ajout d'EAU (3 sec)"); digitalWrite(pumpWaterPin, HIGH); delay(3000); digitalWrite(pumpWaterPin, LOW); } Serial.println("Pause de stabilisation (2 sec)...\n"); delay(2000); iteration++; } }
float measureFlow() { Serial.println("=== MESURE DU DEBIT ==="); Serial.println("Pompe circuit: ON"); digitalWrite(pumpCircuitPin, HIGH); // 10 mesures de 1 seconde chacune for (int i = 0; i < 10; i++) { pulseCount = 0; unsigned long startTime = millis(); // Mesure pendant 1 seconde while (millis() - startTime < 1000) { int currentState = digitalRead(flowSensorPin); if (lastState == HIGH && currentState == LOW) { unsigned long currentTime = millis(); if (currentTime - lastPulseTime > minPulseInterval) { pulseCount++; lastPulseTime = currentTime; } } lastState = currentState; } // Calcul du débit float flowRate = (pulseCount / 450.0) * 60.0; flowReadings[i] = flowRate; Serial.print("Mesure "); Serial.print(i + 1); Serial.print("/10: "); Serial.print(flowRate, 2); Serial.println(" L/min"); } // Arrêt de la pompe digitalWrite(pumpCircuitPin, LOW); Serial.println("Pompe circuit: OFF"); // Calcul de la moyenne float sum = 0; for (int i = 0; i < 10; i++) { sum += flowReadings[i]; } float avgFlow = sum / 10.0; Serial.print("\nDébit moyen: "); Serial.print(avgFlow, 2); Serial.println(" L/min"); return avgFlow; }
void transferMixture() { Serial.println("\n=== TRANSFERT DU MELANGE ==="); Serial.println("Pompe transfert + Vanne: ON (30 sec)"); digitalWrite(transferPumpPin, HIGH); digitalWrite(transferValvePin, HIGH); delay(30000); digitalWrite(transferPumpPin, LOW); digitalWrite(transferValvePin, LOW); Serial.println("Pompe transfert + Vanne: OFF"); Serial.println("Transfert terminé!"); }
void checkLevel() { long distance = ultrasonic.MeasureInCentimeters(); Serial.print("[NIVEAU] Distance: "); Serial.print(distance); Serial.println(" cm"); if (distance < NIVEAU_MIN) { Serial.println("\n!!! ALERTE: RISQUE DE DEBORDEMENT !!!"); Serial.print("Distance mesurée: "); Serial.print(distance); Serial.print(" cm < "); Serial.print(NIVEAU_MIN); Serial.println(" cm"); // Arrêt de toutes les pompes digitalWrite(pumpWaterPin, LOW); digitalWrite(pumpGrenadinePin, LOW); digitalWrite(pumpCircuitPin, LOW); Serial.println("\n=== VIDANGE D'URGENCE ==="); // Vidange digitalWrite(transferPumpPin, HIGH); digitalWrite(transferValvePin, HIGH); delay(30000); digitalWrite(transferPumpPin, LOW); digitalWrite(transferValvePin, LOW); Serial.println("\n========================================"); Serial.println(" ERREUR: NIVEAU CRITIQUE ATTEINT"); Serial.println(" Vidange effectuée - Programme arrêté"); Serial.println("========================================\n"); // Arrêt du programme while(1) { delay(1000); } } }
|