Petite mise à jour de notre article sur la liste des UCS LEGO avec les derniers sets sortis. (...)
Un NXT à commande vocale !
Le kit de base NXT comporte un microphone. On peut s’en servir comme télécommande. Voici comment.
La commande vocale s’insinue partout. Les derniers GPS, les téléphones portables incluent maintenant des processeurs suffisamment puissants, voire même des puces dédiées, leur permettant de proposer cette fonctionnalité.
Le NXT ne la propose pas de base, comblons donc cette lacune !
Ben oui mais comment qu’c’est-y don’ possible, cré fieux !??
Effectivement, les plus avertis d’entre vous auront vite remarqué que le NXT ne contient pas un Intel Quad Core ni 2 Gb de RAM et se demandent donc une architecture si modeste peut quand même faire reconnaitre la voix !
Forcément, y’a un truc.
Mon idée n’est pas de reconnaitre la voix en tant que telle, mais un ordre.
Whouah, quelle différence sibylline !
Ok, je développe.
Évidemment, le NXT n’est pas capable de reconnaitre des mots, et encore moins des phrases. En revanche, il sait capter du bruit via son micro.
Ce micro n’indique au NXT que l’intensité sonore qu’il détecte, avec un niveau variant de 0 (rien) à 100 (saturation du micro). Le NXT possède aussi des timers. Je commence à voir votre oeil qui s’illumine !
Voilà : il suffit de mesurer pendant combien de temps un niveau sonore est détecté !
On utilise un timer qu’on déclenche lorsque le niveau sonore détecté par le NXT dépasse un certain seuil (qu’on calibre auparavant sur le niveau sonore ambiant). C’est la détection de l’ordre (T0).
C’est bien, on a détecté un ordre. Mais lequel ?
En fait, le timer s’arrête lorsque le niveau sonore baisse, c’est à dire la fin de l’ordre (T1).
Du coup, il suffit de comparer T1-T0 (=ordre) à une table.
Exemple :
Si 0 < ordre < 500 ms, alors effectuer telle action
Si 500 ms < ordre < 1 s, alors effectuer telle autre action
Si 1s < ordre < 1,5 s, alors effectuer encore telle autre action.
etc.
Voici, ci-dessous, un programme en RobotC (à copier/coller directement dans RobotC, qui remettra en forme) qui met en pratique cette théorie. Dans ce programme, vous verrez qu’en fonction de la longueur de votre ordre, un numéro s’affiche sur l’écran.
A vous de modifier cela pour faire faire à votre NXT ce que vous voulez !
Un bémol cependant : il faut évidement garder le niveau sonore à un certain niveau pour que le NXT continue de mesurer la durée de l’ordre. C’est pour cela que j’ai ajouter une petite pause dans la boucle. Elle évite de couper la mesure entre 2 mots. C’est une petite bidouille qui peut être améliorée, je vous laisse tester !
A bientôt pour de nouvelles aventures !
#pragma config(Sensor, S1, soundSensor, sensorSoundDB)
//*!!Code automatically generated by 'ROBOTC' configuration wizard !!*//
/*--------------------------------------------------------------------------------------------------------*\
|* *|
|* - commandes vocales - *|
|* ROBOTC on NXT *|
|* *|
|* This program runs tasks depending on sound delay, which can be assimilated to vocal commands. *|
|* *|
|* ROBOT CONFIGURATION *|
|* NOTES: *|
|* 1) The 1 second delay is needed to avoid obtaining inaccurate initial readings. *|
|* *|
|* MOTORS & SENSORS: *|
|* [I/O Port] [Name] [Type] [Description] *|
|* Port B motorB NXT Right motor *|
|* Port C motorC NXT Left motor *|
|* Port 1 soundSensor Sound Sensor Sound Db Right *|
\*-------------------------------------------------------------------------------------------------------*/
int NiveauReference, DureeSon;
task main()
{
NiveauReference = 0;
DureeSon = 0;
wait1Msec(1000); // A one-second wait is required to cleanly initialize the Sound Sensor.
eraseDisplay();
//initializing ambiant sound level
NiveauReference = SensorValue[soundSensor];
nxtDisplayTextLine(0, "niveau actuel :");
nxtDisplayTextLine(1, "%2i", NiveauReference);
wait1Msec(3000);
eraseDisplay();
while(true) // Infinite loop
{
ClearTimer(T1); // reseting timer and showing the current sound level
nxtDisplayTextLine(0, "niveau son :");
nxtDisplayTextLine(1, "%2i", SensorValue[soundSensor]);
// checking if the sound level detects words
while (SensorValue[soundSensor] > (NiveauReference + 10))
{
DureeSon = time1[T1]; // incrementing the variable according to timer to have the sound delay eared by the NXT
nxtDisplayTextLine(2, "Ecoute depuis"); // indicating from how long the NXT "ears" words (orders)
nxtDisplayTextLine(3, " %2i ms", DureeSon);
wait1Msec(250); // pause to avoid breaking measure word after word, can be adjusted.
/* this pause is a kind of pb as if you are between 2 words at the end of pause, the loop ends...
another way of programing could be the following :
loop:
{
check sound level,
if sound level > reference + 10 then initiate timer
wait 500 ms (or a little less, for next measuring processing time)
measure timer :
if the sound level is under reference +10, then order 1 and end loop
else
wait another 500 ms (so we have a 1 second delay/order)
if the sound level is under reference +10, then order 2 and end loop
else
wait 1000 ms (so we have a 2 seconds delay/order)
if the sound level is under reference +10, then order 3 and end loop
else
wait another 1000 ms (so we have a 3 seconds delay/order)
if the sound level is under reference +10, then order 4 and end loop
else
wait another 1000 ms (so we have a 4 seconds delay/order)
if the sound level is under reference +10, then order 5 and end loop
else
wait another ? ms (so we have a more than 4 seconds delay/order)
if the sound level is under reference +10, then order 6 and end loop
}
*/
}
// checking if an "order" have been "eared"
if (DureeSon > 0)
{
// defining orders depending on the order's delay
if ((DureeSon > 0) & (DureeSon < 500)) DureeSon = 1;
if ((DureeSon > 500) & (DureeSon < 1000)) DureeSon = 2;
if ((DureeSon > 1000) & (DureeSon < 2000)) DureeSon = 3;
if ((DureeSon > 2000) & (DureeSon < 3000)) DureeSon = 4;
if ((DureeSon > 3000) & (DureeSon < 4000)) DureeSon = 5;
if (DureeSon > 4000) DureeSon = 6;
switch (DureeSon)
{
case 1:
nxtDisplayTextLine(3, "Ordre 1");
wait1Msec(2000);
break;
case 2:
nxtDisplayTextLine(3, "Ordre 2");
wait1Msec(2000);
break;
case 3:
nxtDisplayTextLine(3, "Ordre 3");
wait1Msec(2000);
break;
case 4:
nxtDisplayTextLine(3, "Ordre 4");
wait1Msec(2000);
break;
case 5:
nxtDisplayTextLine(3, "Ordre 5");
wait1Msec(2000);
break;
case 6:
nxtDisplayTextLine(3, "Ordre 6");
wait1Msec(2000);
break;
case 0:
nxtDisplayTextLine(3, "Ratage...");
wait1Msec(2000);
break;
default:
}
// reinitializing the "order"
DureeSon = 0;
eraseDisplay();
}
}
}