Lissage des signaux SoundSensor

Bonjour à tous,

J'ai créé un module pour pouvoir allumer une bande de LEDs lorsque je joue de la basse.
Pour faire simple : quand je joue une note, la bande s'allume, quand je ne joue rien, elle s'éteint.
Je souhaite que l'on voie les notes une par une, et donc que lorsqu'une note est courte, que la bande ait le temps de s'éteindre pour se rallumer à la note suivante.
Pour faire tout cela, je me suis débrouillé, tout fonctionne sauf une seule chose :
Lorsque je joue une note longue, la bande s'allume un peu plus longtemps, mais clignote aléatoirement...

Pour prendre le son, j'ai modifié un "sound detector", normalement fourni avec un micro, que j'ai remplacé par une prise jack pour brancher la basse. Ce sound detector est branché à l'arduino Uno, et la bande de LEDs ws2812 aussi.

Voici le code que j'ai fait :

#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
  #include <avr/power.h>
#endif

#define PIN 6
int soundSensor = 2;

Adafruit_NeoPixel strip = Adafruit_NeoPixel(300, PIN, NEO_GRB + NEO_KHZ800);

void setup() {
 
  strip.begin();
  strip.show(); // Initialize all pixels to 'off'
  pinMode(soundSensor, INPUT);
  Serial.begin(9600);

  for (int i=0; i<=299; i++)
  strip.setPixelColor(i, 223, 223, 223); 

}

void loop() {
  int statusSensor = digitalRead (soundSensor);

  if (statusSensor == 1)
  {
    strip.setBrightness(230);
    delay(100);
    strip.setBrightness(200);
    delay(10);
    strip.setBrightness(170);
    delay(10);
    strip.show();
    delay(100);
  }

  else
  {
    strip.setBrightness(10);
    strip.show();
  }
  Serial.println(digitalRead (soundSensor));

}

La vue console me permet de voir que le "Sound Sensor" a 2 positions : 1 ou 0. Soit il entend du son, soit pas du tout.
Mais parfois, ça ne marche pas à 100% :
Pour les petites notes (qui ne posent pas de problème), la console affiche par exemple :

0
0
0
0
1 ---> La note est jouée, la lumière s'allume
1
0 ---> La note s'arrête, la lumière s'éteint
0

En revanche, et c'est là où ça se gâte, pour une note longue, cela m'affiche :

0
0
0
1 ----> début de la note longue
1
1
1
1
1
1
1
0 ----> Petit bug dans la matrice de mon sound sensor, la lumière s'éteint subrepticement
1 ----> La lumière se rallume car la note n'est toujours pas finie
1
1
0 ----> Re-petit bug comme avant
1 ----> La lumière se rallume car la note n'est toujours pas finie
1
1
1
0 ----> La lumière s'éteint car la note est VRAIMENT finie :slight_smile: (pfiou !)
0
0
0

Déjà, désolé pour ce gros post, mais je souhaite être le plus clair possible :slight_smile:

Enfin, quelqu'un aurait-il une idée pour "lisser" les captations du sound sensor ? Sachant que j'ai déjà joué sur la sensibilité du bouzin, je suis au max, rien à faire de ce côté là.

Toute idée, ou début d'idée, me seront d'une très grande aide !

Merci par avance pour votre temps et votre aide précieuse, et belle journée / soirée !

b

Un petit UP ? merci !

Avec une moyenne glissante des dernières mesures.

Merci Christian pour ta réponse. Je vais tenter cela de ce pas :slight_smile: et vous tiens informés

Salut camarade bassiste !
Je suppose que tu as relié la sortie de la basse à la broche 2.
Le signal envoyé par la basse est symétrique par rapport à 0V, c-à-d qu'il varie très rapidement autour de 0 V.
Il est faux de croire que "la broche mesure 1" implique "il y a du son" et que "la broche mesure 0" implique "il n'y a pas de son".

Il faut faire une acquisition analogique du signal, sur plusieurs mesures, faire la somme des carrés des échantillons et comparer le résultat à un seuil pour décider s'il y a du son ou pas.
Voir le file de discussion arduino decibel meter

Bonjour Biggil,

Merci pour ta réponse :slight_smile: effectivement ça m'avait traversé l'esprit à la lecture de ce fil :slight_smile:
Je teste ça donc, et je vous dis !

Re-bonjour,

J'ai bien avancé, et merci à Biggil pour ton aide :slight_smile: J'ai bien fait une acquisition analogique du signal et ça fonctionne beaucoup, beaucoup mieux ! :smiley:
J'ai lissé les acquisitions sur 10 échantillons en faisant une moyenne glissante. Le seul truc à gérer maintenant est d'optimiser le code, car il y a une latence d'environ 300/400ms, ce qui est encore assez visible :confused:
Je vais donc peaufiner mon code pour que l'Arduino ait moins de choses à cogiter :smiley:

Pour ceux que ça intéresse, voici mon code. Et si vous avez des pistes d'améliorations n'hésitez pas ! En tout cas merci beaucoup à la communauté !

Pour info : lorsque la moyenne de mes échantillons est en dessous de 280, je dis à la LED Strip de s'éteindre. C'est parce que lorsque la basse est branchée et qu'il n'y a aucun son de joué, l'analog prend une valeur de 30 ou 31 en général. quand une note est jouée, ça monte à plus de 1000, puis ça redescend vers 30 ou 31. Du coup, pour éviter que lors d'une note longue la LED soit allumée trop longtemps, je bloque la LED lorsque l'on passe en dessous de 280 de moyenne :slight_smile:

#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
  #include <avr/power.h>
#endif

#define PIN 6

Adafruit_NeoPixel strip = Adafruit_NeoPixel(300, PIN, NEO_GRB + NEO_KHZ800);

const int nEchantillons = 10;
 
int echantillon[nEchantillons];
int indice = 0;       
float total = 0;               
float moyenne = 0;                 
 
int inputPin = A0;
 
void setup() {
  strip.begin();
  strip.show();
  for (int i=0; i<=299; i++)
  strip.setPixelColor(i, 223, 223, 223);
  Serial.begin(9600);
  for (int i = 0; i < nEchantillons; i++) {
    echantillon[i] = 0;
  }
}
 
void loop() {
  // Soustraction de l'echantillon précédent
  total = total - echantillon[indice];
  
  // Lecture du capteur
  echantillon[indice] = analogRead(inputPin);
  Serial.print(echantillon[indice]);
  
  // Ajout du dernier echantillon
  total = total + echantillon[indice];
  
  // Incrémentation de l'indice
  indice++;
  // si on est à la fin du tableau ...
  if (indice >= nEchantillons) {
    // ...retour au début
    indice = 0;
  }
 
  // calcul de la moyenne
  moyenne = total / nEchantillons;
 
  Serial.print(",");
  Serial.println(moyenne);
  if (moyenne >= 280)
  {
    strip.setBrightness(230);
    strip.show();
  }

  else
  {
    strip.setBrightness(10);
    strip.show();
  }
  
}

Ca marche parce que l'Arduino ne mesure que des valeurs analogiques positives. Le signal étant (à peu près) symétrique par rapport à zéro, toutes les parties négatives ( < 0 V) sont perdues.
Si l'arduino pouvait lire ces valeurs négatives, ta méthode ne marcherait pas, car les + et les - se compenseraient et ton résultat voisinerait zéro.
C'est pour ça qu'on doit calculer non pas la somme des échantillons, mais la somme des carrés des échantillons. Le résultat est alors une image de la puissance du signal.

Par ailleurs ton échantillonage se fait à haute fréquence (aucun délai dans le fonction loop() ). Comme le signal que tu analyses contient des bases fréquences (guitare basse), ta moyenne mobile doit osciller pas mal. Tu devrais calmer un peu le jeu en insérant une attente d'un vingtaine de microsecondes entre chaque acquisition.

Merci Biggil pour tes conseils, je vais appliquer cela !