====== 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. {{ :projekte2014:schnaps-runden-roboter:projektdokumentation:img_2747.jpg?600 |Nessie}} \\ \\ ==== Navigation - der Linienfolger ==== {{:projekte2014:schnaps-runden-roboter:projektdokumentation:img_2714.jpg?300 | 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: {{ :projekte2014:schnaps-runden-roboter:projektdokumentation:pololu_a4988_schaltplan.png? |}} Quelle: [[http://www.pololu.com/product/1182|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 [[http://www.pololu.com/product/1182|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 [[http://www.pololu.com/product/1182|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. {{ :projekte2014:schnaps-runden-roboter:projektdokumentation:img_2751.jpg?400 |}} 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. {{ :projekte2014:schnaps-runden-roboter:projektdokumentation:sonar.png?400 |}} 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. [[http://www.generationrobots.com/de/content/65-ultraschallsensoren-für-kollisionvermeidung|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** {{ :projekte2014:schnaps-runden-roboter:projektdokumentation:sonarglas.png?300 |}} 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. \\ {{:projekte2014:schnaps-runden-roboter:projektdokumentation:sonarglas2.png?300 |}} 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. {{ :projekte2014:schnaps-runden-roboter:projektdokumentation:sonarglasrechnung1.png?400 |}} 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. {{ :projekte2014:schnaps-runden-roboter:projektdokumentation:sonarglasrechnung2.png?400 |}} 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//). {{ :projekte2014:schnaps-runden-roboter:projektdokumentation:sonarglasrechnung3.png?400 |}} 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 ==== {{:projekte2014:schnaps-runden-roboter:projektdokumentation:img_2769.jpg?300 | }} 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: {{ :projekte2014:schnaps-runden-roboter:projektdokumentation:armV2-1.png?500 |}} 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: {{ :projekte2014:schnaps-runden-roboter:projektdokumentation:armV2-2.png?500 |}} Mathematisch lässt sich //h// nun mittels des Satz des Pythagoras ermitteln. Betrachten wir dazu ein Bild im Koordinatensystem mit allen bekannten Variablen: {{ :projekte2014:schnaps-runden-roboter:projektdokumentation:armV2-3.png?500 |}} $$h= sonardistance - \sqrt{armlength^2-distance^2}.$$ Dabei bezeichnet den die Variablen //armlength// und //sonardistance// den jeweiligen Abstand zum Mittelpunkt der Servokonstruktion. {{ :projekte2014:schnaps-runden-roboter:projektdokumentation:img_2747-beschriftet.jpg?600 |}} Wir sind jetzt soweit, dass das Glas auf der Kreisbahn steht. Nun müssen wir den Arm um den richtigen Winkel drehen: {{ :projekte2014:schnaps-runden-roboter:projektdokumentation:arm4.png?500 |}} 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 === {{ :projekte2014:schnaps-runden-roboter:projektdokumentation:img_2774.jpg?100| Die Innenseite des Tanks}} {{ :projekte2014:schnaps-runden-roboter:projektdokumentation:img_2772.jpg?100| 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.