====== Objet interactif en Bluetooth ====== * Porteur(s) du projet : Damien MUTI DESGROUAS * Date : 13/11/2020 * Licence : libre ! * Contexte : Apprentissage ===== Présentation ===== En s'inspirant des [[wiki:tutoriels:affiche-interactive:accueil|affiches interactives]], il est possible de créer des objets interactifs capables de réagir en lançant un média (son, vidéo, animation). Cette interaction intervient par exemple lorsque la valeur renvoyée par la mesure d'un paramètre associée à un capteur est inférieure à un seuil. On choisit exemple un [[wiki:tutoriels:arduino-capteurs:arduino-capteurs#capteur_de_distance_ultrason_grove|capteur de distance à ultrason]]. Le système comporte deux cartes Arduino équipée chacune d'un [[wiki:tutoriels:arduino:module-bleutooth|module Bluetooth]] leur permettant de communiquer. ===== Carte 1 - fixée sur l'habit ===== ==== Montage ==== La carte Arduino comporte : * un capteur de [[wiki:tutoriels:arduino-capteurs:arduino-capteurs#capteur_de_distance_ultrason_grove|capteur de distance à ultrason]] et * un [[wiki:tutoriels:arduino:module-bleutooth|module Bluetooth]]. Le schéma de câblage est le suivant : {{ :wiki:tutoriels:processing:processing_10:envoie_donnees_distance_bt_bb.png?800 |}} Le code Fritzing est le suivant : {{ wiki:tutoriels:processing:processing_10:envoie_donnees_distance_bt.fzz.zip |}} ==== Programme Arduino ==== Le programme consiste à : * Mesurer la distance via un capteur ultrason (Grove Ultrasonic Ranger) * Envoyer les données mesurées sur le port Bluetooth via le module HC-06 Le code Arduino est le suivant : {{ :wiki:tutoriels:processing:processing_10:envoie_donnees_via_bt_arduino_carte1.zip |}} /* Mesurer la distance via un capteur ultrason (Grove Ultrasonic Ranger) * Envoyer les données mesurées sur le port Bluetooth via le module HC-06 */ // module Bluetooth HC06 #include SoftwareSerial hc06(2, 3); // Capteur de distance ultrason Grove Ultrasonic Ranger #include "Ultrasonic.h" Ultrasonic ultrasonic(7); // le module Grove est branché sur le slot D7 // données lue sur le capteur de distance long distance=0; // Gestion de la led byte led = 13; int Tblink = 100; float isBlink = false; // drapeau pour lancer le clignotement... ou non void setup() { // pin 13 OUTPUT pinMode(led, OUTPUT); //Initialiser le Serial Monitor Serial.begin(9600); //Initialiser le Bluetooth Serial Port hc06.begin(9600); } void loop() { // Lecture de la valeur du capteur distance = ultrasonic.MeasureInCentimeters(); //Write sensor data to HC06 hc06.println(distance); // patienter xx ms entre deux mesures et envoies delay(250); } void clignoterLed(int led, int Ta, int Te) { // led : patte connécéet à la led, Ta: temps d'allumage, Te: temps led éteinte digitalWrite(led, HIGH); delay(Ta); digitalWrite(led, LOW); delay(Te); } ===== Carte 2 - connectée au PC ===== Lorsque le PC utilisé ne comporte pas de module Bluetooth intégré, il suffit d'utiliser une deuxième carte Arduino comportant un module Bluetooth. ==== Montage ==== La carte Arduino comporte uniquement : * un [[wiki:tutoriels:arduino:module-bleutooth|module Bluetooth]]. Le schéma de câblage est le suivant : {{ :wiki:tutoriels:processing:processing_10:reception_donneesbt_et_envoie_vers_processing_bb.png?400 |}} Le code Fritzing est le suivant : {{ :wiki:tutoriels:processing:processing_10:reception_donneesbt_et_envoie_vers_processing.fzz.zip |}} ==== Programme Arduino ==== Le programme Arduino permettant la réception des données envoyées par la Carte 2 est le suivant : {{ :wiki:tutoriels:processing:processing_10:reception_donnees_capteur_hc06_1.zip |}} /* Réception par Processing des données issues du port Bluetooth - Module HC06 via le port série de la 2ième carte Arduino Envoie des données reçues via le port série vers le programme Processing*/ #include SoftwareSerial hc06(2, 3); // réception des données envoyées sur le port bluetooth String cmd = ""; int distance = 0; // Gestion de la led byte led = 13; int Tblink = 20; // période de clignotement float isBlink = false; // drapeau pour lancer le clignotement... ou non void setup() { // pin 13 OUTPUT pinMode(led, OUTPUT); //Initialiser le Serial Monitor Serial.begin(9600); //Initialiser le Bluetooth Serial Port hc06.begin(9600); } void loop() { //Lecture des données depuis le module HC06 while (hc06.available() > 0) { cmd += (char)hc06.read(); } //Select function with cmd if (cmd != "") { // convertir la comande en un entier distance = cmd.toInt(); // conversion de la chaine de caractère en un entier : distance mesurée cmd = ""; //reset cmd } // envoie des données sur le port Série -> Processing Serial.println(distance); clignoterLed(led, Tblink, Tblink); // allumer la led à chaque envoie de donnée // patienter x ms delay(100); } void clignoterLed(int led, int Ta, int Te) { // led : patte connécéet à la led, Ta: temps d'allumage, Te: temps led éteinte digitalWrite(led, HIGH); delay(Ta); digitalWrite(led, LOW); delay(Te); } ==== Connexion des deux cartes en Bluetooth ==== Voir tutoriel suivant : * [[http://www.martyncurrey.com/connecting-2-arduinos-by-bluetooth-using-a-hc-05-and-a-hc-06-pair-bind-and-link/|Connecting 2 Arduinos by Bluetooth using a HC-05 and a HC-06: Pair, Bind, and Link - Martin Curey]] ==== Programme Processing ==== Le programme Processing permettant la réception et le traitement des données envoyées par la Carte 2 est le suivant : {{ :wiki:tutoriels:processing:processing_10:objet_interactif_processing.zip |}} /** Objet interactif - On reçoit une donnée du port série, on teste la valeur de cette donnée, cela lance une image, une vidéo, une animation, un son, etc... */ /// librairies import processing.sound.*; import processing.video.*; import processing.serial.*; // variables globales PImage im; // une image SoundFile son; // un son - un seul lecteur CD audio Movie vid; // une vidéo - un seul lecteur DVD vidéo // bouton image active ? // est-ce que l'image est active ? Si oui, on affiche l'image boolean animation_active = false; // true ou false (2 valleurs possibles) => 1 bit (0 ou 1) // bouton son actif ? boolean son_actif = false; float tempsDebutSon = 0; // temps du début de la musique a été joué // bouton video active ? boolean video_active = false; /// dialogue avec la carte Arduino Serial myPort; // Create object from Serial class String inBuffer; // Data received from the serial port int donneePortSerie; // entier converti de la chaine de caractère reçue sur le port série // seuil de détection float seuil = 25; // distance de seuil = 25cm void setup() { // initialisation des paramètres d'affichage & chargement des sons, vidéos, etc. size(500, 500); noStroke(); background(0); // initialisation des variables globales im = loadImage("images/chien.jpg"); // chargement du son son = new SoundFile(this, "sons/beat.aiff"); //println(son.duration()); // chargement de la video vid = new Movie(this, "videos/affiche.mp4"); /// Port série // Print a list of the serial ports, for debugging purposes: printArray(Serial.list()); String portName = Serial.list()[0]; myPort = new Serial(this, portName, 9600); } void draw() { // lecture des données sur le port série : lectureDonneePortSerie(); // test des données lues sur le port série et choix de l'interactivité (vidéo, son, animation) // choisir le média à lancer : // son //gestionSon("sons/beat.aiff"); // video gestionVideo("videos/ArmstrongAlunissage.mp4"); // "videos/affiche.mp4" // animation gestionAnimation(); // affichage de la vidéo //////////////////////////////////////// if (video_active) { image(vid, 0, 0, width, height); } else { background(0); // fond noir } // affichage de l'animation////////////////////////////////////// if (animation_active) { lancerAnimation(); } } ////////////////////////////////////// Méthodes /////////////////////////////// void movieEvent(Movie movie) { //// gestion de la vidéo vid.read(); } //////////////////////////////////////////////// Son /////////////////////////////////////////////////// void gestionSon(String nomDuSon) { if (donneePortSerie < seuil && donneePortSerie>0 && !son.isPlaying()) { // son // jouer le son SSI la distance est inférieur à un seuil, strictement supérieure à 0 et si le son ne joue pas déjà //affichage de la distance lue println("Distance = "+donneePortSerie+" cm"); // lancement du son lancerSon(nomDuSon); } else if (donneePortSerie > seuil && son.isPlaying()) { //si la distance est supérieure au seuil ET que le son joue : arrêter le son son.stop(); } } void lancerSon(String nomDuSon) { if (!son.isPlaying()) { // le son ne joue pas // chargement du son 1 son = new SoundFile(this, nomDuSon); // jouer le son 1 son.loop(); } } //////////////////////////////////////////////// Video /////////////////////////////////////////////////// void gestionVideo(String nomVideo) { if (donneePortSerie < seuil && donneePortSerie>0 && !video_active) { // video // jouer le son SSI la distance est inférieur à un seuil, strictement supérieure à 0 et si la vidéo ne joue pas déjà //affichage de la distance lue println("Distance = "+donneePortSerie+" cm"); // lancement du son lancerVideo(nomVideo); } else if (donneePortSerie > seuil && video_active) { //si la distance est supérieure au seuil ET que la video joue : arrêter la video vid.stop(); clear(); video_active = false; } } void lancerVideo(String nomVideo) { if (video_active == false) { // la vidéo 1 ne tourne pas // chargement de la video 1 vid = new Movie(this, nomVideo ); vid.loop(); video_active = true; } } //////////////////////////////////////////////// animation /////////////////////////////////////////////////// void gestionAnimation() { if (donneePortSerie > 100) { // on appuie sur la touche "espace" => lancer l'animation "image" animation_active = true; } else { animation_active = false; } } void lancerAnimation() { float x = 30 + random(-20, 20); // random sur la position float y = 30 + random(-20, 20); image(im, x, y, 200, 200); } void lectureDonneePortSerie() { //String inBuffer=""; // lecture des données sur le port série if ( myPort.available() > 0) { // si une donnée est disponible sur le port série inBuffer = myPort.readString(); // lire la donnée et la stoquer dans inBuffer (chaine de caractères - String) } //conversion des données String -> int if (inBuffer != null) { // si la chaine de caractère n'est pas nulle //println("inBuffer="+inBuffer +"(String)"); //afficher la chaine de caractère inBuffer donneePortSerie=int(inBuffer); // convertir la chaine de caractère en un entier // affichage de la distance en cm println("Distance = "+donneePortSerie+" cm"); // afficher l'entier correspondant } } Ce programme est identique à celui effectué pour les objets interactifs : [[wiki:tutoriels:processing:processing_9:processing_9|Objet interactif avec détection de distance grâce une carte Arduino et un capteur de distance à ultrasons]]. Dans ce dernier exemple, les capteurs sont directement branchés à la carte Arduino qui est connectée au PC, sans passer par un module Bluetooth. ===== PC comportant une connexion Bluetooth ===== ==== Processing ==== Sur un PC sur Windows 10, le système d'exploitation permet de régler le port Bluetooth comme un port série. Il faut ouvrir la fenêtre de paramétrage du Bluetooth et choisir "Paramètres avancés". Paramétrer alors le port Bluetooth d'entrée comme un port Série. Idem pour le port de sortie Bluetooth (voir figure ci-dessous) : {{ :wiki:tutoriels:processing:processing_10:bt_settings_on_w10.png?400 |}} Par la suite, Processing ne sait pas qu’il s’agit d’une communication série sur Bluetooth, série sur USB ou autre… il s’agit simplement d’une communication série sur un port COM. Il est donc possible de faire communiquer Processing (fonctionnant sur le PC) avec la Carte Arduino 1 (connectée à l'habit) en utilisant simplement la librairie Serial. Le programme est identique à celui développé précédemment : * {{ :wiki:tutoriels:processing:processing_10:objet_interactif_processing.zip |}} Quelques recherches sur le forum Processing : * [[https://discourse.processing.org/t/anyone-possible-make-project/25109/17| ]] * https://discourse.processing.org/t/communication-over-laptops-bluetooth/14056 ==== Une API JAVA pour la communication Bluetooth ==== Dans le cas où le PC utilisé comporte un module Bluetooth, il faut adapter le programme Processing précédant en faisant en sorte que les données envoyée par la Carte 1 en Bluetooth soit directement reçues par le PC. Pour cela, il faudrait utiliser une Librairie Processing permettant de contrôler le module Bluetooth du PC. Cependant au moment de l'écriture de ce tutoriel (13/11/2020) cette librairie n'existe pas. La solution est d'utiliser une [[https://fr.wikipedia.org/wiki/Interface_de_programmation|API]] JAVA (Application Programming Interface - interface de programmation applicative) dédiée à la communication Bluetooth. Il existe plusieurs API JAVA permettant la gestion de la communication Bluetooth : * [[https://www.oracle.com/technical-resources/articles/javame/bluetooth-wireless-technology-part1.html|Oracle - Bluetooth wireless technology part 1]] * [[https://www.oracle.com/technical-resources/articles/javame/bluetooth2.html|Oracle - Bluetooth wireless technology part 2]] ==== Quelques exemples ==== Voici quelques exemples de programme utilisant l'API JAVAX : * [[https://www.programcreek.com/java-api-examples/index.php?api=javax.bluetooth.LocalDevice| programcreek]] * [[http://www.bluecove.org/bluecove/apidocs/overview-summary.html|]] * [[http://www.aviyehuda.com/blog/2010/01/08/connecting-to-bluetooth-devices-with-java/|]] * [[https://www.programcreek.com/java-api-examples/?api=javax.bluetooth.LocalDevice|]] * [[https://stackoverflow.com/questions/15343369/sending-a-string-via-bluetooth-from-a-pc-as-client-to-a-mobile-as-server|]] ==== Quelques vidéos ==== * [[https://www.youtube.com/watch?v=TLXpDY1pItQ|]] * [[https://www.youtube.com/watch?v=aQcJ4uHdQEA|Bluetooth for Android and Arduino HC-05 Module, Java implementation]]