Weitere Informationen zum Ultraschallsensor PING))) findet man unter
Mit dem PING))) Ultraschallsensor erkennt der Activity Bot Hindernisse und bestimmt den Abstand zu ihnen. Obwohl der PING))) Sensor Ähnlichkeit mit zwei große Augen hat, verhält er sich doch mehr wie Ohr und Mund.
Wie eine Fledermaus zur Orientierung Laute ausstößt und über die Reflexion des Schalls Hindernisse erkennt und ihnen ausweicht arbeitet auch der PING))) Sensor. Er emittiert, sobald er getriggert wird, ein Ultraschallsignal, wartet auf das Echo des Signals und gibt Zeichen, sobald er es erhalten hat. Der Propeller Controller merkt sich die Zeit zwischen der Triggerung des PING))) Sensors und dem Erhalt des Rücklaufsignals. Über diese Rücklaufzeit lässt sich anschließend der Abstand zu einem Objekt berechnen.
Mit dieser Eigenschaft kann ein Activity Bot verschiedene Navigationsstrategien ausführen:
Umfahren von Hindernissen während einer Geländefahrt
Einhaltung eines konstanten Abstandes zu einem bewegten Objekt
In dieser Übung wird eine PING))) Sensorschaltung aufgebaut. Mit ihr werden Abstände zu verschiedenen Objekten bestimmt und man bekommt ein Gefühl dafür, was dieser Detektor kann und was nicht. Der Sensor verfügt über drei Anschlussleitungen: Spannung, Masse und Signal. Über die Signalleitung erhält der Propeller Controller die Information für die Abstandsberechnungen.
Aufbau einer PING))) Sensorschaltung | |
Aufgaben |
|
PING))) Sensor und Servo Portanschluss: Sobald du anfängt eigene Projekte zu entwickeln, möchtest du vielleicht den Sensor irgendwo am Roboter platzieren, auf jeden Fall nicht auf dem Steckbrett. Das geht sehr elegant über die Servoport-Anschlüsse P16-P17, wenn der Power-Jumper auf 5V eingestellt wird. Der PING))) Sensor kann dann mit einem 3-Pin Erweiterungskabel direkt mit einem Servoport-Anschluss verbunden werden. Jeder von ihnen ist mit einem 3,9kOhm Widerstand in Reihe zum Propeller I/O Pin geschaltet; dadurch entfällt der 2,2kOhm Widerstand, den wir jetzt auf dem Steckbrett verwenden.
Die Echoortung mit Hilfe des PING))) Sensors funktioniert mit Objekten, die den Ultraschall gut reflektieren in einem Entfernungsbereich bis zu 3,3 Metern. Kleinere Objekte reflektieren zu wenig Ultraschall, deshalb werden sie nicht erkannt. Zylindrische und runde Körper sowie Wände, die direkt angestrahlt werden, reflektieren sehr gut. Nähert man sich einer Wand mit einem Ultraschallsensor seitlich, dann wird der Schall zwar reflektiert aber nicht zum Sender zurückgeworfen. Weiche Oberflächen, wie zum Beispiel Vorhänge und Stofftiere, absorbieren den Ultraschall und werfen kein Echo zurück.
Bei Hindernissen, die den Ultraschall reflektieren, kann der PING))) Sensor Entfernungen zwischen 3cm und 3m bestimmen. Dabei beeinflusst die Lufttemperatur die Genauigkeit der Entfernungsberechnung. Wer mehr darüber erfahren möchte, kann dies hier tun: Prop-Sensoren et al. - Ultraschallsensor - 1 - Ultraschallsensor PING)))
Im Testprogramm wird die Abstandsberechnung mit Hilfe des PING)))-Sensors im SimpleIDE Terminal ausgegeben. Damit kann schnell überprüft werden, wie genau er arbeitet, indem verschiedene Objekte in verschiedenen Abständen vor ihm aufgestellt werden oder der Sensor zu einer Wand in verschiedenen Winkeln platziert wird.
Der PING))) Test | |
Aufgaben |
|
Das Programm Ping_Abstand.c
Terminalausgabe zum Programm Ping_Abstand.c
Wie arbeitet das Programm?
Der Ping))) Sensor benötigt vom Propeller Controller ein kurzes HIGH/LOW Signal als sogenannten Start- oder Triggerimpuls, um die Messung zu beginnen. Der Sensor gibt ein Ultraschallsignal aus und setzt den SIG-Pin auf HIGH. Er wird auf LOW gesetzt, sobald das Echosignal erkannt wird. Die Zeit, die der SIG-Pin auf HIGH war (dies entspricht der Echolaufzeit) kann jetzt vom Propeller Controller bestimmt werden.
Mit Hilfe der Funktionen aus der Bibliothek ping werden die mathematischen Berechnungen durchgeführt, die aus der Echolaufzeit den Objektabstand bestimmen.
Im Programm muss dazu nur die Funktion ping_cm mit dem Parameter für den I/O Pin, der mit dem Sensor verbunden ist, aufgerufen werden. Der Rückgabewert der Funktion wird in der Variablen abstand vom Typ integer abgelegt. Die Ausgabe im Terminalfenster regelt der nachfolgende print-Befehl. Der Parameter HOME sorgt dafür, dass der Cursor links oben im Terminalfenster mit der Ausgabe beginnt und CLREOL löscht alle Zeichen in der Cursorzeile.
Was du wissen solltest!
Über die Bibliothek ping wird die Echolaufzeit in Mikrosekunden gemessen und es wird angenommen, dass die Schallgeschwindigkeit bei Raumtemperatur von 22,2°C bei 0,03448 cm/µs liegt. Da sich Schall gleichförmig ausbreitet, gilt die Gleichung s = c * t, dabei steht s für den zurückgelegten Weg des Schalls, c für die Schallgeschwindigkeit in Luft und t für die Zeit.
Für die Abstandsberechnung muss berücksichtigt werden, dass der Schall die Entfernung zum Objekt zweimal zurück legt (Hin- und Rückweg), deshalb muss die entsprechende Gleichung lauten:
Werden beide Seiten der Gleichung durch zwei dividiert, erhält man die Gleichung
0,03448/2 ist ungefähr 1/58, deshalb lässt sich die Gleichung zur Berechnung des Abstandes in cm über die Echolaufzeit in Mikrosekunden über folgende Formel berechnen:
Versuch mal dies!
Die Zeitmessung in der Einheit Mikrosekunden kann über eine ping-Funktion im Terminalfenster ausgegeben werden.
Abstand und Echolaufzeit | |
Aufgaben |
Ergänze im Programm Ping_Abstand.c die Zeilen 12 und 13 und speichere das neue Programm unter Projects - Save Projects As ... unter dem Namen Ping_Abstand_Laufzeit.c ab. Starte das Programm und überprüfe die Terminalausgabe. |
Das Programm Ping_Abstand_Laufzeit.c
Jetzt kommst du!
Überprüfe mit deinem Taschenrechner, dass sich die Entfernung in Zentimetern über den Quotienten aus Echolaufzeit und 58 ergibt. Beachte, dass in der Sprache C Berechnungen von Integer-Größen immer nach unten abgerundet werden.
Abstände können wir jetzt mit dem PING))) Sensor in der Einheit Zentimeter bestimmen und wir wissen, bei welchen Objekten der Sensor reagiert und bei welchen nicht oder nur sehr schlecht. Für die Navigation mit diesem Sensor sind wir also bestens gerüstet.
Der Programmcode muss so aussehen, dass der Roboter geradeaus fährt, bis er ein Hindernis erkennt, dass zum Beispiel weniger als 20cm von ihm entfernt ist. Dann soll er seine Geschwindigkeit reduzieren und anhalten. Anschließend erfasst er durch eine Drehbewegung die Umgebung und prüft, ob irgendwo der Abstand zu einem Objekt größer als 20cm ist. Dies ist für ihn das Signal weiter geradeaus zu fahren. Mit Hilfe von Zufallszahlen lässt sich das Reaktionsverhalten des Activity Bot etwas interessanter gestalten. Sie legen fest, in welche Richtung der Roboter drehen soll, sobald er einem Objekt zu nahe gekommen ist.
Bevor es an die Erkundung des Raumes mit dem Roboter geht, testen wir ein kleineres Programm und überprüfen damit, ob der ActivityBot auch tatsächlich vor einem Hindernis anhält und sich von ihm abwendet. In diesem Beispielprogramm fährt der ActivityBot immer geradeaus, solange die erfassten Objekte mehr als 20cm von ihm entfernt sind. Ist der Abstand kürzer als 20cm, senkt der Roboter seine Geschwindigkeit kontinuierlich ab (ramping) und hält schließlich an. Er dreht anschließend auf der Stelle und überprüft, in welcher Richtung die Objekte weiter als 20cm von ihm entfernt sind.
Stopp und Drehmanöver | |
Aufgaben |
|
Das Programm PING_Hindernisse.c
Wie arbeitet das Programm?
In diesem Programm benutzen wir die Rückgabewerte des Befehls ping_cm(8) in Entscheidungsbefehlen, statt sie in einer Variablen abzulegen. Deshalb benötigen wir keine Variable Entfernung oder Abstand. Aber wir benötigen eine Variable, in der wir eine Zufallszahl hinterlegen können, damit die Drehung später bestimmt werden kann. Deshalb ist in Zeile 5 die Variable Drehung vom Typ int deklariert.
Zeile 9
drive_setRampStep(10) legt die Zahl der Ticks pro Sekunde fest, um die sich die Geschwindigkeit in der Zeit von 1/50 Sekunde ändern darf. Der Parameter ist hier mit 10 angegeben, das heißt, dass die Änderung in einer 50-tel Sekunde bei 10 Ticks pro Sekunde liegen darf.
Zeile 10
drive_ramp(128, 128) steigert die Geschwindigkeit in Schritten von 10 Ticks pro Sekunde. Mit einer Rampe von 10 dauert es 13/50 Sekunden = 0,26s, um auf die volle Geschwindigkeit zu kommen. Jeder Schritt steigert sich um 10, außer dem letzten, der von 120 auf 128 erfolgt.
Zeile 11
while(ping_cm(8) >= 20) pause(5); Dies ist eine 1-Zeilen Schleife, die alle 5ms überprüft, ob die Funktion ping_cm(8) ein Hindernis erfasst hat. Ist das nicht der Fall, dann wird eine Pause von 5ms eingelegt. Diese Schleife wird solange durchlaufen und der ActivityBot bewegt sich geradeaus weiter, bis ein Hindernis erkannt wird. Sobald es erkannt wird, es ist dann 20cm oder weniger vom Roboter entfernt, wird die Schleife verlassen und der Befehl in
Zeile 12
drive_ramp(0, 0) ausgeführt. Er lässt den Roboter innerhalb von 0,26s stoppen. Der ActivityBot muss jetzt entscheiden in welche Richtung er sich drehen soll, um das Hindernis zu umgehen. Dafür wird die Funktion rand aus der Bibliothek math benutzt (sie ist in simpletools enthalten) und legt fest, ob nach links oder rechts gedreht wird. Die generierte Zufallszahl liegt zwischen 0 und 2.147.483.648. Bei jedem Programmaufruf von rand wird eine neue Zufallszahl ausgegeben.
Zeile 13
Die Programmzeile drehung = rand() %2 teilt die Zufallszahl durch 2 und merkt sich den verbleibenden Rest. Der kann bei einer Division durch 2 nur 0 oder 1 sein; dieser Wert wird der Variablen drehung zugewiesen.
Zeilen 14 - 17
Bei einer Zufallszahl 1 dreht sich der ActivityBot nach rechts (drive_speed(64, - 64)), bei einer 0 nach links (drive_speed(-64, 64)).
Zeile 18
wird solange ausgeführt, wie ein Hindernis erkannt wird. Hat sich der ActivityBot weit genug gedreht und erkennt kein Hindernis mehr, stoppt er.
Wenn alles so funktioniert wie beschrieben, lassen sich die meisten Programmzeilen in einer while(1)-Endlosschleife unterbringen.
Was du wissen solltest!
Bibliotheksliste
Diese Anwendung benutzt Funktionen aus vier verschiedenen Bibliotheken:
simpletools (pause),
abdrive (jeder Befehl, der mit drive_ beginnt)
ping (ping_cm) und
math (rand).
Auf die Bibliothek math wurde hier nicht näher eingegangen, da sie in simpletools enthalten ist. Es wäre aber kein Fehler, wenn man diese Bibliothek explizit in der Liste am Anfang des Programms mit
#include<math.h>
aufruft. Sie wird nach allgemeiner Übereinkunft statt in Anführungszeichen von den Zeichen < > eingeschlossen, da sie ein Teil von Propeller GCC und nicht Teil der Propeller C Tutorial´s custom libraries (wie zum Beispiel simpletools, abdrive und ping) ist.
Versuch mal dies!
Im folgenden Programm arbeiten wir mit einer while(1)-Endlosschleife, während der Roboter auf seinem Weg Hindernissen auszuweichen versucht. Einzig der Befehl drive_ramp(0, 0) ist nicht Teil dieser Endlosschleife.
Das Programm Ping_Hindernisse2.c | |
Aufgaben |
|
Das Programm Ping_Hindernisse2.c
Jetzt kommst du!
Wenn du mehr machen möchtest, hier sind ein paar Herausforderungen für dich.