Projets:Hackberry Fabrikarium Inde

De wikilab

Description du projet

Ce projet a été réalisé à Bombay dans le cadre du Fabrikarium.

La documentation a été réalisé en anglais sur le site Hackaday Le projet Hackberry Feedback a été développé pour que les personnes amputées et utilisatrices de la main Hackberry puissent avoir un feedback lorsqu'elles saisissent un objet. Le retour pourrait se traduire par une sensation de température et/ou de force.

Ce projet comprend la fixation de deux types de capteurs, détectant température et force, sur la main imprimée Hackberry 3D. Il y aura deux résistances de détection de force, une sur le pouce et l'autre sur la paume et la résistance sensible à la température sera quant à elle fixée sur la paume. Ces capteurs permettront à une personne amputée de ressentir la température et la force lors de la saisie d'un objet. La fixation de ces capteurs se présente comme une amélioration de la main imprimée Hackberry 3D.

Le diagramme schématique suivant résume le projet Hackberry Feedback System.


Schéma Hackberry Feedback.jpg

Equipe

  • Hinal Shah
  • Sourabh ZunkeSourabh Zunke
  • Jean Noel Lefèvre
  • ashish kumarpardeshi
  • Bodo Hoenen
  • Delphine Bézier
  • Akshit GandhiAkshit Gandhi
  • Sahal Hashim
  • Sanskruta Dhotre
  • Farhan KhanFarhan Khan
  • Nicolas Huchet

Matériel nécessaire

  • Arduino Uno
  • Capteur de température
  • Bouton tactile capacitif
  • WS2813 LedStrip - 144 Leds / mètres (20 leds)
  • Résistances 10K ohm
  • Résistances de détection de force
  • Servomoteur
  • Interrupteurs

Outils nécessaires

Main Hackberry

La fabrication de la main Hackberry imprimée en 3D implique l'assemblage de diverses pièces imprimées en 3D. Ci-joint le lien qui fournit toutes les informations concernant la fixation des différentes parties:

https://myhumankit.org/en/tutoriels/myoelectric-exiii-hand/

Système de rétroaction FSR

Les FSR, c'est-à-dire les résistances de détection de force, sont des capteurs qui permettent de détecter la pression physique, la compression et le poids. Le FSR est composé de 2 couches séparées par une entretoise. Plus on appuie sur, plus ces points d'élément actif touchent le semi-conducteur qui fait descendre la résistance. Les FSR sont fondamentalement une résistance qui change sa valeur résistive (en ohms Ω) en fonction de la pression exercée.

Le FSR a été tirée de 5V et abaissée par une résistance de 10K (un simple diviseur de tension) de manière à ce que nous obtenions en sortie une résistance correspondante à la pression appliquée.

  • Reportez-vous au schéma ci-dessous pour faire le système de rétroaction FSR
  • Connectez un FSR à la broche analogique A5 pour lire la force du pouce
  • Connectez un FSR à la broche analogique A4 pour lire la force de la paume (Palm)

code

Feedback bionic

ceci est le code du système de feedback. le code utilise le filtrage médian pour filtrer le bruit et les fluctuations reçues lors des lectures du FSR. Les lectures des deux FSR sont utilisées pour faire tourner un servomoteur afin de simuler un retour à l'utilisateur.


#include <Servo.h> 

#define FORCELEN 50
Servo feedback;
int FRsensor_Thumb = A5;  //Analog pin to read Thumb force
int FRsensor_Palm = A4;   //Analog pin to read Pam force
int Thumb_value = 0;
int Palm_value = 0;
int max_force = 0;  //maximum force
int degree = 0;
int THUMBFORCE[FORCELEN]; //Array for mean filter on the thumb force
int PALMFORCE[FORCELEN];  //Array for mean filter on the palm force
int thumb_index = 0;      // Global index of thumb filter array
int palm_index = 0;       // Global index of palm filter array

void setup() {
  Serial.begin(9600);  
  feedback.attach(3);
  feedback.write(0);
  int thumb_val = analogRead(FRsensor_Thumb);
  int palm_val = analogRead(FRsensor_Palm);
  //Initializing the array's
  for(int i=0; i<FORCELEN; i++){
   THUMBFORCE[i] = thumb_val;
   PALMFORCE[i] = palm_val; 
  }
  
}

int thumbfilter(int val){
  float result;
  THUMBFORCE[thumb_index++] = val;
  //Cyclic array implementation
  if(thumb_index > FORCELEN){
    thumb_index = 0;
  }
  float sum = 0;
  for(int i=0; i<FORCELEN; i++){
    sum = sum + THUMBFORCE[i];  //Sum of all values in array
  }
  result = sum/FORCELEN;    //Average of the array
  return (int)result;
}

int palmfilter(int val){
  float result;
  PALMFORCE[palm_index++] = val;
  if(palm_index > FORCELEN){
    palm_index = 0;
  }
  float sum = 0;
  for(int i=0; i<FORCELEN; i++){
    sum = sum + PALMFORCE[i];
  }
  result = sum/FORCELEN;
  return (int)result;
}

void loop() {
  Thumb_value = thumbfilter(analogRead(FRsensor_Thumb));
  Palm_value = palmfilter(analogRead(FRsensor_Palm));
  max_force = max( Thumb_value, Palm_value);
  Serial.print(1000);
  Serial.print("\t");
  Serial.print(Thumb_value);
  Serial.print("\t");
  Serial.print(Palm_value);
  Serial.print("\t");
  degree = map(max_force, 0, 1023, 0, 60);  //mapping the force to servo rotation in degrees (0-60)
  //degree = max_force*0.06;
  feedback.write(degree); //writing the feedback to the servo
  Serial.print(degree);
  Serial.print("\t");
  Serial.println("");
  delay(5);  
}

Temperature feedback

#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
#include <avr/power.h>
#endif
#include <math.h>
#include <Metro.h> //Include Metro library

#define PIN 6
#define TEMPFILTERLENGHT 200
#define SEUILTEMP 5
#define NUMPIXELS 22
#define TEMPSENSE 1
#define HAVEFUN 2
#define COLD -1
#define HOT 1
#define NEUTRAL 0

const int B = 4275;               // B value of the thermistor
const int R0 = 100000;            // R0 = 100k
const int pinTempSensor = A0;     // Grove - Temperature Sensor connect to A5
const int TouchPin = 2;

Metro TempTimer = Metro(100); //interval in milliseconds
Metro LedStripTimer = Metro(50);


Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);
int TempFilter[TEMPFILTERLENGHT];
int Mode = HAVEFUN;



void setup()
{
  pinMode(TouchPin, INPUT);
  Serial.begin(115200);
  strip.begin();
  strip.show(); // Initialize all pixels to 'off'
  int temp = TemperatureRead();
  FilterInit(temp);
}



void loop()
{
  int Char;

  CheckMode();
  switch (Mode)
  {
    case TEMPSENSE:
      if (TempTimer.check() == 1)TempSense();
      break;

    case HAVEFUN:
      rainbowCycle(5);
      break;
  }
}
void CheckMode()
{
  static int State = 0;

  switch (State)
  {
    case 0:
      if (digitalRead(TouchPin))
      {
        State = 1;
        Mode = TEMPSENSE;
        int temp = TemperatureRead();
        FilterInit(temp);
      }
      break;
    case 1:
      if (!digitalRead(TouchPin)) State = 2;
      break;
    case 2:
      if (digitalRead(TouchPin))
      {
        State = 3;
        Mode = HAVEFUN;
      }
      break;
    case 3:
      if (!digitalRead(TouchPin)) State = 0;
      break;
  }
}
//********************************************************
void TempSense()
{
  static int Temp, Ftemp;
  int DeltaT;
  bool Hot, Cold;
  static int LedLevel = 0;
  int R, G, B;
  static int TempState=NEUTRAL;
  
  Temp = TemperatureRead();
  Ftemp = TemperatureFilter(Temp);
  
  if (Temp >= Ftemp+SEUILTEMP )Hot = true;
  else Hot = false;
 
  if (Temp <= Ftemp-SEUILTEMP )Cold = true;
  else Cold = false;

  switch(TempState)
  {
    case NEUTRAL:
        if(Hot) TempState=HOT;
        if(Cold) TempState=COLD;
        
    break;
    case HOT:
        if(!Hot && (LedLevel == NUMPIXELS+1 )) TempState=NEUTRAL;
       
    break;
    case COLD:
        if(!Cold && (LedLevel == NUMPIXELS+1 ))TempState=NEUTRAL;
       
    break;
  }

  
  Serial.print(500);
  Serial.print(" ");
  Serial.print(700);
  Serial.print(" ");
  Serial.print(Temp);
  Serial.print(" ");
  Serial.print(Ftemp);
  Serial.print(" ");
  /*
    if (Cold) Serial.print("Cold");
    if (Hot) Serial.print("Hot");
    Serial.print(" Level=");
    Serial.print(LedLevel);*/
  Serial.println();

  if (LedStripTimer.check() == 1)
  {
    //if (Cold || Hot)
    if((TempState==HOT) || (TempState==COLD))
    {
      if (LedLevel < NUMPIXELS + 1) LedLevel++;
    }
    else LedLevel--;
    if (LedLevel < 0) LedLevel = 0;

    //if (Hot) 
    if(TempState==HOT)
    {
      R = 255;
      G = 0;
      B = 0;
    }
    //if (Cold)
    if(TempState==COLD) 
    {
      R = 0;
      G = 0;
      B = 255;
    }
    for (int i = 0; i < NUMPIXELS; i++)
    {
      strip.setPixelColor(i, 0, 0, 0);
    }
    if (LedLevel > 0)
    {
      for (int i = 0; i < (LedLevel - 1); i++)
      {
        strip.setPixelColor(i, R, G, B);
      }
    }
    strip.show();
  }
}

//********************************************************

int TemperatureRead()
{
  int a = analogRead(pinTempSensor);
  float R = 1023.0 / a - 1.0;
  R = R0 * R;
  //float temperature = 1.0 / (log(R / R0) / B + 1 / 298.15) - 273.15; // convert to temperature via datasheet
  //return ((int)temperature * 10);
  return a;
}
int TemperatureFilter(int Value)
{
  static int Index = 0;
  float Result = 0;
  TempFilter[Index] = Value;
  Index++;
  if (Index > TEMPFILTERLENGHT) Index = 0;
  for (int i = 0; i < TEMPFILTERLENGHT; i++)
  {
    Result += (float)TempFilter[i];
  }
  Result = Result / TEMPFILTERLENGHT;
  return ((int)Result);
}
void FilterInit(int temp)
{
   for (int i = 0; i < TEMPFILTERLENGHT; i++)
  {
    TempFilter[i] = temp;
  }
}
//*******************************************************
void ColorPropagate(int R, int G, int B, int Delay)
{
  for (int i = 0; i < NUMPIXELS; i++)
  {
    strip.setPixelColor(i, R, G, B);
    strip.show();
    delay(Delay);
  }
}
//*******************************************************

int rainbowCycle(uint8_t wait)
{
  uint16_t i, j;
  for (j = 0; j < 256 * 5; j++)
  {
    for (i = 0; i < strip.numPixels(); i++)
    {
      strip.setPixelColor(i, Wheel(((i * 256 / strip.numPixels()) + j) & 255));
      CheckMode();
      if (Mode == TEMPSENSE) return (0);
    }
    strip.show();
    delay(wait);
  }
}
// Input a value 0 to 255 to get a color value.
// The colours are a transition r - g - b - back to r.
uint32_t Wheel(byte WheelPos) {
  WheelPos = 255 - WheelPos;
  if (WheelPos < 85) {
    return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3);
  }
  if (WheelPos < 170) {
    WheelPos -= 85;
    return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3);
  }
  WheelPos -= 170;
  return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
}