P42 Dispositif à retour tactile

De Wiki d'activités IMA
Révision datée du 10 janvier 2017 à 18:08 par Pfitouss (discussion | contributions) (Avancé du travail)

Contexte du sujet

L'E-vita s'inscrit dans une nouvelle démarche en faveur de l'interface homme-machine. Depuis des année la technologie exploite nos sens de différente manière, l'idée de faire répondre la machine et de se faire comprendre par l'utilisateur, est obligatoire au bon fonctionnement de programme et autre fonctions. L'ouï, la vue sont les sens les plus exploiter par la technologie depuis le commencement. Mais depuis un long moment le toucher se répand sur les différents système afin de s'approcher au plus près de l'utilisateur, l'écran tactile s'inscrit donc dans une nouvelle ère technologique, où les machines ne sont plus contrôler via des interrupteur ou bouton, mais via les différentes possibilités du toucher sur un écran. Noter cependant que si depuis très longtemps les écran nous transmettent des informations, que l'on arrive également à contrôler des système via le son (clap des mains pour éteindre la lumière), il n'existe pas de dispositif tactile qui fonctionne en duplex (Homme vers machine, machine vers homme).

C'est dans ce contexte que le bureau d'étude de l'IRCICA met au point l'E-Vita, un dispositif tactile qui non seulement permet la communication d'un homme vers la machine mais qui est également capable de faire communiquer,grâce au toucher, la machine vers l'utilisateur. Le projet E-Vita, lancé en 2003, est capable aujourd'hui, via différentes applications test, de faire ressentir à son utilisateur différentes formes d'ondes (motifs), via des céramiques piezo-electriques. La dalle se met à vibrer sous le doigt de l'utilisateur ainsi la machine communique avec son utilisateur.

Objectif du sujet

L'objectif de ce Projet de fin d'étude, et de réétudier la loi de contrôle qui permet au µC de contrôler les céramiques. Actuellement une couche hardware supérieur récupère le mouvement du doigt ainsi que sa vitesse afin de faire ressentir à l'utilisateur un motif, une vibration électronique unique, typiquement une forme d'onde. L'idée principale et de rajouter de la dynamique dans la commande des céramiques afin que les motif ne soit plus enregistrée en dur dans le micro-controleur. Une possibilité envisageable pour cette définition de motif ainsi que la transmission de l'ordre, et de passer dans le domaine fréquentielle. Je citais plus haut que le dispositif se décompose en plusieurs couches matérielles et logicielles, afin de les faire communiquer une couche transport OSC est utilisé afin de faire communiquer le micro-controller et le Banana Pi. Seulement pour des raison évidentes lorsque la plaque vibre, il n'y a que la surface de contact qui se mets réellement à osciller, on a donc ici un soucis de delai entre le moment où l'utilisateur pose son doigt, se déplace, et le suivi de par le programme des zone de vibrations. Il est envisageable si le projet se déroule bien de pouvoir réétudier la question de la programmation événementielle de la tablette tactile, afin que se temps de latence soit le plus bas possible.

Protocole de communication OSC

Afin de faire la liaison entre le Banana Pi et le micro-controlleur, la couche liaison est réalisé grâce au protocole Open Sound Control. OSC est un protocole créer afin de faciliter la transmission d'information multimédia sur un réseau. Utilisé pour la transmission de musique cela s'adapte a notre transmission de fréquence pour la vibration des céramique. Cette communication utilise les normes TCP et UDP pour la communication temps réel entre le serveur et le client.

Les paquets sont transmis avec deux informations, la première information est la taille du paquet OCS et la deuxième le paquet lui-même. La taille des paquets OCS sont toujours un multiple de 4. Cela permet un alignement des différents block transmis. Le contenus d'un paquet peut soit être un OSC Messages ou un OSC Bundle

Quand le serveur reçoit un simple OSC Message il doit s'empresser d'invoquer la méthode associé. A la différence, le OSC Bundle qui comporte lui-même une identification de temps, la méthode devra être éxécuté si le Time-Tag du bundle est égal ou déjà passé, et à l'inverse devra stocker le bundle et lancé la méthode au bon moment si le Time-Tag indique un évèvenement futur.

Cette réalisation permet un résultat temps réel sur l'application, entre le moment du contact entre le doigt et la tablette et l'action de vibration des céramiques.

Retour des valeurs d'amplitude sur la plaque piezo

Aujourd'hui le contrôle des céramique se fait grâce à des fichiers écrits en "dur" dans le programme, chacun des ses fichiers se présente sous la forme d'un tableau de 10000 valeurs d'entier. Un entier est composé de 4 octets, sachant que 4 formes d'ondes sont utilisées dans la gamme de fréquence (50, 100, 500, 1000, 5000, 10000). Cela correspond donc à 6*4*4*10000 = 960 ko de mémoire utilisé.

Une solution évidente serait de non pas récupérer la valeur dans un tableau mais bien de la calculer voir de la prédire en fonction du déplacement, de la dimension de l'écran, de la fréquence de rafraîchissement.

Signal Sinusoîdal -> sin(wt)
Signal Carré -> x(t) = 1 , 0 < t <= T et 0, T < t < 2T.
Signal dent de scie -> x(t) = t, 0 < t < 2T
Signal Dirac

Un passage dans le domaine fréquentiel permettrait de généralisé le calcul des valeurs de retour. Ainsi qu'une représentation plus formelle du problème.


Cahier des charges

Établir une représentation visuel d'un mouvement de rotation sur une application de verrrouillage/dévérouillage par code/retour tactile.


Avancé du travail

Afin d'apréhender le probleme facilement j'ai commencer par représenté un segment en direction du chiffre en cours de sélection.

Photo ligne & & 6

Ligne numero 1.png
Ligne numero 6.png


Le code correspondant est un banal switch/case inscrit dans la fonction draw() :

  fill(255, 0, 0);
   switch (currentNumber){
   case 1:
     fill(255, 0, 0);
     line(240,340,116,800-552);
     break;
     
   case 2:
     fill(255, 0, 0);
     line(240,340,239,800-676);
     break;
   case 3:
     fill(255, 0, 0);
     line(240,340,384,800-558);
     break;
     
   case 4:
     fill(255, 0, 0);
     line(240,340,381,800-372);
     break;
 
   case 5:
  fill(255, 0, 0);
     line(240,340,237,800-257);
     break;
   case 6:
   
    fill(255, 0, 0);
     line(240,340,98,800-372);
     break;
 }

Je décide donc de réaliser un cercle autour du bouton "OK" avec 4 segments permettant d'observer une rotation du cercle toujours dans la fonction draw() :

if (!creatingCode){
     translate(240, 333); // On place le référentiel au centre du bouton "OK"
    
     rotate(direction * millis() * 0.001 * TWO_PI / 1O.0);   // Créer une rotation de 360° en 10 secondes.
     noFill();
     strokeWeight(5);
     ellipseMode(CENTER);
     ellipse(0,0,145,145); 
     line(75,0,90,0);
     line(-75,0,-90,0);
     line(0,75,0,90);
     line(0,-75,0,-90);
   }

Pour l'instant la rotation se fait sans arrêt, cela ne convient qu'a moitié, mais elle permet tout de même de tourner plus vite si jamais on appuie plus d'une fois sur une des flèches jaunes.

Afin d'obtenir une solution plus adéquate divers variables globales sont utilisées :

int direction = 0;       // Sens de direction rotation 0 = fixe / +n = décalage trigo / -n = décalage anti-trigo
int nb_frame = 0;        // Enregistre le nombre de frame lorque l'on appuie sur une des flèches.
float phi = 0.;          // Sert contient le calcul de la phase pour la rotation.

La variable direction est modifié à chaque appuie sur une des deux flèches jaunes. Elle incrémente un compteur qui reset à chaque fin de rotation. La rotation est rendu possible grâce au combo pushMatrix()/popMatrix() elle me permet d'afficher 6 segments séparés d'un angle de pi/3. La variable phi correspond à la phase du premier segment, c'est cet élémént qui réalise réellement la rotation.

if (!creatingCode){
     translate(240, 333);                                               // Centrage sur "OK"
     noFill();
     strokeWeight(5);
     ellipseMode(CENTER);
     ellipse(0,0,145,145);
     if (frameCount < nb_frame +60){                                    // Calcul de la position du premier segment
        phi = direction * ((nb_frame-frameCount)/60.) * PI/3;           // Le frameRate est fixé à 60 itérations/s
     }else{
       direction =0;                                                    // Reset de la variable d'appui
     }
     //Creation des segments
     for (int i=0; i<6; i++){                                           // Cette boucle permet donc de créer les 6 segments et de donner l'impression qu'il tourne autour du cercle 
       pushMatrix();
       rotate(phi + i*PI/3);
       line(75,0,90,0);
       popMatrix();
     }
   }