Commit f4056f09 authored by Damien OLIVIER's avatar Damien OLIVIER

Décibel

parent 3e3c7109
--- ---
layout: document-with-math-support layout: document-with-math-support
title: Led's dance title: Led's dance
authors: Faironnier J.L_et_d authors: Faironniers J.L_et_D
tags: arduino,leds,atelier tags: arduino,leds,atelier
brouillon: true brouillon: true
image: /images/doc/ateliers/10ansBU.jpg image: /images/doc/ateliers/10ansBU.jpg
...@@ -295,10 +295,10 @@ uint32_t roueChromatique(byte teinte, float saturation, float lumiere) ...@@ -295,10 +295,10 @@ uint32_t roueChromatique(byte teinte, float saturation, float lumiere)
} }
~~~ ~~~
On complète en ajoutant une fonction qui allume `n` les consécutives en donnant le numéro de la première et le numéro de la dernière. On écrit une fonction qui eteint `n` leds consécutives en donnant le numéro de la première et le numéro de la dernière.
~~~ C++ ~~~ C++
void allumeEntre(uint8_t ledDepart, uint8_t ledArrivee, uint32_t couleur) { void eteintEntre(uint8_t ledDepart, uint8_t ledArrivee) {
uint8_t tmp; uint8_t tmp;
if (ledDepart > ledArrivee) if (ledDepart > ledArrivee)
{ {
...@@ -307,12 +307,99 @@ void allumeEntre(uint8_t ledDepart, uint8_t ledArrivee, uint32_t couleur) { ...@@ -307,12 +307,99 @@ void allumeEntre(uint8_t ledDepart, uint8_t ledArrivee, uint32_t couleur) {
ledArrivee = tmp; ledArrivee = tmp;
} }
for (int quelleLed = ledDepart; quelleLed <= ledArrivee; quelleLed++) for (int quelleLed = ledDepart; quelleLed <= ledArrivee; quelleLed++)
anneau.setPixelColor(quelleLed, couleur); anneau.setPixelColor(quelleLed, anneau.Color(0, 0, 0));
} }
~~~ ~~~
En s'inspirant de cette dernière on pourrait écrire une fonction qui allume `n` leds consécutives en donnant le numéro de la première, le numéro de la dernière et la couleur.
Nous allons écrire une version plus sophistiquée qui allume un gradient de couleur entre les leds considérées. On utilise pour cela une fonction `map (valeur, source_limite_basse, source_limite_haute, destination_limite_basse, destination_limite_haute)` :
* `valeur` : le nombre à mettre à l'echelle ;
* `source_limite_basse` : la borne inférieure de l'échelle de la valeur ;
* `source_limite_haute` : la borne supérieure de l'échelle de la valeur ;
* `destination_limite_basse`: la borne inférieure de la nouvelle échelle ;
* `destination_limite_haute`: la borne supérieure de la nouvelle échelle.
La valeur renvoyée est la valeur mise à l'échelle. On utilise la fonction `map()`, la couleur est choise par le numéro de led à allumer.
~~~ C++
void allumeEntre(uint8_t ledDepart, uint8_t ledArrivee, unsigned int angleDepart, unsigned int angleArrivee) {
uint8_t tmp;
if (ledDepart > ledArrivee)
{
tmp = ledDepart;
ledDepart = ledArrivee;
ledArrivee = tmp;
}
for (int quelleLed = ledDepart; quelleLed <= ledArrivee; quelleLed++)
anneau.setPixelColor(quelleLed,roueChromatique(map(ledArrivee - ledDepart + 1, 0, N_LEDS - 1, angleDepart, angleArrivee), 1, 0.5));
}
~~~
On repart de notre programme qui lisait la sortie du micro, pour une meilleure lisibilité on écrit une fonction `acquisition()` qui réalise le traitement.
~~~ C++
unsigned int acquisition()
{
unsigned int echantillon;
unsigned int signalMax = 0;
unsigned int signalMin = 1024;
unsigned long debutCrono = millis(); // Debut d'échantillonnage
unsigned int creteACrete = 0; // Niveau crête à crête
while (millis() - debutCrono < fenetreEchantillonnage)
{
echantillon = analogRead(BROCHE_MICRO);
if (echantillon < 1024) // Valeur cohèrente ?
{
if (echantillon > signalMax)
{
signalMax = echantillon;
}
else if (echantillon < signalMin)
{
signalMin = echantillon;
}
}
}
creteACrete = signalMax - signalMin; // Amplitude crête à crête
return creteACrete;
}
~~~
Il nous reste à définir la fonction `loop()` principale :
~~~ C++
void loop() {
unsigned int amplitude = acquisition(); // Amplitude crête à crête
unsigned int nbAAllumer = map(amplitude, 0, 1024, 0, 17 );
#ifdef DEBUG
Serial.print("amplitude = "); Serial.println(amplitude);
Serial.print("nbAAllumer = "); Serial.println(nbAAllumer);
#endif
eteintEntre(nbAAllumer, N_LEDS - 1); // On éteint les leds en trop ...
if (nbAAllumer > 0) allumeEntre(0, nbAAllumer - 1, 120, 0);
anneau.show();
}
~~~
## Pour aller plus loin
Notre baroufledomètre est terminé. Des améliorations sont possibles, nous traitons les mesures linéairement ce qui n'est pas correct. Nos oreilles sont sensibles à des **variations** de pression
entre 0,00002 Pa (20 μPa) et 200 Pa (la pression atmosphérique est de 101 300 Pa), l'étendue de l'échelle est donc de 10⁶ et elle est donc très grande. D'autre part c'est la **variation relative** entre deux sons que nous percevons et non pas une variation absolue. Un son exerçant une pression acoustique de 0,02 Pa relativement à 0,01 Pa est aussi fort qu'un son de 2 Pa relativement à 1 Pa. Le son a augmentre de 100% !
On utilise donc le décibel pour mesurer le son, c'est une échelle logarithmique. Dans l'usage courant, un niveau de bruit exprimé en décibels est un niveau de pression acoustique Lp = O dB avec comme référence 20 μPa. Cette échelle est trompeuse car non linéaire. Un bruit de 55 dB (bruit d'une conversation) ajouté à un bruit de 55 dB n'est pas un bruit de 110 db,
Pour la première source : $L_{I1} = 10 \ln (I_1/I_0)$ et pour la deuxième $L_{I1} = 10 \ln (I_1/I_0)$. Le niveau d’intensité acoustique résultant du fonctionnement des deux sources est donc $L_{I} = 10 \ln ((I_1 + I_2)/I_0)$ Les deux sources produisent icic la même intensité, $I_1 = I_2$, $L_{I} = 10 \ln (2 \times I_1/I_0) = L_{I1} + 10 \ln 2$, donc environ 55 + 3 dB = 58 dB.
[faironnerie ABC]: <https://faironnerie-abc.xyz/> [faironnerie ABC]: <https://faironnerie-abc.xyz/>
[4681b06b]: https://www.arduino.cc/en/Main/ArduinoBoardNano "Arduino Nano" [4681b06b]: https://www.arduino.cc/en/Main/ArduinoBoardNano "Arduino Nano"
[adafruit]: <https://learn.adafruit.com> ~~~
Notre [adafruit]: <https://learn.adafruit.com>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment