Go Down

Topic: TPE Projet sur le Son (Read 2644 times) previous topic - next topic

LinuskUser

Bonjour, bonsoir,
Je suis actuellement en première S et je dois faire une Expérience pour un projet sur le son, celle-ci doit avoir pour objectif de donner la vitesse du son à partir d'une seule variable : la température ambiante ( soit la température de la pièce ), pour cela j'ai réalisé le code suivant :



Code: [Select]

/* Calculer la vitesse du son en fonction de la température de la pièce
 *  R* = Constante de Gay Lussac = GayLussac
 *  y = coéfficient adiabatique du gaz = gamma
 *  T = température en Kelvin = tempKelvin
 *  Vc = Vitesse du son = vitSon
 *  M = Masse molaire = mMol
 *  
 *  Fréquence du son (Hz) = freqHz;
*/


// Ecran à cristaux liquides
#include <LiquidCrystal.h>  // Bibliothèque de l'écran à cristaux liquide
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);   // Initialisation des pins de l'écran




const float GayLussac = 8.314472; // (J/K)
const float gamma = 1.40; // dans un air pur / sec
const float mMol = 0.029; // 29.0 x 10^-3 kg/mol
double vitSon;
int tempKelvin;


int freqHz = 250; // Plus la fréquence est élevée plus le son est aigu

void setup() { // Initailisation du programme 1 fois
  Serial.begin(9600); // initialisation de la communication série
  // Améliore la précision de la mesure en réduisant la plage de mesure
  analogReference(INTERNAL); // Pour Arduino UNO
  //Ecran LCD display
  lcd.begin(16, 2);  // affichage 16x2
  

}

void loop() { // fonction de boucle qui refait tout le système entre parenthèses à l' "inifini".
  // Temperature                       /!\ Malheureusement ne prend que des valeurs positives
  // Mesure la tension sur la broche A1
  int valeur_brute = analogRead(A1);
  
  // Transforme la mesure (nombre entier) en température via un produit en croix
  float temperature = (valeur_brute * (5.0 / 1024)) * 100;
  
  // Envoi la mesure au PC pour affichage et attends 250ms
  Serial.println(temperature);
  
    
   //Transformation °C en °K
   tempKelvin = temperature + 273.15;

   //Calcul vitesse du son :
   vitSon = sqrt((gamma * GayLussac * tempKelvin) / mMol);


//------------------------------------------------ Partie absolument inutile ----------------------------------
  // Produit un son à freqHz Hertz.
  // Freq du son
  int keyVal = analogRead(A0);
  // Serial.println(keyVal);                  
  if(keyVal == 1023) {
    tone(8, freqHz);  
  } else {
    noTone(8); // Coupe le son actif si la valeur de keyVal est égale à 1023 (lorsque l'on relâche le bouton " sonore " ).
  }
//-----------------------------------------------------------------------------------------------------------------------

  // LCD affichage actif
  lcd.setCursor(0, 0);
  lcd.print("Temp : " + String(temperature) + " C");
  lcd.setCursor(0, 1);
  lcd.print("Vit : " + String(vitSon) + " m/s");
  
  delay(1500);  //  Fait recommencer le système dès le début de la boucle jusqu'à ce que l'on coupe l'alimentation du programme.
}




Maintenant voilà le problème, mon programme affiche plusieurs valeurs de température (en Celsius), seulement elles sont toutes différentes les unes des autres, ce qui fait que ça fausse les résultats.

Dans une pièce de 20°C environ j'obtiens comme valeur :     ( C = °C )
18.6 C
7.85 C
10.11 C
18.49 C
3.98 C
14.95 C
14.19 C
5.27 C
18.17 C
8.49 C
9.35 C


J'ai beau chercher à travers mon code mais il me semble que rien ne pose problème, c'est pour cette raison que je viens demander à la communauté, y aurait-il un problème dans le code, ou autre chose ?

J'espère avoir bien décrit la situation, merci d'avance,
Joyeux Noël, et Bonne année 2017.

68tjs

#1
Dec 24, 2016, 05:21 pm Last Edit: Dec 24, 2016, 05:22 pm by 68tjs
Si tu expliquai le principe de l'expérience ?
Nous voulons bien aider mais nous sommes aussi intéressés par comprendre et apprendre.

Et si tu donnai la référence des capteurs que tu utilises ne crois-tu pas que tu aurai plus de chance d'avoir des réponses ?
Parce que là pas de chance je n'ai pas commandé de boule de cristal au père noël :smiley-mr-green: .

Fais nous un petit schéma de câblage aussi car si ton capteur est analogique genre LM35 tu as pu tomber dans l'erreur que font tous les débutants avec ce capteur.

LinuskUser

Re, en gros le but serait de mettre le programme dans deux environnements (un frai et un chaud), et de prouver par l'expérience que le son peut varier selon la température.
On comparerai / étudierai la vitesse du son entre les deux environnements.

Pour le capteur, enfin j'espère que s'en est un : je sais pas si c'est le vrai nom, mais dessus il y a écrit : BC547 B 331.

Et... je viens de me rendre compte 10 minutes après avoir écrit la ligne précédente que ce BC547 B 331 est un transistor et que je l'ai confondu avec un capteur de température.. malheureusement, j'en ai pas trouvé dans mon kit arduino..
Je préfère garder le post ouvert tant que j'aurai pas trouvé un capteur de température, au cas où..

Voici la photo :

LinuskUser

Quel capteur de température vous me conseillerez d'acheter, pour mon programme du coup ? (Arduino UNO)

J-M-L

#4
Dec 24, 2016, 06:43 pm Last Edit: Dec 24, 2016, 06:55 pm by J-M-L
Le LM35 ou le DS18B20 sont fréquemment utilisés et pas chers. Précision moyenne.

Sinon pour à peine un peu plus cher le MCP9808 sera plus précis

Il y en a d'autres comme le TSYS01, TMP36, MCP9700A,...
Hello - Please do not PM me for help,  others will benefit as well if you post your question publicly on the forums.
Bonjour Pas de messages privés SVP, postez dans le forum directement pour que ça profite à tous

LinuskUser

Merci, je peux en savoir un peu plus sur l'erreur de débutant à propos du LM35 ?
Et selon, le capteur, je dois changer quelque chose dans mon code ?

J-M-L

#6
Dec 24, 2016, 07:25 pm Last Edit: Dec 24, 2016, 07:35 pm by J-M-L
Quote
l'erreur de débutant à propos du LM35 ?
a quoi faites vous référence?

EDIT - ok le post de 68tjs - je suppose qu'il veut parler d'un condensateur de découplage à mettre au plus près, cf le tutoriel lié ci dessus pour plus de détails - ou alors de bien penser à aRef INTERNAL

Sinon chaque composant aura son mode de lecture. Ce que je ne vois pas trop dans votre code  où la vitesse du son est mesurée? Ce que vous faites c'est afficher la vitesse théorique en fonction de la T°. C'est "juste" ça l'objectif?




Note technique si la performance de calcul comptait:

 dans le cas de l'air (composé en majorité de gaz parfaits diatomiques) au voisinage de la température ambiante, la célérité du son peut être approchée par la linéarisation suivante :

cair = (331,5 + 0,607·θ) m·s−1
où θ (thêta) est la température en degrés Celsius (θ = T-273,15 (T étant en Kelvin))

Cette formule approchée permet d'obtenir la célérité du son de −20 à +40 °C avec une incertitude inférieure à 0,2 % - pas forcément un pb donc vu la précision de mesure de T° que vous aurez.

Ça  évite la racine carrée le passage en K et la division qui prennent du temps sur votre uno (mais bon...)

Sinon au niveau du code pour l'affichage évitez la classe String... préférez un tableau de caractères
Hello - Please do not PM me for help,  others will benefit as well if you post your question publicly on the forums.
Bonjour Pas de messages privés SVP, postez dans le forum directement pour que ça profite à tous

loulous24

Salut Newbie,

J'avoue que je ne connais pas la formule de calcul de la vitesse de la lumière en fonction de la température de l'air, si tu pouvais la donner ça serait bien que l'on puisse vérifier tout ton code.

En vérité, tu ne mesure pas du tout une température et ceci pour n'importe quel capteur... En vérité tu mesures une tension (qui varie en fonction de la température) donc tu dois avoir deux valeurs de références (si ton capteur est linéaire, c'est à dire que si la température augmente d'un degré alors la tension augmentera de x Volts, quelque soit les valeurs de départ et d'arrivée, si on est dans les bornes du capteur bien sur) par exemple 20° et 30° et la tension au borne du capteur qui correspond à ces deux températures (tu pourras construire une fonction affine avec ces deux points (en 1°S ça devrait aller...) qui donne la température en fonction de la tension (f(U) = t avec U la tension et t la température) et ensuite appliquer cette fonction dans ton code (comme ça à chaque fois que tu as une tension Ux, tu fais f(Ux) et tu as la température...

Petite aide, ton arduino ne donne même pas Ux entre 0 et 5V mais un chiffre entre 0 et 1023, tu peux alors faire Ux = map(analogRead(A1), 0, 1023, 0, 5) et tu as une tension entre 0 et 5 V qui est au borne de ton capteur de température.

Si tu n'as pas compris, je répondrai à tes questions.

En guise d'exercice avant de recevoir ton capteur : Tu pourrais essayer de trouver la fonction f(U) = t si je te dis que chez moi il fait 20 °C et que mon capteur indique 3 V et que dehors il fait 0°C et que mon capteur indique 2V, sachant que j'ai un capteur linéaire (c'est à dire que f est une fonction du type : f(U) = aU + b). Bonne chance.

Loulous24

LinuskUser

En effet, je n'ai pas mesuré la vitesse du son mais je calculée, avec la formule suivante :
sqrt() = racine carré

sqrt((Coef adiabatique de l'air * Constante de Gay Lussac * Temp en Kelvin) / M de l'air).

Ce qui donne :
sqrt((8.314472*1.4*TempKelvin)/0.029)



Cela dit, comme à annoncé J-M-L, on peut très bien avoir comme formule :
cair = (331,5 + 0,607·θ) m·s−1



Pour vous répondre loulous24, j'obtiens f(U) = 20U - 40, pour votre exercice.


Un grand merci à vous ! Il me restera plus qu'a chercher un bon capteur afin d'appliquer votre aide. Et peut-être que j'aurai quelques autres questions à poser plus tard à propos de ce projet.

Sur ce, je vous souhaites encore une fois un Joyeux Noël !


loulous24

Bravo LinuskUser, tu as réussi l'exercice.

Dans ton code du coup, tu pourrais peut-être créer quatre variables T1, U1, T2, U2 qui stockent les valeurs de température et de tension associé et le programme peut calculer tout seul a et b dans la fonction f(U) = aU + b. Et si tu veux recalibrer ton capteur, tu n'auras qu'à modifier U1, T1, U2 et T2 et le programme se chargera du reste... Vu que c'est noël, je te donne la relation : a = (T2 - T1)/(U2 - U1) et b = T1 - U1*a.

Joyeux noël

Loulous24

troisiemetype

Pour ce que ça vaut, il y a un capteur de température intégré à l'Atmega 328. Voir le chapitre 28.8 de la fiche technique. Il est donné pour une précision absolue de +- 10°, ce qui n'est pas génial, mais est étalonnable. A voir, dans quelle mesure le fait que la capteur soit intégré au microcontrolleur peut influencer la mesure, puisqu'il doit chauffer un peu, même légèrement. L'avantage c'est que si tu as un arduino sous la main ça ne coûte rien d'essayer.

_pepe_

#11
Dec 25, 2016, 01:03 pm Last Edit: Aug 19, 2018, 03:19 pm by _pepe_
Supprimé

68tjs

Quote
EDIT - ok le post de 68tjs - je suppose qu'il veut parler d'un condensateur de découplage à mettre au plus près, cf le tutoriel lié ci dessus pour plus de détails - ou alors de bien penser à aRef INTERNAL
Non.
Ca c'est pour les mesures analogiques en général.

LM35 ou LM335 ou texas XX35
Ces capteurs donnent seulement 10 mV par degré.
10mV de perturbation en analogique c'est très vite fait et souvent copieusement dépassé donc il faut :
- un câblage très propre.
- Liaison avec la carte arduino :
    - torsader les fils de mesure et de masse ensemble
    - ne JAMAIS utiliser le fil de masse arduino/capteur pour un autre composant, j'ai bien écrit JAMAIS.
      la raison est que si le fil de masse est utilisé par d'autres composants il véhiculera le courant de ces autres composants et comme les fils sont légèrement résistif du fait de la loi d'ohm il se produira une légère chute de tension qui s'ajoutera à la sortie du capteur et que le CNA du micro traduira en degrés supplémentaires.
Toujours câbler les masse en étoiles : avec la carte arduino comme centre de l'étoile.

Sinon tu as des capteurs analogiques qui "ont été numérisés" et qui s'utilisent avec des signaux numériques de 5 V d'amplitude :  donc plus de soucis avec les mV qui traînent.

Il y a le DS18B20 déjà cité mais aussi le DHT22 qui fait aussi mesure d'humidité. Fuir le DHT11 peu précis et limité.

Qualité des mesures de température :
Ne pas confondre la précision absolue, la sensibilité et la fidélité.
Précision absolue :
Peu de capteur ont une bonne précision absolue.  C'est très rare de voir deux thermomètres indiquer la même valeur. Ce n'est pas grave si le capteur est fidèle.
Fidélité :
Un capteur fidèle est un capteur qui replacé dans des conditions identiques donnera toujours la même indication.
Cette indication peut être fausse de quelques degrés ce n'est pas grave car du fait de la fidélité le décalage est constant et on peut apporter une correction après étalonnage avec un thermomètre de référence.
Sensibilité :
C'est l'aptitude à détecter des (petit ou gros) écarts de température.


LinuskUser

#13
Dec 25, 2016, 04:42 pm Last Edit: Dec 25, 2016, 05:11 pm by LinuskUser
J'ai bien suivi vos conseils, et ai changé plusieurs lignes dans le code :

Code: [Select]

/* Calculer la vitesse du son en fonction de la température de la pièce
 *  R* = Constante de Gay Lussac = GayLussac
 *  y = coéfficient adiabatique du gaz = gamma
 *  T = température en Kelvin = tempKelvin
 *  Vc = Vitesse du son = vitSon
 *  M = Masse molaire = mMol
 * 
 *  Fréquence du son (Hz) = freqHz;
*/



// Ecran à cristaux liquides
#include <LiquidCrystal.h>  // Bibliothèque de l'écran à cristaux liquide
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);   // Initialisation des pins de l'écran






const float GayLussac = 8.314472; // (J/K)
const float gamma = 1.40; // dans un air pur / sec
const float mMol = 0.029; // 29.0 x 10^-3 kg/mol
int T1, U1, T2, U2;
double vitSon;
int tempKelvin;
float a, b;




int freqHz = 250; // Plus la fréquence est élevée plus le son est aigu






void setup() { // Initailisation du programme 1 fois
  Serial.begin(9600); // initialisation de la communication série
 
  //Ecran LCD display
  lcd.begin(16, 2);  // affichage 16x2

  // Valeurs de températures et de tensions associées
  // Ces 4 valeurs sont des exemples pour l'instant             T température  U tension
  T1 = 20.0;
  U1 = 3.0;
  T2 = 0.0;
  U2 = 2.0;



  // f(U) = aU + b     f(tension) = température
  // Calcul de a et de b
  a = (T2 - T1) / (U2 - U1);
  b = T1 - U1*a;
 

}



void loop() {
  // Temperature               
  // Mesure la tension sur la broche A1
  float Ux = map(analogRead(A1), 0, 1023, 0, 5); // tension alors entre 0 et 5 V



  float temperature = a*Ux + b;

  /*
  // Transforme la mesure (nombre entier) en température via un produit en croix
  temperature = (Ux * (5.0 / 1024)) * 100.0;
  */


 
  // Envoi la mesure au PC pour affichage
  Serial.println(String(temperature) + " C  ---  " + String(Ux) + " V" );
 
   
   //Transformation °C en °K
   tempKelvin = temperature + 273.15;

   //Calcul vitesse du son :
   vitSon = sqrt((gamma * GayLussac * tempKelvin) / mMol);
   //ou cair = (331,5 + 0,607·θ) m·s−1    θ = température Celsius   [-20°;+40°C]







//------------------------------------------------ Partie absolument inutile ----------------------------------
  // Produit un son à freqHz Hertz.
  // Freq du son
  int keyVal = analogRead(A0);
  // Serial.println(keyVal);                 
  if(keyVal == 1023) {
    tone(8, freqHz); 
  } else {
    noTone(8); // Coupe le son actif si la valeur de keyVal est égale à 1023 (lorsque l'on relâche le bouton " sonore " ).
  }
//-----------------------------------------------------------------------------------------------------------------------




  // LCD affichage actif                        <-----------------------  ( !!!
  lcd.setCursor(0, 0);
  lcd.print("Temp : " + String(temperature) + " C");
  lcd.setCursor(0, 1);
  lcd.print("Vit : " + String(vitSon) + " m/s");
 
  delay(250); 
}





A noter que je n'ai pas encore mon capteur sous la main donc je n'ai pas ajouté les légères lignes de codes liées à celui-ci. Par contre au niveau, de la ligne // LCD affichage actif, il faudrait utiliser une certaine fonction de tableau de caractères à la place de la fonction String, mais je ne vois absolument pas comment je pourrai " le coder " ( le tableau ).

Je compte partir sur un capteur tel que LM35DZ, << capable de mesurer des températures de 0 à 100°C avec une précision de 1.5°C aux extrêmes. >> d'après ce site : https://www.carnetdumaker.net/articles/mesurer-une-temperature-avec-un-capteur-lm35-et-une-carte-arduino-genuino/        .
A moins que je me trompe, je ne pense pas pouvoir dépasser les extremums 0°C ~ 70°C si facilement, sans griller les circuits.

EDIT : Quoi qu'en effet le DS18B20 à l'air aussi intéressant à ce niveau là sachant que je reste dans un endroit avec l'air qui est Sec.

C'est bon j'ai trouvé ! J'ai utilisé la fonction sprintf() :
Code: [Select]


char message[16] = "";

  // LCD affichage actif
  lcd.setCursor(0, 0);
  sprintf(message, "Temp : %d C", temperature);
  lcd.setCursor(0, 1);
  sprintf(message, "Vit : %d m/s", vitSon);


68tjs

#14
Dec 25, 2016, 05:55 pm Last Edit: Dec 25, 2016, 05:56 pm by 68tjs
Le LM35DZ n'est pas 0/100° .
L'indice Z indique qu'il n'est que 0 / +70°C

Cette information ne se trouve que dans la datasheet du produit : IL FAUT LIRE LES DATASHEETS.

Quote
je ne pense pas pouvoir dépasser les extremums 0°C ~ 70°C si facilement, sans griller les circuits.
Le micro-contrôleur est -40° / +85°. Il s'agit là de température ambiante, l'intérieur de la puce peut atteindre +150° (même s'il vaut mieux éviter)
La difficulté est que les fournisseurs de cartes ne donnent aucune indication sur les composants annexes comme les résistances, quartz/résonateurs et condensateurs.

Si tu dois travailler à des températures élevées il faudra te pencher sur les calculs thermiques ce qui me parait bien lourd pour un TPE.

@_pepe_
Quote
J'ai également pu constater que la précision absolue annoncée n'était pas effective sans un étalonnage préalable (ou alors il fait 95°C ±10°C dans ma maison d'après les valeurs typiques de la datasheet).
Tout dépend de ce que mesure ce capteur. Pour moi il est fait pour mesurer la température de la puce et donc les 95°ou le 75 ° de la seconde série de mesure me semblent parfaitement réaliste.
On est d'accord que cette température de puce va dépendre de l'activité du micro et surtout du courant qui entre ou sort des sorties du micro.

Il serait intéressant de refaire la manip avec différents courants dans les charges des sorties, et nec plus ultra en mode source et sink.


Go Up