View  Edit  Attributes  History  Attach  Print  Search

ACCUEIL | ARDUINO > S'INSTALLER > DEBUTER > APPROFONDIR | PROCESSING | MECATRONIQUE | MATERIEL | OUTILS | TESTS | Plus...|
Python > Shell > ATELIERS Python + Qt > PyQt apps > PyQt+Arduino | Mes Robots | RepRap | Mes lib'Arduino | Mes shields Arduino | Mes distros | Les Mini-PC |
ATELIERS ARDUINO| VIDEOS | COMPRENDRE | REFERENCES | CODER | TECHNIQUE | GNU/LINUX | LIENS | Rien à voir |

EeePC-Bot : Contrôle des moteurs depuis une interface Processing avec annonce sonore par synthèse vocale et bruitages sonores

Par X. HINAULT - Page créée le : 11/04/2011.

(cliquer sur l'image pour agrandir)

1.  Présentation

  • Contrôle des moteurs et des différents mouvements (avant, arriere, stop, tourne droite, etc...) à partir d'une chaîne de caractères reçue sur le port série en provenance d'une interface Processing ou du Terminal série du logiciel Arduino.
  • Par exemple, pour que les moteurs aillent en avant, on fera enAvant(vitesse) où la vitesse sera une valeur comprise entre 0 (arrêt) et 255 (maximum). La vitesse sera exprimée sur 3 chiffres : la valeur 0 sera appliquée sous la forme enAvant(000).
  • Les fonctions disponibles sont :
    • arret()
    • tourneDroite (int vitesse)
    • tourneGauche (int vitesse)
    • enArriere (int vitesse)
    • enAvant (int vitesse)

avec :

  • vitesse de 0 à 255 (impulsion PWM)
  • sens = 0 : en arriere et sens=1 : en avant
  • Ce programme déclenche la synthèse vocale sur le eeePC par l'envoi d'une chaine de la forme espeak=chaine=
  • Ce programme déclenche la lecture de fichier son sur le eeePC par l'envoi d'une de la forme nomfichier.type

Ce programme utilise les fonctionnalités suivantes :

  • Utilise la connexion série vers le PC

Ressources utiles associées à ce programme :

  • La librairie Serial - pour les communications séries entre la carte Arduino et l'ordinateur ou d'autres composants

2.  Matériel Nécessaire

2.1  L'espace de développement Arduino

  • ... pour éditer, compiler le programme et programmer la carte Arduino.

2.2  Le matériel suivant pour réaliser le montage associé

  • des straps,

3.  Instructions de montage

  • La connexion série vers le PC utilise les broches 0 et 1 (via le câble USB)
  • Connexion de l'interface DFRobot 2A Moteur CC sur les broches de la carte Arduino :
    • Connecter broche de sens du moteur 1 sur la broche 4
    • Connecter broche de vitesse du moteur 1 sur la broche 5
    • Connecter broche de sens du moteur 2 sur la broche 7
    • Connecter broche de vitesse du moteur 2 sur la broche 6

4.  Le schéma théorique du montage

Le schéma théorique du montage (cliquer pour agrandir)

5.  Le circuit du montage

Le schéma du montage à réaliser (cliquer pour agrandir)

6.  Explication du programme

7.  Mise en oeuvre du programme

7.1  Préparation du montage et programmation de la carte Arduino :

  • Commencer par réaliser le montage indiqué sur plaque d'expérimentation
  • Ensuite, programmer la carte Arduino avec ce programme (en bas de page) selon la procédure habituelle

7.2  Fonctionnement

  • Dans le Terminal Série, saisir l'instruction voulue : par exemple, enAvant(100). Le robot va avancer en avant à petite vitesse.
  • Saisir arret() : le robot s'arrete
  • etc...
  • Les fonctions disponibles sont :
    • arret()
    • tourneDroite (int vitesse)
    • tourneGauche (int vitesse)
    • enArriere (int vitesse)
    • enAvant (int vitesse)

avec :

  • vitesse de 0 à 255 (impulsion PWM)
  • sens = 0 : en arriere et sens=1 : en avant

8.  Le programme complet en langage Arduino

A copier/coller directement dans l'éditeur Arduino


// --- Programme Arduino ---
// Trame de code générée par le générateur de code Arduino
// du site www.mon-club-elec.fr

// Auteur du Programme : X. HINAULT - Tous droits réservés
// Programme écrit le : 11/4/2011.

// ------- Licence du code de ce programme -----
//  This program is free software: you can redistribute it and/or modify
//  it under the terms of the GNU General Public License as published by
//  the Free Software Foundation, either version 3 of the License,
//  or any later version.
//  This program is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU General Public License for more details.
//  You should have received a copy of the GNU General Public License
//  along with this program.  If not, see <http://www.gnu.org/licenses/>.

// ////////////////////  PRESENTATION DU PROGRAMME ////////////////////

// -------- Que fait ce programme ? ---------
 /*
 Contrôle des moteurs et des différents mouvements (avant, arriere, stop, tourne droite, etc...)
 à partir d'une chaîne de caractères reçue sur le port série.

 Déclenche des messages vocaux en synthèse vocale
 Déclenche des bruitages sonores par lecture de fichier son

 */


// --- Fonctionnalités utilisées ---

// Utilise la connexion série matérielle vers le PC
// Utilise / fonctionne avec une interface Processing coté PC
// Utilise une carte d'interface moteurs CC DFRobot 2A

// -------- Circuit à réaliser ---------

// La connexion série matérielle vers le PC utilise les broches 0 et 1 (via le câble USB)

// Connexion de l'interface DFRobot 2A Moteur CC sur les broches de la carte Arduino :
// Connecter broche de sens du moteur 1 sur la broche 4
// Connecter broche de vitesse du moteur 1 sur la broche 5
// Connecter broche de sens du moteur 2 sur la broche 7
// Connecter broche de vitesse du moteur 2 sur la broche 6

// /////////////////////////////// 1. Entête déclarative ///////////////////////
// A ce niveau sont déclarées les librairies incluses, les constantes, les variables, les objets utiles...

// --- Déclaration des constantes ---

// --- Inclusion des librairies ---

// --- Déclaration des constantes utiles ---

const int AVANT=1; // constante sens moteur
const int ARRIERE=0; // constante sens moteur
const int STOP=0; // constante vitesse moteur

// --- Déclaration des constantes des broches E/S numériques ---

//--- moteur 1 est le moteur Gauche
const int sensMoteur1=4; // Constante pour la broche 4
const int vitesseMoteur1=5; // Constante pour la broche 5

const int sensMoteurGauche=4; // Constante pour la broche 4
const int vitesseMoteurGauche=5; // Constante pour la broche 5

//---- moteur 2 est le moteur droit
const int vitesseMoteur2=6; // Constante pour la broche 6
const int sensMoteur2=7; // Constante pour la broche 7

const int vitesseMoteurDroit=6; // Constante pour la broche 6
const int sensMoteurDroit=7; // Constante pour la broche 7

// --- Déclaration des constantes des broches analogiques ---


// --- Déclaration des variables globales ---

 int octetReception=0; // variable de stockage des valeurs reçues sur le port Série
 String chaineReception=""; // déclare un objet String vide pour reception chaine
 String chaineTest=""; // déclare un objet String pour opération sur la chaine recue

int valeur=0; // variable utile
long param=0; // paramètre transmis

// --- Déclaration des objets utiles pour les fonctionnalités utilisées ---


// ////////////////////////// 2. FONCTION SETUP = Code d'initialisation //////////////////////////
// La fonction setup() est exécutée en premier et 1 seule fois, au démarrage du programme

void setup()   { // debut de la fonction setup()

// --- ici instructions à exécuter 1 seule fois au démarrage du programme ---

// ------- Initialisation fonctionnalités utilisées -------  

Serial.begin(115200); // initialise connexion série matérielle à 115200 bauds
// IMPORTANT : régler le terminal côté PC avec la même valeur de transmission


// ------- Broches en sorties numériques -------  
 pinMode (sensMoteur1,OUTPUT); // Broche sensMoteur1 configurée en sortie
 pinMode (vitesseMoteur1,OUTPUT); // Broche vitesseMoteur1 configurée en sortie
 pinMode (vitesseMoteur2,OUTPUT); // Broche vitesseMoteur2 configurée en sortie
 pinMode (sensMoteur2,OUTPUT); // Broche sensMoteur2 configurée en sortie

// ------- Broches en entrées numériques -------  

// ------- Activation si besoin du rappel au + (pullup) des broches en entrées numériques -------  

// ------- Initialisation des variables utilisées -------  

// ------- Codes d'initialisation utile -------  


} // fin de la fonction setup()
// ********************************************************************************

////////////////////////////////// 3. FONCTION LOOP = Boucle sans fin = coeur du programme //////////////////
// la fonction loop() s'exécute sans fin en boucle aussi longtemps que l'Arduino est sous tension

void loop(){ // debut de la fonction loop()

//--- fichiers sons espeaker disponibles :
// test_des_moteurs.wav
// stop_moteur.wav
// moteur_gauche_en_marche_avant.wav
// moteur_droit_en_marche_avant.wav
// moteur_gauche_en_marche_arriere.wav
// moteur_droit_en_marche_arriere.wav
// je_tourne_a_droite.wav
// je_recule.wav
// j_avance.wav

// --- ici instructions à exécuter par le programme principal ---

//---- code type réception chaine sur le port série ---
while (Serial.available()>0) { // tant qu'un octet en réception
        octetReception=Serial.read(); // Lit le 1er octet reçu et le met dans la variable

        if (octetReception==10) { // si Octet reçu est le saut de ligne
                Serial.println ("Chaine recue="+chaineReception); // affiche la chaine recue

                analyseChaine(chaineReception); // appelle la fonction d'analyse de la chaine en réception

                chaineReception=""; //RAZ le String de réception
                break; // sort de la boucle while
        }
        else { // si le caractère reçu n'est pas un saut de ligne
                chaineReception=chaineReception+char(octetReception); // ajoute le caratère au String
        }

} // fin tant que  octet réception

//----- une fois que le saut de ligne est reçu, on sort du While et on se positionne ici


//chaineReception="";

//------------- fin analyse chaine ---------------



//while(1); // stop loop

} // fin de la fonction loop() - le programme recommence au début de la fonction loop sans fin
// ********************************************************************************


// ////////////////////////// FONCTIONS DE GESTION DES INTERRUPTIONS ////////////////////


// ////////////////////////// AUTRES FONCTIONS DU PROGRAMME ////////////////////

//------------- fonction d'analyse de la chaine reçue sur le port série ----

//--------------- testInstruction : test si instruction de la forme instruction(xxx) ------------

boolean testInstruction(String chaineTest) { // reçoit chaine et renvoie true si instruction valide

  long posRef=chaineTest.length();// position de référence pour analyse (xxx)

  if (chaineReception.substring(0,posRef)==chaineTest) { // si reçoit l'instruction chaineTest(000)
  // nb substring : dernier caractere exclu

    Serial.print("Arduino va executer : ");

    Serial.print(chaineTest); // affiche

    param=stringToLong(chaineReception.substring(posRef,posRef+3)); // extraction valeur 3 chiffres à partir caractères
    Serial.print(param); // affiche

    if (chaineReception.substring(posRef+3,posRef+4)==")") { // si fermeture parenthèse = instruction valide

      Serial.println(")"); // affiche
      Serial.println("Instruction valide !"); // affiche
      return(true); // renvoie true si instruction valide

    } // fin si fermeture parenthèse

    else {

      Serial.println("Instruction invalide !"); // affiche
      return(false); // renvoie false si instruction invalide

    } // fin else

  } // fin si reçoit l'instruction chaineTest(000)

} // fin fonction testInstruction  

//------------------- fin test instruction ------------

//------------ analyseChaine ---------------
void analyseChaine(String chaineRecue) { // fonction d'analyse de la chaine recue

  // ---- analyse de la chaine recue sur le port Série ----
  chaineReception=chaineReception.trim(); // enlève les espaces

  //xxxxxxxxxxxxxxxxxxx instructions sans paramètres xxxxxxxxxxxx
  if (chaineReception=="arret()") { // si instruction reçue
    arret(); // exécute instruction si valide
    joueSon("r2d2_1.mp3",true); // joue son et attend fin son
    parleSon("Arret des moteurs", true); //synthèse vocale de la chaine et attend fin son
  }

  //xxxxxxxxxxxxxxxxxxxx instructions avec paramètres xxxxxxxxxxxxxxx

  //-------------- test instruction enAvant -----------
  if (testInstruction("enAvant(")==true) { // si instruction reçue valide
    joueSon("r2d2_3.mp3",true); // joue son et attend fin son
    parleSon("J'avance - vitesse à "+ String(int(100*param/255))+" pour cent", true); //synthèse vocale de la chaine et attend fin son
    enAvant(param); // exécute instruction
  } // fin test enAvant(xxx)

  //-------------- test instruction enArriere -----------
  if (testInstruction("enArriere(")==true) { // si instruction reçue valide
    joueSon("r2d2_3.mp3",true); // joue son et attend fin son
    parleSon("Je recule - vitesse à "+String(int(100*param/255))+" pour cent", true); //synthèse vocale de la chaine et attend fin son
    enArriere(param); // exécute instruction
  } // fin test enArriere(xxx)

  //-------------- test instruction tourne Droite -----------
  if (testInstruction("tourneDroite(")==true) { // si instruction reçue valide
    joueSon("r2d2_4.mp3",true); // joue son et attend fin son
    parleSon("Je tourne à droite - vitesse à "+String(int(100*param/255))+" pour cent", true); //synthèse vocale de la chaine et attend fin son
    tourneDroite(param); // exécute instruction
  } // fin test tourneDroite(xxx)

  //-------------- test instruction tourne Gauche -----------
  if (testInstruction("tourneGauche(")==true) { // si instruction reçue valide
    joueSon("r2d2_4.mp3",true); // joue son et attend fin son
    parleSon("Je tourne à gauche - vitesse à "+String(int(100*param/255))+" pour cent", true); //synthèse vocale de la chaine et attend fin son
    tourneGauche(param); // exécute instruction
  } // fin test tourneDroite(xxx)

} // ---------------- fin fonction analyse chaine ----------------------

// ---------- fonction de conversion d'un String numérique en long

long stringToLong(String chaineLong) { // fonction conversion valeur numérique String en int

    long nombreLong=0; // variable locale
    int valeurInt=0; // variable locale

    for (int i=0; i<chaineLong.length(); i++) { // défile caractères de la chaine numérique

      valeurInt=chaineLong.charAt(i); // extrait le caractère ASCII à la position voulue - index 0 est le 1er caractère
      valeurInt=valeurInt-48; // obtient la valeur décimale à partir de la valeur ASCII  

     if (valeurInt>=0 && valeurInt<=9) { // si caractère est entre 0 et 9
       nombreLong=(nombreLong*10)+valeurInt;
     } // fin si caractère est entre 0 et 9


    } // fin for défile caractères

 return (nombreLong); // renvoie valeur numérique

} // ---------- fin stringToLong ------------


//------------ fonction déclenche lecture fichier coté PC --------
void joueSon(String fichierSon, boolean retour) { // fonction joue son à partir nom fichier - si retour=true, attend caractère H fin son

  Serial.println(fichierSon);  //----- Message série pour message sonore dans Processing

  if (retour==true) { // si doit attendre fin son
    while (Serial.available()==0); // attend arrivée d'une réponse
    while(Serial.read()!='H'); // attend un H renvoyé par Processing à la fin son
  } // fin if retour==true

} // ---------------- fin joueSon --------------

//------------- fonction parleSon() pour synthèse vocale -------
void parleSon(String texte, boolean retour) { // envoie chaine pour synthese vocale sur le port Série - si retour=true, attend caractère H fin son

  String envoi="espeak="+texte+"="; // chaine comprise entre 2 =
  Serial.println(envoi);


  if (retour==true) { // si doit attendre fin son
    while (Serial.available()==0); // attend arrivée d'une réponse
    while(Serial.read()!='H'); // attend un H renvoyé par Processing à la fin son
  } // fin if retour==true

} // fin parle son


//------------- fonctions gestion moteurs robot ---------------

//--- fonction controle moteur Droit
void moteurDroit(int sens, int vitesse) { // sens = 0 en arriere, sens = 1 en avant,

  analogWrite(vitesseMoteurDroit,vitesse); // génère une impulsion PWM sur la broche de vitesse du moteur
  digitalWrite(sensMoteurDroit,sens); // Marche arriere

}

//--- fonction controle moteur Gauche
void moteurGauche(int sens, int vitesse) { // sens = 0 en arriere, sens = 1 en avant,

  analogWrite(vitesseMoteurGauche,vitesse); // génère une impulsion PWM sur la broche de vitesse du moteur
  digitalWrite(sensMoteurGauche,sens); // Marche arriere

}

//--- fonction stop = arret complet
void arret() {

  analogWrite(vitesseMoteurGauche,STOP); // génère une impulsion PWM sur la broche de vitesse du moteur
  analogWrite(vitesseMoteurDroit,STOP); // génère une impulsion PWM sur la broche de vitesse du moteur

}

//---- fonction tourne à Droite
void tourneDroite (int vitesse) {

  moteurGauche(AVANT, vitesse);
  moteurDroit(ARRIERE, vitesse);

}

//---- fonction tourne à Gauche
void tourneGauche (int vitesse) {

  moteurGauche(ARRIERE, vitesse);
  moteurDroit(AVANT, vitesse);

}

//---- fonction en arriere
void enArriere (int vitesse) {

  moteurGauche(ARRIERE, vitesse);
  moteurDroit(ARRIERE, vitesse);

}

//---- fonction en avant
void enAvant (int vitesse) {

  moteurGauche(AVANT, vitesse);
  moteurDroit(AVANT, vitesse);

}

//---- vitesse
void vitesse (int vitesse) { // modifie la vitesse sans modifier le sens

   analogWrite(vitesseMoteurGauche,vitesse); // génère une impulsion PWM sur la broche de vitesse du moteur
   analogWrite(vitesseMoteurDroit,vitesse); // génère une impulsion PWM sur la broche de vitesse du moteur
}
// ////////////////////////// Fin du programme ////////////////////
 

9.  Programme Processing côté PC

9.1  Explication

  • Sur un système Gnu/Linux tel qu'Ubuntu, on dispose d'un lecteur de fichiers sons et vidéos multiformat très performant, mplayer. Ce programme peut être lancé en ligne de commande facilement. D'où l'idée de l'utiliser depuis Processing pour lancer la lecture d'un fichier son en ligne de commande.
  • La ligne de commande à utiliser sera de la forme : mplayer /home/hinault/Bureau/mes_sons/r2d2_2.mp3 -quiet Ici le paramètre -quiet a pour effet de limiter les messages renvoyés dans la console.
  • La ligne de commande pour la synthèse vocale sera de la forme : espeak -v fr -s 140 « lecture texte espeak » . Pour plus d'infos, faire man espeak dans un terminal.
  • Pour lancer une ligne de commande système depuis Processing sous Ubuntu, on utilise un tableau de String pour y mettre les éléments de la ligne de commande et on envoie le tout vers la console système via un bout de code en Java. Le pied !

9.2  Ressources utiles

9.3  Le programme

  • Mettez des fichiers sons dans le répertoire de votre choix. Indiquer dans le programme le chemin des fichiers sons et tester plusieurs sons en changeant le nom du fichier son dans le programme. Vous trouverez ici une série de sons utilisables, dont quelques bruits de r2d2 sympas...
  • Adapter la ligne de chemin du répertoire des sons à votre situation !!
  • Lancer le programme et amusez-vous bien !

// Programme processing
// généré avec le générateur de code Processing
// www.mon-club-elec.fr
// par X. HINAULT - Avril 2011 - tous droits réservés

/////////////// Description du programme ////////////
// Utilise un/des objets String (chaîne de caractère)
// Utilise le port Serie

// Utilise la librairie GUI controlP5
// Utilise un/des bouton(s) simple(s) (Button)
// Utilise un/des champ(s) texte (Textfield)
// Ajoute un bouton et un champ pour chemin fichier

// Utilise la ligne de commande programmée
// Utilise mplayer pour jouer des sons (Ubuntu)
// Utilise espeaker pour la synthèse vocale des sons (Ubuntu)


/*
Reçoit la chaine renvoyée par Arduino et l'affiche dans la console.
La chaine de texte reçue est synthétisée si le format est valide.  

Le fichier son voulu est joué en fonction de la chaine de caractères reçue
à l'aide d'une ligne de commande programmée qui lance le logiciel système Mplayer (Ubuntu)

Permet également l'envoi vers Arduino pour tests d'une chaîne saisie dans un champ texte.
*/


// XXXXXXXXXXXXXXXXXXXXXX ENTETE DECLARATIVE XXXXXXXXXXXXXXXXXXXXXX

// inclusion des librairies utilisées

import processing.serial.*; // importe la librairie série processing


import controlP5.*; // importe la librairie GUI controlP5
// cette librairie doit être présente dans le répertoire /libraries du répertoire Processing
// voir ici : http://www.sojamo.de/libraries/controlP5/

// déclaration objets

String chaineEnvoi = ""; // déclare un objet String (chaine de caractère)

String[] command ; // pour envoi ligne de commande espeak

String nomFichier=""; // variable pour nom du fichier son à jouer
String cheminFichier="/home/xavier/Bureau/mes_sons/"; // chemin complet avec / de fin
//--- chemin où se trouvent les fichiers sons - à adapter selon les cas ---


// --- port Série ---
Serial  myPort; // Création objet désignant le port série


// --- interface GUI ---
ControlP5 controlP5; // déclare un objet principal de la librairie GUI controlP5


Button envoiButton; // déclare objet Button  

Textfield chaineText; // déclare des objets Textfield

// déclaration variables globales

//------ déclaration des variables de couleur utiles ----
int jaune=color(255,255,0);
int vert=color(0,255,0);
int rouge=color(255,0,0);
int bleu=color(0,0,255);
int noir=color(0,0,0);
int blanc=color(255,255,255);
int bleuclair=color(0,255,255);
int violet=color(255,0,255);


// XXXXXXXXXXXXXXXXXXXXXX  Fonction SETUP XXXXXXXXXXXXXXXXXXXXXX

void setup(){ // fonction d'initialisation exécutée 1 fois au démarrage

        // ---- initialisation paramètres graphiques utilisés
        colorMode(RGB, 255,255,255); // fixe format couleur R G B pour fill, stroke, etc...
        fill(0,0,255); // couleur remplissage RGB
        stroke (0,0,0); // couleur pourtour RGB
        rectMode(CORNER); // origine rectangle : CORNER = coin sup gauche | CENTER : centre
        imageMode(CORNER); // origine image : CORNER = coin sup gauche | CENTER : centre
        //strokeWeight(0); // largeur pourtour
        frameRate(30);// Images par seconde

        // --- initialisation fenêtre de base ---
        size(400, 130); // ouvre une fenêtre xpixels  x ypixels
        background(0,0,0); // couleur fond fenetre

// --- initialisation des objets et fonctionnalités utilisées ---

        //------------- initialisation port série ----
        println(Serial.list()); // affiche dans la console la liste des ports séries
        // Vérifier que le numéro du port série utilisé est le meme que celui utilisé avec  Serial.list()[index]
        myPort = new Serial(this, Serial.list()[0], 115200); // Initialise une nouvelle instance du port Série
        //myPort = new Serial(this, "/dev/ttyUSB0", 115200); // Initialise une nouvelle instance du port Série
        myPort.bufferUntil('\n'); // attendre arrivée d'un saut de ligne pour générer évènement série

        //======== Initialisation Objets GUI ControlP5 =========

        controlP5 = new ControlP5(this); // initialise l'objet principal de la librairie GUI controlP5

        // typeObjet nomObjet=controlP5.addObjet(paramètres); // pour info : déclaration / initialisation possible en 1 ligne
        // Textfield field = controlP5.addTextfield("myWindowTextfield",70,130,100,20); // exemple

        //======== Initialisation Objets Button =========

        //---- le bouton envoi chaine
        envoiButton=controlP5.addButton("envoiButton",0,width-60,height-40,50,24); // initialise et ajoute un Button au ControlP5
        envoiButton.setLabelVisible(true); // affichage des labels
        envoiButton.setLabel("ENVOI"); // fixe label du bouton
        envoiButton.setColorActive(color(255,0,0)); // fixe la couleur active
        envoiButton.setColorForeground(color(0,255,255)); // fixe couleur avant

        //======== Initialisation Objets Textfield =========

        //---- champ texte saisie chaine
        chaineText=controlP5.addTextfield("cheminText",10,height-40,300,20); // initialise et ajoute un Textfield au ControlP5
        chaineText.setAutoClear(false); // autoeffacement après return
        chaineText.setValue(chaineEnvoi); // initialise Texte du champ
        chaineText.setLabelVisible(true); // affichage des labels
        chaineText.setLabel("CHEMIN"); // fixe label
        chaineText.setColorActive(color(255,0,0)); // fixe la couleur active
        chaineText.setColorForeground(color(0,255,255)); // fixe couleur avant




} // fin fonction Setup

// XXXXXXXXXXXXXXXXXXXXXX Fonction Draw XXXXXXXXXXXXXXXXXXXX

void  draw() { // fonction exécutée en boucle

// tout se passe dans SerialEvent

} // fin de la fonction draw()

// XXXXXXXXXXXXXXXXXXXXXX Autres Fonctions XXXXXXXXXXXXXXXXXXXXXX

//------------- Fonction de gestion des évènements série ----
void serialEvent (Serial myPort) { // fonction appelée lors de la survenue d'un évènement série

        // ******** Gestion de la valeur reçue sur le port série : **********

        String inString = myPort.readStringUntil('\n'); // chaine stockant la chaîne reçue sur le port Série
        // saut de ligne en marque de fin

        if (inString != null) { // si la chaine recue n'est pas vide


        print (inString); // affichage brut de la chaine recue        

        //xxxxxxxxxxxxxxxxxxxxxxxxxx Gestion du nom de fichier son xxxxxxxxxxxxxxxxxxxxxxxxxx

                //------------ analyse de la chaine reçue et sélection son --------
        //String nomFichier=""; // String pour nom fichier

        //----- tous les noms de fichiers suivants seront reconnus et lancés en lecture
        //------ les fichiers doivent dans le répertoire de la variable cheminFichier (voir début programme)

        if (match(inString,"r2d2_1.mp3")!=null) nomFichier="r2d2_1.mp3"; // test la chaine reçue et définit nom fichier son associé
        if (match(inString,"r2d2_2.mp3")!=null) nomFichier="r2d2_2.mp3"; // test la chaine reçue et définit nom fichier son associé
        if (match(inString,"r2d2_3.mp3")!=null) nomFichier="r2d2_3.mp3"; // test la chaine reçue et définit nom fichier son associé
        if (match(inString,"r2d2_4.mp3")!=null) nomFichier="r2d2_4.mp3"; // test la chaine reçue et définit nom fichier son associé
        if (match(inString,"r2d2_5.mp3")!=null) nomFichier="r2d2_5.mp3"; // test la chaine reçue et définit nom fichier son associé

                //---- jeu de sons espeaker enregistrés ---
        if (match(inString,"moteur_gauche_en_marche_arriere.wav")!=null) nomFichier="moteur_gauche_en_marche_arriere.wav"; // test la chaine reçue et définit nom fichier son associé
        if (match(inString,"test_des_moteurs.wav")!=null) nomFichier="test_des_moteurs.wav"; // test la chaine reçue et définit nom fichier son associé
        if (match(inString,"stop_moteur.wav")!=null) nomFichier="stop_moteur.wav"; // test la chaine reçue et définit nom fichier son associé
        if (match(inString,"moteur_gauche_en_marche_avant.wav")!=null) nomFichier="moteur_gauche_en_marche_avant.wav"; // test la chaine reçue et définit nom fichier son associé
        if (match(inString,"moteur_droit_en_marche_avant.wav")!=null) nomFichier="moteur_droit_en_marche_avant.wav"; // test la chaine reçue et définit nom fichier son associé
        if (match(inString,"moteur_droit_en_marche_arriere.wav")!=null) nomFichier="moteur_droit_en_marche_arriere.wav"; // test la chaine reçue et définit nom fichier son associé
        if (match(inString,"je_tourne_a_droite.wav")!=null) nomFichier="je_tourne_a_droite.wav"; // test la chaine reçue et définit nom fichier son associé
        if (match(inString,"je_tourne_a_gauche.wav")!=null) nomFichier="je_tourne_a_gauche.wav"; // test la chaine reçue et définit nom fichier son associé
        if (match(inString,"je_recule.wav")!=null) nomFichier="je_recule.wav"; // test la chaine reçue et définit nom fichier son associé
        if (match(inString,"j_avance.wav")!=null) nomFichier="j_avance.wav"; // test la chaine reçue et définit nom fichier son associé


         if (nomFichier!="") { // si une chaine valide a été reçue

            joueSonMplayer(cheminFichier, nomFichier); // appelle la fonction lecture son avec mplayer - sous Ubuntu

           //--- signale à Arduino fin son
           myPort.write('H'); // envoie le caractère H sur le port Série pour signaler fin son
           nomFichier=""; // RAZ nom fichier

         } // fin si chaine valide pour lecture fichier son


          //xxxxxxxxxxxxxxxxxxxxxxxx Gestion chaine texte pour espeak xxxxxxxxxxxxxxxx

          if (match(inString,"espeak=")!=null) { // si chaine contenant espeak= reçue

            println("Chaine espeak valide reçue ! "); // debug

            String[] chaines = split(inString, '='); // sépare chaine par le signe =

            println (chaines[0]); // chaine espeak
            println (chaines[1]); // chaine à parler

            if (chaines[1]!="") { // si une chaine valide a été reçue

              direTexte (chaines[1]); // espeak la chaine extraite

             //--- signale à Arduino fin son
             myPort.write('H'); // envoie le caractère sur le port Série

            } // fin si list[1] pas vide

          } // fin si chaine espeak

        } // fin condition chaine recue pas vide


} // fin de la fonction de gestion des évènements Série



// Gestion des évènements des objets GUI controlP5 ----

//------ fonction gestion globale des évènements GUI controlP5
public void controlEvent(ControlEvent theEvent) {
        //println(theEvent.controller().name());// affiche le nom de l'évènement
}

        //---- evenement bouton envoi chaine

void envoiButton(int theValue) { // fonction évènement Button de meme nom - reçoit la valeur

        println("Evènement envoiButton");

        myPort.write(chaineText.getText()+"\n"); // envoie la chaine suivi saut ligne sur le port Série
        print("Envoi de la chaine :");
        print(chaineText.getText()+"\n");
        chaineText.setValue(""); // vide le champ texte


} // fin evènement bouton envoi

// ------ gestion évènement Textfield ------

        //---- evenement champ texte chemin fichier

public void chaineText(String theText) { // fonction évènement Textfield de meme nom - déclenché par return - reçoit la chaine

        //println("Evènement CheminText avec valeur = "+theText);

        chaineEnvoi=theText; // mémorise le contenu du champ

        //println("Le chemin est :"+chaineEnvoi);

} // fin evènement champ texte chemin fichier


//--------------------- fonction lecture son avec Mplayer ---------------
void joueSonMplayer(String cheminSon, String fichierSon) {

 //------ code type pour jouer son avec mplayer par ligne commande (Ubuntu) ----

command = new String[3]; // tableau String pour la ligne de commande

// mplayer /home/hinault/Bureau/mes_sons/r2d2_2.mp3 -quiet
command[0] = "mplayer";
command[1] = cheminSon+fichierSon;
command[2]="-quiet";

//--- exécution de la ligne de commande (code Java)

try {
    Process p = exec(command); // exécute la commande

    //--- récupère la sortie de la commande dans la console de Processing
    BufferedReader in = new BufferedReader(new InputStreamReader(p.getInputStream()));
    String line = null;
    while ((line = in.readLine()) != null) {
      System.out.println(line);
    }//fin while
  } // fin try
  catch (IOException e) { // gestion exception
    e.printStackTrace();
  }  // fin catch

} //--------------------- fin joueSonMplayer


//------------- fonction d'appel à espeak par ligne de commande -----

void direTexte(String texte) {
  // le paquet espeak doit etre installé sous Ubuntu (depuis la logithèque)

command = new String[8];
// espeak -v fr -s 140 « lecture texte espeak »
// espeak -v fr -s 80 -p 30 \"moteur droit en marche avant\"
command[0] = "espeak";
command[1] = "-v";
command[2]="fr+m4";
// les voix sont dans /usr/share/espeak-data/voices/!v
// les variantes dispo sont : croak  f1  f2  f3  f4  fast  klatt  klatt2  klatt3  m1  m2  m3  m4  m5  m6  m7  whisper
// pour utiliser une variante faire :  espeak -ven+m3
command[3]="-s"; // la vitesse
command[4]="120"; // entre 30 et 200
command[5]="-p"; // la tonalité
command[6]="40"; // entre 0 et 99
command[7]="\""+texte+"\""; // le texte entre guillemets

// param bien : voix m4/vitesse 120/ tonalité =40
// param bien : voix m2 / vitesse 100 / Tonalité = 20

//--- exécution de la ligne de commande
try {
    Process p = exec(command); // exécute la commande

    //--- récupère la sortie de la commande dans la console de Processing
    BufferedReader in = new BufferedReader(new InputStreamReader(p.getInputStream()));
    String line = null;
    while ((line = in.readLine()) != null) {
      System.out.println(line);

    }

  }
  catch (IOException e) {
    e.printStackTrace();
  }  

}

/* >>>>>>>>>>>>>>>>>>>>>>>>> page man de espeak <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

10.  Pour aller plus loin...

  • On peut exécuter ce programme sur le eeePC embarqué et prendre la commande à distance depuis un PC fixe en utilisant un simple accès au bureau à distance par VNC du PC embarqué. Voir ici : Configurer un accès bureau distant entre 2 PC sous Ubuntu
  • En activant la webcam, on a également le retour vidéo du PC embarqué : sympa !