Benutzer-Werkzeuge

Webseiten-Werkzeuge


Seitenleiste

projektewise24:projekt6:doku

Projektdokumentation Nerf-Bot

Projektlabor Robotik Wintersemester 2024/25

Disclaimer: Dieses Projekt ist nicht fertig gestellt. Es werden CAD-Modelle in Tinkercad zur Anschauung benutzt. Diese sind zu meist in Fusion360 modelliert worden. Zusätzlich werden Mechaniken anhand eines Prototyps erläutert.

CAD-Model des Roboters, enthält druckfertige Teile. Bitte Beschreibung beachten.


Einleitung


Wir haben uns vorgenommen, einen autonomen Roboter zu bauen, der grundsätzlich in der Lage ist, mithilfe eines Visuellen Inputs Gesichter in seinem Sichtfelds zu erkennen, sich mithilfe von Motoren oder Servos auf diese auszurichten, und dann mit einem Nerf-Pfeil darauf zu feuern. In der Ideenfindungsphase wollten wir den Roboter mobil machen, dies wurde allerdings verworfen und mit einem stationären Design ersetzt, ebenso wurde die geplante offizielle Nerf durch ein selbst designt und gebautes Model ersetzt. Eine Webcam ist auf dem Roboter installiert und mit einem Computer verbunden, der ein modifiziertes Gesichtserkennungsprogramm laufen lässt, dieses ist open source, links und weitere Details können am Ende dieses Abschnitts gefunden werden. Diese Gesichtserkennungssoftware überprüft das von der Webcam aufgenommene Bild mithilfe eines Face-Detection-Models der „Open Source Computer Vision Library“ auf Frontale Gesichter. Wird ein Gesicht erkannt, so berechnet die Software den Standort des Gesichts, so wie die Entfernung des Gesichtes von dem Mittelpunkt des Bildes. Über Serial-Kommunikation werden dann Daten an den Arduino geschickt, der aufgrund dieser Daten zwei Servo-Motoren so bewegt, dass sich die Kamera auf das Gesicht ausrichtet. Parallel läuft auf dem Arduino eine weitere Befehlsschleife, die ein mit Nerf Darts geladenes Magazin bewegt, und abschießt.

LINKS
Die Face Tracking Software die wir nutzen ist von einem Programmierer und YouTuber namens LittkeFrenchKev entwickelt worden, und basiert auf OpenSource Bibiliotheken. Die Software wurde leicht angepasst und modifiziert um für unsere Zwecke nutzbar zu sein. Die Website des Entwickler, das GitHub-Repo mit dem original Code sowie die Bibliotheken sind hier verlinkt, eine Analyse des Codes sowie mehr Informationen über unsere Modifikationen sind in diesem Abschnitt zu finden.

DISCLAIMER
Da fast alle Mitglieder der Gruppe, beschlossen haben den Kurs zu verlassen, konnte der Roboter leider nicht fertig gestellt werden. Zwar ist sowohl die Software, als auch die Arduino-Implementierung fast fertig programmiert, sowie die meisten Teile druckfertig, doch hat es am Ende an Zeit und Koordination gemangelt. Wir werden trotzdem alles, was fertig gestellt werden konnte hier präsentieren, und hoffen, dass ein Eindruck des Roboters vermittelt werden kann.


Umsetzung


Der Roboter besteht im Grunde aus vier Teilen: Einer Grundplatte, auf der sich der Rest des Roboters befindet, die für das horizontale schwenken verantwortlich ist. Der Halterung des Roboters, die auf der Grundplatte installiert ist und den Roboter vertikal kippen kann:
Hier nicht transparent Abb.1: CAD-Skizze des Frames und der Riemenverbindung zum Neigen der Gun

Der Trigger und die Magazine-Schiene, die das Schießen und Nachladen übernehmen: Das Magazin auf der Magazin-Schiene und der Trigger Abb.2: CAD-Model der Magazin-Mechanik

Und der Abschuss-Mechanismus, bestehen aus den Flywheels und der Kamera Halterung. Mehr zu den Flywheels hier Flywheels

Abb.3: Foto, geöffnete Flywheels eines N-Strike Elite Stockade Blasters

Der Roboter muss in der Lage sein, sich frei auf seinen Rotationsachsen bewegen zu können, weshalb das Entwerfen der Mechanik sowie der physischen Teile sehr viel Zeit in Anspruch nahm.

 Schaltplan mit Pushbutton und nMOS Der Arduino sorgt für einen konstanten Stromfluss im Breadboard, über das alle anderen Komponenten verkabelt sind. Der Microswitch wird hier durch einen normal Pushbutton dargestellt, wird aber auf die gleiche Art und Weise angeschlossen. Nur wenn der Knopf gedrückt wird, kann der Arduino einen Stromfluss am Pin 12 ablesen.
Die Flywheels, die im Grunde aus zwei zusammengelöteten DC-Motoren bestehen, sind mit ihrem Power-Kabel an die vom Arduino ausgegebenen 5V angeschlossen, und mit ihrem GND-Kabel an den nMOS. Dieser funktioniert als ein simples Logic-Gate: nur wenn der „Gate“-Pin des nMOS vom Arduino angesteuert wird, kann Strom zwischen dem „Source“ und „Drain“-Pin fließen und dadurch die Motoren an- und ausschalten.

Abb.4: Schaltplan zum Anschließen aller elektronischen Bestandteile an den Arduino


Einzelne Systembestandteile: Das Face Tracking

Der Grundbaustein des gesamten Roboters, auf dem seine gesamte funkionalität basiert, ist die Fähigkeit, Bilder auszuwerten und Gesichter zu erkennen. Über eine USB-Verbindung erhält der Computer die hochauflösende Bilder der Webcam, die sich mit dem Roboter bewegt. Die Software besteht aus mehreren Scripts, die parallel laufen und einander aufrufen. Zunächst wird das Bild in Graustufen umgewandelt, um das Face-Detection-Model mit dem verarbeiteten Bild zu füttern. Dieses Überprüft das Bild auf ein oder mehrere Gesichter, und gibt, falls welche gefunden werden, ihre Positionen wieder. Der Abstand der Bild-Mitte sowie des Gesichtes wird berechnet, und liegt dieser Abstand unter einem bestimmten Wert, so wird das Gesicht als getrackt verarbeitet.

Vid.1: Screenrecording, Program state check

Die Bewegungen der Servos sowie der Zustand des Roboters (searching, aiming, locked) werden dann berechnet, und als Datensatz an den Arduino gesandt. Da der Computer als einziges die Daten der Kamera erhält und verarbeitet, ist die fehlerlose Weiterleitung der interpretierten Daten an den Arduino der wichtigste Vorgang im gesamten Prozess. Dadurch ist die Kommunikation zwischen Arduino und Computer am anfälligsten für Errors, war eine der größten Herausforderungen im gesamten Bearbeitungsprozess, und läuft immer noch nicht völlig zuverlässig.

Einzelne Systembestandteile: Kommunikation zwischen Arduino und Computer

Diese Datensätze sehen ungefähr so aus:<XXX, YYY; Z> (Beispiel:<113, 90, 1>)
Hierbei stehen die ersten beiden Integer für die Winkel der Pan- bzw tilt-Servo-Motoren, und der letzte Wert für den „LED_state“, eine Variable die dem Arduino sagt in welchem Zustand der Roboter sich gerade befindet, ob er nach einem Ziel sucht, ein Gesicht gefunden hat und sich darauf ausrichtet, oder bereits Zielt. Dem Namen folgend werden auch die Indikator-LEDs von dieser Variable gesteuert.

Der Computer wartet dann auf eine Antwort des Arduino, bevor er das nächste Bild verarbeitet und den nächsten Datensatz schickt.

Einzelne Systembestandteile: Die Bewegung des Roboters

Der Roboter hat zwei unabhängig voneinander ansteuerbare Rotationsachsen, auf denen er sich in einem Bereich von etwa 10° bis 170° bewegen kann, abhängig von den Winkelgrenzen der eingesetzten Servo-Motoren.
Der für die horizontale Rotation verantwortliche pan-Motor ist der größten Belastung ausgesetzt, und befindet sich unterhalb des Roboters innerhalb der Grundplatte. Von dort aus treibt der Motor über ein simples Getriebe die Grundscheibe an. Durch genaues Drucken des Getriebes ist eine präzise Steuerung und eine hohe Kraftübertragung möglich.
Der tilt-Servo sitzt direkt auf der Grundplatte und steuert über einen Riemen die Neigung der Gun, und ist durch diesen Riemen verbunden mit einem Rahmen um den Hauptteil des Roboters. Dadurch kann der gesamt „Kopf“, bestehend aus dem Trigger, dem Magazin, den Flywheels und der Kamera ohne Probleme noch unten und oben gekippt werden. Um Kollision mit der Grundplatte zu vermeiden, sitzt der Kopf etwa 10cm über der Grundplatte, und erlaubt dadurch theoretisch eine volle Umdrehung.

Abb.5: Skizze, Frontansicht des Neigungsmechanismus mit Riemen

Einzelne Systembestandteile: Schießen und Nachladen

Der Roboter nutzt sogenannte „Flywheels“ um die Darts abzuschießen. Flywheels sind im Grunde zwei einander gegenüberliegende, gegensätzlich rotierende Scheiben. Die Darts werden von einem Trigger zwischen diese Scheiben geschoben, die durch ihre Geschwindigkeit und Reibung den Dart stark beschleunigen.
Die Darts werden in ein beliebig erweiterbares gedrucktes Magazin geladen. Dieses Magazin wird auf der Magazin-Schiene vor dem Trigger platziert, um dann vom Magazin-Servo Motor am Trigger entlang bewegt zu werden. Das Magazin verfügt über Erhöhungen auf der Oberseite, die einen Micro Switch, der direkt über dem Zentrum des Triggers angebracht ist, drücken. Sollte dieser Knopf gedrückt werden, so weiß der Arduino, dass das Magazin mit einer Kammer nun direkt zwischen dem Trigger und den Flywheels liegt, und sich nichts verkantet.

Der Trigger verfügt über Zähne auf einer Seite, wodurch die Rotationsbewegung des Trigger-Servos und des daran befestigten Zahnrads in eine lineare Bewegung umgesetzt werden. Der Trigger wird in das geladene Magazin geschoben, und drückt dadurch den Pfeil zwischen die Flywheels. Das Magazin wird dann weiterbewegt, bis die nächste Kammer ausgerichtet ist. Sollten alle Pfeile verschossen worden sein, so wird das Magazin automatisch ausgeworfen. Vid.2: Video, Flywheel Demonstration

Note: Der Arduino weiß tatsächlich nicht, ob überhaupt ein Magazin geladen ist, er reagiert einzig und allein auf die Aktivierung des Mikro Schalters. Ist das Ende des Magazins erreicht, so wird der Schalter nicht mehr gedrückt, und der Magazin-Servo schaltet sich nicht aus.

Einschub: Der Prototyp

Um den Code soweit zu testen wie möglich, wurde ein einfacher Prototyp aus Pappe entworfen. Dieser unterstützt zwei-Achsige Bewegung, und, in Verbindung mit einem Breadboard, auch beliebig viele andere Bestandteile.

Frontalansicht: 2 Servos und LEDs Aufsicht: 2 Servos und LEDs Nahaufnahme Neigung
Abb.6: Foto: Frontalansicht des Prototypens, Abb.7: Foto, Draufsicht des Prototypen, Abb.8: Foto, Nahaufnahme des Neigungsmechanimsus im Prototypen

Alles Videomaterial in dieser Dokumentation wurde mithilfe des Prototypen erfasst.


Technische Daten


Hardware:

Mikrocontroller

Wir nutzen einen Arduino Uno aus den Beständen des Labors.

Webcam

Eine HD-Webcam von Vinmoog ist mit dem Computer verbunden, auf dem die Face Tracking Software läuft. Die Daten der Kamera kommen nie in direkten Kontakt mit dem Arduino. Die Kamera ist auf dem Roboter direkt über dem Lauf fixiert.

"tilt-Servo" Servo Motor

Genutzt wird der DigitalReelay-S-5252-030-Servo Motor, ein positional-Servo mit einer Reichweite von etwa 10-170° aus dem Laborinventar.

"pan-Servo" Servo Motor

Um das volle Gewicht des zusammengebauten Roboters und aller Teile bewegen zu können, wurde ein stärkerer Servo Motor als im Labor vorhanden benötigt. Der Miuzei Digital Servo MS24 mit einem unterstützten Gewicht von bis zu 20kg wir deshalb zur Rotation des Roboters genutzt.

"trigger-Servo" Servo Motor

Um die Darts aus dem Magazin in die Flywheels zu bewegen, wird ein positional-micro-Servo genutzt, der leicht und klein genug ist um sehr einfach installiert zu werden. Dafür nutze ich einen SG92R-MicroServo aus dem Starterset.

"magazine-Servo" Servo Motor

Der Servo zum weiterbewegen des Magazins ist der einzige continuous-servo der im Roboter verbaut ist, das bedeutet, ein Servo-Motor der keine Winkel-Begrenzung hat sondern sich frei bewegen kann. Dafür nutze ich ebenfalls einen Micro-Servo um Platz zu sparen, und zwar einen MicroServo-9g-SG90.

Flywheels

Flywheels with open Cage Als Abschussmechanismus nutze ich die Flywheels sowie den sogenannten „Flywheel-Cage“ und den Lauf eines offiziellen N-Strike Elite Stockade-Blasters. Die Motoren sind neu verkabelt und mit dem Arduino verbunden, so dass sie durch einen nMos-MOSFET-Transistor angesteuert werden können, und dadurch mit bis zu 5V versorgt werden.
 Original Blaster

Abb.9: Foto, Geöffneter Flywheel-Cage

Abb.10: Screenshot, N-Strike Elite Stockade Blaster, Quelle der verbauten Flywheels

Limit Switch

Zum erkennen, ob das Magazin mit dem Trigger und Flywheels in Reihe ist, damit der Dart ohne das etwas klemmt abgeschossen werden kann, nutze ich einen KW-11-3Z-A-MicroSwitch. Dieser ist im Grunde ein hochempfindlicher Knopf, an dem ich mithilfe des Arduino ablesen kann, ob er gedrückt wird oder nicht.

Energieversorgung

Der Arduino wird von der Computer-Schnittstelle konstant mit 5 Volt versorgt. Durch den 5V-Pin des Arduinos ist es möglich, alle Bestandteile des Roboters ausreichend mit Strom zu versorgen.


Das Magazin

Das Magazin besteht aus einer 17mm hohen und 70mm dicken Platte, in die beliebig viele Kammern eingefügt werden können. Jede Kammer hat einen Durchmesser von 13mm, und eine Wanddicke in alle Richtungen von 2mm. Dadurch ergibt sich folgende Formel für die Länge des Magazins:
Formel zum berechnen der Länge des Magazins in mm Hier bei gibt „n“ die Anzahl der Kammern an, also die Kapazität des Magazins. Bei unserem fertig modelliertem Magazin handelt es sich um ein Magazin mit einer Kapazität von 11 Darts, also einer Länge von 167mm
Abb.11: Screenshot, Formel zum Berechnen der Länge des Magazins in Abhängigkeit von der Kapazität

Mittig über jeder Kammer befindet sich eine Erhöhung, die den MicroSwitch oberhalb des Triggers auslöst und so sicher geht, dass das Magazin zentral ausgerichtet ist.
Skizze und Berechnungen zur Größe der Zahnräder/Gear Racks. Das Magazin verfügt über zwei mittige Einschnitte an der Unterseite, die auf gleiche negative Schienen auf einer Magazin-Grundplatte angepasst sind. In dieser Grundplatte befinden sich zwei Zahnräder, die über eine eingebettete Achse mit dem Magazin-Servo-Motor verbunden sind, und über Zahnstangen (Gear Racks) an der Unterseite des Magazins dieses entlang des Triggers bewegen. Diese Zahnräder sind mit dem Abstand der Achse und der Gear Racks auf den Millimeter angepassst.
Das Entwickeln von Zahnrädern passend zu bereits gegebenen Umständen (wie z.B. Abstand der Achsen, also Durchmesser des Zahnrades) ist komplizierter als am Anfang angenommen, weshalb auch hier viel Zeit verloren ging. Am Beispiel des Magazinantriebs wird dieser Vorgang nun dargelegt.

Abb.12: Skizze, Zahnrad Schematik für Magazin


Ein paar wichtige Größen müssen vorher definiert werden. Damit zwei Zahnräder miteinander „meshen“ können, das Bedeutet, Problemlos ineinander greifen, müssen der Pitch Diameter, der Pressure Angle und das Module gleich sein, und sie müssen im Richtigen Abstand voneinander angebracht sein.

Link to image Der „Pitch Diameter“ ('PD'; Pitch Diamteter') ist der Durchmesser des Zahnrades, berechnet von der Mitte der Zähne, der sogenannte „Pitch Circle“. In diesem Fall liegt die Achse 13mm von dem Pitch Circle des Gear Racks entfernt. Dadurch lässt sich ein Pitch Diameter von 26mm berechnen.

PD = 26mm

Der „Pressure Angle“ (α; 'Alpha') bestimmt den Winkel der Zähne zueinander, ein geringer Pressure Angle sorgt für eine geringere Kraftübertragung im Austausch für mehr Präzision. Da es um nicht besonders viel Gewicht geht, wurde sich für einen Mittelwert von 20° Entschieden.

α = 20°

Das „Module“ (m; 'klein M') ist die Größe der Zähne, und ist das Verhältnis zwischen Pitch Diameter und der Anzahl der Zähne. Je geringer das Module, desto mehr Zähne sind benötigt, es gehen effiziente Kraftumsetzung verloren, damit die Zähne besser meshen und präziser gesteuert werden können. Deshalb haben wir uns für ein Module von 2 entschieden.

m = 2

Da wir mit zwei verschiedenen Arten von Zahnrädern arbeiten, hier mit einem sogenannten „Spur Gear“ und einem „Spur Rack“ brauchen wir mehrere verschiedene Formeln. Die Länge des Gearracks ist bereits bekannt: Abb.13: Webbild, Visualisierung der Zahnrad-Größen
Die Länge des Magazins, also 167mm.

Die Anzahl an Zähnen im GearRack Zrack lässt sich nun aus der Formel l=m*pi*Zrack berechnen (m=Module, l=Länge des Magazins), nach Umstellen der Formel erhalten wir Zrack~26.

Zrack = 26

Die Anzahl der Zähne des Zahnrads Zgear lässt sich aus dem Pitch Diameter und dem Module berechnen, mit der Formel Z=PD/m, also Zgear=26/2 = 13 .

Zgear = 13

Damit die Zähne ohne zu klemmen meshen können, muss es einen Backlash (b, 'klein B') geben, das bedeutet, die Zähne werden leicht verkleinert, so dass es immer ein bisschen Spielraum zwischen Zähnen gibt. Je kleiner der Backlash, desto präziser können sie gesteuert werden, allerdings vergrößert sich damit auch die Belastung der einzelnen Zähne. Da keine großen Kräfte oder hohe Geschwindigkeiten im Spiel sind, beträgt der Backlash hier 0.1mm, d.h. alle Zähne sind um 0.1mm kleiner.

b = 0.1mm

Die Dicke beider Teile muss ebenfalls gleich sein, spielt aber eigentlich keine Rolle. Wir nutzen eine Gear- und Rackdicke von 5mm.

Pin Belegung

Pin Name Zweck
d2 redLED aktiviert und deaktiviert die rote LED (LED 1 → kein Face detected)
d3 yellowLED aktiviert und deaktiviert die gelbe LED (LED 2 → face detected)
d4 greenLED aktiviert und deaktiviert die grüne LED (LED 3 → face locked)
d6 panServo steuert die horizontale Rotation des Roboters
d7 tiltServo Kontrolliert die Neigung der Gun
d8 triggerServo bewegt den Trigger um einen Dart in die Flywheels zu schieben
d9 magazineServo bewegt das Magazin weiter
d10 flywheelServo startet oder stoppt die Flywheels über einen nMOS
d12 contactPin verbunden mit dem MicroSwitch um Magazinausrichtung zu überprüfen

Tab.1: Tabelle zur Belegung der Digital Pins am Arduino UNO


Code und Software


Diese ZIP enthält den Python source-code, die Executable und den Arduino Code

Der gesamte Code ist ausgiebig kommentiert, das FaceTracking ist bereits im Abschnitt Einzelne Systembestandteile: Das Face Trackingerklärt, weshalb hier genauer auf den Arduino-Code eingegangen wird.

LFK_face_tracking

Die einzige nennenswerte Änderung des Codes, abgesehen von größtenteils gescheiterten Stabilisierungen, ist eine veränderung der Roaming-Logic, also wie der Roboter sich bewegt, wenn es gerade kein face zu tracken gibt.

Im originalen Code nutzt der Roboter random numbers, um sich auf beiden Achsen zufällig im definierten Bereich zu bewegen. Diese Logik wurde durch eine simplere Version ersetzt. Da der Roboter insgesamt deutlich schwerer ist als das Beispiel auf welches das Programm eigentlich zugeschnitten ist, waren Modifikationen von Nöten, so wurde der zufällige Neigungswinkel komplett entfernt und durch konstante 90° ersetzt, das bedeutet beim Roaming Vid.3: Video, Prototyp beim 'Roaming'
bleibt die Kamera bei einer neutralen, mittleren Neigung.

Arduino Code

Der originale Code bestand nur aus der Kommunikation zwischen Arduino und Computer, sowie der Steuerung zweier implementierter Servos, der pan- und tilt-Servos. Erweitert wurde dieser Code um eine Reihe an neuen Funktionen die den Rest des Roboters kontrollieren, wie vor allem die checkMagazine-Funktion, die das Abschießen der Darts übernimmt.

Der Arduino beginnt seine Funktion mit einer kurzen LED-Sequenz, und bewegt alle Servos in ihre Ausgangsposition.
Die loop, die danach ausgeführt wird, ist relativ simple:
Loop function des Arduino
Abb.14: Skizze, Aktivierungsdiagramm der Arduino loop()-funktion

Dieser Code Abschnitt ist einer der Herausfordernsten, nicht weil die Funktion an sich etwas komplexes tut, sondern weil sie auf einem schon existierenden Framework gebaut werden musste. Da das Programm auf Schleifendurchläufen basiert, musste eine etwas komplexere Lösung gefunden werden, weshalb mit states und der millis()-funktion gearbeitet werden muss.

Zum Anzeigen hier klicken ⇲

Zum Verstecken hier klicken ⇱

void trigger()  //bewegt den Trigger um die Darts in die Flywheels zu bewegen
{
  if (triggerState == 0)                                            //State 0: Funktion wird das erste mal von magazineCheck aufgerufen
  {                                                                   //Voraussetzung: Magazin ist ausgerichtet und ein Face ist gelocked
    triggerServo.write(180);                                        //bewegt den trigger Servo und schiebt damit den Trigger in das Magazin
    target_millis = current_millis+500;                             //es wird ein delay von 500ms festgelegt um sicherzugehen, dass der dart abgeschossen wurde
    triggerState = 1;                                               //initialisiert die nächste State für den nächsten loop-durchgang
  }
  else if (triggerState == 1 && current_millis > target_millis)     //State 1: Funktion wird das zweite (n-te) mal aufgerufen nur wenn der delay abgelaufen ist 
  {                                                                   //um sicher zu gehen dass der Trigger nicht klemmt wenn das Magazin sich weiterbewegt
    triggerServo.write(90);                                         //setzt den Trigger zurück in die 'primed'-position, bereit den nächsten dart zu schießen
    triggerState = 2;                                               //initialisiert den nächsten State für die nächsten loop-durchgänge
  }
  else if (triggerState == 2 && current_millis > target_millis+200) //State 2: erst wenn ein weiterer delay von 200ms vorbei ist damit man sicher gehen kann,
  {                                                                   //dass der Trigger das Magazin nicht vom weiterfahren blockiert
    magazineServo.write(100);                                       //Magazin-Servo wird gestartet
    triggerState = 0;                                               //da trigger() nur aufgerufen werden kann wenn das Magazin ausgerichtet ist, reicht es 
  }                                                                   //den State zurückzusetzten  
}

Instabilität und Crashes

Die größten Probleme mit der Software und dem Code stammen von der Kommunikation zwischen Arduino und dem Programm.

In der file comm_ard.py gibt es eine Funktion namens recvFromArduino(), die genau das tun soll: Daten vom Arduino empfangen, decoden und verarbeiten. Das Problem hier bei ist folgender Code Abschnitt:

...
 while msg.find("initiate programm") == -1:  #string.find("ard starting msg") return -1 if value not found
            print("waiting for ard msg")
            while self.ser.inWaiting() == 0:  #inWaiting() return number of bytes in buffer, equivalent of Serial.available in arduino
                pass
 
            msg = self.recvFromArduino()   #return decoded serial data line 35
...
 
def recvFromArduino(self):
...            
     while ord(x) != self.startMarker:         # ord() return utf-8 for a char(1 length string)  ex: return 60 for char <
                 x = self.ser.read()           # loop until start marker found

Gibt es nämlich einen Fehler beim Senden dieser Daten, und die Kommunikation wird corrupted, hängt das Programm in dieser Schleife fest und stürzt ab wenn der input buffer überfließt.
Man kann das beheben, indem man in beiden Programmen, dem Arduino und der Python-Software, besseres error-handling einbaut, zum Beispiel indem man einen timer setzt, den Buffer jeden durchlauf überprüft und cleart, oder ähnliches. Leider fehlt uns dazu die Zeit.
Korrupte Datensätze liegen vermutlich an überlasteten Anschlüssen und schlechter Verbindung meinerseits, da ich einen USB-Hub mit einem USBA-USBC-Adapter nutzen muss um sowohl Kamera als auch Arduino gleichzeitig anschließen zu können. Vid.4: Screenrecording, Crash-Ursache: Buffer Overflow aufgrund einer infinite Loop


Ein weiteres Beispiel für das crashen des Programmes aufgrund von korrupter Kommunikation lässt sich in der gleichen Funktion, nur ein paar Zeilen weiter finden:

        # save data until the end marker is found
        while ord(x) != self.endMarker:  # loop until end marker found
            if ord(x) != self.startMarker:  # if not start marker
                print("raw data: ",x)
            try:
                message_received = message_received + x.decode("utf-8")  # add decoded char to string
                byteCount += 1  # WHY IS BYTECOUNT FOR?
                x = self.ser.read()  # read next char
            except:
                print("error decoding data")
                x = self.ser.read()  #read next char, skipping bad one

Hier wartet das Programm auf den End-Marker, ist dieser jedoch korrupt und kann nicht gelesen werden, so werden die characters

\r
\n

ausgelesen. Das ist Data das das Programm nicht erwartet, und es kann damit nicht umgehen.
Wie das aussieht, sieht man in diesem Video: Vid.5: Screenrecording, Crash-Ursache: Korrupte Endmarker

Side note: Diese Characters werden vom Arduino automatisch am Ende jeder Nachricht hinzugefügt: Ein „carriage return“ \r der denCurser zurück zum Anfang der aktuellen line bewegt, und der „new line character“ \n, der eine neue Linie beginnt. Diese sind Teil der Serialen Kommunikation, sollten allerdings durch den End Marker '>', der davor versandt wird, nicht gelesen werden.


Ergebniss

Auch wenn der Roboter nicht fertig gestellt werden konnte, sind viele Teile bereits weit fortgeschritten. Es gibt ein fertiges Design mit vielen Druckfertigen Teilen, auch wenn hier noch viel Arbeit ansteht, vor allem was die Grundplatte angeht.

Der Code ist voll mit bugs und das Programm stürzt andauernd ab, doch die Ursachen für diese Instabilität sind bekannt und behebbar. Fast alle Teile sind bereits fertig programmiert, nur hier und da gibt es Teile die nur durch ausgiebiges Testen mit einem fertigen Modell verbesserbar sind, wie Bspw. die Verzögerung im Trigger.

Der Prototyp ist bereits in der Lage, viele Funktionen des Roboters zu simulieren, wie die Bewegung, die LEDs oder sogar die Bewegung der anderen Servo Motoren. Offensichtlich bestehen viele Ausbaumöglichkeiten, besonders in Fragen der Stabilität, aber mit der Menge an bereits fertig gestellten Teilaufgaben kann man nicht nur den Roboter beenden, sondern sogar erweitern, ihn Bspw. Mobil machen, Farben erkennen lassen, und vieles mehr. Das Framework das hier erarbeitet wurde muss zwar zunächst fertig gestellt werden, kann dann jedoch auf fast alles angepasst werden. Die Nerf kann durch Paintball, T-Shirts, Wasser ersetzt werden, das Face-Tracking durch Color-Tracking, die Möglichkeiten sind endlos.


projektewise24/projekt6/doku.txt · Zuletzt geändert: 2025/03/31 03:22 von uszer