ACTIVITE ARDUINO/PYTHON : Mesures de pression et de température avec tracé en temps réel

Objectif : Réaliser des mesures de pression et de température à l’aide d’un microcontrôleur, avec acquisition en temps réel sur Python. Cela pourrait être utile dans le cadre d’une séance de travaux pratiques sur l’étude de l’évolution de la pression de vapeur saturante de l’eau en fonction de la température (loi de Rankine ln(Psat) = A-B/T)

Voici le montage à réaliser :

Il est aussi possible d’utiliser la mallette Educaduino d’Eurosmart, elle permet d’utiliser des capteurs « clé en main » sans câblage. Voir détails en fin d’article

Voici le code Arduino :

// Programme d'utilisation du capteur de température et de pression avec Arduino.
 //Définition des broches analogiques utilisées par le capteur.
 #define _NUMER0_BROCHE_ANALOGIQUE_TENSION A1  //Broche analogique utilisée par le capteur pour la mesure de la tension aux bornes de la CTN
 #define _NUMER0_BROCHE_ANALOGIQUE A0          //Broche analogique utilisée par le capteur pression.
 long temps;
 float R= 10000.0;
 //==================================================================================================
 // Convertit la valeur numérique en une valeur de tension.
 // Le Convertisseur Analogique Numérique converti la tension sur 10bits.  
 // Pour une tension de 0V la valeur numérique est 0.
 // Pour une tension de 5V la valeur numérique est 1023.  
 //==================================================================================================
 float ConvertiValeurMesureAnalogiqueEnTension(int _valeurNumerique)
 {
 // La fonction de conversion valeur numérique/tension est de la forme tension = a * valeurNumerique. 
 const int   _VALEUR_NUMERIQUE_MIN= 0;
 const float _VALEUR_TENSION_MIN  = 0.0;
 const int   _VALEUR_NUMERIQUE_MAX= 1023;   // convertisseur 10bits 
 const float _VALEUR_TENSION_MAX  = 5.0;
   //calcul du coefficient directeur
   float a = (_VALEUR_TENSION_MAX-_VALEUR_TENSION_MIN)/(_VALEUR_NUMERIQUE_MAX-_VALEUR_NUMERIQUE_MIN);
   //calcul de la tension
   float tension_V= a * _valeurNumerique; 
   return(tension_V);
 }
 //==================================================================================================
 // Convertit la valeur de la résistance de la CTN en une valeur de temperature.
 // S'inspire de la méthode de Steinhart.
 //==================================================================================================
 float ConvertiResistanceEnTemperature(float resistance)
 {
 // Caracteristiques de la CTN  
 const float _TEMPERATURE_NOMINALE = 25;
 const float _THERMISTANCE_NOMINALE = 10000;
 const float _COEFFICIENT_B = 3950; 
 float temperature = resistance/ _THERMISTANCE_NOMINALE;
   temperature = log(temperature);
   temperature /= _COEFFICIENT_B;
   temperature += 1.0 /(_TEMPERATURE_NOMINALE + 273.15);
   temperature = 1.0 /temperature;
   temperature -= 273.15;
   return(temperature);
 }
 //==================================================================================================
 // Procédure d'initialisation des périphériques
 //==================================================================================================
 void setup() {
 // Initialisation de la communication série avec le terminal à 9600 baud.
   Serial.begin(9600);
   temps = millis();
 }
 //==================================================================================================
 // Convertit la valeur de tension en une valeur de pression.
 // On mesure une tension de 0,2V pour une pression de  150hPa (un étalonnage du capteur montre que la tension de 0,2 V donnée par le constructeur pour 15 kPa peut varier légèrement ! On a choisi ici 0,27 )
 // On mesure une tension de 4,7V pour une pression de 7000hPa.  
 //==================================================================================================
 float ConvertiTensionEnPression(float _tension)
 {
 // La fonction de conversion tension vers pression est de la forme pression = a * tension +b.  
 const float _VALEUR_PRESSION_MIN= 150.0;
 const float _VALEUR_TENSION_MIN = 0.27;
 const float _VALEUR_PRESSION_MAX= 7000.0; //  
 const float _VALEUR_TENSION_MAX = 4.7;
   // calcul du coefficient directeur
   float a = (_VALEUR_PRESSION_MAX-_VALEUR_PRESSION_MIN)/(_VALEUR_TENSION_MAX-_VALEUR_TENSION_MIN);
   // calcul du coefficient décalage à l'origine.
   float b = _VALEUR_PRESSION_MAX - a * _VALEUR_TENSION_MAX;
   //calcul de la pression
   float pression_Pa= (a * _tension) + b; // Pression en hecto Pascal.
   pression_Pa = pression_Pa * 100;       // Pression en Pascal
   return(pression_Pa);
 }
 //==================================================================================================
 // Boucle principale Arduino.
 //==================================================================================================
 void loop() {
   temps= millis();
   // Lecture de la valeur tension du capteur sur l'entrée analogique _NUMER0_BROCHE_ANALOGIQUE_TENSION. 
   // La valeur mesurée par le Convertisseur Analogique Numérique prend pour valeur 0 pour une tension de 0V et 1023 pour une tension de 5V.
   int valeurNumeriqueTension = analogRead(_NUMER0_BROCHE_ANALOGIQUE_TENSION);
   // Conversion de la valeur numerique en tension.
   float tension_T_V   = ConvertiValeurMesureAnalogiqueEnTension(valeurNumeriqueTension);
 // Calcul du courant , à partir de la tension aux bornes de la résistance de 10 kohms = Tension alimentation - tension CTN
   float courant_A   = (5.0 - tension_T_V)/R; //Calcul de l'intensité du courant en A
   //Calcul de la résistance de la CTN
   float resistance_ohm = tension_T_V / courant_A;
 //Appel de la méthode de la libraire pour la conversion de la résistance en température.
   float temperature_degreC= ConvertiResistanceEnTemperature(resistance_ohm);
 //Affichage des résultats
   Serial.print("t : ");
   Serial.print("\t");
   Serial.print(temps); 
 Serial.print(" Temp : ");    // Transmission de la chaine " Température:"
   Serial.print(temperature_degreC); // Transmission de la temperature en °C
   Serial.print(" degresC ");              // Transmission de l'unité.
 // Lecture de la valeur du capteur sur l'entree analogique. 
   // La valeur mesurée par le Convertisseur Analogique Numérique prend pour valeur 0 pour une tension de 0V et 1023 pour une tension de 5V.
   int valeurNumerique = analogRead(_NUMER0_BROCHE_ANALOGIQUE);
 float tension_P_V   = ConvertiValeurMesureAnalogiqueEnTension(valeurNumerique);
 float pression_Pa = ConvertiTensionEnPression(tension_P_V);
 //Affichage des résultats
 Serial.print(" Pression : ");         // Transmission de la chaine " Pression:"
   Serial.print(pression_Pa);          // Transmission de la pression absolue calculée.
   Serial.println(" Pa");  

 delay(5000);                      // Délai en ms d'1s pour faciliter la visualisation.
 }

Lien Github pour ce code : https://github.com/jonasforlot/python-arduino/tree/main/Donn%C3%A9es%20s%C3%A9rie%20PvapSat/Pvap_CTN

Remarque

Un étalonnage du capteur montre que la tension de 0,2 V donnée par le constructeur pour 15 kPa peut varier légèrement ! On a choisi ici 0,27 V)

Un script Python est aussi proposé ici pour récupérer les données et tracer une courbe.

Dans cet article , je ne rentrerai pas dans les détails pour les étapes de récupération de données. Pour cela, je vous invite à consulter l’article qui explique ces différentes étapes sur ce lien :

Récupération des données d’une carte Arduino avec Python

Voici le code Python pour récupérer les données et tracer le graphe en temps réel


 #importation des modules
 import serial
 import serial.tools.list_ports # pour la communication avec le port série
 import matplotlib.pyplot as plt  # pour le tracé de graphe
 from matplotlib import animation # pour la figure animée
 import time # gestion du temps
 

 #initialisation des listes
 

 liste_temps=[] # liste pour stocker les valeurs de temps en partant de t=0
 liste_T = [] # liste pour stocker les valeurs de température
 liste_P = [] # liste pour stocker les valeurs de pression
 

 t_acquisition = 1000.0
 Tmax= 110.0 # en °C
 Pmax =140000.0 # en Pa
 

 #Ecriture dans un fichier txt
 lines=['t\tT\tP\n'] #première ligne du fichier txt
 #pour le graphe en temps réel
 def animate(i):
     global sys,line0,line1,t0,t1,u0,u1
     line_data = Data.readline()
     print (line_data)
     # on retire les caractères d'espacement en début et fin de chaîne
     listeDonnees = line_data.strip()
     # on sépare les informations reçues séparées par les espaces et on stocke ces informations dans une liste pour chacune de lignes
     listeDonnees = line_data.split()
     print (listeDonnees)
 

 

     if len(listeDonnees)== 11 : # parfois des lignes de données vides peuvent être envoyées, il faut les "écarter"
         temps = (float(listeDonnees[2].decode()))/1000.0 # après consulation des données, nous choisissons le 3ème élément de listeDonnees
         temp = float(listeDonnees[5].decode()) # après consulation des données, nous choisissons le 4ème élément de listeDonnees
         pression = float(listeDonnees[9].decode()) # après consulation des données, nous choisissons le 10ème élément de listeDonnees
 

         while temps <= t_acquisition:
             liste_T.append(temp)
             print("Température = %f"%(temp)) # affichage de la valeur de la température
             liste_temps.append(temps)
             print("temps mesuré = %f"%(temps), " s") # affichage de la valeur du temps absolu
             liste_P.append(pression)
             print("Pression = %f"%(pression)) # affichage de la valeur de la pression
             line0.set_data(liste_temps,liste_T)
             line1.set_data(liste_temps,liste_P)
 

             line = str(liste_temps[-1]) +'\t'+ str(liste_T[-1])+'\t'+ str(liste_P[-1])+'\n'
             lines.append(line)
             fichier = open('U:\Documents\data_arduino.txt', 'w').writelines(lines) #création d'un nouveau fichier texte,indiquer le bon chemin
             return line0,line1,
 

 # Fonction pour la récupération des données série venant de la carte Arduino
 def recup_port_Arduino() :
     ports = list(serial.tools.list_ports.comports())
     for p in ports:
         if 'Arduino' in p.description :
             mData = serial.Serial(p.device,9600)
     print(mData.is_open) # Affiche et vérifie que le port est ouvert
     print(mData.name) # Affiche le nom du port
     return mData
 

 

 

 

 

 

 Data =recup_port_Arduino() #récupération des données
 

 # Création figure
 fig,(ax1,ax2) = plt.subplots(2,figsize=(10,10))
 line0, = ax1.plot([],[])
 line1, = ax2.plot([],[])
 ax1.set_xlabel('temps en s')
 ax1.set_ylabel('température en °C')
 ax1.axis([0,t_acquisition,0,Tmax])
 ax2.set_xlabel('temps en s')
 ax2.set_ylabel('Pression en Pa')
 ax2.axis([0,t_acquisition,0.0,Pmax])
 

 

 #Animation
 ani = animation.FuncAnimation(fig, animate, frames=2000,  interval=20,repeat=False)
 

 plt.show()
 

 # plt.close(fig)
 Data.close() # pour arrêter la lecture des données série
 

 

 fig,(ax1,ax2) = plt.subplots(2,figsize=(10,10))
 ax1.set_title('température=f(t)') # titre du graphique
 ax1.scatter(liste_temps,liste_T, color ='r', marker = 'o') # On affiche les points de coordonnées (t,T) avec des points rouges
 ax1.set_xlabel('temps en s')
 ax1.set_ylabel('température en °C')
 ax1.axis([min(liste_temps),max(liste_temps),min(liste_T),max(liste_T)])  #limites pour les axes avec les valeurs extrêmes de temps et de température
 

 ax2.set_title('pression=f(t)') # titre du graphique
 ax2.scatter(liste_temps,liste_P, color ='b', marker = 'o') # On affiche les points de coordonnées (t,P) avec des points bleus
 ax2.set_xlabel('temps en s')
 ax2.set_ylabel('Pression en Pa')
 ax2.axis([min(liste_temps),max(liste_temps),min(liste_P),max(liste_P)])  #limites pour les axes avec les valeurs extrêmes de temps et de pression
 plt.show()  #afficher le graphique (ne rien mettre dans la parenthèse)
 

 

 

 

 

 

 

Lien Github pour ce script : https://github.com/jonasforlot/python-arduino/blob/main/Donn%C3%A9es%20s%C3%A9rie%20PvapSat/P_Vap_Arduino_CTN.py

Application

Etude de l’évolution de la pression de vapeur saturante de l’eau

Matériel :

  • 1 potence + 1 noix
  • Chauffe-ballon et support boy
  • Ballon 500 mL Pyrex rempli à moitié d’eau distillée avec quelques grains de carborundum
  • Bouchon 3 trous avec robinet + tuyau pour capteur pression + sonde CTN
  • Le dispositif avec Arduino décrit dans cet article

Protocole

  • Chauffer le ballon jusqu’à ébullition le robinet ouvert.
  • Une fois l’ébullition atteinte, fermer le robinet et laisser le ballon refroidir (à l’air ambiant ou dans un cristallisoir rempli d’eau). On considère que tout l’air est purgé et qu’il ne reste que la vapeur d’eau dans le ballon.
  • Lancer l’acquisition avec Python pour mesurer les valeurs de pression de la vapeur d’eau (qui est la pression de vapeur saturante) et de température (pendant environ 20’).
  • Le graphe s’affiche en temps réel pendant l’acquisition et les valeurs sont stockées dans un fichier texte data_arduino.txt (indiquer le chemin du fichier dans le script)

Courbe

Complément

Utilisation de la carte Educaduino d’Eurosmart

Il est possible aussi d’utiliser la carte Educaduino du fournisseur Eurosmart pour utiliser des capteurs de pression et de température qui se branchent sur la carte avec des connexions USB, nous pouvons aussi y intégrer un shield avec écran LCD pour affichage des valeurs.

https://www.educaduino.fr/

Matériel :

  • 1 potence + 1 noix
  • Chauffe-ballon et support boy
  • Ballon 500 mL Pyrex rempli à moitié d’eau distillée avec quelques grains de carborundum
  • Bouchon 3 trous avec robinet + tuyau pour capteur pression + sonde CTN
  • 1 carte Educaduino avec écran LCD + capteurs pression absolue et température + câble

Protocole

  • Chauffer le ballon jusqu’à ébullition le robinet ouvert.
  • Une fois l’ébullition atteinte, fermer le robinet et laisser le ballon refroidir (à l’air ambiant ou dans un cristallisoir rempli d’eau). On considère que tout l’air est purgé et qu’il ne reste que la vapeur d’eau dans le ballon.
  • Lancer l’acquisition avec Python pour mesurer les valeurs de pression de la vapeur d’eau (qui est la pression de vapeur saturante) et de température (pendant environ 20’).
  • Le graphe s’affiche en temps réel pendant l’acquisition et les valeurs sont stockées dans un fichier texte data_arduino.txt (indiquer le chemin du fichier dans le script)

Voici le code Arduino :


 #include                   //Librairie d'utilisation de l'écran LCD 2*16.
 LiquidCrystal ecranLCD(12, 11, 5, 4, 3, 2); //Création de l'objet d'exploitation de l'afficheur LCD.
 //Définition des broches analogiques utilisées par le capteur.
 #define _NUMER0_BROCHE_ANALOGIQUE_TENSION A12  //Broche analogique utilisée par le capteur pour la mesure de la tension. (Dépend de la localisation du capteur sur la carte EDUCA DUINO Lab).
 #define _NUMER0_BROCHE_ANALOGIQUE_COURANT A13 //Broche analogique utilisée par le capteur pour la mesure du courant. (Dépend de la localisation du capteur sur la carte EDUCA DUINO Lab).
 #define _NUMER0_BROCHE_ANALOGIQUE A8          //Broche analogique utilisée par le capteur pression. (Dépend de la localisation du capteur sur la carte EDUCA DUINO Lab).
 long temps;
 //==================================================================================================
 // Converti la valeur numérique en une valeur de tension.
 // Le Convertisseur Analogique Numérique converti la tension sur 10bits.  
 // Pour une tension de 0V la valeur numérique est 0.
 // Pour une tension de 5V la valeur numérique est 1023.  
 //==================================================================================================
 float ConvertiValeurMesureAnalogiqueEnTension(int _valeurNumerique)
 {
 // La fonction de conversion valeur numérique/tension est de la forme tension = a * valeurNumerique. 
 const int   _VALEUR_NUMERIQUE_MIN= 0;
 const float _VALEUR_TENSION_MIN  = 0.0;
 const int   _VALEUR_NUMERIQUE_MAX= 1023;   // convertisseur 10bits 
 const float _VALEUR_TENSION_MAX  = 5.0;
   //calcul du coefficient directeur
   float a = (_VALEUR_TENSION_MAX-_VALEUR_TENSION_MIN)/(_VALEUR_NUMERIQUE_MAX-_VALEUR_NUMERIQUE_MIN);
   //calcul de la tension
   float tension_V= a * _valeurNumerique; 
   return(tension_V);
 }
 //==================================================================================================
 // Converti la valeur numérique en une valeur de tension.
 // Le Convertisseur Analogique Numerique converti en un courant.  
 // Le courant est determiné par la mesure d'une tension aux bornes d'une résistance de 10kOhms
 //==================================================================================================
 float ConvertiValeurMesureAnalogiqueEnCourant(int _valeurNumerique)
 {
 const float _RESISTANCE = 10000.0; //Résistance de 10kOhms    
   // Conversion de la valeur numérique en tension
   float tension_V= ConvertiValeurMesureAnalogiqueEnTension(_valeurNumerique); 
   float courant_A= tension_V / _RESISTANCE;
   return(courant_A);
 }
 //==================================================================================================
 // Converti la valeur de la résistance de la CTN en une valeur de temperature.
 // S'inspire de la méthode de Steinhart.
 //==================================================================================================
 float ConvertiResistanceEnTemperature(float resistance)
 {
 // Caracteristiques de la CTN  
 const float _TEMPERATURE_NOMINALE = 25;
 const float _THERMISTANCE_NOMINALE = 10000;
 const float _COEFFICIENT_B = 3950; 
 float temperature = resistance/ _THERMISTANCE_NOMINALE;
   temperature = log(temperature);
   temperature /= _COEFFICIENT_B;
   temperature += 1.0 /(_TEMPERATURE_NOMINALE + 273.15);
   temperature = 1.0 /temperature;
   temperature -= 273.15;
   return(temperature);
 }
 //==================================================================================================
 // Procédure d'initialisation des périphériques
 //==================================================================================================
 void setup() {
   //Initialisation de l'écran LCD 2 lignes de 16 caractères.
   ecranLCD.begin(16, 2);
   // Initialisation de la communication série avec le terminal à 9600 baud.
   Serial.begin(9600);
   temps = millis();
 }
 //==================================================================================================
 // Converti la valeur de tension en une valeur de pression.
 // On mesure une tension de 0V pour une pression de  200hPa.
 // On mesure une tension de 5V pour une pression de 4000hPa.  
 //==================================================================================================
 float ConvertiTensionEnPression(float _tension)
 {
 // La fonction de conversion tension vers pression est de la forme pression = a * tension +b.  
 const float _VALEUR_PRESSION_MIN= 200.0;
 const float _VALEUR_TENSION_MIN = 0.0;
 const float _VALEUR_PRESSION_MAX= 4000.0; //  
 const float _VALEUR_TENSION_MAX = 5.0;
   // calcul du coefficient directeur
   float a = (_VALEUR_PRESSION_MAX-_VALEUR_PRESSION_MIN)/(_VALEUR_TENSION_MAX-_VALEUR_TENSION_MIN);
   // calcul du coefficient décalage à l'origine.
   float b = _VALEUR_PRESSION_MAX - a * _VALEUR_TENSION_MAX;
   //calcul de la pression
   float pression_Pa= (a * _tension) + b; // Pression en hecto Pascal.
   pression_Pa = pression_Pa * 100;       // Pression en Pascal
   return(pression_Pa);
 }
 //==================================================================================================
 // Boucle principale Arduino.
 //==================================================================================================
 void loop() {
   temps= millis();
   // Lecture de la valeur tension du capteur sur l'entrée analogique _NUMER0_BROCHE_ANALOGIQUE_TENSION. 
   // La valeur mesurée par le Convertisseur Analogique Numérique prend pour valeur 0 pour une tension de 0V et 1023 pour une tension de 5V.
   int valeurNumeriqueTension = analogRead(_NUMER0_BROCHE_ANALOGIQUE_TENSION);
   // Conversion de la valeur numerique en tension.
   float tension_T_V   = ConvertiValeurMesureAnalogiqueEnTension(valeurNumeriqueTension);
 // Lecture de la valeur courant du capteur sur l'entree analogique _NUMER0_BROCHE_ANALOGIQUE_TENSION. 
   // La valeur mesurée par le Convertisseur Analogique Numérique prend pour valeur 0 pour une tension de 0V et 1023 pour une tension de 5V.
   // Le courant est déterminé par la mesure de la tension aux bornes d'une résistance de 10kOhms.
   int valeurNumeriqueCourant = analogRead(_NUMER0_BROCHE_ANALOGIQUE_COURANT);
   // Conversion de la valeur numérique en courant.
   float courant_A   = ConvertiValeurMesureAnalogiqueEnCourant(valeurNumeriqueCourant);
 //Calcul de la résistance
   float resistance_ohm = tension_T_V / courant_A;
 //Appel de la méthode de la libraire pour la conversion de la résistance en température.
   float temperature_degreC= ConvertiResistanceEnTemperature(resistance_ohm);
 //Affichage des résultats
   Serial.print("t : ");
   Serial.print("\t");
   Serial.print(temps); 
 Serial.print(" Temp : ");    // Transmission de la chaine " Température:"
   Serial.print(temperature_degreC); // Transmission de la temperature en °C
   Serial.print(" degresC ");              // Transmission de l'unité.
 // Lecture de la valeur du capteur sur l'entree analogique. 
   // La valeur mesurée par le Convertisseur Analogique Numérique prend pour valeur 0 pour une tension de 0V et 1023 pour une tension de 5V.
   int valeurNumerique = analogRead(_NUMER0_BROCHE_ANALOGIQUE);
 float tension_P_V   = ConvertiValeurMesureAnalogiqueEnTension(valeurNumerique);
 float pression_Pa = ConvertiTensionEnPression(tension_P_V);
 //Affichage des résultats
 Serial.print(" Pression : ");         // Transmission de la chaine " Pression:"
   Serial.print(pression_Pa);          // Transmission de la pression absolue calculée.
   Serial.println(" Pa");    
 ecranLCD.clear();                     // Efface l'écran et positionne le curseur en 1ère colonne, 1ère ligne.
   ecranLCD.setCursor(0,0);              // Positionne le curseur en 1ère colonne, 1ère ligne.
   ecranLCD.print("T = ");        // Affichage du mot "Temperature".
 // Affichage de la température en °C
 ecranLCD.print(temperature_degreC);   // Affichage de la température.
   ecranLCD.print((char)223);            // Affichage du caractère '°'.
   ecranLCD.print("C");                  // Affichage de l'unité.
 ecranLCD.setCursor(0,1);              // Positionne le curseur en 1ère colonne, 2ème ligne.
   ecranLCD.print("P = ");           // Affichage du mot "Pression"
 // Affichage de la pression en Pascal
 ecranLCD.print(pression_Pa);   // Affichage de la pression absolue en Pa.
   ecranLCD.print(" Pa");                // Affichage de l'unité.
 delay(5000);                      // Délai en ms d'1s pour faciliter la visualisation.
 }

Lien Github pour ce code : https://github.com/jonasforlot/python-arduino/blob/main/Donn%C3%A9es%20s%C3%A9rie%20PvapSat/Pvap_CTN_LCD.ino

Une fois ce code Arduino téléversé, nous pouvons récupérer les valeurs avec le même script Python utilisé en début d’article :

Lien Github : https://github.com/jonasforlot/python-arduino/blob/main/Donn%C3%A9es%20s%C3%A9rie%20PvapSat/P_Vap_Arduino_CTN.py

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *