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)
- Le capteur de température est une CTN qu’on peut trouver facilement dans le commerce : https://www.amazon.fr/Aussel-pi%C3%A8ces-num%C3%A9rique-thermique-temp%C3%A9rature/dp/B01LL9JFIG/
- Le capteur de pression est le MPX5700AP, ce modèle est un peu coûteux (il y a peut-être d’autres alternatives…) : https://www.labomalin.fr/produit/capteur-de-pression-mpx5700ap-composant-electronique/
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.
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