====== Dokumentation ======
\\
=====Einleitung=====
Der Kartograph ist ein Roboter, welcher die Aufgabe hat eine Karte von einem geschlossenen Raum, in dem er sich befindet, zu erstellen.
Um das zu erreichen, fährt er durch diesen Raum und scannt mit Hilfe von Infrarotsensoren die Wände ab. Damit auch wir seine Messergebnisse verstehen, werden diese anschließend mittels einer zwei-dimensionale Karte dargestellt, in der die Wände und Objekte des Raums eingezeichnet sind. Alle nicht benötigten Bauteile haben wir von “[[projektews1415:malokal|Malokal]]” abgebaut, bis wir nur noch die Grundplatte, die Räder und die Motoren hatten, da diese in ihrem Aufbau schon unseren Vorstellungen entsprachen.
\\
\\
=====Konstruktion=====
{{ :projektesose18:kartograph:karto-uebersicht.png |}}
Übersicht der einzelnen Roboter-Komponenten
====Aufbau====
Folgende Teile haben wir für den Kartographen verwendet:
^ Name ^ Anzahl ^
|Grundplatte mit 3 Rädern| 1 |
|Arduino Nano| 1 |
|A4988 Stepper Motor Driver Carrier| 2 |
|Kabel+Steckdosen| |
|(4) Stepper Motor (Bipolar)| 2 |
|8V Batterie | 1 |
|Batterie Wächter| 1 |
|Infrarotsensor | 3 |
**Tabelle 1:** Übersicht Bauteile
Welche in folgender Art angeordnet sind:
{{ :projektesose18:kartograph:fullsketch.png |}}
Bildquelle: [[https://www.pololu.com/product/2476]]
Bei den drei verwendeten Infrarotsensoren handelt es sich um das Produkt “GP2Y0A60SZLF” von Sharp. Dabei werden die Ergebnisse analog ausgegeben, können also der Spannung entnommen werden. Der einigermaßen zuverlässige Messbereich reicht von 10 cm bis zu 150 cm.
===Anschluss des Sensors===
Die Anschlüsse des Sensors sind hier die vier Löcher. Damit die Anschlüsse an ein Steckbrett montiert werden können, wird eine 4er-Reihe von 2,45 mm dicken und rechtwinkligen “header pins” (rechts in der Abbildung) angeschlossen, welche mit den Sensoren mitgeliefert wurden. Diese werden an den Sensor gelötet, aufgrund der besseren Stabilität und der Leitfähigkeit. \\
\\
Die Sensoren könnten somit direkt in ein Steckbrett gesteckt werden. Allerdings sollen diese mit Kabeln an das Brett angeschlossen werden, weil die Sensoren so am Brett angebracht sind, dass die “header pins” nach oben gerichtet sind. (Das in der Abbildung größere Loch auf der linken Seite haben dient zur Montage des Sensors an das Brett mit einer Schraube und dazu passenden Mutter.) Wir haben sogenannte “Steckdosen” verwendet, die vier Kabel fassen
{{:projektesose18:kartograph:sharpdistsensor_mit_abschluessen.jpg?550}}
__Die einzelnen Anschlüsse:__ \\
{{:projektesose18:kartograph:sharpdistsensor.jpg?300 |}} \\
Outputs des Sensors
EN (nicht verwendet): Ein sogenannter “Enable Pin”; Funktion irrelevant. \\
**OUT** (rotes Kabel): Output der Spannung, bzw. der Messergebnisse \\
**VCC** (braunes/gelbes Kabel): 5-Volt-Anschluss, bzw. Spannungsquelle \\
**GND** (schwarzes Kabel): Ground-Anschluss \\
\\
Bildquelle: [[https://www.pololu.com/product/2476]]
\\
====Motoren====
Der Kartograph bewegt sich mittels zweier bipolarer Stepper-Motoren fort. Ein Stepper-Motor läuft, wie der Name schon andeutet, nicht stetig, sondern in vielen kleinen Steps bzw. Schritten. Die Größe des Winkels eines Steps ist fest vorgegeben. Unser Motor braucht z.B. 28 Steps, damit das mit ihm verbundene Rad 1cm zurücklegt.
{{ :projektesose18:kartograph:img_20180703_163904.jpg?200 |}}
Nahansicht Motor
\\
Eine Schwierigkeit der wir begegneten war, dass die Motoren nicht beide gleichzeitig laufen konnten, da sie mit nur einem Arduino verbunden waren und dieser unterschiedliche Prozesse nicht parallel ausführen kann.
Gelöst wurde dieses Problem dadurch, dass sich die beiden Räder nun in sehr kleinen Zeitabständen abwechselnd bewegen.
Für den Kartographen ist aber nicht nur wichtig, dass er sich fortbewegen, sondern auch, dass er sich drehen kann. Um eine bessere Flexibilität zu erreichen, haben wir uns entschieden, dass der Kartographen sich auf der Stelle dreht. Das heißt, dass sich die Räder “gleichzeitig” in entgegengesetzte Richtungen bewegen.
Die Grundplatte hat einen Durchmesser von 30cm. Das heißt der Umfang beträgt 94cm. Da das Rad mit 28 Steps 1 cm zurücklegt, braucht es z.B. für eine Viertelumdrehung, 23.5 cm, 658 Steps pro Motor.
\\
Der Motor ist über einen Treiber mit dem Arduino verbunden. Das geschieht auf folgende Weise:
{{ :projektesose18:kartograph:f2227348-6ff3-4c40-a5c2-d1ebb71171ef.jpeg |}}
Verbindung vom Arduino und Treiber
Bildquelle:[[https://www.pololu.com/product/1182]]
\\
\\
=====Ausgabe der Sensor-Messergebnisse=====
Um die Messwerte des Sensors in Arduino zu erhalten, wird die “SharpDistSensor”-Bibliothek benötigt. Diese muss manuell in Arduino installiert werden (//“Sketch”// → //“Bibliothek einbinden”// → //“Bibliotheken verwalten”// → Bibliothek suchen und installieren). Anschließend muss diese mit einem “include”-Befehl im Code eingebunden werden.
Die Bibliothek kann [[https://github.com/DrGFreeman/SharpDistSensor|hier]] eingesehen werden. Dabei sind unter “examples” mehrere Beispielcodes.
#include //Einbinden der SharpDistSensor-Bibliothek
const byte sensorPin = A0; //Angabe des analogen Pins
const byte medianFilterWindowSize = 5; //je höher, desto geringer das "Messrauschen" (odd number, 1 = no filtering)???
SharpDistSensor sensor(sensorPin, medianFilterWindowSize); //Objekt der SharpDistSensor-Klasse instanziieren
void setup() {
Serial.begin(9600);
}
void loop() {
sensor.getDist(); //Ausgabe der Messwerte
}
====Auswertung der Messergebnisse====
Als Messergebnis geben die Sensoren einen Wert zurück, welcher jedoch weder die Distanz in einer uns bekannten Einheit ist (z.B. Meter), noch sich proportional zu einer solchen Einheit verhält.
Deswegen haben wir mit jedem Sensor 10 feste Abstände gemessen und protokolliert, welche Werte er uns gab.
Im Abstand von je 10 Zentimetern erhielten wir für den linken Sensor z.B.:
^Abstand (cm)^Wert^
| 10 | 74 |
| 20 | 162 |
| 30 | 256 |
| 40 | 357 |
| 50 | 416 |
| 60 | 475 |
| 70 | 524 |
| 80 | 558 |
| 90 | 585 |
| 100 | 607 |
Tabelle 2: Zuordnung der Messwerte zu ihren Abständen
Diese Werte gaben wir bei Excel ein. Mittels der „Trendline hinzufügen“-Funktion, gab und Excel eine Kurve und Funktion, welche das Verhältnis vom Abstand zum Wert auf 1cm genau beschrieben.
{{ :projektesose18:kartograph:wertexy.png |}}
graphische Darstellung der Zurodnung der Messwerte zu ihren Abständen
Für den linken Sensor war die Funktion dann die Folgende:
y = 1E-05x2 + 0,0032x + 0,939
\\
Der gemessene Wert ist dabei der x-, und der Abstand der y-Wert.
Jeder Sensor gibt bei der Messung unterschiedliche Werte aus. Also muss für jeden Sensor individuell eine Umrechnungsfunktion entwickelt werden. \\
Das gleiche haben wir dann auch für die anderen 2 Sensoren gemacht und bekamen für den vorderen Sensor y = 0,1099x + 2,2006. Den rechten Sensor haben wir aufgeteilt. Bis 40cm lautet sie y= 0,1099x + 2,5828 und danach y=0,1953125x- 34,97656.
\\
Als Code sieht die Umrechnung folgendermaßen aus:
void updateSensors() {
double temp = sensorLeft.getDist(); //Distanz des linken Sensors ermitteln
sensorLeftData = (pow(10, -5) * pow(temp, 2) + 0.0032 * temp + 0.939) * 10;
}
\\
\\
====Verwendung der Daten in Processing====
Processing visualisiert die Messergebnisse, die der Roboter an das Programm schickt.
{{ :projektesose18:kartograph:screenshot_1_.png |}}
Messung eines Gegenstandes mit Ausgabe in Processing
===Funktionsweise===
Während der Roboter in der echten Welt fährt, wird in Processing währenddessen der Vorgang aufgezeichnet. Der Roboter in Processing ist ein Kreis. An diesem befinden sich die drei Infrarotsensoren jeweils als Linie dargestellt. Diese zeichnen die Messergebnisse auf.
===Größenverhältnisse===
In Processing müssen die Größenverhältnisse von Roboter und Messergebnissen stimmen, damit keine große Verfälschung der Messung aufgezeichnet wird.
Ein Zentimeter in der realen Welt ist so groß wie ein Pixel auf dem Bildschirm. Der Roboter hat einen Durchmesser von ca. 30cm. Somit hat die size-Variable (Zeile 12), welche die Höhe und Breite der Ellipse (also des Kreises) bestimmt, auch den Wert 30. \\
\\
Bei der Messung gehen wir davon aus, dass der Messbereich auf den Bildschirm in Processing passt. Falls das nicht der Fall ist, so ist es möglich die
Größe des Fenster in Processing über die Variablen "xWindow" und "yWindow" anzupassen. Stattdessen kann mit der "faktor"-Variable das gesamte Messbild verkleinert werden.
===Position des Roboters===
Der Roboter bewegt sich über Positionsupdates in Processing. Dazu werden die X- und Y-Koordinaten aus dem Datenpaket entnommen (enthalten in s[2] und s[3]; Datenpaket siehe "Beispiel für Konsolenausgabe des Arduino (Datenpaket)" in [[https://www.mintgruen.tu-berlin.de/robotikWiki/doku.php?id=projektesose18:kartograph:doku#kommunikation_zwischen_arduino_und_processing|Kommunikation zwischen Arduino und Processing]]).\\
In Arduino beginnt das Koordinatensystem bei 0, 0. Wenn also die Koordinaten direkt übernommen werden würden, so wäre der Roboter am Rand. Um diesen etwas mehr in das Fenster in Processing zu setzen, werden die Variablen xStart und yStart verwendet. Diese werden je nach Situation auf die Variablen xKoord und yKoord addiert oder subtrahiert. Wenn z.B. der Roboter im Fenster in Processing von unten links starten soll und dann ein Rechteck oben rechts abfahren wird, so ist es sinnvoll xStart mit xKoord zu addierten, da der Roboter sich nach rechts bewegt. Bei der Y-Posititon würde allerdings bei Addition der Variablen yStart und yKoord der Roboter nach unten aus dem Fenster fahren. Daher sollte in dem yKoord von yStart abgezogen werden. (ein erklärendes Bild könnte hier eingefügt werden, falls das zu trocken erklärt ist)
Dies geschieht in der move()-Methode:
xPos = xStart + xKoord * faktor;
yPos = yStart - yKoord * faktor;
Die Variable faktor dient dazu, die Größe der Darstellung innerhalb des Fensters zu skalieren. Z.B. ist bei einem geringeren Faktor der Roboter (Kreis), die Infrarotsensoren (Linien) und der zurückgelegte Weg kleiner. Nützlich ist das, um die Messungsdarstellung zu vergrößern oder zu verkleinern. Wenn z.B. der zu messende Raum so groß ist, dass der Roboter außerhalb des Fensters in Processing fahren würde, so wäre es praktisch, den Faktor anzupassen. Dies ist allerdings nur vor der Messung einstellbar.
===Darstellung der Messdaten===
Je Sensor ist eine Linie vorhanden, wobei die Länge der Linie von dem Messergebnis abhängt. Die Linie hat ihren Ursprung an der jeweiligen Position am Roboter. Wenn das Messergebnis des Sensors 50cm beträgt, so sollte auch die Line ca. 50 Pixel lang sein (ohne Beachtung der Variable “faktor”).
Die Sensoren haben zwei verschiedene Messergebnisse. Einmal kann nichts vor dem Roboter innerhalb der Reichweite stehen und andernfalls schon. Die Messreichweite haben wir auf 70cm festgelegt, da bis zu dieser Distanz die Umrechnung der Daten in Metern am genauesten war. Wenn also eine Distanz von über 70cm gemessen wurde, so wird die gemessene Distanz auf die Reichweite, also 70cm gesetzt. Das hat den Grund, das alle Messdaten außerhalb der Reichweite nicht beachtet werden sollen, bzw. gekennzeichnet werden sollen. Dadurch ist die Darstellung übersichtlicher und es ist zu erkennen, wo der Roboter noch zu fahren hat.
Zeile 106:
if (leftData > 70) leftData = 70;
Wenn die Messdaten einen Wert von 70 überschreiten, so werden diese auch in einer anderen Farbe dargestellt:
if (leftData == 73*faktor) stroke(255, 23, 5);
Ausrichtung der Sensoren:
Je nach Richtung des Roboters sind auch die Sensoren ausgerichtet. Wenn z.B. der Roboter nach links (auf dem Bildschirm) ausgerichtet ist, also die Variable direction dem Wert “L” entspricht, so wird z.B. der linke Sensor vom Roboter aus nach unten gerichtet sein.
if (direction.equals("L"))
line(xPos+1-(6*faktor), yPos+pLeft, xPos-(6*faktor), yPos+leftData);
Im aktuellen Programmcode werden allerdings nicht die Sensoren als Linie dargestellt, sonder die Linie vom vorherigen zum aktuellen Messergebnis.
__Erklärung der Werte der Parameter:__\\
vorherige Messwerte:\\
xPos+1-(6*faktor): Die aktuelle X-Position wird um 1 addiert, da der
vorherige gemessene Wert einen Schritt zurück liegt. Der Sensor befindet
sich außerdem 6cm vor dem Mittelpunkt des Roboters, weswegen aufgrund
der Richtung 6cm abgezogen werden müssen.
\\
\\
yPos+pLeft: in pLeft wird der vorherige Messwert gespeichert (siehe
draw()-Methode Zeile 44+45)
Die restlichen Variablen sollten nun selbsterklärend sein.
**Beispiel im Video: Kartographierung einer Mülltonne**\\
{{:projektesose18:kartograph:kartog_video_roboter_1.mp4|}}
====Kommunikation zwischen Arduino und Processing====
===Gesendete Daten von Arduino===
Die Kommunikation erfolgt nur von Arduino zu Processing, um die Messergebnisse darzustellen. Bei jedem Aufruf der Methode sharpDistSensor() (in der Arduino-Datei “SharpDistSensorBasic”) wird eine Zeile an Daten versendet. Darin enthalten sind die Messdaten des linken und des rechten Infrarotsensors, die X- und Y-Position und die Richtung des Roboters im Verhältnis zur Ausgangsposition und -richtung.\\
\\
__Beispiel für Konsolenausgabe des Arduino **(Datenpaket)**:__\\
(Sensordaten[links];Sensordaten[rechts];X-Position;Y-Position)
49;70;30;65;U
49;70;30;66;R
70;70;31;66;R
...
===Daten von Arduino empfangen===
Um die vom Arduino gesendete Daten in Processing zu empfangen, sollte das Konsolenfenster in der Arduino-Software nicht ausgeführt werden, da sonst Processing auf die Daten keinen Zugriff haben kann.\\
\\
Zunächst sollte die Bibliothek processing.serial.Serial importiert werden (Zeile 1) und ein Serial-Objekt deklariert werden (Zeile 2). Dieses Objekt dient als Datenübermittler und hat Funktionen, um die Daten auslesen zu können.
Bevor das Objekt instanziiert werden kann müssen zwei Parameter bekannt sein.\\
\\
Instanziierung des Serial-Objekts “myPort”
myPort = new Serial(this, portName, 9600);
Der erste Parameter bleibt normalerweise auf “this” und ist nicht von Bedeutung. Der Parameter namens portName ist ein String und enthält den (USB-)Anschluss vom Computer, von dem die Daten gelesen werden sollen. Dabei handelt es sich selbstverständlich um den Anschluss (oder Port), der mit dem Arduino verbunden ist. Um herauszufinden, an welchen Anschluss der Arduino mit dem Computer verbunden ist, kann der Befehl Serial.list() verwendet werden. Dieser gibt eine Liste aller Anschlüsse zurück.
String[] ports = Serial.list();
//for(int i = 0; i < ports.length; i++) println(ports[i]);
Hier wurde die Liste zwischengespeichert und ausgegeben. Es sollte sich hierbei um den Anschluss handeln, der auch bei der Arduino-Software unter “Port” angegeben ist. Wenn der Port gefunden wurde, muss dieser angegeben werden. Achtung: Wenn das Programm auf einem anderen Computer oder Anschluss getestet wird, muss unter Umständen der Port erneut gesucht und gesetzt werden.
Beispiel für Angabe des Ports:
String portName = ports[5];
Bei dem letzten Parameter des Serial-Konstruktors (9600) handelt es sich um die Übertragungsrate des Arduino. Dabei sollte die gleiche Übertragungsrate wie im Arduino-Programm verwendet werden (zu finden in der Datei “Kartograph” in der Methode “setup()” in Serial.begin(9600);).
===Empfangene Daten in Processing speichern===
In der Methode getData() werden die Daten, die der Arduino schickt gesammelt. Mit dem Befehl readStringUntil(‘\n’) ist es möglich die Daten bis zum Zeilenumbruch (also “\n”) zu lesen und einem String zuzuweisen.\\
\\
Zeile 75:
String data = myPort.readStringUntil('\n');
Ausnahmefall
Falls der Arduino aus irgendwelchen Gründen gar keine Daten sendet, so enthält der String data den Wert null. Dieses null kann nicht weiter verwendet werden, sodass die Methode einfach mit einem return vorzeitig beendet wird.
Zeile 77:
if (data == null) return;
Damit die einzelnen Daten den jeweiligen Variablen in Processing zugeordnet werden können, muss der String aufgeteilt werden. Mit der [[https://processing.org/reference/split_.html|split()]]-Methode wird dies realisiert, wonach die einzelnen Daten in einen String-Array vorhanden sind. Dazu wird der Methode übergeben, mit welchem Buchstaben (char) die Daten getrennt werden sollen und in welchem String-Array die Daten gespeichert werden.\\
\\
Beispiel:\\
Nachricht vom Arduino:
49;70;30;65;D
Befehle in Processing (Zeile 75 und 77):
String data = myPort.readStringUntil('\n');
String[] s = split(data, ‘;’);
__Die Daten im Array:__\\
* Messdaten [links]: s[0] == 49;
* Messdaten [rechts]: s[1] == 70;
* X-Position: s[2] == 30;
* Y-Position: s[3] == 65;
* Richtung: s[4] == D;
Der String-Array s enthält somit die einzelnen Bestandteile.
Allerdings müssen diese vor der Übergabe an die Variablen in Processing in den jeweiligen Datentyp konvertiert werden. Bei den Mess- und Positionsdaten handelt es sich nämlich um Gleitkommazahlen (float), wobei die aus dem String entnommenen Daten immer noch einzelne Strings sind.\\
\\
im Code (ab Zeile 95)
leftData = float(list[0]);
rightData = float(list[1]);
xKoord = float(list[2]);
yKoord = float(list[3]);
direction = list[4];
direction braucht nicht konvertiert werden, da es sich bei der Variable schon um
einen String handelt.
\\
\\
=====Steuerung des Roboters=====
====Bewegen der Stepper====
Um die Stepper-Motoren in Bewegung zu setzen, benutzen wir die Bibliothek “Stepper”.
\\
Der gesamte im Folgenden beschriebene Quellcode in diesem Abschnitt befindet sich in der Datei “Motor”.
\\
// change this to fit the number of steps per revolution for your motor
const int stepsPerRevolution = 200;
// initialize the stepper library on pins 2/3 and 5/6:
Stepper myStepper1(stepsPerRevolution, 3, 2);
Stepper myStepper2(stepsPerRevolution, 5, 6);
-> Zeile 4-9
\\
Hier werden zwei Objekte initialisiert, welche die beiden Stepper im Code repräsentieren.
Durch diese vier Zeilen bewegen wir die je Stepper um einen Schritt in die jeweilige Rotationsrichtung, also den Roboter um einen Schritt nach vorne.
\\
myStepper1.step(-1);
delayMicroseconds(2500);
myStepper2.step(1);
delayMicroseconds(2500);
-> Zeile 30-33 (und 65-68 / 76-79)
\\
Diese Zeilen benutzen wir auch zur Drehung des Roboters. Haben beide Einsen in den Klammern kein Vorzeichen dreht sich der Roboter gegen den Uhrzeigersinn, haben sich ein negatives dreht er sich im Uhrzeigersinn.
Die Anzahl an Schritten, die die Stepper pro Einheit machen sollen regulieren wir über ''for''-Schleifen.
for (int i = 0; i < wert * skalierung; i++) {…}
-> (leicht verändert) ab Zeile 29 / 63 / 74
\\
Dabei ist steht die Variable ''skalierung'' für Anzahl an Schritten, die die Stepper machen müssen, um sich eine Einheit zu nach vorne zu bewegen bzw. um eine zu drehen. Beim Vorwärtsfahren (in der ''forward''-Funktion) beträgt die Skalierung ''28.6'', beim im Uhrzeigersinn Drehen ''5.225'' und beim gegen den Uhrzeigersinn Drehen ''5.28''.
\\
Die Einheit des Vorwärtsfahren ist Zentimeter, die des Drehens ist Grad.
\\
Die Variable ''wert'' wird als Parameter beim Funktionsaufruf übergeben und kann in ''forward()'' jede positive Integer-Zahl sein, während die Drehungsfunktion (''rotation()'') kann jedoch nur mit 180, 90, -90 oder -180 Grad aufgerufen werden. Das liegt daran, dass wir den Kartographen immer nur rechtwinklig drehen lassen, da es ansonsten zu kompliziert wäre.
In ''forward()'' rufen wir als Erstes auch immer die Funktion ''sharpDistSensor()'' auf, welche die Entfernungen misst und an //Processing// verschickt.
====Orientierung im Raum====
In ''rotation()'' wird zuerst immer die Funktion ''changeOrientation()'' auf, welche (mit Hilfe eines switch-case-Konstruktes) zum jeweiligen Drehungsgrades die Richtung verändert.
\\
Diese wird in der Variablen ''orientation'' gespeichert und hat am Anfang den Wert 1, welcher für das Fahren in die rechte Richtung steht (0 steht für oben, 2 für unten und 3 für links). Somit ist die Variable "immer auf dem neuesten Stand" und wir wissen immer in welche Richtung unser Roboter gerade fährt.
Damit wir jetzt noch wissen wo er sich gerade befindet, haben wir zusätzlich diese Variablen in der Datei “Kartograph” definiert:
\\
float xPos = 0;
float yPos = 0;
float xMax = 0;
float yMax = 0;
-> Zeile 1-4
\\
In ''xPos'' und ''yPos'' werden die x- und y-Position des Roboters gespeichert, während ''xMax'' und ''yMax'' die Größe des Raums in x- und y-Richtung speichern.
Die beiden Positionsvariablen werden direkt in ''forward()'' verändert - also eine von beiden wird erhöht oder erniedrigt, je nachdem in welche Richtung der Roboter zu dem Zeitpunkt guckt -, welche wir in der Funktion ''raumAbmessung()'' aufrufen. Diese befindet sich in der Datei ''Steuerung'' und lässt den Roboter einmal im Rechteck entlang den vier den Raum begrenzenden Wänden fahren.
\\
Ist der Roboter das erste Mal von der Startposition nach rechts fahrend zu einer seinen Weg versperrenden Wand angekommen, dreht er sich um 90 Grad gegen den Uhrzeigersinn und fährt weiter, bis er auf eine zweite Wand stößt und sich nochmal in die gleiche Richtung dreht. Das ganze macht er dann noch zwei Mal, bis er wieder an (oder auch kurz vor) seiner Startposition angelangt ist, jedoch sind nur die ersten zwei Strecken relevant für die Bestimmung der Raumgröße.
\\
while (frontData > abstand) {
forward(1);
}
switch (orientation) {
case 0 : yMax = yPos;
break;
case 1 : xMax = xPos;
break;
}
rotation(-90);
xMax += 20 + abstand + 8.5;
yMax += 20 + abstand + 8.5;
-> Zeile 6-18
\\
Das switch-case-Konstrukt wird nur ausgeführt, wenn der Roboter vor einer Wand angelangt ist. Durch ''orientation'' weiß er, dass er sich nur dreht, wenn er nach oben oder nach rechts guckt. Am Ende wird noch ein bissche was auf die Größenangaben drauf gerechnet, da die Position von der Mitte des Roboters aus gerechnet wird und diese natürlich nicht genau vor der Wand zum Stillstand kommt, sondern in einem gewissen Abstand (wird in ''abstand'' gespeichert ist beträgt bei uns aktuell 20 cm) vom Roboter und zusätzlich plus dem Abstand zwischen der Mitte und dem Frontsensor.
Die ''while''-Schleife am Anfang lässt den Roboter solange geradeaus fahren (''forward(1);''), bis der Frontsensor den Mindestabstand (''abstand'') misst und nach der eventuellen Größenbestimmung dreht er sich wie oben schon erwähnt um 90 Grad gegen den Uhrzeigersinn (''rotation(-90);'').
===== Ergebnis =====
==== Endstand des Projekts ====
Der Roboter kann ein Objekt umfahren und somit einigermaßen genau kartographieren. Dabei muss die Fläche, die der Roboter von der Ausgangsposition abfahren soll, angegeben werden. Allerdings gibt es noch einige Baustellen.
==== bestehende Fehler ====
=== linker Infrarotsensor ===
Der linke Infrarotsensor ist sehr instabil und die Messergebnisse sind sehr unscharf. Daher wird zum Kartographieren nur der rechte Sensor verwendet, sodass der Roboter ein Rechteck entgegen des Uhrzeigersinns fährt. Möglicherweise sind die Kabelverbindungen nicht stabil oder der Sensor musst ersetzt werden.
=== Auswertung der Messdaten ===
Der Infrarotsensor auf der rechten Seite des Roboters ist zwar genau, dafür ist die Funktion falsch, die die Messergebnisse in Dezimetern umrechnet. Dabei sind höhere Messergebnisse umgerechnet näher am Roboter, als in der Realität. Diese Funktion muss noch angepasst werden.
=== Stepper-Motoren ===
Die Drehung der Stepper-Motoren ist ungenau. In manchen Fällen dreht der Motor sich bei z.B. einer 90°-Drehung zu wenig oder zu viel. Vielleicht müssen die Motoren umgetauscht werden, oder die Verbindungen geprüft werden. Weil der Roboter ungenau fährt, wurde die Entwicklung eines Fahralgorithmus vernachlässigt.
==== Ausblick ====
=== Fahr-Algorithmus ===
Ein Algorithmus nach dem der Roboter den Raum abfährt wurde konzipiert, jedoch nicht umgesetzt, aufgrund anderer Komplikationen. Vor der Umsetzung sollte allerdings der Stepper-Motor zuverlässig funktionieren. Für den Algoritmus gibt es verschiedene Lösungen, daher ist das Konzept nicht aufgeführt.
=== Kamera ===
Möglich wäre es, eine Kamera zu installieren, um während der Messung die Karte in Processing mit den Kamerabildern zu bestücken. Somit würden nicht nur die Grenzen des zu messenden Raums dargestellt werden, sondern der Raum an sich. Mit den Bildverarbeitungsalgorithmus des Projekts "[[projektesose18:rembrandt:doku|Rembrandt]]" könnten sogar die Kanten hervorgehoben werden, um somit eine skizzenartige Abbildung des Bodens zu erhalten.
===== Code =====
{{:projektesose18:kartograph:kartograph_code.zip|}}