arduino decibel meter

Bonjour à tous et à toutes,

Je sais que de nombreux post sur le sujet existent mais aucun ne m'a donné pleine et entière satisfaction.

Je développe un grand projet dans lequel une partie consiste à mesurer le niveau sonore en décibels.

Pour cela je dispose bien évidemment d'une carte arduino mais aussi d'un micro a electret avec ampli intégré de gain réglable (voir photo)

Pour la calibration je dispose d'une source de 30 dB.

Mais voila mon probleme.... je peche sur le code, je ne comprends pas convertir la valeur de sortie du micro en decibel

const int MIC = A0; 
int adc;
int dB, PdB; 

void setup() {
Serial.begin(9600); 
  
}

void loop(){

  PdB = dB; //Store the previous of dB here
  
adc= analogRead(MIC); //Read the ADC value from amplifer 
Serial.println (adc);//Print ADC for initial calculation

//delay(100);

}

Merci à tous ceux qui me donnerons un éclair de génie ;D

capteur-micro-electret-arduino.jpg

Expliquez pourquoi la littérature existante ne vous satisfait pas?

choce:
... je peche sur le code, je ne comprends pas [comment] convertir la valeur de sortie du micro en decibel ...

Quelle opération mathématique permet de passer d'une amplitude au décibel ? Avec votre moteur de recherche préféré, recherchez comment coder cette opération en langage C.

Cordialement.

Pierre

Un peu de vernis sur les décibels pour aider à comprendre la littérature dont la lecture studieuse est indispensable.

Le principe de base est qu'un décibel ce n'est pas une unité de mesure comme le mètre l'est pour les distances.
Le Bell (unité officielle) c'est un rapport entre une mesure et une référence exprimées dans la même unité, c'est donc un nombre pur.

Par extension (ou abus de langage) à partir du moment où tout le monde utilise la même référence il est facile de faire la confusion entre le rapport et la valeur absolue de la mesure. Ce qui fait qu'on peut trouver le dB utilisé comme une unité de mesure, mais je le répète, même si tout le monde se comprend, c'est un abus de langage qui rend la compréhension difficile aux débutants.

Pour des raisons de commodité le rapport est exprimé en logarithme décimaux.
Comme le Bell est un rapport très grand en pratique on utilise le déciBell (dB) vaut 1 Bell/10.

Son avantage est celui des logarithmes : une multiplication devient une addition et une division une soustraction. Les grands nombres sont aussi plus faciles à manipuler :
rapport : 10 = 10 dB; 100 = 20 dB; 1000 = 30 dB, etc
C'est pour cela qu'il a été inventé par les télécommunications qui accumulent des divisions (atténuation du câble) et des multiplications (gain des amplificateurs).
Il porte le nom de l'inventeur du téléphone Graham Bell.

Le son se mesurant comme une puissance sonore il faut commencer par trouver qu'elle est la valeur de puissance qui a été choisie comme référence.
La suite n'est plus qu'une application de la documentation.
Bonnes lectures studieuses.

On ne calcule pas une puissance (ou des dB) sur un seul échantillon !
Il faut faire un échantillonage, c-à-d acquérir N valeurs régulièrement espacées dans le temps. Par exemple N=1024.
Le fréquence d'échantillonage doit être au moins 2 fois plus grande que la plus haute fréquence contenue dans ton signal.
Ensuite la puissance est calculée comme la somme des carrés des échantillons, divisée par N.
Enfin on divise cela par la puissance de calibration obtenue avec ta source à 30 dB.
Puis on transforme en dB avec la formule qui va bien.
Et on oublie pas d'ajouter 30.

Tout d'abord merci beaucoup pour vos réponses si nombreuses et complètes,

Je voulais donc résumer les choses pour etre sur d'avoir compris

je fais les mesures sur 1024 echantillons, je les mets au carré puis les sommes et enfin divise par le nombre d'echantillon
Je regarde quel sortie j'obtiens avec ma source de 30 dB, je divise le résultat précédent par cette valeur et enfin ajoute 30 et j'obtiens ma valeur en dB

int num_Measure = 1024 ; // Set the number of measurements   
int pinSignal = A0; // pin connected to pin O module sound sensor   
long Sound_signal;    // Store the value read Sound Sensor   
long sum = 0 ; // Store the total value of n measurements   
long level = 0 ; // Store the average value   
int sortie_source = 234; // valeur de sortie avec source de 30 dB
 
void setup ()  
{   
  pinMode (pinSignal, INPUT); 
  Serial.begin (115200);  
}  
   
void loop ()  
{  
  //  128 signal readings   
  for ( int i = 0 ; i <num_Measure; i ++)  
  {  
   Sound_signal = analogRead (pinSignal);  
    sum =sum + Sound_signal^2;  
  }  
 
  level = (sum / num_Measure)/(sortie_source)+30; // Calculate the average value   
  Serial.print("Sound Level: ");
  Serial.println (level);  
  sum = 0 ; // Reset the sum of the measurement values  
  delay(100);

Est-ce bien ca ?

Merci d'avance

biggil:
On ne calcule pas une puissance (ou des dB) sur un seul échantillon !
Il faut faire un échantillonage, c-à-d acquérir N valeurs régulièrement espacées dans le temps. Par exemple N=1024.
Le fréquence d'échantillonage doit être au moins 2 fois plus grande que la plus haute fréquence contenue dans ton signal.
Ensuite la puissance est calculée comme la somme des carrés des échantillons, divisée par N.
Enfin on divise cela par la puissance de calibration obtenue avec ta source à 30 dB.
Puis on transforme en dB avec la formule qui va bien.
Et on oublie pas d'ajouter 30.

Nous ne sommes pas ici dans le contexte de la théorie de Shannon. S'il faut faire plusieurs prises de son, c'est uniquement afin de faire un filtrage sur plusieurs mesures afin de lisser la valeur obtenue. Ces mesures doivent être assez rapprochées afin que le contexte sonore n'ait pas évolué. Une dizaine de mesures suffisent. Par contre, là où vous avez raison est le mode de calcul de la valeur filtrée : c'est la moyenne des valeurs au carré (valeur efficace).

Cordialement.

Pierre

Petite question sur la source de "son" étalon.
Quel type de son : sinusoïdal ou autre ?

Deuxième question : la conversion puissance de l'onde sonore / volts se fait dans le microphone.
Quelle est la fonction de transfert du microphone ?

Ce qui est sous-jacent derrière ma question est : est-ce qu'en sortie de l'amplificateur il faut faire du 10log (cas de la puissance) ou du 20log (cas des volts).
J'ai toujours évolué dans le domaine des transmissions, jamais dans celui du sonore, et cette question est la question piège par excellence. Celle que les personnes expérimentées abordent toujours très prudemment.

En régime sinusoïdal :
P/Po(dB) = 10 log(P/Po)
formule générale : p = ui
P = U2/R
Po = Uo2/R
P/Po = U2/Uo2
et comme log(a2) = 2log(a)
P/Po(db) = 10log(U2/Uo2) = 20log(U/Uo)

Tout dépend de la fonction de transfert du microphone que j'ignore, mais j'ai tellement vu de "d'erreurs d'appréciations" que je soulève le problème.

choce:
Je regarde quel sortie j'obtiens avec ma source de 30 dB, je divise le résultat précédent par cette valeur et enfin ajoute 30 et j'obtiens ma valeur en dB

Tu as oublié le passage du rapport aux dB : decibels = 20 log ( rapport)

    sum =sum + Sound_signal^2;

On écrit sum =sum + Sound_signal * Sound_signal; c'est + efficace !

ChPr:
Une dizaine de mesures suffisent.

S'il y a des basses fréquences et que les 10 pts sont pris quand le signal est proche de zéro, ça ne donne pas un puissance moyenne. On ne coupe malheureusement pas à une analyse de traitement du signal : choix de la fréquence d'échantillonage, choix du nombre de points : tout ça joue. C'est un peu trop lointain dans mon esprit pour donner les bonnes formules ici...

68tjs:
est-ce qu'en sortie de l'amplificateur il faut faire du 10log (cas de la puissance) ou du 20log (cas des volts).

Le signal électrique du microphone est sensé être analogue à l'onde de pression. Ce n'est donc pas une puissance, mais une amplitude (qui peut être négative). C'est pour çà qu'on élève au carré, et au final on prend 20 log (x).

biggil:
... S'il y a des basses fréquences et que les 10 pts sont pris quand le signal est proche de zéro, ...

Ma remarque vient du fait que je ne me plaçais pas dans le même contexte que vous.

Votre contexte est l'échantillonnage du signal, je ne l'avais pars perçu comme tel, et dès lors, votre raisonnement est correct.

Je me plaçais dans un contexte ou chaque mesure était déjà la représentation du volume sonore, comme le montrait jadis les "afficheurs analogiques à aiguilles".

Désolé.

Pierre.

biggil:
C'est pour çà qu'on élève au carré, et au final on prend 20 log (x).

Je pense avoir saisi mais je n'en suis pas assuré.

biggil:
Le signal électrique du microphone est sensé être analogue à l'onde de pression.

L'image de la pression c'est la tension où le carré de la tension ?
Je n'arrive pas a le savoir.

Que représente réellement le signal de sortie ?
Peut -être qu'un peu de développement serait utile.

C'est un spectre c'est à dire qu'il n'y a pas qu'une seule vibration mais une multitude de vibrations de fréquences et d'amplitudes différentes.
Dans ce cas les seules quantités qu'on a le droit d'additionner sont les puissances.

Pour les tensions on a introduit la notion de valeur efficace.
La valeur efficace d'une tension périodique quelconque est la valeur qu'aurait une tension continue qui sur une période de la tension quelconque développerait la même chaleur dans la même résistance --> cela reste basé sur les puissances.

Dans le cas particulier d'une tension sinusoïdale la relation entre la valeur crête (Vm) et la tension Veff est :
Vm = racine(2) * Veff , ---> ce n'est valable que pour une onde sinusoïdale.

Dans le cas d'un spectre pour calculer la valeur de tension efficace équivalente on prend la racine carrée de la somme des carrés des valeurs efficaces élémentaires --> encore une fois c'est basé sur les puissances.
Au passage c'est bien la seule et unique application où l'emploi du terme "rms" n'est pas faux, ça c'est fait :grin: .

Généralement cette mesure se fait dans une bande de mesure définie.
En absence de filtre passe bande ce sera la bande passante du microphone/amplificateur qui jouera ce rôle.
Le filtre passe bande joue un rôle mathématique d'intégration.
En absence de connaissance de la courbe de réponse de l'ensemble microphone/amplificateur le sono-dBmètre qu'on essaye de construire sera ce qu'il est, mais ne pourra pas être considéré comme un appareil de référence.

Pour mesurer cette valeur de tension efficace il faut un voltmètre adapté.
Les seuls voltmètres efficaces vrais que je connais sont des voltmètres à thermocouple.

Avec l'adc du micro contrôleur il faudra faire un traitement. Sur ce point tout le monde est d'accord.
Le premier qui me viens à l'esprit serait un traitement de Fourier (j'annonce de suite je n'en suis pas spécialiste, j'ai plus joué de l'analyseur de spectre que du calculateur).

biggil:
la puissance est calculée comme la somme des carrés des échantillons, divisée par N.

Je ne connais pas cette méthode (mes connaissances sont limités aussi).
Est-ce équivalent à un traitement de Fourier ?
As tu de la doc dessus ?

@choce

Je sais que de nombreux post sur le sujet existent mais aucun ne m'a donné pleine et entière satisfaction.

Voilà je pense que tu as compris pourquoi rien ne t'as donné satisfaction.
Sujet bien plus délicat qu'il n'y parait.

@68tjs:
Le signal électrique du microphone prends des valeurs positives ou négatives. Ce ne peut donc pas être une puissance, qui ne peut être que positive. Si tu enregistres un générateur BF (branché à un HP), tu auras une belle sinuoïde (ou onde carré, triangulaire...).
Le signal du microphone est analogue à l'onde de pression, pas à son carré.

Pour la démonstration de la formule de calcul de la puissance, tapes "puissance d'un signal échantilloné" sur GrosGueule.

Il est inutile d'envisager une transformée de Fourier dans ce contexte. Ca n'amène rien de plus.

Le traitement du signal est une science à part entière - que je suis loin de maîtriser. Tout est compliqué !

Notre ami choce a la chance de disposer d'une source de référence. Donc son sonomètre doit en tirer profit, selon la méthode que j'ai exposée plus haut. Bien sûr, pour que cela ait un sens, il faudra que les bruits mesurés soient à peu près de même nature que ceux de l'étalon (c-à-d qu'il aient des spectres comparables).

choce:
je fais les mesures sur 1024 echantillons, je les mets au carré puis les sommes et enfin divise par le nombre d'echantillon
Je regarde quel sortie j'obtiens avec ma source de 30 dB, je divise le résultat précédent par cette valeur et enfin ajoute 30 et j'obtiens ma valeur en dB

[...]

Est-ce bien ca ?

Il y a un autre problème (à part l'oubli de la convertion rapport->décibels).
Tu n'as aucune idée de la fréquence d'échantillonage. Pour que ce que je t'ai conseillé ait un sens, il est nécessaire que les échantillons soient prélevés à intervalles réguliers.

Si je t'ai parlé de 1024 points, c'est que j'avais implicitement en tête une fréquence d'échantillonage de 44.1 kHz (comme sur un CD audio). La durée de l'acquisition est alors de 1024/44100 = 23 millisecondes.

Pour calculer correctement ta puissance sonore, il faut que tu échantillones sur une durée qui contient au moins une période de la fréquence la plus basse contenue dans le signal. Avec 23 ms tu peux choper une période d'un signal à 43 Hz (proche de la limite basse de l'audition ... et du micro)

Pour échantilloner à 44.1 kHZ, il faut faire une mesure toutes les 22.68 microsecondes. Je ne sais pas si l'Arduino peut faire cela. C'est pour ça que sur un ordinateur, cette tâche est confiée à une carte son, plutôt qu'au processeur principal de la machine.

@biggil
Tu as tout à fait raison.
Je recherchais une notion d'intégrale et je ne voyais pas intervenir le temps.
Je me suis rendu-compte de mon erreur trop tard dans la soirée pour rectifier.

En fait c'est parce que le temps s'éliminait dans l'application finale.
Ta méthode n'est rien d'autre que l'application de la définition de la valeur efficace qu'en plus , honte à moi, j'avais rappellé.

Les échantillons se prennent avec des intervales bien réguliers, tu fais l'intégrale en applicant la méthode des rectangles pendant une période de temps correspondant dans ton exemple à 1024dt (dt= le temps entre deux échantillons).
La surface de chaque rectangle est égale aux volts élevés au carré multipliés par l'intervale dt entre deux échantillons. La somme des surfaces des rectangle est divisée par par dt
1024.
Dans l'exploitation finale dt n'apparait plus.

Pour déterminer les fréquences basse et haute tout va dépendre du niveau d'information contenu dans la documentation du microphone-amplificateur.
Si la documentation est "maigre" on peut aussi envisager de la miise au point expérimentale sur un bruit réel représentatif de celui qui sera à mesurer : voir à partir de quel moment l'augmentation du nombre d'échantillons et de la fréquence d'échantillonage n'influent plus sur le résultat

Prévoir une lecture de la datasheet du microcontroleur pour configurer l'ADC correctement.
AnalogRead le configurant de manière très conservative pour ne pas avoir de soucis, il va falloir mettre un peu les mains dans le cambouis des registres, mais cela reste simple.

Point pratique important : quand on lance l'ADC la première mesure est toujours plus lente et souvent entachée d'erreur, la virer systématiquement.

Avez-vous recherché avec votre moteur de recherche préféré : "Arduino sonomètre" ? Enre autres réponses, celle-ci me semble pertinente.

Cordialement.

Pierre

biggil:
... Pour échantilloner à 44.1 kHZ, il faut faire une mesure toutes les 22.68 microsecondes. Je ne sais pas si l'Arduino peut faire cela. ...

Quand j'ai réalisé mon petit oscilloscope avec un MEGA 2560, je suis monté à un fréquence de lecture de l'ADC de l'ordre de 100 kHz. Donc 44.1khz (ou une valeur proche selon la possibilité des diviseurs) devrait passer.

Pour autant, cette analyse sur 1024 échantillons (voire 2048 ou 4096) ne donnera qu'une indication "ponctuelle" du niveau sonore. Selon qu'on veut afficher un niveau "crête" ou un niveau "moyen", il y aura un post traitement (moyennage ou autre) à faire.

Si après, vous voulez vous conformer à des normes (dB A par exemple), il vous faudra étalonner votre micro et procéder à des pondérations fréquentielles.

Yout cela vous laisse un champ d'investigation gigantesque :slight_smile:

Cordialement.

Pierre

68tjs:
quand on lance l'ADC la première mesure est toujours plus lente et souvent entachée d'erreur, la virer systématiquement.

je viens de penser à un truc : l'ADC de l'Arduino ne mesure que des tensions positives (si j'ai bien compris).
Or le microphone va envoyer des tensions symétriques par rapport à zéro, donc des négatives.

Si ça n'abime pas l'Arduino (je suis une quiche en électronique), ça va écrêter la moitié du signal. Sur un signal sinusoïdal, on n'aura que les arches positives.

Les méthodes évoquées ci-avant continuent à fonctionner, mais tout ça devient franchement scabreux...

Exact mais la solution est très simple, c'est la méthode classique pour relier des amplis en électronique analogique.

Il est possible de faire un décalage en tension avec un pont de résistance qui délivre autour de 2,5V.
Le point milieu du pont est appliqué directement sur l'entrée du micro
La sortie de l'ampli et le point milieu du pont sont relié avec une liaison capacitive.
Il est même fort probable que la sortie de l'ampli se fasse déjà au travers d'un condensateur.

De toutes façons, il lui sera très certainement nécessaire de prévoir un ampli à gain ajustable s'il souhaite avoir une bonne étendue de mesure, vu que ça va vitre avec les dB.

Cordialement.

Pierre

ChPr:
vu que ça va vitre avec les dB.

Oui, faut jouer la transparence :wink: