Une gestuelle pictographique

Porteur du projet : Mélanie Lacroix

Date : 13/01/2015

Contexte : MACROPROJET#2

Lien : Le geste

Le projet

slide.pdf

PRÉSENTATION

Pour mon mémoire je m'intéresse aux gestes que nous faisons tous lors de nos prises de paroles: notre communication non-verbale. Ainsi, après avoir fait le constat que ces gestes étaient que peu considérés par le public récepteur du message, j'ai voulu trouver des dispositifs permettant de mettre “en lumière” ces gestes pour que le public y soit plus vigilent, plus curieux. Ce projet a donc consisté à créer un dispositif tactile permettant de capter le geste produit par le locuteur lors de sa prise de parole pour le traduire par images à l'écran. Cela permet donc de rendre visible sur la durée ces gestes émis et par conséquence permet de les conserver pour pouvoir les reproduire, les apprendre...

ÉVOLUTION

A ce jour, les dispositifs tactiles dont je parle sont les résistances branchées sur la carte Arduino. Cela ne permet donc pas de relever les gestes inconscients exécutés lors d'un discours oral. En effet, le locuteur est plutôt un performeur ici, il a conscience qu'il exécute un geste étant donné qu'il a prit la décision de toucher la résistance. J'ai donc l'objectif d'intégrer ces résistances à un support textile (veste/tee-shirt/combinaison) qui permettrait alors de les dissimuler. Ces résistances alors non-visibles seraient donc activée par le locuteur implicitement lorsque ce dernier aurait un contacte avec son corps (recouvert du vêtement).

Exemples de touches tactiles:

ENJEUX

Créer une relation directe entre le corps et la forme

Réhabiliter la fonction du geste

Visibilité du corps acteur

Apporter une dimension sensible au monde numérique

Matériel

1 carte ARDUINO

1 breadboard

1 connecteur ARDUINO/USB

4 résistances 1M ohms

5 fils connecteurs mâle/mâle

Montage

Code Arduino

/* Code d'origine provenant de: https://skyduino.wordpress.com/2012/06/02/arduino-faire-une-touche-tactile-avec-une-simple-resistance/ */
/* REMARQUE: des résistances >1M ohms doivent être utilisées pour ce montage */
/* Seuil de détection des résistances*/
const uint16_t THRESHOLD = 42;
/*Code d'initialisation: exécuté 1 fois au lancement du programme*/
void setup()
{
/* Ouvre le port série et fixe le debit de communication avec l'ordinateur à 9600 bauds (unité de mesure des télécommunications)*/
Serial.begin(9600);
}
/* Boucle sans fin: exécutée sans fin et en boucle aussi longtemps que l'Arduino est sous tension*/
void loop()
{
/* Branchement des résistances */
/* X = chiffre du plus petit port-entrée où est branchée la 1ere résistance => ici entrée n°2*/
/* Y = chiffre du plus grand port-entrée où est branchée notre dernière résistance + 1 => ici entrée n°5 + 1 = 6 */
const int X = 2;
const int Y = 6;
for (uint8_t i = X; i < Y; ++i){ /* Boucle pour vérifier l'état de chaque résistance */
// uint_8 = entier naturel (0, 1, 2, 3, ...) codé sur 8bits, donc de 0 à 255
/* Test si la "touche", la résistance, a été touchée ou non */
char sensor;
if (touch_measure(i) > THRESHOLD)
sensor = i + 'A' - X; /* Si la résistance est touchée, sensor vaut 'A' / 'B' / ... suivant si c'est la première / deuxième / ... résistance */
// X est la variable définie juste au dessus, X=2, la valeur du premier port
else
sensor = i + 'a' - X; /* Si la résistance n'est pas touchée, c'est une lettre minuscule */
/* Envoie par le port série l'état de la résistance. Une lettre majuscule veut dire touchée, minuscule non touchée. */
Serial.write(sensor);
}
/* Délai no-flood */
delay(250);
}
uint8_t touch_measure(uint8_t measurePin){
/* Registre bas-niveau, DDR = port de configuration, PORT = port de sortie, PIN = port d'entrée */
uint8_t xport = digitalPinToPort(measurePin);
volatile uint8_t *ddr = portModeRegister(xport);
volatile uint8_t *port = portOutputRegister(xport);
volatile uint8_t *pin = portInputRegister(xport);
/* Résultat de la mesure, Bitmask de la broche à mesurer */
uint8_t cycles, bitmask = digitalPinToBitMask(measurePin);
/* Décharge la capacité en contact avec la broche */
*port &= ~(bitmask); // Place la broche à LOW
*ddr |= bitmask; // Place la broche en sortie
delayMicroseconds(1000); // Attendre pour être sur que la capacité est déchargée
/* Place la broche en entrée, sans résistance de pull-up ! */
/* (La résistance de >1M ohms externe servira de résistance de pull-up) */
*ddr &= ~(bitmask);
/* Mesure le nombre de cycles CPU requis avant que la broche ne commute */
for(cycles = 0; cycles < 256; ++cycles){
if (*pin & bitmask) break; // Si la broche a commuté on quitte la boucle
}
/* Re-décharge la capacité en contact avec la broche
* afin d'éviter tout parasitages d'une autre mesure sur une autre broche.
* Dans le cas contraire il serait impossible de manipuler plus d'une touche "tactile" */
*port &= ~(bitmask);
*ddr |= bitmask;
/* Retourne le résultat */
return cycles;
/* Documentation sur qu'est ce qu'une "broche" (citée au-dessus) : http://www.mon-club-elec.fr/pmwiki_reference_arduino/pmwiki.php?n=Main.ApprendreBrochesEntreeSortie */
}

Code Processing

// Pour la communication Série avec la carte Arduino
import processing.serial.*;
Serial myPort;
// Les formes
int nbFormes; // Variable suivant le nombre de formes à afficher
boolean[] afficher; // Tableau vrai ou faux
float[] rotation; // Tableau retenant la rotation déjà appliquée à chaque forme
PVector[] deplacement; // Variable retenant qu'on a touché ou non la résistance
void setup() { // L'ensemble des paramètres qui suivent sont appelés durant toute l'éxécution du programme
// Initialisation de la fenêtre
size(1300, 700); // Taille de la fenêtre
background(255); // Couleur de l'arrière-plan
rectMode(CENTER); // Change la manière dont sont interprétés les paramètres de la fonctino rect()
//à voir -> https://www.processing.org/reference/rectMode_.html
// Initialisation des formes, elles apparaissent lorsqu'on touche la résistance
nbFormes = 4; // Nombre de formes suivant le nombre de résistances à toucher
afficher = new boolean[nbFormes];
afficher[0] = false;
afficher[1] = false;
afficher[2] = false;
afficher[3] = false;
//afficher[*] = true ou false // Code à rentrer pour chaque nouvelle résistance
// true : la forme s'affiche dès l'ouverture du programme
// false : la forme s'affiche que lorsque la résistance est touchée
// Initialise les deplacements des formes
rotation = new float[nbFormes];
for (int i = 0; i < nbFormes; i++)
rotation[i] = 0;
deplacement = new PVector[nbFormes];
deplacement[0] = new PVector(0, 0); // (x, x) = décallage par rapport au centre de la fenêtre
deplacement[1] = new PVector(200, 20);
deplacement[2] = new PVector(300, 600);
deplacement[3] = new PVector(-5, -8);
// Liste les ports séries puis écoute le port COMX
println(Serial.list());
String portName = Serial.list()[0]; // 0 ou 1, suivant l'ordinateur
myPort = new Serial(this, portName, 9600);
}
float angle = 0;
void draw() { // Le contenu de cette fonction est appelé en boucle.
// Communication avec l'Arduino
serialEvent(myPort);
// Dessin des formes
// Forme 1
if (afficher[0]) { // Si la résistance n°O est touchée alors la forme qui suit est affichée
translate(width/2, height/2); // Position de la forme dans la fenêtre
rotate(rotation[0]); // Met la forme à sa rotation acquise jusque là
fill(255); // Couleur
stroke(47, 21, 245); // Contour
rect(deplacement[0].x, deplacement[0].y, 20, 20); // Dessin de la forme, et position
rotate(-rotation[0]); // Annule la rotation pour ne pas changer la forme suivante
rotation[0] += radians(10); // Augmente la rotation de la forme
deplacement[0].add(new PVector(0.2, 0.1)); // Augmente le déplacement
}
// Forme 2
if (afficher[1]) { // Si la résistance n°1 est touchée alors la forme qui suit est affichée
translate(width/2, height/2); // Position de la forme dans la fenêtre
rotate(rotation[1]); // Met la forme à sa rotation acquise jusque là
fill(200, 5, 100); // Couleur
stroke(200, 5, 100); // Contour
ellipse(deplacement[1].x, deplacement[1].y, 4, 8); // Dessin de la forme, et position
rotate(-rotation[1]); // Annule la rotation pour ne pas changer la forme suivante
rotation[1] += radians(20); // Augmente la rotation de la forme // Augmente le nombre de forme à la rotation
deplacement[1].add(new PVector(0.5, 0.1)); // Augmente le déplacement
}
// Forme 3
if (afficher[2]) { // Si la résistance n°2 est touchée alors la forme qui suit est affichée
translate(width/3, height/5); // Position de la forme dans la fenêtre
rotate(rotation[2]); // Met la forme à sa rotation acquise jusque là
fill(90, 105, 30); // Couleur
stroke(90, 105, 30); // Contour
rect(deplacement[2].x, deplacement[1].y, 10, 16); // Dessin de la forme, et position
rotate(-rotation[2]); // Annule la rotation pour ne pas changer la forme suivante
rotation[2] += radians(5); // Augmente la rotation de la forme
deplacement[2].add(new PVector(0.3, 0.2)); // Augmente le déplacement
}
// Forme 4
if (afficher[3]) { // // Si la résistance n°3 est touchée alors la forme qui suit est affichée
translate(width/4, height/2); // Position de la forme dans la fenêtre
rotate(rotation[3]); // Met la forme à sa rotation acquise jusque là
fill(255); // Couleur
stroke(254, 203, 0); // Contour
ellipse(deplacement[3].x, deplacement[1].y, 100, 30); // Dessin de la forme, et position
rotate(-rotation[3]); // Annule la rotation pour ne pas changer la forme suivante
rotation[3] += radians(5); // Augmente la rotation de la forme
deplacement[3].add(new PVector(0.2, 0.4)); // Augmente le déplacement
}
// Si on appuie sur Suppr ou sur la barre d'espace, on efface le dessin
if (keyPressed) {
if (key == DELETE || key == BACKSPACE) {
// L'arrière-plan du programme redevient blanc
background(255);
}
}
// Pour enregistrer l'image faite: clic droit souris
if (mouseButton == RIGHT) {
// Sauvegarde en mettant la date et l'heure dans le nom pour ne pas effacer les images précédentes
// Ajouter un compteur au nom de l'image ne permettrait pas de conserver toutes les images produites: les images crées lors d'un lancement antèrieur du programme seraient remplacées
//par les nouvelles créées lors d'un nouveau lancement de programme.
save("gestes-"+year()+month()+day()+"-"+hour()+minute()+second()+".png");
// Affiche dans la barre de commentaire "sauvegarde de l'image", permet donc de savoir quand notre image est sauvegardée
println("sauvegarde de l'image");
}
}
void serialEvent(Serial myPort) { // Communication avec la carte Arduino
while (myPort.available() > 0) { // Exécute le code de la boucle tant qu'il y a des données reçues non traitées
int inByte = myPort.read(); // Récupère le prochain octet de donnée provenant du port série
// Si on touche la résistance > Lettres majuscules -> activation
if (inByte >= 'A' && inByte < 'A' + nbFormes) {
// Change l'état de la forme
afficher[inByte - 'A'] = true;
}
// Si on ne touche pas la résistance > Lettres minuscules -> désactivation
else if (inByte >= 'a' && inByte < 'a' + nbFormes) {
// Change l'état de la forme
afficher[inByte - 'a'] = false;
}
}
}

Vidéo

Résultats

Remarques

Espace d'échange concernant ce sujet. Cliquez sur modifier et commentez! (ACC) bonjour, je ne saisis pas bien le choix sonore pour cette vidéo... pourquoi ne pas préférer justement des expressions orales (intonations, onomatopées, etc.)