Haptic Glove

From air
Jump to navigation Jump to search
  • UE/Module: Projet IHM Avancé de RICM5
  • Enseignant: Didier Donsez
  • Elèves RICM5: Christophe Havard (chef de projet), Renaud Collin

Introduction

La perception haptique est désormais présente dans la plupart des téléphones portables, les manettes de jeux vidéos, les consoles de jeu portables etc. Son intérêt premier est d'augmenter les sensations de l'utilisateur en stimulant, en plus de son sens de la vue, son sens du toucher.

La plupart des appareils nomades possèdent un vibreur qui permet d'associer un stimuli visuel (action sur un objet virtuel) à un stimuli physique, en l'occurence une vibration de l'appareil. Par exemple, sur la plupart des téléphones, il est possible de faire vibrer l'appareil à chaque appui sur une lettre lors de l'écriture d'un SMS.

Mais qu'en est-il d'une grande/très grande surface tactile type "table"? Il est impossible d'y intégrer des vibreurs. Il faut donc trouver un autre moyen de faire ressentir à l'utilisateur les actions qu'il effectue sur la surface.

Ce projet vise donc à réaliser un gant qui permet d'associer à chaque action sur un objet virtuel, une vibration dans la main de l'utilisateur. LE cerveau de celui-ci fera naturellement le lien entre ce qu'il voit et ce qu'il ressent.

Objectifs

Dans le cadre des projets d'approfondissement RICM5, nous avons proposé de concevoir et fabriquer un gant équipé de vibreurs à chaque doigt. De plus, nous fournirons l'API permettant de contrôler les vibrations de chaque doigt.

Matériel

Optional

For finger contacts

Haptic Glove v0.1 Haptic Glove v0.2 Haptic Glove v0.2 Haptic Glove v0.2

Source code

Progam to drive the haptic glove

/*
 Haptic Glove
 
 Reads 15 bytes-long command (encoding the level and the duration of the 5 vibration motors connected to the Arduino' PWM pins) and vibrate during the duration the motors.
 
 Vibration Motor, sku: ROB-08449
 http://www.sparkfun.com/products/8449
 http://www.sparkfun.com/products/8468
 "With a 2-3.6V operating range, these units shake crazily at 3V"

 Septembre 18, 2011 by Didier Donsez 
 
 This example code is in the public domain.

 Input format is 5 groups of 3 hexadecimal characters
  one group per motor
  first char is the vibration level (F is Max)
  second char is the vibration level setted after the duration (0 to stop vibration)
  third char is the duration of the vibration (value is  char * 16 * COEF milliseconds)
 
 Test by sending the following inputs with the serial monitor

 F09000000000000
 000F09000000000
 000000F09000000
 000000000F09000
 000000000000F09
 F09F09F09F09F09
 F01F03F05F07F09

 F51F53F55F57F59 // continue vib after duration
 000000000000000 // stop all vibrations
 */

const int MAXVIB=180; // 180 is 3.6V if Vin is 5V (Arduino Uno)
const int COEF=10; // Coeficient for duration (Max duration is 256 * COEF milliseconds

const int NUMVIB=5; // Number of vibration motors (one per finger)

byte levelVib[NUMVIB]; // Level for vibration
byte levelEndVib[NUMVIB]; // Level for vibration after the delay
byte durationVib[NUMVIB]; // Duration for vibration
byte pinVib[NUMVIB] = {3, 5, 6, 10, 11 }; // Analog output pins that the vibration motors are attached to

const byte FLEX_SENSOR_PIN=A0; // pin number of the flex sensor

const int NUMCONTACTPOINTS=4; // number of electric contacts points (contacts are made with conductive textiles and conductive threads)
byte pinContactPoints[NUMCONTACTPOINTS] = {2, 4, 7, 8 }; // Digital input pins that the contacts are attached to (the thumb finger is on the Vin). Use pull-down.

void setup() {
  // initialize serial communications at 9600 bps:
  Serial.begin(9600); 
  
  for (int i=0; i<NUMVIB; i++) {
    pinMode(pinVib[i], OUTPUT);     
  }

  for (int i=0; i<NUMCONTACTPOINTS; i++) {
    pinMode(pinContactPoints[i], INPUT);     
  }
}

void loop() {
  
    sendInputs();
    
    // TODO eliminate LF and CR
    if (Serial.available() >=(NUMVIB*3)) {
      for (int i=0; i<NUMVIB; i++) {
        levelVib[i]=convertLevel(Serial.read());
        if(levelVib[i]>MAXVIB) {
          levelVib[i]=MAXVIB; // protect the motor
        }
        levelEndVib[i]=convertLevel(Serial.read());
        if(levelEndVib[i]>MAXVIB) {
          levelEndVib[i]=MAXVIB; // protect the motor
        }
        durationVib[i]= convertDuration(Serial.read());
        if(durationVib[i]==0) {
          durationVib[i]=0;     
        }
      }
 
      for (int j=0; j<NUMVIB; j++) {
        // calculate next duration
        byte minDuration=0xFF;
        byte cpt=0;
        for (int i=0; i<NUMVIB; i++) {
          if(durationVib[i]>0 && durationVib[i]<minDuration) {
            minDuration=durationVib[i];
            cpt++;
          }
        }
        if(cpt==0) {
          return;
        }
        
        if(j==0){      
          for (int i=0; i<NUMVIB; i++) {
            // if levelVib[i]==0, the vibration is stopped
            analogWrite(pinVib[i], levelVib[i]);
          }
        }
        
        // sendInputs();
        delay(minDuration*COEF);
        
        for (int i=0; i<NUMVIB; i++) {
          if(durationVib[i]!=0) {
            durationVib[i]-=minDuration;
          }
          if(durationVib[i]==0 && levelVib[i]>0) {
            analogWrite(pinVib[i], levelEndVib[i]);
          }
        }    
      }
    }
}

void sendInputs(){   
    // send the flex sensor value on TX
    Serial.print(map(analogRead(FLEX_SENSOR_PIN), 0, 1023, 0, 255));
    // send the contacts states flags on TX
    for (int i=0; i<NUMCONTACTPOINTS; i++) {
      if (digitalRead(pinContactPoints[i]) == HIGH) {
        Serial.print("1");
      } else {  
        Serial.print("0");        
      }
    }
}

byte parse(byte b) {
  if(b>='0' && b<='9') {
    return (b-'0');
  } else if(b>='A' && b<='F') {
    return (b-'A'+10);
  } else return 0;
}

byte convertLevel(byte b) {
  return map(parse(b), 0, 0x0F, 0, MAXVIB);
}

byte convertDuration(byte b) {
  return parse(b)<<4;
}

Program to test contacts and motors

/*
 Haptic Glove Test
 
 This program tests the finger contacts of the haptic glove. The vibration motor associated with a finger vibrates when the finger and the thumb are in contact.
 
 Vibration Motor, sku: ROB-08449
 http://www.sparkfun.com/products/8449
 http://www.sparkfun.com/products/8468
 "With a 2-3.6V operating range, these units shake crazily at 3V"

 Septembre 30, 2011 by Didier Donsez 
 
 This example code is in the public domain.

 */
const int MAXVIB=180; // 180 is 3.6V if Vin is 5V (Arduino Uno)

const int NUMCONTACTPOINTS=4; // number of electric contacts points (contacts are made with conductive textiles and conductive threads)

boolean state[NUMCONTACTPOINTS];
byte pinVib[NUMCONTACTPOINTS] = {5, 6, 10, 11 }; // Analog output pins that the vibration motors are attached to
byte pinContactPoints[NUMCONTACTPOINTS] = {2, 4, 7, 8 }; // Digital input pins that the contacts are attached to (the thumb finger is on the Vin). Use pull-down.

void setup() {
  // initialize serial communications at 9600 bps:
  // Serial.begin(9600); 
  
  for (int i=0; i<NUMCONTACTPOINTS; i++) {
    pinMode(pinVib[i], OUTPUT);     
    pinMode(pinContactPoints[i], INPUT);     
    state[i]=false;
  }
}

void loop() {
    boolean change=false;
    for (int i=0; i<NUMCONTACTPOINTS; i++) {
      if (digitalRead(pinContactPoints[i]) == HIGH) {
        if(!state[i]) {
         analogWrite(pinVib[i], MAXVIB);
         state[i]=true;
         change=true;
        }
      } else {  
        if(state[i]) {
         analogWrite(pinVib[i], MAXVIB);
         state[i]=false;
         change=true;
        }
      }
    }
    if(change) {
      delay(250);
    } else {
      delay(100);
    }
}