OHWL!

Aus HRW FabLab MediaWiki
Wechseln zu: Navigation, Suche
OHWL!
thumb

EntwicklerInnen


Nick Franke, Niklas Degenhart, Talia Deckardt

Gehäuse

3D Druck PETG

Programmiersprachen


HTML5, Arduino programming language

Software



Autodesk Fusion 360, Arduino IDE



"OHWL!" ist ein Fahrerassistenzsystem für Rollstühle und besteht aus einer Mikrocontrollersteuerung und einer 3D-Druck Halterung.

Projektbeschreibung[Bearbeiten]

NutzerInnen die auf einen Rollstuhl angewiesen sind, haben zusätzliche Anforderungen an die visuelle Wahrnehmung: Besteht keine Möglichkeit einen direkten Kontakt mit dem Untergrund aufzunehmen und ist der Rollstuhl zusätzlich motorisiert sowie groß, wird das Sichtfeld jedoch stark eingeschränkt. Das gefahrlose Navigieren um Hindernisse wie Bodenschwellen oder Bordsteinkanten ist so nicht ohne weiteres möglich. Sind weitere Sinne wie Hören oder der Gleichgewichtssinn eingeschränkt, so entstehen auch hier Bedarfe die eingeschränkte Wahrnehmbarkeit der Umgebung zu unterstützen. Mittels unseres eingebetteten Systems soll in diesen Fällen der Informationsmangel über die Umgebung überbrückt und die Wahrnehmbarkeit erweitert werden.

Dazu erfasst das System die unmittelbare Umgebung des Rollstuhls mittels Sensoren und indiziert über Aktoren das entsprechende Feedback. Dieses soll über verschiedene Formen des Feedbacks ermöglicht werden um die erfahrbaren sensorischen Einschränkungen der Betroffenen im Alltag auf ein Mindestmaß zu reduzieren.

Ergonomischer Hintergrund[Bearbeiten]

Abb.1: Sichtfeld für Überwachungsaufgaben. Quelle: DIN EN 894-2:2009-02

Sitzhaltung und Blickfeld

Im Sitzen ist das Blickfeld in natürlicher Weise eher dem Boden zugeneigt als frontal horizontal ausgerichtet. Etwaigen physiologischen Konsequenzen wie Nackenverspannungen und Fehlhaltungen gilt es durch geschickte Positionierung und Anbindung vorzubeugen. Voraussetzung für die optimale Positionierung und Anbindung des Anzeigemoduls sind in Abbildung 1 sichtbar: Der Blickbereich A ist den anderen vorzuziehen. Ist dies z. B. aufgrund von Erkrankungen der Wirbelsäule nicht möglich, so ist auch Blickbereich B in der Anwendung möglich. Blickbereich C ist hingegen ungeeignet. In diesem Fall wäre es besser das visuelle Feedback mit Audio zu unterstützen oder gänzlich zu ersetzen.


Abb.2: Sichtanalyse. Quelle: RWTH Aachen

Farbwahrnehmung

Während der Entwicklung haben wir uns intensiv mit den Themen Ergonomie, Farbverarbeitung und Sehfeld auseinandergesetzt. Ziel unserer Recherchen war ein komfortables und sicheres System zu gestalten. Im Vergleich mit ähnlichen Systemen ist uns aufgefallen, dass Eigenschaften menschlichen Sehvermögens wenig Beachtung finden. Häufig wird die Farbe Rot als Signal eingesetzt um auf Gefahren hinzuweisen. Dabei ist die Wahrnehmbarkeit von Rot am Rande des Sichtfelds stark eingeschränkt. Darüber hinaus ist es wichtig das Farbspektrum so anzupassen, dass die Wahrnehmbarkeit bei verschiedenen Lichtverhältnisse die zeit- und wetterabhängig garantiert sind. Außerdem nimmt die Farbwahrnehmung am Rande des Sehfelds ab; es ist demnach entscheidend einen Farbraum zu wählen der sowohl am Rande des Sehfelds als auch bei diversen äußeren Faktoren wahrnehmbar ist. Die Farbe Blau oder Gelb kamen dabei in Frage.


Abb.3: Griffarten zur Unterstützung der Informationsabgabe. Quelle: DIN EN 894-3:2010-01

Bedienbarkeit der verstellbaren Anzeige

Unser Ziel war es in Absprache mit der Endnutzerin eine verstellbare Anzeige zu entwerfen, welche für sie bedienbar ist und ihr auch optisch zusagt. Um die Bedienbarkeit zu gewährleisten und auf ihre Bedürfnisse spezifisch einzugehen identifizierten wir folgende Anforderungen an das Anzeigeelement: es muss stabil, verstellbar, elegant, ohne Umfassungsgriff und mit wenig Kraftaufwand translatorisch bedienbar sein. Die in Frage kommenden Handlungsoptionen zur Informationsabgabe an die verstellbare Anzeige sind auf der Abbildung als Kontaktgriff "1" und Zufassungsgriff "2" dargestellt. Von diesen Voraussetzung aus waren Entwürfe zu Drehelementen, Teleskop sowie verstellbare Drahtelemente keine Option mehr. Als in Frage kommendes Modell entschieden wir uns für ein Anzeigeelement in der Form eines breiten Fächers welcher flach auf einer Armlehne angebracht werden kann. Darüberhinaus ist es möglich diesen wunschgerecht zu individualisieren mit Druck und Folie.

Hardware und Materialien[Bearbeiten]

Wir setzen 4 Mikrocontroller und 3 TOF Sensoren sowie 2 LEDs ein. Die Daten der Sensorik wird über 3 Mikrocontroller des Typs Arduino Pro Mini verarbeitet und anschließend auf einem ESP32 zusammengefasst. Der ESP32 stellt eine Benutzeroberfläche über ein Wifi-Netzwerk bereit, und wertet zugleich die Daten der Arduino-Controller aus. Die LEDs werden an einer Halterung auf dem Rollstuhl befestigt und blinken in einer höheren Frequenz, je nach dem wie nah sich der Rollstuhl einer möglichen Gefahr wie etwa einem Bordstein befindet.

Name Beschreibung Produktbild
ESP32 Mikrocontroller für Weboberfläche
ESP32
Arduino Pro Mini Sensor und Datenverarbeitung
Arduino Pro Mini
VL53L0X Sensoreinheit
VL53L0X


Bei der Gehäuse Erstellung mit 3D-Druck verwenden wir PETG(Co-Polyester) bei einer Layerhöhe von 0,2mm


Name Beschreibung Produktbild
Gehäuse Gehäuse für Arduino Pro Mini und TOF-Sensor
Gehäuse
Halterung Halterung am Rollstuhl
Halterung
LED-Gehäuse Gehäuse für die LEDs
LED-Gehäuse
ESP-Gehäuse Gehäuse für den ESP32
ESP-Gehäuse
Kugelgelenk Kugelgelenk für das Gehäuse der Sensorik und des Arduino Pro Mini
VL53L0X

Software[Bearbeiten]

Es wurden zwei Programme entwickelt, jeweils für den Arduino Pro Mini und den ESP32. Im ersten Beispiel ist der Ablauf der Sensorerfassung zu sehen.

Wir senden über einen Serialport. Dieser wird gleich zu Anfang initialisiert.

Adafruit_VL53L0X lox = Adafruit_VL53L0X();
//SDA = 4, SCL=5
const int numReadings = 20;
SoftwareSerial mySerial(10,11); //RX, TX

Für den Moving-Average Filter werden zusätzliche Werte initiiert.

int readings[numReadings];
int readIndex = 0;
int total = 0;
int average = 0;

Es wird ein Frequenzband für die Serielleübertragung festgelegt.

void setup() {
 Serial.begin(57600);
 // wait until serial port opens for native USB devices
 while (! Serial) {
   delay(1);
 }
 mySerial.begin(9600);
 Serial.println("Aktiv");
 Serial.println("ToF Sensor // Smoothing");
 if (!lox.begin()) {
   Serial.println(F("Failed to boot VL53L0X"));
   while(1);
 }
 // power 
 Serial.println(F("VL53L0X API Simple Ranging example\n\n")); 
 for (int thisReading = 0; thisReading < numReadings; thisReading++) {
   readings[thisReading] = 0;
 }
}


In diesem Bereich werden die Sensordaten mit einem Moving-Averrage-Filter geglättet.

void loop() {
 VL53L0X_RangingMeasurementData_t measure;
   
 Serial.print("Reading a measurement... ");
 lox.rangingTest(&measure, false); // pass in 'true' to get debug data printout!


 if (measure.RangeStatus != 4) {  // phase failures have incorrect data
   total = total - readings[readIndex];
   readings[readIndex] = measure.RangeMilliMeter;
   
   total = total + readings[readIndex];
   
   readIndex = readIndex + 1;
 
   if(readIndex >= numReadings){
     readIndex = 0;
   }
 
   // calculate the average
   average = total / numReadings;
   if (average >= 0){
     mySerial.write(average);
     Serial.println(average);
   }
   
 
   delay(1);
 } else {
   Serial.println(" out of range ");
 }
   
}



Der ESP32 bietet aufgrund des verhältnismäßig schnellen Prozessors sowohl die Möglichkeit ein WLAN-Netzwerk bereit zu stellen, als auch einen Webserver für die Nutzeroberfläche bereit zu stellen. Für die Realisierung der Netzwerkgrundlage bedienen wir uns einer Vorlage von Rui Santos. Diese haben wir weiterentwickelt und für unser Projekt angepasst.

Der ESP wird für drei Serialinputs vorbereitet.

HardwareSerial Serial3(2);
HardwareSerial RightSerial(1);
HardwareSerial BackSerial(1);

Das Gesamte System soll von der Weboberfläche ein und aus geschaltet werden können, darum wird der System-Zustand einer boolean Funktion untergeordnet. Das gesamte System arbeitet nur wenn die boolean Funktion auf true steht. Außerdem werden an dieser Stelle bereits die WLAN-Sicherheitsparameter sowie Port und Header der später dargestellten Website definiert

boolean SystemStatus = true;
// Replace with your network credentials
const char* ssid     = "OHWL!";
const char* password = "HRW12345";
// Set web server port number to 80
WiFiServer server(80);
// Variable to store the HTTP request
String header;
// Auxiliar variables to store the current output state
int output26State = LOW;
int output27State = LOW;
// Assign output variables to GPIO pins
const int output26 = 26; //Left LED
const int output27 = 27; //Right LED
unsigned long preMillis = 0;
void setup() {
 Serial.begin(115200);
 Serial.println("Session Start");
 
 //Back Sensor
 RightSerial.begin(38400,SERIAL_8N1,34,35);//RX, TX
 //Right Sensor
 BackSerial.begin(19200, SERIAL_8N1,22,23);//RX, TX
 //Left Sensor
 Serial3.begin(9600,SERIAL_8N1,18,19);//RX, TX
 
 // Initialize the output variables as outputs
 pinMode(output26, OUTPUT);
 pinMode(output27, OUTPUT);
 // Set outputs to LOW
 digitalWrite(output26, LOW);
 digitalWrite(output27, LOW);
 // Connect to Wi-Fi network with SSID and password
 Serial.print("Setting AP (Access Point)…");
 // Remove the password parameter, if you want the AP (Access Point) to be open
 WiFi.softAP(ssid, password);
 IPAddress IP = WiFi.softAPIP();
 Serial.print("AP IP address: ");
 Serial.println(IP);
 
 server.begin();
}


In der Loop()-Funktion werden die Sensordaten erfasst und schließlich für die LED prepariert.


void loop(){
 if(BackSerial.available() && SystemStatus == true){
   
   int StateBack = BackSerial.read(); // Serial of back sensor
   unsigned long ms = millis();
   Serial.println("State Back:" + StateBack);
   if(StateBack>=300 && SystemStatus == true){
     if( (ms-preMillis) >=100){
       preMillis = ms;
     
     if(output26State == LOW && output27State == LOW){
       output26State = HIGH;
       output27State = HIGH;
     }else{
       output26State = LOW;
       output27State = LOW;
     }
    }
   }else{
    output26State = LOW;
    output27State = LOW;
   }
   digitalWrite(output26, output26State);
   digitalWrite(output27, output27State);  
 }
 if(RightSerial.available() && SystemStatus == true){
   int StateRight = RightSerial.read(); // Serial of right sensor
   Serial.println("State Right:" + StateRight);
   unsigned long ms = millis();

Der Webserver wird über einen Client Print Zeile für Zeile ausgegeben und erwartet gleichzeitig, dass der Link auf der dargestellten Website angeklickt wird. Anfragende Browser erhalten eine Website und können mit dieser interagieren.

 WiFiClient client = server.available();   // Listen for incoming clients
 if (client) {                             // If a new client connects,
   Serial.println("New Client.");          // print a message out in the serial port
   String currentLine = "";                // make a String to hold incoming data from the client
   while (client.connected()) {            // loop while the client's connected
     if (client.available()) {             // if there's bytes to read from the client,
       char c = client.read();             // read a byte, then
       Serial.write(c);                    // print it out the serial monitor
       header += c;
       if (c == '\n') {                    // if the byte is a newline character
         // if the current line is blank, you got two newline characters in a row.
         // that's the end of the client HTTP request, so send a response:
         if (currentLine.length() == 0) {
           // HTTP headers always start with a response code (e.g. HTTP/1.1 200 OK)
           // and a content-type so the client knows what's coming, then a blank line:
           client.println("HTTP/1.1 200 OK");
           client.println("Content-type:text/html");
           client.println("Connection: close");
           client.println();
           
           
           if (header.indexOf("GET /26/on") >= 0) {
             Serial.println("System ON");
             SystemStatus = true;
           } else if (header.indexOf("GET /26/off") >= 0) {
             Serial.println("System OFF");
             SystemStatus = false;
           }
           
           // Display the HTML web page
           client.println("<!DOCTYPE html><html>");
           client.println("<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">");
           client.println("<link rel=\"icon\" href=\"data:,\">");
           // CSS to style the on/off buttons 
           // Feel free to change the background-color and font-size attributes to fit your preferences
           client.println("<style>html { font-family: Helvetica; display: inline-block; margin: 0px auto; text-align: center;}");
           client.println(".button { background-color: #4CAF50; border: none; color: white; padding: 16px 40px;");
           client.println("text-decoration: none; font-size: 30px; margin: 2px; cursor: pointer;}");
           client.println(".button2 {background-color: #555555;}</style></head>");

Sonstiges[Bearbeiten]

Als Weiterentwicklungsoption bietet sich der Ausbau der Sensorik an. Da der gut wahrnehmbare Farbraum je nach entsprechenden der Lichtverhältnisse variiert, ist es sinnvoll einen dynamischen Farbwechsel zwischen Gelb und Blau vor zu nehmen. Dies soll mittels eines Lichtsensors realisiert werden.

Ausserdem könnte ein Wechsel von einer einzelnen LED auf ein LED-Band hilfreich sein: Der sichtbare Wechsel des Feedbacks nicht nur in der Beleuchtungsstärke und Farbe könnte dynamischer gestaltet werden. Das LED Band könnte, ähnlich einem Tacho, detaillierteres Feedback ermöglichen.