Localisation sonore avec Arduino

Bonjour, je suis tombé sur ce post Localisation d'une source sonore avec un ATmega328

J'ai donc tenté de reproduire ce code avec mes deux Capteur de son

Je n'arrive pas à avoir un retour correcte

Voici mon code

/*
 Name:		Roby_LocalisationSonore.ino
 Created:	03/12/2015 09:51:45
 Author:	Denis
*/

// Variables globale
int VAL1G;
int VAL1D;
int VAL2G;
int VAL2D;

int nbMesure = 10;
int microG = A0;
int microD = A1;

int methodeDeCalcul = 1;


void setup()
{
  pinMode(microG, INPUT);
  pinMode(microD, INPUT);
  Serial.begin(9600);
}

void loop()
{
  int resultat = localiserSon();
  Serial.println(resultat);
  delay(1000);
}

 // Détecte le son et calcule la différence
 // des signaux des deux micros
int localiserSon()
{
  byte i = 10;

  while (--i)
  {
    // Remise à zéro de l'échantillons
    VAL1G = 0;
    VAL1G = 0;
    VAL2G = 0;
    VAL2D = 0;

    // Récupération des échantillons
    for (int i = 0; i < nbMesure; i++)
    {
	VAL1G = abs(analogRead(microG));
	VAL1D = abs(analogRead(microD));
    }
	// Deuxiéme récupération des échantillons
    for (int i = 0; i < nbMesure; i++)
    {
	VAL2G = abs(analogRead(microG));
	VAL2D = abs(analogRead(microD));
    }
	// Comparaison des valeurs
    if (VAL2G > VAL1G && VAL2D > VAL1D)
    {
    // Calcul de la différence entre les deux micros gauche et droit
    // Deux possibilité de calcul

    // Avec compensation de la pente
    if (methodeDeCalcul == 1)
      return ((VAL2D - VAL2G + VAL1D - VAL1G) / (VAL2D - VAL1D + VAL2G - VAL1G));

    // Sans compensation de la pente
    else if (methodeDeCalcul == 2)
      return (VAL2D - VAL2G + VAL1D - VAL1G);
    }
  }
  return 0;
}

Bonsoir,

A premiere vue tu as initialisé 2 fois la meme variable :

VAL1G = 0;
VAL1G = 0;

mais pas la variable VAL1D ca ne viendrait pas de la ?

Bonjour,

Ca sert à quoi de faire 10 mesures puisque seule la dernière est prise en compte?

CA sert à faire une moyenne du son entendu
En fait c'est "+=" et non "=" qu'il fallait mettre

Extrait du code

// Récupération des échantillons
for (int i = 0; i < nbMesure; i++)
{
    VAL1G += abs(analogRead(microG));
    VAL1D += abs(analogRead(microD));
}
// Deuxiéme récupération des échantillons
for (int i = 0; i < nbMesure; i++)
{
    VAL2G += abs(analogRead(microG));
    VAL2D += abs(analogRead(microD));
}

J'ai peu importe le son environnent un retour quasiment à toujours à zéro :frowning:

Bonjour,

Par rapport au code de la page de référence, tu ne sommes pas les valeurs lues

Ceode de référence :

for(int i=0;i<nbMeasures;i++) { 
      val1b += abs(analogRead(micL));
      val2b += abs(analogRead(micR));
    }

Ton code :

 for (int i = 0; i < nbMesure; i++)
    {
 VAL2G = abs(analogRead(microG));
 VAL2D = abs(analogRead(microD));
    }

Il manque le + devant le =.

C'est une première piste...

Coyotte

Oups... doublé sur le fil... :slight_smile:

Bon j'ai fait quelques test sur les micros.

J'ai une détection constante aux alentours des 512 sur les deux micros et si je déconnecte l'alimentation des micros je continue à avoir une détection aux alentours des 50, 60.

Bon voici un code maison. Je pense me diriger plus vers cette voie

Plutôt que de récupérer la force du signal analogique, je me suis dit pourquoi ne pas récupérer le moment ou le son est entendu.

  • Si le micro droit entend le son avant le micro gauche c'est que la source sonore vient de la droite
  • Sinon si le micro gauche entend le son avant le micro droit, c'est que la source sonore vient de la gauche

Voici mon code qui doit bien sur être retravaillé

byte microG = 2;
byte microD = 4;
int ad_value;

void setup() 
{
  pinMode(microG,INPUT);
  pinMode(microD,INPUT);
  Serial.begin(9600);
}

void loop() 
{
  int resultat = localiserSon();
  if(resultat != 0)
  {
    Serial.println(resultat);
    delay(1000);
  }
}

int localiserSon()
{
  int detectionG = 0;
  int detectionD = 0;
  int i = 1000;
  if (digitalRead(microG) == LOW)
  {
    detectionG = millis();
    while (digitalRead(microD) != LOW || i--){
    }
    detectionD = millis();
  }
  else if (digitalRead(microD) == LOW)
  {
    detectionD = millis();
    while (digitalRead(microG) != LOW || i--){
    }
    detectionG = millis();
  }
  return detectionG - detectionD;
}
[\code]

Quand on valide un son sur un des deux micros on boucle (avec une sortie à 1000 itération pour éviter les boucles infinie) jusqu’à ce que l'autre micro valide également le son.

Il ne reste plus qu'a retourner la différence.

J'ai un peu modifié le code et ça a l'air de pas mal fonctionner .

J'ai un décalage de 20 ms à droite et -20 ms à gauche quand je parle à une distance de 20cm. Je ferai d'autre test demain

Bonjour,

Tes résultats sont un peu étranges. Sachant que le son fait 340m/s, pour parcourir 20cm il faut 0.6ms. Comment il peut y avoir un décalage de 20ms?

Tu as raison. Ce résultat vient du fait que je sortais de la boucle au bout de 5000 itérations si pas de détection de l'autre micros. ca veut donc dire que je parlé trop faiblement pour que le deuxieme micros capte le son :frowning:

  if (digitalRead(microG) == LOW)
  {
    detectionG = micros();
    while (digitalRead(microD) != LOW)
    {
      i--;
      if (i == 0)
        break;
    }
    detectionD = micros();
  }
[\code]

En parlant plus fort j'ai donc des valeurs différentes qui sont plus aux alentours des 1 à -1


Pour avoir des résultats plus précis je vais faire des essais avec micros()

Premiers essais à peu prés concluant avec une localisation sonore basé sur la différence entre le moment ou les micros captent le son.

Il faut avoir des micros régler sur le même seuil.

Voici le code

void loop()
{
	int resultat = localiserSon();
	if (resultat != 0)
	{
		// mise à jour du résultat obtenue avec le précédent Résultat
		resultat += resultatPrecedent;

		// bridage du résultat sur une plage de -300 à 300
		if (resultat > 300)
			resultat = 300;
		else if (resultat < -300)
			resultat = -300;

		Roby_Regarde_Position(resultat, 0);

		// Enregistrement de la valeur actuel dans resultatPrecedent
		resultatPrecedent = resultat;
		delay(500);
	}
}
// Fonction de localisation d'une source sonore
int localiserSon()
{
	// Variables nécessaires
	detectionG = 0;
	detectionD = 0;
	uint16_t i = 100;

	// Un son est capté sur le micro gauche
	if (digitalRead(microG) == LOW)
	{
		detectionG = micros(); // enregistrement du moment précis ou on capte le son
		valeurG = analogRead(microGA); // enregistrement de la valeur analogique du son

		// on boucle tant qu'on ne capte pas le son sur l'autre micro
		while (digitalRead(microD) != LOW)
		{
			// break pour sortir de la boucle si aucun son n'est détecté sur le deuxième micro
			i--;
			if (i == 0)
				break;
		}

		detectionD = micros(); // enregistrement du moment ou on sort de la boucle
		valeurD = analogRead(microDA); // enregistrement de la valeur analogique du micro droit
	}

	// Un son est capté sur le micro droit
	else if (digitalRead(microD) == LOW)
	{
		detectionD = micros();// enregistrement du moment précis ou on capte le son
		valeurD = analogRead(microDA);// enregistrement de la valeur analogique du son

		// on boucle tant qu'on ne capte pas le son sur l'autre micro
		while (digitalRead(microG) != LOW)
		{
			// break pour sortir de la boucle si aucun son n'est détecté sur le deuxième micro
			i--;
			if (i == 0)
				break;
		}
		detectionG = micros();// enregistrement du moment ou on sort de la boucle
		valeurG = analogRead(microGA);// enregistrement de la valeur analogique du micro gauche
	}

	// calcul de la différence entre les deux détections dans une plage de -300 à 300
	int difference = detectionD - detectionG;
	if (difference > 300)
		difference = 300;
	else if (difference < -300)
		difference = -300;

	// retour de la valeur calculée
	if (i != 0)
		return difference;
	else
		return 0;
}
// Regarde dans la direction de la position donnée
// sans dépasser les valeurs max et min autorisée
void Roby_Regarde_Position(int x, int y)
{
	x += 512;
	y += 512;

	_roby_XL320.begin(115200);
	_roby.begin(_roby_XL320);

	// Position x
	if (x <= MAX_X && x >= MIN_X)
		_roby.moveJoint(TETE_X, x);
	else if (x > MAX_X)
		_roby.moveJoint(TETE_X, MAX_X);
	else if (x < MIN_X)
		_roby.moveJoint(TETE_X, MIN_X);

	// Position y
	if (y <= MAX_Y && y >= MIN_Y)
		_roby.moveJoint(TETE_Y, y);
	else if (y > MAX_Y)
		_roby.moveJoint(TETE_Y, MAX_Y);
	else if (y < MIN_Y)
		_roby.moveJoint(TETE_Y, MIN_Y);

	_roby_XL320.end();
	delay(150);
}

Petite vidéo de démonstration

Voila. J'aimerai améliorer le système pour le rendre plus précis donc si vous avez des idées d'amélioration adapté à l'Arduino je suis preneur :smiley: