Auf dieser Seite können zusätzliche Materialien der Dokumentation des Themas „Konzeption und Herstellung einer elektronischen Hand- und Unterarmprothese, die durch 3D-Druckverfahren hergestellt und drahtlos mit einem externen Handschuh mit Fingerbeugungssensoren gesteuert wird auf Basis des ESP32 Mikrocontrollers“ heruntergeladen oder eingesehen werden.



Bilder Galerie


Quellenverzeichnis der Dokumentation:

  1. https://www.amazon.de/gp/bestsellers/digital-text/611274031/ref=zg_bs (Stand: 7.4.2021)
  2. https://www.youtube.com/watch?v=fY-TsxkxYwA (Stand: 7.4.2021)
  3. http://inmoov.fr/ (Stand 10.8.2020)
  4. https://de.wikipedia.org/wiki/Arduino_(Plattform) (Stand 7.4.2021)
  5. Von Clic17 – Eigenes Werk, CC BY-SA 4.0, https://commons.wikimedia.org/w/index.php?curid=34226017 (Stand 7.4.2021)
  6. https://de.wikipedia.org/wiki/InMoov (Stand 10.8.2020)
  7. Eigenes Werk nach CC BY-SA 4.0 von Philipp Lemke vom 15.10.2018
  8. http://inmoov.fr/project/ (Stand 7.4.2021)
  9. https://creativecommons.org/licenses/by-nc/3.0/deed.de (Stand 7.4.2021)
  10. https://www.amazon.de/3D-Druck-Handbuch-f%C3%BCr-junge-Einsteiger-ebook/dp/B08848681V (Stand 8.4.2021)
  11. „3D-Druck Handbuch für junge Einsteiger: 3D-Druck mit Ultimaker Cura für SchülerInnen und LehrerInnen“ von Philipp Lemke von 2020 [10]
  12. https://www.az-delivery.de/products/az-delivery-servo-mg995?variant=12236815138912 (Stand 10.4.2021)
  13. Battery Shield, Modell digital nachgebaut und gerendert. Software Fusion360
  14. https://www.amazon.de/gp/product/B0822Q4VS4 (Stand 10.4.2021)
  15. VTC6 Akkus, Modell digital nachgebaut und gerendert. Software Fusion360
  16. https://www.amazon.de/gp/product/B087R9XXM8 (Stand 10.4.2021)
  17. Datenblatt: https://cdn.shopify.com/s/files/1/1509/1638/files/ESP-32_DevKit_C_V4_Datenblatt_AZ-Delivery_Vertriebs_GmbH_24ec770f-c65e-4bd3-92c9-cd64b4d070b8.pdf?v=1615364587 (Stand 10.4.2021)
  18. https://www.az-delivery.de/products/esp-32-dev-kit-c-v4 (Stand 10.4.2021)
  19. https://www.amazon.de/gp/product/B085WJCRX8 (Stand 10.4.2021)
  20. https://www.amazon.de/gp/product/B0754MNQPN (Stand 10.4.2021)
  21. https://www.amazon.de/gp/product/B07HVND5DL (Stand 10.10.2020)
  22. https://de.wikipedia.org/wiki/Kohlenstofffaser (Stand 10.4.2021)
  23. https://www.amazon.de/gp/product/B086RVJ36S (Stand 10.4.2021)
  24. Eigenes Werk nach CC BY-SA 4.0 von Philipp Lemke vom 10.04.2021
  25. https://www.sparkfun.com/products/8606 (Stand 10.4.2021)
  26. https://cdn.sparkfun.com/datasheets/Sensors/ForceFlex/FLEXSENSORREVA1.pdf (Stand 10.4.2021)
  27. https://heltec.org/project/wifi-kit-32/ (Stand 11.4.2021)
  28. https://www.amazon.de/gp/product/B076P8GRWV (Stand 11.4.2021)
  29. Datenblatt http://resource.heltec.cn/download/WiFi_Kit_32/WIFI_Kit_32_pinoutDiagram_V2.pdf (Stand 11.4.2021)
  30. https://www.amazon.de/gp/product/B07YWLCTLK (Stand 14.4.2021)
  31. https://www.amazon.de/gp/product/B087LTZW61 (Stand 14.4.2021)
  32. https://www.amazon.de/gp/product/B07MC4G4S8 (Stand 14.4.2021)
  33. https://www.amazon.de/gp/product/B07NDBPYBR (Stand 14.4.2021)
  34. https://www.amazon.de/gp/product/B07BHRGJLJ (Stand 14.4.2021)
  35. https://www.amazon.de/gp/product/B083DC38TZ (Stand 14.4.2021)
  36. https://www.amazon.de/gp/product/B07TT69PPV (Stand 14.4.2021)
  37. https://de.wikipedia.org/wiki/CAD (Stand 14.4.2021)
  38. https://grabcad.com/library/lm2596-dc-to-dc-buck-converter-module-1 (Stand 14.4.2021)
  39. https://fritzing.org/ (Stand 14.4.2021)
  40. https://www.amazon.de/Artillery-Sidewinder-Neuestes-vormontiert-300x300x400mm/dp/B089NFVBGG (Stand 14.4.2021)
  41. https://www.amazon.de/dp/B07X37DT9M (Stand 15.4.2021)
  42. https://www.arduino.cc/en/software (Stand 15.4.2021)

Programmierung des Handschuhs:

//ESP32 MAC-Adresse Prothese: 3C:61:05:3F:B9:B8
//ESP32 MAC-Adresse Handschuh: C4:4F:33:76:E6:8D

//Bibliotheken werden hinzugefügt
#include "Arduino.h"
#include "heltec.h"
#include <esp_now.h>
#include <WiFi.h>
#include <Wire.h>

//ESP32 MAC-Adresse Prothese: 3C:61:05:3F:B9:B8
uint8_t broadcastAddress[] = {0x3C, 0x61, 0x05, 0x3F, 0xB9, 0xB8};

//Pins für die Beugungssensoren werden definiert
const int F1_Pin = 36;  //Daumen
const int F2_Pin = 37;  //Zeigefinger
const int F3_Pin = 38;  //Mittelfinger
const int F4_Pin = 39;  //Ringfinger
const int F5_Pin = 34;  //kleiner Finger

// 5-Dimensionales Array um später konvertierte Daten zu speichern
int converted_flex[5];

// Variable, um abzuspeichern, ob das Senden erfolgreich war
String success;

//Struktur für zu sendende Daten (Muss gleich mit Empfänger sein)
typedef struct struct_message {
  int send_F1;
  int send_F2;
  int send_F3;
  int send_F4;
  int send_F5;
} struct_message;

// Erstellt ein struct_message Objekt, um ausgehende Daten zu //speichern
struct_message datatosend;

// Callback-Funktion, wenn Daten gesendet werden
void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) {
  Serial.println();
  if (status ==0){
    success = "Delivery Success :)";
  }
  else{
    success = "Delivery Fail :(";
  }
}

void setup() {
  //Serial Monitor wird gestartet (Nur für Debugging)
  Serial.begin(115200);

  //WiFi wird im Modus WIFI_STA gestartet
  WiFi.mode(WIFI_STA);

  //Display wird initialisiert
  Heltec.begin(true /*DisplayEnable Enable*/, false /*LoRa Disable*/, true /*Serial Enable*/);
  Heltec.display->setContrast(255);
  Heltec.display->clear();

  Heltec.display->drawString(0, 0, "Handschuh gestartet \n Verbindung wird \n hergestellt.");
  Heltec.display->display();
  
  //ESP-NOW wird initialisiert
  if (esp_now_init() != ESP_OK) {
    Heltec.display->drawString(0, 0, "Die Verbindung mit \n der Prothese konnte \n nicht hergestellt \n werden!");
    Heltec.display->display();
    return;
  }

  //Registrierung einer Callback-Funktion, die aufgerufen wird, wenn Daten gesendet werden
  esp_now_register_send_cb(OnDataSent);
  
  //Peer wird registiert
  esp_now_peer_info_t peerInfo;
  memcpy(peerInfo.peer_addr, broadcastAddress, 6);
  peerInfo.channel = 0;  
  peerInfo.encrypt = false;
  
  //Peer wird hinzugefügt
  if (esp_now_add_peer(&peerInfo) != ESP_OK){
    Serial.println("Failed to add peer");
    return;
  }
  
  Heltec.display->drawString(0, 0, "Handschuh initialisiert \n und 
  Verbindung \n hergestellt.");
  Heltec.display->display();
  //Pins für Beugungssensoren werden initialisiert
    pinMode(F1_Pin, INPUT);
    pinMode(F2_Pin, INPUT);
    pinMode(F3_Pin, INPUT);
    pinMode(F4_Pin, INPUT);
    pinMode(F5_Pin, INPUT);

}

void loop() {
  Heltec.display->clear();

  //Daten der Beugungssensoren werden gelesen und in flex_read_NUMMER gespeichert
  int flex_read_1 = analogRead(F1_Pin);
  int flex_read_2 = analogRead(F2_Pin);
  int flex_read_3 = analogRead(F3_Pin);
  int flex_read_4 = analogRead(F4_Pin);
  int flex_read_5 = analogRead(F5_Pin);

  //Rohdaten des Bewegungssensors werden in grobe Werte von 0 bis 100 umgewandelt
  converted_flex[0] = 100 - ((flex_read_1 - 1050) / 5.5);
  converted_flex[1] = 100 - ((flex_read_2 - 1000) / 6);
  converted_flex[2] = 100 - ((flex_read_3 - 800) / 8.5);
  converted_flex[3] = 100 - ((flex_read_4 - 1100) / 6.5);
  converted_flex[4] = 100 - ((flex_read_5 - 800) / 9);

  //Da Werte unter 0 und über 100 enstehen können, werden sie bereinigt
  for (int i=0; i <= 5; i++){
    if(converted_flex[i] < 0){
      converted_flex[i] = 0;
    }
    if(converted_flex[i] > 100){
      converted_flex[i] = 100;
    }
  }

  //Zu sendende Daten werden in datatosend verpackt
  datatosend.send_F1 = converted_flex[0];
  datatosend.send_F2 = converted_flex[1];
  datatosend.send_F3 = converted_flex[2];
  datatosend.send_F4 = converted_flex[3];
  datatosend.send_F5 = converted_flex[4];

  //Sende Daten
  esp_err_t result = esp_now_send(broadcastAddress, (uint8_t *) 
  &datatosend, sizeof(datatosend));

  //Für Debugging
  if (result == ESP_OK) {
    Serial.println("Sent with success");
  }
  else {
    Serial.println("Error sending the data");
  }  
  //Ausgabe der Werte am Display
  Heltec.display->drawString(0, 0, "Daumen: " + 
  String(converted_flex[0])+ "%\n" + "Zeigefinger: " + 
  String(converted_flex[1])+ "%\n" + "Mittelfinger: " + 
  String(converted_flex[2])+ "%\n" +"Ringfinger: " + 
  String(converted_flex[3])+ "%\n" +"kleiner Finger: " + 
  String(converted_flex[4])+ "%");
  Heltec.display->display();

  //Daten werden im Intervall von 50 ms gelesen, umgewandelt und gesendet. Das Display wird somit auch jeden 50ms aktualisiert.
  delay(50); 
}

Programmierung der Prothese

//ESP32 MAC-Adresse Prothese (Empfänger): 3C:61:05:3F:B9:B8
//ESP32 MAC-Adresse Handschuh (Sender): C4:4F:33:76:E6:8D
//Einfügen der Bibliotheken
#include <esp_now.h>
#include <WiFi.h>
#include <ESP32Servo.h>
#include <Wire.h>

//Erstellen von Servo Objekten. Servo1 für den Daumen usw.
Servo servo1;
Servo servo2;
Servo servo3;
Servo servo4;
Servo servo5;

//minimale und maximale Pulsweitenlänge der Servos //(Datenblatt)
int minUs = 500;
int maxUs = 2500;

//Pins der Servos werden festgelegt
int servo1Pin = 12;
int servo2Pin = 14;
int servo3Pin = 27;
int servo4Pin = 25;
int servo5Pin = 26;

//ESP32 wird in pwm Zustand versetzt
// PWM (Pulsweitenmodulation) wird für die Ansteuerung der // Servomotoren benötigt.
ESP32PWM pwm;

//ESP32 MAC-Adresse Handschuh: C4:4F:33:76:E6:8D
uint8_t broadcastAddress[] = {0xC4, 0x4F, 0x33, 0x76, 0xE6, 0x8D};

// 5-Dimensionales Array um einkommende Daten zu Speichern
int converted_flex[5];


//Struktur für einkommende Daten (Muss gleich mit Sender sein)
typedef struct struct_message {
  int send_F1;
  int send_F2;
  int send_F3;
  int send_F4;
  int send_F5;
} struct_message;

// Erstellt ein struct_message Objekt um einkommende Daten zu speichern
struct_message incomingReadings;

// Callback-Funktion wenn Daten empfangen werden
void OnDataRecv(const uint8_t * mac, const uint8_t *incomingData, int len) {
  memcpy(&incomingReadings, incomingData, sizeof(incomingReadings));
//Eingehende Daten warden mit prozentual mit den Werten der // Servos im geöffneten Zustand verrechnet und im converted_flex Array gespeichert
  converted_flex[0] = incomingReadings.send_F1*0.6;
  converted_flex[1] = incomingReadings.send_F2*0.9;
  converted_flex[2] = incomingReadings.send_F3*0.9;
  converted_flex[3] = incomingReadings.send_F4*1.0;
  converted_flex[4] = incomingReadings.send_F5*0.8;

}
 
void setup() {
  //Array auf Ausgangsposition 0 stellen
  converted_flex[0] = 0;
  converted_flex[1] = 0;
  converted_flex[2] = 0;
  converted_flex[3] = 0;
  converted_flex[4] = 0;
  
  //Alle Timer werden zugewiesen, um bestmögliche 
  // Synchronisation zu gewährleisten
  ESP32PWM::allocateTimer(0);
  ESP32PWM::allocateTimer(1);
  ESP32PWM::allocateTimer(2);
  ESP32PWM::allocateTimer(3);

  //Frequenz des Servos wird definiert (50hz)
  servo1.setPeriodHertz(50);
  servo2.setPeriodHertz(50);
  servo3.setPeriodHertz(50);
  servo4.setPeriodHertz(50);
  servo5.setPeriodHertz(50);

  //Servos werden eingebunden
  servo1.attach(servo1Pin, minUs, maxUs);
  servo2.attach(servo2Pin, minUs, maxUs);
  servo3.attach(servo3Pin, minUs, maxUs);
  servo4.attach(servo4Pin, minUs, maxUs);
  servo5.attach(servo5Pin, minUs, maxUs);
  
  //Serial Monitor wird gestartet (Nur für Debugging)
  Serial.begin(115200);
 
  //WiFi wird im Modus WIFI_STA gestartet
  WiFi.mode(WIFI_STA);

  //ESP-NOW wird initialisiert
  if (esp_now_init() != ESP_OK) {
    Serial.println("Fehler beim initialisieren von ESP-NOW");
    return;
  }
  
  //Peer wird registiert
  esp_now_peer_info_t peerInfo;
  memcpy(peerInfo.peer_addr, broadcastAddress, 6);
  peerInfo.channel = 0;  
  peerInfo.encrypt = false;
  
  //Peer wird hinzugefügt       
  if (esp_now_add_peer(&peerInfo) != ESP_OK){
    Serial.println("Failed to add peer");
    return;
  }
  
  //Registrierung einer Callback-Funktion, die aufgerufen wird wenn Daten empfangen werden
  esp_now_register_recv_cb(OnDataRecv);
}
 
void loop() {

//Ausführen der Methode updatefingers()
updatefingers();
//Daten werden im Intervall von 50 ms empfangen und die Servos werden auf den neuen Wert aktualisiert.

delay(50);
}

void updatefingers(){
  //Servos werden auf den übertragenen Wert gesetzt  
  servo1.write(converted_flex[0]);
  servo2.write(converted_flex[1]);
  servo3.write(converted_flex[2]);
  servo4.write(converted_flex[3]);
  servo5.write(converted_flex[4]); 

//Servowerte warden in über die serielle Schnittstelle an den Computer übertragen (Für Debugging)
  Serial.println("Daumen: " + String(converted_flex[0])+ "%\n" + "Zeigefinger: " + String(converted_flex[1])+ "%\n" + "Mittelfinger: " + String(converted_flex[2])+ "%\n" +"Ringfinger: " + String(converted_flex[3])+ "%\n" +"kleiner Finger: " + String(converted_flex[4])+ "%");
  Serial.println();
}

Achtung: Zeilennummern im Code entsprechen nicht den Zeilennummern des Codes in der Dokumentation. Der Code ist jedoch identisch.