Différences entre versions de « Projets:Hackberry Fabrikarium Inde »

De wikiup
Sauter à la navigation Sauter à la recherche
 
(7 versions intermédiaires par le même utilisateur non affichées)
Ligne 1 : Ligne 1 :
 +
{{Infobox projet
 +
|Image principale=Temperature feedback hackberry.jpg
 +
|Description=Retour visuel sur la température de l'objet saisi avec la prothèse Hackberry
 +
|Porteur de projet=Bionico
 +
|Contributeurs=Hinal Shah, Sourabh ZunkeSourabh Zunke, Jean Noel Lefèvre, Ashish kumarpardeshi, Bodo Hoenen, Delphine, Akshit GandhiAkshit Gandhi, Sahal Hashim, Sanskruta Dhotre, Farhan KhanFarhan Khan
 +
|Fabmanager=Bionico
 +
|Référent documentation=Bodo Hoenen, Delphine
 +
|Catégorie de handicap=Membre supérieur
 +
|Etat d'avancement=Réalisés
 +
|Statut de la documentation=Complète
 +
|Relecture de la documentation=Non vérifiée
 +
|Techniques=arduino
 +
|Durée de fabrication=de 4 à 8 h
 +
|Coût matériel=Moins de 50 euros
 +
|Niveau=Facile
 +
|Licence=by-sa
 +
|Projet date=2017-10-16
 +
|Partenaires=Makers Asylum (Fablab Mumbai)
 +
|Nom humanlab=Humanlab_MHK
 +
}}
 +
[[File:temperature_feedback_hackberry.jpg|400px|right]]
 +
 
==Description du projet==
 
==Description du projet==
 +
Ce projet a été réalisé à Bombay dans le cadre du [https://myhumankit.org/agenda/event/steam-fabrikarium-mumbai-cap-linde/ Fabrikarium].
 +
 +
La documentation a été réalisé en anglais sur le site [https://hackaday.io/project/51025-hackberry-feedback-system 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.
 
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.
  
Ligne 51 : Ligne 76 :
  
 
==code==
 
==code==
===Temperature feedback===
+
===Feedback bionic===
<code>
+
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.
<pre>
+
 
 +
 
 +
<code><pre>
 
#include <Servo.h>  
 
#include <Servo.h>  
  
Ligne 132 : Ligne 159 :
 
</pre>
 
</pre>
 
</code>
 
</code>
 +
 +
===Temperature feedback===
 +
<code c++><pre>
 +
#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);
 +
}
 +
 +
 +
 +
</pre></code>
 +
  
  
 
[[Category:Projets]]
 
[[Category:Projets]]
 +
[[Category:Réalisés]]
 +
[[Category:Membre supérieur]]

Version actuelle datée du 18 juillet 2022 à 10:52

Hackberry Fabrikarium Inde

Temperature feedback hackberry.jpg

Informations
Description Retour visuel sur la température de l'objet saisi avec la prothèse Hackberry


Catégorie Membre supérieur
Etat d'avancement Réalisés
Techniques arduino
Durée de fabrication de 4 à 8 h
Coût matériel Moins de 50 euros"Moins de 50 euros" n’est pas dans la liste (De 50 à 100 euros, De 100 à 200 euros, Plus de 200 euros, Moins de 10 euros, De 10 à 50 euros) de valeurs autorisées pour la propriété "A coût matériel".
Niveau Facile
Licence by-sa
Date de création 2017-10-16
Équipe
Porteur de projet Bionico
Contributeurs Hinal Shah, Sourabh ZunkeSourabh Zunke, Jean Noel Lefèvre, Ashish kumarpardeshi, Bodo Hoenen, Delphine, Akshit GandhiAkshit Gandhi, Sahal Hashim, Sanskruta Dhotre, Farhan KhanFarhan Khan
Fabmanager Bionico
Référent documentation Bodo Hoenen, Delphine
Partenaires: Makers Asylum (Fablab Mumbai)
Nom humanlab Humanlab_MHK
Documentation
Statut de la documentation Complète
Relecture de la documentation Non vérifiée
Temperature feedback hackberry.jpg

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);
}