====== 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]]