Benutzer-Werkzeuge

Webseiten-Werkzeuge


Seitenleiste

projekte2014:schnaps-runden-roboter:projektdokumentation:hauptseite

Projektdokumentation - Nessie der Shot-Roboter

Hauptseite

Themenbeschreibung und Überblick

Nessie ist ein Roboter, der fahren, einer schwarzen Linie auf einem weißen Untergrund folgen, Shotgläser rechts dieser Linie erkennen und diese mit einer im integrierten Tank befindlichen Flüssigkeit befüllen kann.

Als Plattform dient eine einfache Holzplatte. Der Antrieb erfolgt duch zwei jeweils motorisierte Vorderräder, hinten ist ein drehbar gelagertes Stützrad angebracht. Die Linienerkennung ist duch zwei Phototransistoren zur Unterscheidung heller und dunkler Oberflächen sowie einer LED zur gleichmäßigen Ausleuchtung des zu erkennenden Untergrunds realisiert. Zur Glaserkennung wird ein Sonar genutzt, das vor dem rechten Vorderrad angebracht ist. Befüllt werden die Shotgläser über einen schwenk- und senkbaren Arm, der hinten am Roboter angebracht ist, an welchem entlang ein Schlauch vom Tank zum Ende des Arms führt. Der Tank ist eine einfache Tupper-Dose, die erhöht auf der Hauptplattform angebracht ist. Zur Dosierung wird der Schlauch durch einen Servo abgekniffen, bzw. geöffnet. Außerdem wird durch zwei Elektroden am Ende des Arms erkannt, wenn das Shotglas voll ist. Gesteuert wird der Roboter durch einen Arduino Nano V3.0, zur Stromversorgung des gesamten Systems dienen acht AA-Batterien ein Reihe.

Wir gehen davon aus, dass sich auf der Strecke des Roboters keine Hindernisse befinden und alle Shotgläser zur Rechten der Strecke in Abständen zwischen 2cm und 18cm aufgestellt sind.

Nessie

 Die Navigations-Einheit Um die Navigation möglichst einfach zu realisieren, haben wir uns für einen simplen Linienfolger entschieden. Um einer schwarzen Linie auf einem weißen Untergrund zu folgen, benötigen wir zwei Phototransistoren, die orthogonal zur Linie angebracht sind. Verlässt einer der Transistoren dann die Linie, wissen wir, dass in die entgegengesetzte Richtung gelenkt werden muss. Verlassen beide die Linie, muss in die Richtung gelenkt werden, in welcher die Linie zuletzt verlassen wurde.

Um den Untergrund gleichmäßig auszuleuchten, haben wir zwischen den beiden Transistoren eine LED angebracht. Um die Transistoren und die LED voneinander zu trennen und zu gewährleisten, dass ausschließlich der Untergrund, nicht die Umgebungshelleigkeit, gemessen wird, haben wir alle drei getrennt in einen Holzblock eingelassen. Angebracht ist die Konstruktion so, dass die Transistoren und die LED im Abstand von etwa 1-2cm über dem Untergrund befinden.

In unserer Umsetzung kann sich Nessie über mehrere Schritte hinweg daran erinnern, in welche Richtung gelenkt werden muss. Das ist besonders dann wichtig, wenn ungeachtet der Linie für mehrere Schritte geradeaus gefahren werden muss. Das ist u.a. immer dann der Fall, wenn ein Glas ausgemessen oder zur Befüllung zu ihm vorgefahren wird.

Die Phototransistoren geben Werte zwischen 0 und 1024 aus und wir haben durch Messungen mit dem fertigen Aufbau einen Schwellenwert gefunden, unter welchem die Phototransistoren bleibt, wenn er sich über der schwarzen Linie befindet und welchen er definitiv überschreitet, wenn er sich über dem weißen Tisch befindet.

Die Stepper-Motoren

Für den Antrieb haben wir uns für zwei Stepper-Motoren entschieden, weil wir mit diesen eine präzise Steuerung und Messung der zurückgelegten Entfernung realisieren können. Stepper-Motoren bewegen sich schrittweise, wobei die Schrittlänge von der Schrittzahl des Steppers sowie dem Durchmesser der angebauten Räder abhängt. Wir haben uns für Stepper mit 200 Schritten (Sprich: Eine Rotation um 360° entspricht 200 Schritten) und Räder mit 90mm Durchmesser entschieden. Um konstante Bewegung durchzuführen müssen nur mehrere Schritte in kurzer Zeit ausgeführt werden.

Um die Schrittlänge zu berechnen, muss man erst den Umfang der Räder berechnen - in unserem Fall also 90mm $\cdot$ $\pi$ ≈ 282,743mm

Diesen teilt man durch die Schrittzahl und erhält so die Länge eines einzelnen Schrittes - bei uns 282,743mm/200 ≈ 1,414mm

Stepper-Motoren lassen sich mit Hilfe von Stepper-Treibern ansteuern. Das sind Controller, die sehr simple Impulse von einem Arduino in Bewegungsimpulse für die Stepper-Motoren übersetzen und den Strom der Stromquelle auf für den Stepper verträgliche Werte begrenzen. Wir haben uns für zwei Pololu A4988 Treiber entschieden, die wir auf einem vorgefertigten Carrier inklusive Kühlung für den kleinen Chip über amazon erwerben konnten.

Diese Pololus werden wie folgt in der Schaltung untergebracht:

Quelle: Pololu.com

Zu Beachten ist, dass bei Nutzung eines Arduinos als „Logic Power Supply“ direkt der 5V Pin sowie einer der Ground-Pins des Arduino genutzt werden können. Damit lassen sich die Pololus direkt durch den Arduino mit Energie versorgen. Nun schliesst man noch jeweils einen digitalen Pin des Arduino an DIR und STEP und kann so den Stepper steuern. Die 1A, 1B und 2A, 2B Pins müssen so mit Spulen im Stepper verbunden werden, dass 1X und 2X jeweils mit einer Spule verbunden sind.

Die Pololus erlauben auch durch die Pins Sleep, Reset und Enable die Stromversorgung der Stepper zu kontrollieren und z.B. zu unterbrechen, etwa um Strom zu sparen, in unserer Implementation ist das aber unnötig, daher werden Sleep und Reset verbunden (wenn Reset schwebt, bewegt sich der Stepper nicht) und Enable ignoriert.

Außerdem erlauben die Pins MS1, MS2 und MS3 Teil-Schritte zwischen Halb- und 16tel-Schritte zu machen. Teil-Schritte zu benutzen kann die Beweung sanfter machen und Problemen mit Schlupf entgegenwirken. Wir nutzen Halb-Schritte und haben entsprechend der Tabelle auf der Produkt-Seite den Pin MS1 mit der 5V-Bahn des Arduino verbunden.

Um mit den Pololus Stepper-Motoren nutzen zu können muss außerdem über das Potentiometer auf der Platine die Stromstärke begrenzt werden. Alles Nötige dazu lässt sich ebenfalls auf der Produkt-Seite unter „Current limiting“ finden.

Die Augen - Die Erkennung des Glases

Die Registrierung eines Glases haben wir durch ein Sonar realisiert. Dieses ist an der rechten Seite vor dem Arm angebracht. Durch eine Verlängerung, befindet es sich sogar vor der Grundplatte und somit dem restlichen Roboter.

Durch die Verlängerung wird das Sonar auch etwas tiefer angebracht als beispielsweise der Arm. Das hat den einfachen Zweck, das Sonar auf eine Höhe mit den Gläsern zu bringen.

Ein Sonar sendet Schallwellen aus, welche von Objekten reflektiert werden. Diese Reflexionen nimmt das Sonar dann wieder auf.

In diesem Bild sehen wir, dass das Sonar Objekte in einem Winkel von 30° erkennt. Es wird aber immer das gemessen, welches am nächsten dran steht (rote Linie). Das Sonar misst dabei die Zeit ab Absenden der Schallwelle bis sie wieder zurückkehrt. Mit Hilfe der Schallgeschwindigkeit (29 ms/cm) können wir diese Dauer in ein Längenmaß umrechnen. Das ganze hat eine Reichweite von 2 cm bis 4,5 m. In diesem Artikel wird das Sonor etwas ausführlicher erklärt.

Wir bemerken, dass wir aufgrund der Sonareigenschaften die Setting-Annahme treffen, dass keine weiteren Gegenstände (außer der Gläser) in der Nähe stehen. Schließlich kann das Sonar nicht erkennen, was genau vor ihm steht.

Was macht jetzt also unser Roboter? Bisher folgt er einer Linie. Dabei wird bei jedem Schritt das Sonar gefragt, ob es denn ein Objekt in der Nähe gefunden hat. Dabei machen wir immer mehrere Messungen und bilden einen Mittelwert, um Messungenauigkeiten zu verringern. Wenn nun aber nichts in der Nähe steht, kann das ganz schön lange dauern, ehe die Schallwellen zurück kommen. Um dem ein wenig Abhilfe zu verschaffen, ist unser Sonar nicht ganz parallel zum Boden angebracht, sodass spätestens ab 50 cm der Boden gemessen wird. Als nächstes wollen wir ein Glas erkennen, dazu haben wir uns zwei Ansätze überlegt.

Version 1

Wenn das Glas in den Messbereich kommt, fangen wir an die Schritte zu zählen, die wir brauchen, um an dem Glas vorbeizufahren (diese Variable nennen wir später length). Dabei fahren wir nur gerade aus und „ignorieren“ die Linie zunächst, um später zu ihr zurückzukehren.

Währenddessen misst das Sonar den Abstand zum Glas und wir suchen uns das Minimum aus allen Messungen. Dies sollte uns den Wert geben, wie er links im Bild zu sehen ist. Diesen Wert nennen wir später distance.

Sowohl Messen als auch Zählen enden, wenn das Glas den Messbereich verlässt. Damit wir später vom Mittelpunkt des Glases aus rechnen können, addieren wir zu den Schritten noch den Radius des Glases, also length = length+radiusGlas.

Version 2

Sobald ein Glas in den Messbereich kommt, messen wir einen Abstand $s$, welcher als Mantellinie eines Kegels betrachtet werden kann.

Es ist möglich, aus der Mantellinie $s$ und dem Öffnungswinkel des Kegels $\alpha =30°$ den Abstand $r$ (da es der Radius eines Kegels ist) zu berechnen, mit welchem wir das Glas in die Mitte schieben.

Bezeichnen wir mit $h$ die Höhe des Kegels, so kennen wir die Formeln

$$s = \sqrt{h^2+r^2} \text{ und }$$ $$r= h\cdot\tan\left(\frac{\alpha}{2}\right)$$

aus der Geometrie. Durch umstellen erhalten wir

$$r= \sqrt{\tan\left(\frac{\alpha}{2}\right)^2s^2\left(1+\tan\left(\frac{\alpha}{2}\right)^2\right)^{-1}} =\tan\left(\frac{\alpha}{2}\right)\cdot s\cdot\left(\sqrt{1+\tan\left(\frac{\alpha}{2}\right)^2}\right)^{-1} .$$

Wir fahren nun die Strecke $r+radiusGlas$ ab, damit wir die Mitte des Glases treffen. Hier messen wir nun den Abstand des Glases zum Roboter (später nennen wir diese Variable distance).

Schließlich wollen wir noch auf ein Problem des Sonars hinweisen. Das Sonar ist sehr genau in seinen Messungen, solange das Objekt genau vor ihm steht. Betrachten wir aber Objekte am Rand des Messbereiches, so passieren manchmal kuriose Sachen. Beispielsweise wird ein Objekt abwechselnd erkannt und wieder nicht erkannt. Für unser Vorhaben ist das etwas problematisch, deshalb misst das Sonar nur bei jedem 3. Schritt, damit dieser Rand nicht genau getroffen wird. Weiter spielt auch die Beschaffenheit des Objektes eine Rolle. Das liegt daran, dass die Schallwellen am Objekt reflektiert werden. Bei geraden Objekten werden Schallwellen viel präziser zurückgeworfen, bei runden ist es leider etwas schwieriger, wie es scheint. Ideal wären also eckige Gläser.

Bei Version 1 tritt dieses Problem mindestens zweimal auf, wenn das Glas den Messbereich betritt und wenn es diesen verlässt. Deshalb haben wir uns die zweite Version überlegt, welche das Problem nur einmal beim Betreten des Messbereiches haben sollte. Hier benötigen wir aber genau diese problematische Messung um damit weiter zu rechnen. Diese Messungenauigkeit können wir aber ausgleichen (sie Abschnitt Realisierung im Code). In Variante 1 findet sich die Messungenauigkeit aber auch in der Variable length wieder. Ein weiterer Vorteil der Version ist die nicht durchgängige, sonder nur einmalige, Messung des Sonars in der Mitte. So kann Nessie flüssig längere Strecken fahren. Dadurch entstehen weniger Vibrationen, als bei Version 1, da Nessie hier alle 3 Schritte neu anfahren muss. In der Praxis bewirken diese Vibrationen, dass der Arm sehr wackelt und dadurch die Servos einen Absturz des Gesamtsystems verursachen. Welche Version nun besser ist, können wir nicht wirklich nachweisen. Aber wir haben uns am Ende für Version 2 entschieden. Zum einen haben wir nur einmal das Randproblem und zum anderen stürzen die Arm-Servos nicht ab.

Der Arm - Bewegung zum Glas


Zunächst zum Aufbau. Wir haben ein langes Stück Holz an der rechten Seite unseres Roboters angebracht. Dieses besitzt zwei „Gelenke“. Als Arm soll es sich drehen, sowie heben und senken können. Diese Bewegungsmöglichkeiten erschaffen wir durch zwei verschraubte Servos.

Der untere Servo kann den Arm somit drehen und der obere Servo kann ihn heben und senken. Des Weiteren ist auf dem Arm der Schlauch befestigt, welcher die Flüssigkeit transportiert. Damit diese nicht so leicht aus dem Schlauch tropfen kann, ist der Arm angehoben.



Nun schauen wir uns weiter den Arbeitsverlauf an. Zur Erinnerung, der Roboter ist an einer Linie entlang gefahren und hat ein Glas gefunden. Wir wissen außerdem, wie weit entfernt es steht (diese Variable nennen wir distance). Wir befinden uns nun also in folgender Situation:

Das nächste Ziel ist es, die Armspitze mit dem Schlauchende zum Glas zu bewegen. Dazu werden wir den Arm drehen, also auf einer Kreisbahn bewegen. Um das Glas dadurch treffen zu können, muss das Glas selbst auf der Kreisbahn stehen. Das erreichen wir, indem wir ein gewisses Stück vorwärts fahren (diese Variable nennen wir h). Bildlich sieht das ganze nun so aus:

Mathematisch lässt sich h nun mittels des Satz des Pythagoras ermitteln. Betrachten wir dazu ein Bild im Koordinatensystem mit allen bekannten Variablen:

$$h= sonardistance - \sqrt{armlength^2-distance^2}.$$

Dabei bezeichnet den die Variablen armlength und sonardistance den jeweiligen Abstand zum Mittelpunkt der Servokonstruktion.

Wir sind jetzt soweit, dass das Glas auf der Kreisbahn steht. Nun müssen wir den Arm um den richtigen Winkel drehen:

Für $\alpha$ liefert uns die Geometrie hier folgende Formel

$$\alpha = \arcsin\left(\frac{distance}{armlength}\right).$$

Damit können wir unserem Roboter den Befehl geben, die Strecke h zu fahren und den Arm mithilfe des unteren Sonars um $\alpha$ zu drehen. Um den Schlauch zum Glas zu führen, senken wir den Arm um einen genormten Wert. Dies realisieren wir über den oberen Servo. Letztlich kann das Glas gefüllt werden.

Die Dosierung - wie das Getränk in das Glas kommt

Oben auf dem Roboter ist ein kleiner Tank in Form einer Tupper-Dose angebracht, in welchen das Getränk eingefüllt wird. An diesen Tank ist unten durch einen Stopfen ein Schlauch angebracht, durch welchen die Flüssigkeit vom Tank zum Ende des Arms transportiert wird. Um den Fluss stoppen zu können ist dazwischen noch ein Ventil angebracht. Außerdem ein Sensor, der erkennt, wenn das Glas voll ist.

Der Tank

 Die Innenseite des Tanks  Der Tank im geschlossenen Zustand Da wir keine Dose die nach unten Spitz oder zumindest rund zuläuft (um die Flüssigkeit bis zum letzten Tropfen in den Schlauch fließen zu lassen) finden konnten, haben wir eine rechteckige, flache Dose mit einer Frischhalte-Tüte so präpariert, dass sie steile Wände hat, die zur Schlauch-Öffnung zulaufen. Dazu haben wir die Tüte am oberen Rand mit Heißkleber und unten am Stöpsel mit Silikon festgeklebt. An der Unterseite führt der Schlauch zur dem Arm gegenüberliegenden Seite.


Das Ventil

Statt einer Pumpe oder einem klassischen Ventil haben wir uns aus Kostengründen dazu entschieden, den Schlauch mit einem Servo abzuknicken, um den Fluss des Getränks zu unterbrechen. Dazu haben wir den Servo hinten an Nessie angebracht, wo der Schlauch vom Tank aus zur Rückseite kommt. Dort wird er dann vom Servo so gezogen, dass er an der Ecke der Rückwand umknickt und sich schließt. Das lässt sich auf den folgenden Bildern gut erkennen.

Das Ventil im geöffneten Zustand
 Ventil geöffnet
Das Ventil im geschlossenen Zustand
 Ventil geschlossen

Der Füllstands-Sensor

 Der Füllstands-Sensor erkennt ein volles Glas  Die Elektroden des Füllstands-Sensors Um zu erkennen ob das Glas voll ist, haben wir am Ende des Arms neben dem Schlauch zwei Elektroden angebracht. Eine ist direkt mit dem 5V-Pin des Arduino verbunden, die andere über einen Spannungsteiler mit einem analogen Eingang des Arduino. Durch den Spannungsteiler schwebt der analoge Eingang nicht, gibt also bis an der Elektrode eine Spannung anliegt nur den Wert Null aus. Da das Ende des Arms bis in das Glas gesenkt wird, erreicht die Flüssigkeit die Elektroden bevor es überläuft und wir erkennen, dass es nun voll ist.

Ist das Glas voll, wird das Ventil wieder geschlossen und dann der Arm angehoben.




Details der Gesamt-Konstruktion

Die Kombination aller Komponenten

Die Schokoladenseite
 Die Schokoladenseite
Die Vorderseite
Die Vorderseite
Die Rückseite
Die Rückseite
Einfach nur die Seite
Die Seite

Die Stromversorgung

Um Kosten zu sparen haben wir uns für eine Stromversorgung durch AA-Batterien entschieden. Da die von uns genutzten Pololus mindestens 8V benötigen, nutzen wir einen Batteriehalter der acht AA-Batterien in Reihe hält, wodurch die Spannung der einzelnen Batterien (ca. 1.2V) auf ca 9,6V addiert wird. Damit lässt sich auch der Arduino Nano direkt versorgen, da dies genau in der empfohlenen Input-Spannung von 7-12 Volt liegt.

Der Schaltplan

Statt eines Schaltplans haben wir das Gesamtsystem in Fritzing abgebildet, sodass jeder unser Breadboard exakt nachbilden kann. Außerdem lässt sich damit auch ein vollständiger Schaltplan generieren. Die Fritzing-Datei kann hier heruntergeladen werden.

 Steckplan des Gesamtsystems

Die Teile-Liste

Gesamtliste der verwendeten Teile

Wurde zur besseren Übersichtlichkeit auf eine eigene Seite verbannt.

Realisierung im Code

Zustandsautomat

Für das Programm benutzen wir das Konzept eines sogenannten Zustandsautomaten. Kurz bedeutet dies, dass der Roboter sich in verschiedenen Stadien befinden kann und je nachdem unterschiedliche Aufgaben erfüllt. Sehen wir uns das an unserem konkreten Beispiel an.

Sobald Nessie mit Strom versorgt wird, befindet sie sich im Standby-Modus. Deshalb nennen wir diesen Zustand standby. Bevor sie loslegt, muss zunächst ein Knopf gedrückt werden. Wenn dies geschieht, wechselt sie in den Zustand follow. Hier folgt Nessie der Linie und fragt das Sonar, ob es etwas gefunden hat. Sobald das Sonar ein Glas erkannt hat (das bedeutet das Glas befindet sich im Messbereich), wechselt der Roboter in den Zustand found. Wir merken uns also mittels der Zustände, was vorher bereits passiert ist und können uns so einige Abfragen sparen. Im Zustand found ermitteln wir nun die Distanz zum Glas. Mit dieser Information wechselt Nessie in den Zustand fill. Hier wird das Glas gefüllt, d.h. der Arm wird ausgefahren und das Ventil geöffnet. Sobald das Glas voll ist, gibt die Füllstandserkennung ein Signal aus. Nach diesem wird das Ventil wieder geschlossen und der Arm wieder in Ausgangsposition gebracht. Nessie geht in den Zustand follow zurück und sucht das nächste Glas.



Klassen

Des Weiteren ist unser Code objektorientiert. Das bedeutet, dass wir nicht alles in eine Datei geschrieben haben, sondern gewisse Vorgänge in Klassen ausgelagert haben.
Wir benutzen zwei ausgelagerte Klassen. Eine für die Fahrbewegungen und eine für die Servobewegungen. Die erste Klasse nennen wir Driver.h. Ein Objekt dieser Klasse besteht aus zwei Steppermotoren für den Antrieb und zwei Phototransitoren für die Linienfolgung. Die Klasse erlaubt uns sowohl einer Linie zu folgen, als auch nur geradeaus zu fahren. Dabei merkt sich das Objekt driver jedoch immer in welche Richtung sich die Linie befindet, selbst wenn wir sie verlassen. Dieses „Merken“ realisieren wir wieder über 3 Zustände, straight, right und left.
Die Klasse Filler.h kümmert sich nun um die Servobewegungen. Wie der Name schon sagt, geht es hierbei um das Füllen eines Glases. D.h. der Arm wird richtig ausgerichtet, das Ventil geöffnet und der Füllstand im Glas gemessen. Schließlich gibt es noch die Dateien types.h und typesDriver.h, welche die Zustände für die Hauptdatei NessieMain.ino und die Klasse Driver.h enthalten. Grundsätzlich müssen diese nicht ausgelagert werden. Leider kommt der Compiler damit aber nicht ganz klar. Er liest den Code nicht linear und ist somit der Meinung, dass die Zustände nicht definiert sind. Durch das Auslagern umgehen wir dieses Problem. Bei weiterem Interesse siehe hier.

Theorie ist nicht gleich Realität

In den vorangegangenen Abschnitten wurden einige Rechnungen vorgestellt, welche zur Lösung des Problems beitragen. Diese Rechnungen benutzen Daten, die aus der Umgebung gewonnen werden (z.B. gibt uns das Sonar die Glasdistanz). Diese Daten stimmen jedoch nicht hundertprozentig. Deswegen haben wir zahlreiche Fehlergrößen eingebaut. Beispielsweise suchen wir ein Glas nur alle 5 Schritte. Deshalb geben wir der gemessenen Mantellinie s immer 2.5 Schrittlängen hinzu (siehe Abschnitt Die Augen - Die Erkennung des Glases). Auch die von uns berechnete Restdistanz wird von den Motoren nicht vollständig gefahren, daher erhöhen wir diese etwas. Dabei erhöhen wir sie abhängig davon, wie weit das Glas entfernt steht. Ist es näher an Nessie, so müssen wir weniger korrigieren. Ist es weiter weg müssen wir schon an die 5 cm drauf packen. Diese Werte haben wir durch Versuche, ermittelt. D.h. wir haben Werte geschätzt, es ausprobiert und geguckt, ob wir die Werte verringern oder vergrößern sollten. In der gleichen Art und Weise sind wir auch mit dem Drehwinkel $\alpha$ vorgegangen. Dabei war das Problem, dass man dem Servo zwar präzise Gradzahlen übermittelt, diese aber nur sehr unpräzise umgesetzt werden - die von uns verwendeten Servos schaffen z.B. bei weitem keine vollen 180°, akzeptieren als Eingabe aber dennoch Werte zwischen 0 und 180°. Daher werden die an den Dreh-Servo übermittelten Werte im Code speziell für diesen Servo mit Werten korrigiert, die wir durch wiederholte Versuche gefunden haben. Die Anzahl der Versuche war dabei recht gering und wir haben auch keine Daten aufgenommen. Die Anpassungswerte könnten also sicherlich noch optimiert werden. Sie funktionieren aber für unsere Zwecke gut genug.

Messreihe zur Differenz zwischen der an die Motoren übertragenen und tatsächlich gefahrenen Strecke

Um die Fehlerquelle für das Problem der zu kurzen zurückgelegten Strecke eingrenzen zu können, haben wir eine Reihe von Tests gemacht. Wir haben die Korrektur der Streckenlänge deaktiviert und mit verschiedenen Glas-Distanzen und Ausgaben über die Serielle Schnittstelle sowie manueller Überprüfung mit einem Zollstock eine Reihe von Werten aufgenommen:

Geplante Strecke Tatsächlich gefahrene Delta
10,3 8,1 2,2
11,1 8,3 2,8
14,9 11,3 3,6
15,9 12,5 3,4
18,6 14,4 4,2
19,8 15,1 4,7

Die geplante Strecke entsprach in jedem Fall mit relativ geringen Abweichungen der Strecke, die zum Treffen des Glases zurückzulegen war. Dies legt entweder einen Fehler bei der Umrechnung zwischen Strecke und Schrittzahl Nahe, hier haben wir aber keinen Fehler finden können, oder einen Fehler bei der Ansteuerung der Steppermotoren. Auch hier haben wir im Code keinen Fehler ausmachen können. Für unsere Zwecke hat eine Korrektur der zurückzulegenden Strecke über ein Mapping den Fehler jedoch ausreichend gut ausgleichen können.

Link zum Code

Die aktuellste Version des Codes ist hier zu finden.


Pinliste

Bauelement Pin
Startknopf A3
linker Stepper Schritt 3
linker Stepper Richtung 2
rechter Stepper Schritt 9
rechter Stepper Richtung 7
Sonar Ausgang 12
Sonar Eingang A4
Dreh-Servo 6
Senk-Servo 4
Ventil-Servo 5
Arduino-LED 13
linker Phototransistor A6
rechter Phototransistor A7
ElektrodeA5

Ergebnis und Diskussion

Nessie kann auf einem weißen Untergrund einer schwarzen Linie folgen. Wenn Nessie die Linie verlässt, kann sie zu dieser zurück finden. Auf der Strecke dürfen sich keine Hindernisse befinden, da Nessie diese nicht erkennt. Die Gläser können nur rechts von Nessie stehen und das in einem Abstand von 2-18 cm. Weiter dürfen die Gläser nicht zu nah aneinander stehen, da sonst ein Glas doppelt gefunden werden kann bzw. ein anderes zu spät und die Messschritte nicht mehr zusammen passen. Werden diese Vorgaben erfüllt, so findet Nessie die Gläser, fährt ein Stück, dreht den Arm im richtigen Winkel, senkt ihn und trifft so das Glas. Dann öffnet sich das Ventil und die Flüssigkeit gelangt über den Schlauch in das Glas. Die Elektroden an den Seiten des Schlauches erkennen die Flüssigkeit und das Ventil schließt sich wieder und der Arm kehrt in seine Ausgangsposition zurück. Danach kann Nessie sich dem nächsten Glas widmen, und das solange bis der Strom abgeschaltet wird.

In einem eingeschränkten Setting erfüllt Nessie also alle von uns gestellten Anforderungen.

Natürlich gibt es noch viele Verbesserungsmöglichkeiten. Das fängt mit dem Grundgerüst an. Nessie ist in unserer Version etwas sperrig und groß geworden, da haben wir uns etwas verschätzt. Weiter ist die Tank-Schlauch-Verbindung nicht komplett abgedichtet. Aber unsere Elektronik ist so angebracht, dass die Flüssigkeit sie nicht erreichen kann. Dafür haben wir unter anderem einen Deckel auf dem Tank. Dadurch sieht man aber auch nicht wann der Tank leer ist. Hier wäre also eine Tankanzeige noch von Nutzen.
Die Fortbewegung im follow-Modus ist derzeit noch relativ langsam, da alle fünf Schritte nach einem Glas gesucht wird. Hier ließe sich der Code z.B. dahingehend optimieren, dass im follow-Modus das Sonar immer nur einen Ping statt der aktuellen Zehn aussenden könnte, da hier die Präzision nicht so wichtig ist.

Am Ende sind wir mit der Wahl eines Sonars als Glaserkennungsinstrument auch etwas unzufrieden. Im nachhinein würden wir das Sonar z.B. schwenkbar machen und somit viel genauer die Mantellinie bestimmen. Oder ein anderes Instrument wählen, wie z.B. einen Infrarotsensor. Generell kann man dies aber noch viel weiter treiben. Anfänglich hatten wir auch die Idee, die Gläser mit Transmittern auszustatten. So hätte Nessie Gläser von anderen Gegenständen differenzieren können. Über beispielsweise eine Kamera hätte Nessie sogar ohne Linie zu einem Glas finden können. Andererseits wirkt das in unseren Augen etwas übertrieben. Selbst mit unserem aktuellen Setting kann Nessie sehr gut auf einem Bartisch entlangfahren und Shotgläser nachfüllen. Hier müsste sie nur noch lernen zu wenden. Außerdem sollte sie aber etwas schneller werden. Das Abknicken als Ventil funktioniert so gut, dass auch beim Öffnen der Schlauch eingeknickt bleibt und nur minimal Durchfluss erlaubt. Unsere Ventillösung ist also billig, aber doch nicht ganz ideal.

Letztlich funktionieren sowohl Code als auch Bauteile gut zusammen und erfüllen ihre Aufgaben.

projekte2014/schnaps-runden-roboter/projektdokumentation/hauptseite.txt · Zuletzt geändert: 2016/01/21 12:45 (Externe Bearbeitung)