Difference between revisions of "Haptic Glove"
Jump to navigation
Jump to search
Line 20: | Line 20: | ||
* 1 [http://ardx.org/src/guide/2/ARDX-EG-SPAR-FR-WEB.pdf#page=34 Flex sensor] |
* 1 [http://ardx.org/src/guide/2/ARDX-EG-SPAR-FR-WEB.pdf#page=34 Flex sensor] |
||
* 1 [http://www.sparkfun.com/products/9267 Accelerometer ADXL335] |
* 1 [http://www.sparkfun.com/products/9267 Accelerometer ADXL335] |
||
+ | * 1 gyroscope (WiiMotion) |
||
For finger contacts |
For finger contacts |
||
* Conductive textiles |
* Conductive textiles |
Revision as of 09:04, 12 October 2011
- 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 les applications mobiles, ...
Ce projet vise à réaliser un gant à perception haptique pour des applications tactiles (écrans larges, ...)
Objectifs
Matériel
- 1 glove (cotton, leather)
- Arduino Uno or Lilypad or Arduino FIO
- 1 XBee module or Bluetooth module for wireless communication
- 5 Vibration motors
Optional
- 1 Flex sensor
- 1 Accelerometer ADXL335
- 1 gyroscope (WiiMotion)
For finger contacts
- Conductive textiles
- Conductive threads
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); } }