Benutzer-Werkzeuge

Webseiten-Werkzeuge


Seitenleiste

projektesose2016:leonarduinopublic:start

Leonarduino da Vinci Projektdokumentation

Ein Projekt von und mit: Sergi Domenech Guzy, Laura Knorr, Julian Böll, Mathias Peljo, Robert Lemke, Anja Ilg

Einleitung

Der Leonarduino ist ein fahrender Mal-Roboter, der auf Asphalt oder ähnlichem Untergrund einen Schriftzug sprühen kann. Am Computer werden die Umrisse eines Schriftzuges mit hilfe der Geomerative library in Koordinaten umgewandelt und dann an den Leonarduino, entweder über WLan oder USB-Kabel übergeben oder direkt im Arduino code integriert. Der Leo kann diese Koordinaten abfahren und an den entsprechenden Stellen Farbe sprühen. Der Sprühmechanismus besteht aus einem Drucksprühgerät mit einem 5-Liter-Tank und einem Schlauch mit einer Düse am Ende.


Überblick über das Gesamtsystem

Wir haben uns in drei Untergruppen aufgeteilt mit jeweils eigenen Aufgaben. Die Motoransteuerung Gruppe (Robert, Julian, Mathias), zuständig für die Ansteuerung der Motoren und Räder, die Programmier Gruppe (Sergi) die sich mit dem Umwandeln des Schriftzuges in Koordinaten und das Übertragen an den Arduino befasst hat, und die Sprühmechanismus Gruppe (Laura, Anja) welche sich mit dem Sprühgerät, der Farbe und der Ansteuerung und Montage des Geräts auf dem Roboter beschäftigt hat.

Als wir das Projekt begannen, hatten wir zuerst noch vor Bilder und Funktionsgraphen zu malen. Ausserdem wollten wir mit mehreren Farben und durch Rasterung malen. Wir haben uns aber entschieden diese Sachen weg zu lassen da sie den Rahmen des Projekts sprengen würden.


Beschreibung von Details der einzelnen Systembestandteile

Datenaufarbeitung und -berechnung

Zum einen wurden verschiedene Methoden zur Berechnung von Punkten ausprobiert. Eine Option war das Rastern von Bildern oder Graphen in einzelne “Pixel”, die aber vorerst komplett weggelassen wurde.

Als ersten Versuch habe ich einfache mathematische Funktionen genommen und in einer ArrayList die aufsteigenden x-Werte bis zum Ende des vorgegeben Definitionsbereichs, sowie die jeweils zugehörigen Funktionswerte gespeichert. Diese ArrayList wurde dann durchiteriert und es wurde zwischen einem Punkt und dem darauf folgenden eine Linie eingezeichnet, sodass am ende der Funktionsgraph entstanden ist. Im Beispiel wurde eine Sinusfunktion und eine quadratische Funktion eingefügt und ausgegeben.

Das Implementieren neuer Funktionen war aber relativ umständlich auf diese Weise, denn es musste immer ein neues Objekt der Klasse Funktion erstellt werden, das dann in die ArrayList der Klasse Picture hinzugefügt wurde und es musste eine eigene calcValue() Methode geschrieben werden. Außerdem wären Buchstaben nur durch viele Funktionen mit kleinen Definitionsbereichen darstellbar gewesen. Da es sehr umständlich gewesen wäre für jeden Buchstaben immer viele neue Funktionen zu implementieren habe ich diese Methode irgendwann nicht weiter bearbeitet.

Für Interessierte hier der alte, umständliche und nicht weiter bearbeitete Code um Funktionen darzustellen. leonarduino_processing_code_function.zip

Deshalb dann der Umstieg auf Geomerative, eine Library für Processing, mit der Einschränkung vorerst nur Buchstaben darzustellen. Mit dieser Library konnte der Umriss eines beliebigen Strings in einem bestimmten Font erzeugt werden. Dieser Umriss konnte dann in einzelne Punkte auf dem Umriss umgewandelt werden. Diese Punkte hatten sowohl eine x-Koordinate als auch eine y-Koordinate und konnten so direkt ausgegeben werden. Durch diese Punkte konnten dann die Buchstaben dargestellt werden, indem Linien zwischen ihnen eingezeichnet wurden.

Hier war ein Problem jedoch, dass von Geomerative viele sinnlose Punkte ausgegeben wurden, die für den Umriss des Buchstaben nicht benötigt wurden. Auf Geraden werden nur der erste und letzte Punkt benötigt um sie vollständig darzustellen, alle Punkte dazwischen sind nur unnötig gespeicherte Werte. Dieses Problem hätte direkt durch Geomerative gelöst werden können, indem der Punkteabstand auf dynamisch gestellt worden wäre. So hätte Geomerative direkt nur dann Punkte ausgegeben wenn die Änderung des Winkels einen bestimmten Wert überschreitet. Das diese Möglichkeit besteht war mir aber nicht klar, also musste das Problem durch einen eigenen Algorithmus gelöst werden, der unwichtige Punkte herausfiltert und löscht. Dabei mussten verschiedene Eigenschaften der Punkte überprüft werden, wie im folgenden Pseudocode dargestellt.

Im Beispiel wurde der Umriss von P erstellt, daraus die Punkte ermittelt und dann die unwichtigen gelöscht. Als Vergleich zuerst der Buchstabe ohne gelöschte Punkte und ohne Linien, dann der Buchstabe mit unwichtigen Punkten gelöscht, und dann zwischen den wichtigen Punkten Linien eingezeichnet. Bei allen drei Versionen wurde der gleiche Punktabstand verwendet, damit man sie möglichst gut vergleichen kann. Man kann gut erkennen, dass trotz der gelöschten Punkte der Umriss immer noch gut darstellbar ist und das löschen den Buchstaben nicht kaputt macht.

Übertragung

Ein weiteres Problem war die Übertragung der berechneten Daten auf den Arduino. Auch hier gab es mehrere Möglichkeiten zur Realisierung.

Eine Variante, die auch funktioniert hat, war das Übertragen der Daten per WLan über ein sogenanntes WiFly Modul für den Arduino. Das Modul musste ein Mal für ein bestimmtes Netzwerk eingerichtet werden und dann waren Daten zu IP-Adresse und Port auf dem WiFly gespeichert. Die Einrichtung des Netzwerkes und den Aufbau der Kommunikation habe ich mit von Felix bereitgestelltem Code zum laufen gebracht. Zur Übertragung mussten sich der Laptop und der Arduino dann nur noch im gleichen Netzwerk befinden und die IP-Adresse und den Port des anderen kennen. So konnte ich die in Processing berechneten und in Strings umgewandelten Werte byteweise über das Netzwerk verschicken.

  void transmit(float xVal, float yVal, char spray)    // Diese Methode gibt die an sie uebergebenen Daten ueber das Netzwerk an den Server, in diesem Fall den Arduino, weiter.
  {
    String xCo = Float.toString(xVal);                 // Der uebergebene x Wert wird von float in einen String umgewandelt, da Strings Byteweise ueber das Netzwerk geschickt werden koennen.
    String yCo = Float.toString(yVal);                 // Ebenso mit dem y Wert.
 
    try                                                // Uebergabe des Characters spray und der x und y Werte als String Byteweise über das Netzwerk an den Arduino und dazwischen jeweils ein B (in ASCII) als Character fuer break.
    {
      outToServer.writeChar(spray);                    // Uebergabe des Characters spray, der angibt ob auf dem Weg zum folgenden Punkt gesprueht werden soll oder nicht.
      outToServer.writeChar(66);                       // Uebergabe des Characters B (in ASCII) fuer break, um dem Arduino zu signalisieren, dass der aktuelle String (oder Character) zu Ende ist und gespeichert werden kann.
      outToServer.writeBytes(xCo);                     // Uebergabe des aktuellen x und y Wertes und dazwischen und zum Schluss jeweils wieder ein B (in ASCII).
      outToServer.writeChar(66);
      outToServer.writeBytes(yCo);
      outToServer.writeChar(66);
    }
    catch(Exception e)
    {
      println("Transmit. " + e);                       // Bei Fehlern soll die Exception ausgegeben werden und das Programm nicht abgebrochen werden (durch try-catch Block).
    }
  }

Auf dem Arduino mussten die Bytes dann nur bis zu einem festgelegten Zeichen gelesen werden und als String abgespeichert werden. Diese konnten dann in den jeweiligen Datentyp umgewandelt und dann verarbeitet werden. Hier war das Problem, dass wir im Einsatz draußen nicht immer ein WLan Netzwerk zur Verfügung haben und uns die Zeit für genügend Tests auch im Außenbetrieb ausgegangen ist.

Eine weitere Variante war die Daten über den SerialPort des Arduino zu schicken und auszulesen und zu speichern. Diese Variante funktionierte auch lokal in Tests, jedoch hat sich der Speicher des Arduino beim Trennen vom PC resettet und die übertragenen Daten waren nicht mehr gespeichert. Das war der Grund weshalb wir diese Methode nicht weiter nutzen konnten.

Aus Zeitgründen sind wir letztendlich dazu übergegangen die Werte einfach direkt in den Arduino Code zu integrieren und bei neuen Werten den Code zu verändern und neu auf den Arduino zu laden. Diese Methode ist zwar relativ umständlich und nicht sehr anwenderfreundlich, jedoch war es die einzige Möglichkeit in den letzten Tagen überhaupt noch zu einem sinnvollen Ergebnis zu kommen.


Sprühmechanismus

Das Gerät

Der Leonarduino besitzt einen Sprühmechanismus der aus einem 5 liter Tank und einem Schlauch mit einer Düse besteht. Das Gerät sollte nicht zu teuer sein und eine große Füllmenge haben so dass auch grossflächig gesprüht werden kann. Wir haben uns für ein Drucksprühgerät entschieden, welches diese Ansprüche erfüllt. Ausserdem ist es möglich das Gerät nicht nur mit Wasser sondern auch mit verdünnter Farbe zu befüllen was für einen Mal-roboter natürlich wichtig ist. Die Ansteuerung auf dem Roboter funktioniert mit hilfe eines Servos. Dem Arduino wird übergeben wann gesprüht werden soll. Der Servo ist am Griff vom Sprühgerät angebracht und wenn gesprüht werden soll, bewegt sich dieser und der Griff wird runtergedrückt.

Die Farbe

Die Farbe muss auch ein paar Voraussetzungen erfüllen. Da der Roboter draußen benutzt werden soll, ist eine umweltfreundliche und leicht zu säubernde Farbe wichtig. Ausserdem muss sie wasserlöslich und ungefähr die Viskosität von Wasser haben damit sie auch in unserem Drucksprühgerat benutzt werden kann. Wir haben uns für Kinder Bastelfarbe entschieden da diese sehr verdünnbar ist, trotzdem sehr pigmentiert bleibt und ausserdem nicht giftig ist.

Tests

Mit dem Leonarduino ist es möglich mit Wasser und mit Farbe zu sprühen. Um herauszufinden wie sich beides mit dem Gerät verhält, wurden verschiedene Tests durchgeführt. Es wurden Füllmenge, Sprühstärke, Sprühabstand und Sprühbreit überprüft. Wir haben zuerst mehrere Sprühtests mit Wasser von verschiedenen Höhen gemacht um zu sehen wie sich die Sprühbreite und der Sprühkegel verändert.

Ausserdem haben wir das Gerät mit verdünnter Farbe ausprobiert.

Dabei haben wir herausgefunden dass die Sprühbreite mit Farbe deutlich kleiner ist und wir dementsprechend den Abstand anpassen müssen. Wir haben ausserdem die Farbe ausprobiert um zu sehen wie gut sie deckt, ob sie einfach zu entfernen ist und wie lange sie hällt. Mit der dunkel blauen Farbe hat es sowohl auf Papier als auch auf dem Boden sehr gut funktioniert. Die Farbe ist leider nicht so leicht zu entfernen wie wir anfangs erhofft haben, aber nachdem es ein paar mal ordentlich geregnet hat, ist die Farbe auch wieder verschwunden.


Konstruktion und Gehäuse

Materialliste

(siehe hiezu ggf vorliegende Bilder des Roboters)

  • Arduino nano + Breadboard
  • Drucksprühgerät 5 Liter, 3 Bar („Gloria Spray and Paint“)
  • Holzplatte (mitteldichte Holzfaserplatte)
  • Metal Gearmotor 37Dx54L mm + 64 CPR Encoder (50:1) mit Plastikfelge und Gummireifen x2
  • Bewegliches „Standrad“
  • Servomotor zum Ansteuern des Sprühmechanismus
  • Akku
  • Lego als Grundlage eines Wasserdichten Gehäuses für die Elektronik
Aufbau und was wir uns dabei gedacht haben

Ziel der allgemeinen Konstruktion war es einerseits, die physikalischen Belastungen auf unseren Roboter gering zu halten (hauptsächlich das (Massen)trägheitsmoment, auch Luiftwiderstand), andererseits (und auch daraus folgend) die Gesamtmasse des Systems gering zu halten. Dazu musste beachtet werden, dass allein der volle Farbbehälter mindestens 5 kg wiegt und nahezu 50 cm lang ist, weshalb das Gehäuse durchaus groß wurde und die wirkenden physikalischen Kräfte durchaus betrachtet werden müssen. Hinter der vorliegenden Konstruktion liegen folgende Überlegungen:

  • Die Grundplatte so nah wie möglich an den Boden zu bringen, um das Trägheitsmoment zu verringern
  • Rotationsachse und Schwerpunktsachse nahe aneinander zu legen
  • Den C_w-Wert zu reduzieren, indem der Farbbehälter horizontal und nicht vertikal angeordnet ist (Natürlich treten bei den angestrebten Fahrgeschwindigkeiten nur vernachlässigbare Luftreibungskräfte auf, unsere Befürchtungen waren eher Windböen im Gelände (zB Tempelhofer Feld)
  • Regen und Spritzwasserschutz der Elektronik durch Verkabelung an der Gehäuseunterseite und einem Lego-Gehäuse für den Arduino
  • Herabsenken des Gesamtgewichts des Roboters, um die „kleinen“ Getriebemotoren nicht zu überlasten

Insgesamt liesen sich die Ideen realisieren, allerdings war die Verwendung einer MDF-Platte unklug, da diese im Gegensatz zu anderen gängigen Materialien (Kunststoff, Sperrholz) ein hohes Gewicht besitzt.

Motoransteuerung und Nachregelung

Motoransteuerung und Nachregelung

Die Motoransteuerung hat die Aufgabe, die Motoren des Roboters so zu betreiben, dass eine vorgegebene Vektorgrafik mit einer gleichmäßigen Geschwindigkeit abgefahren wird. Dazu ist eine ständige Nachregelung der Motoren nötig: Deren Ziel ist es, dass der Roboter in zeitlich engen Intervallen sein jeweiliges Ziel (Koordinatenpunkt) neu anpeilt, indem er dessen Ort sowie seine eigenen Polarkoorinaten (Ort, Richtung) kennt. So lässt sich vermeiden, dass der Roboter (zB zufällig durch eine Inhomogenität am Boden) seinen Kurs ändert und sich so die Abweichung vom Ziel für jeden angefahren Koordinatenpunkt immer stärker ändert. Dazu ist der an den Motoren angebrachte CPR-Encoder essenziell: Mit diesem lässt sich die jeweilige Geschwindigkeit der Motoren stets bestimmen und dokumentieren. Damit kann einerseits stets auf eine konstante Geschwindigkeit geregelt werden mit der der Roboter fährt (sonst würde zB der Roboter langsamer fahren, wenn er über eine leichte Anhöhung fährt), andereseits lässt sich mit der Kenntnis, wie oft sich die beiden Räder in welche Richtung gedreht haben, die momentane Richtung des Leonarduinos bestimmen. Dieses Schema ist in der nachfolgenden Abbildung skizziert Der CPR-Encoder besteht im Grunde aus einer mitrotierenden, inhomogenen Metallscheibe (diese besitzt eine diskrete Anzahl an Schlitzen) am Motor, deren Umdrehungen von einem Hallsensor erfasst werden. Dadurch kann aus dessen Signal die Anzahl der effektiven Radumdrehungen (also hinter dem Getriebe) in einem Zeitintervall ausgerechnet werden. In der vorliegenden Abbildung erkennt man hierzu links die Hardware des Encoders und rechts ein effektives Beispielsignal.

Zielanpeilung

Nachfolgend wird schematisch skizziert, wie der Roboter sein Ziel anpeilt, beziehungsweise dementsprechend seine Geschwindigkeit und/oder Rotation ändert. Dazu ist natürlich die Kenntnis seiner eigenen Koordinaten sowie derer des Ziels zwingend erforderlich. Aus seinem eigenen Richtungsvektor ® und dem Zielvektor (z) (siehe Skizze) wird der Winkel, sowie die orthogonale Projektion gebildet. Daraus ergeben sich für den Roboter zwei Geschwindigkeiten: Eine Rotationsgeschwindigkeit (v_dreh), mit der sich dieser in dir Richtung des Ziels dreht, sowie eine Vorwärtsgeschwindigkeit (v_vor) mit der in die aktuelle Richtung gefahren wird. die Gesamtgeschwindigkeit ergibt sich aus der Addition der beiden Teilgeschwindigkeiten. v_vor berechnet sich aus dem Zielvektor mal der orthogonalen Projektion des Richtungsvektors darauf, als v_dreh wird der Winkel mal einen orthogonalen Einheitsvektor auf den Richtungsvektor verwendet. Daraus resultiert folgendes Schema: Ist der Richtungsvektor stark vom Zeilvektor verschieden, so ist der Winkel dazwischen Groß und die orthogonale Projektion klein, also dreht sich der Roboter schnell, während er langsam nach vorne fährt. Stimmen die Vektoren hingegen nahezu überein, dreht sich der Roboter nur sehr langsam, während er schneller nach vorne fährt.

Ergebnis und Diskussion

Das Ziel von unserem Projekt war es einen Roboter zu bauen, welcher Vektorgrafiken in Form von Koordinaten übergeben bekommt und diese Grafik flüssiger Farbe auf den Boden sprühen kann. Dies wurde bisher teilweise erreicht: Der Leonarduino kann die vorgegebenen Punkten anpeilen, dorthin fahren und seine Geschwindigkeit und Postion dabei nachregeln und regulieren. Das Gehäuse/ die Konstruktion hierzu ist soweit fertig. Der Sprühmechanismus ist fertig automatisiert und einsatzbereit.

Problemfelder bei der Entwicklung des Leonarduinos bestanden in der Übertragung der Koordinaten an den Arduino sowie beim Nachregeln der Position während dem Fahren. Zu Details hierzu, siehe die jeweiligen Unterpunkte der Dokumentation. Dadurch war es bisher noch nicht möglich, ausgiebige Tests und „Outdoor“- Erprobungen mit der Leonarduino zu fahren, und diese entsprechend wissenschaftlich zu dokumentieren.

Der eigentliche, makroskopische Aufbau des Roboters wurde relativ zügig fertig gestellt. Da wir uns in einzelne Gruppen aufgeteilt hatten, konnten wir von Anfang an auch alle Aufgaben bearbeiten. Wir hatten genügend Zeit mehrere Tests mit dem Sprühgerät durchzuführen und uns eine gute Montage und Ansteuerung auf dem Roboter zu überlegen.

Insgesamt ist zum Hergang der Roboterentwicklung zu sagen, dass mehr Zeit ins Schreiben und Testen der Software gesteckt werden hätte müssen, als in den Aufbau eines sehr guten Gehäuses. So hätten wir früher die gesteckten Ziele erreichen, und eine Perfektionierung der Konstruktion hinten anstellen können. Es bleibt jedoch zu sagen, dass wir ambitionierte Ziele hatten/haben, und deren Realisierung und Erfüllung innerhalb unserer divergenten Gruppe unter Eigenregie relativ gut funktioniert hat. Auch wurden oft die Themenbereiche und Aufgaben der jeweiligen Gruppenmitglieder geändert, es wurde miteinander gearbeitet, und jeder konnte dort helfen wo sie/er Lust hatte. Dennoch liegt vor allem noch in Schnittstellen, zB zwischen Datenübertragung und -verarbeitung Arbeitsbedarf. Auch wenn wir in den nächsten Wochen noch zusammenarbeiten werden und die gesteckten Ziele noch erreichen wollen, denken wir dass wir innerhalb des Zeitfensters von einem Semester die Möglichkeiten und Potentiale unseres Roboters nicht vollständig ausreizen können. Wir würden uns daher freuen wenn unser Roboter im Zuge des Projektlabors weiterleben würde, und sich zB eine Nachfolgegruppe findet, die diesen weiterentwickelt, verbessert und ggf neue Aufgabenbereiche erschließt: LET 'EM SPRAY!


Code Dateien

Finaler Code für das Programm, um Strings in Processing mit Hilfe der Geomerative Library darzustellen, die unwichtige Punkte herauszunehmen und die wichtigen Werte auszugeben. (Geomerative Library wird benötigt)

Finaler Code für die Ansteuerung und Regelung des Motors.

Abschlusspräsentation

projektesose2016/leonarduinopublic/start.txt · Zuletzt geändert: 2016/10/27 14:15 von c.jaedicke