Unterrichts- und Lernmaterial für Mikrocontroller
Unterrichts- und Lernmaterial fürMikrocontroller

1 - Echotest

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
    

2 - Aufbau und Test einer PING))) Sensorschaltung

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.

(Courtesy of Parallax Inc.)
Aufbau einer PING))) Sensorschaltung
Aufgaben
  • Baue die PING)))-Sensorschaltung nach Schaltskizze auf dem Steckbrett des Prop Activity Boards (Original oder WX Version) auf.
  • Achte darauf, dass zwischen dem SIG-Pin des Sensors und dem Propeller I/O Pin P8 ein 2,2kOhm Widerstand eingebaut wird (siehe Schaltskizze oder Schaltungsaufbau).
Abbildung 1 - Schaltungsaufbau und Schaltskizze (Courtesy of Parallax Inc.)

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.

3 - Der PING))) Test

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.

Abbildung 2 - Verschiedene Positionen, die vom PING))) Sensor nicht oder nur schwer erfasst werden (Courtesy of Parallax Inc.)

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
  • Übertrage das Programm Ping_Abstand.c in den Editor und speichere es ab.
  • Starte das Programm über Run with Terminal aus dem Hauptmenü.
  • Bestimme die Abstände von verschiedenen Objekten (Hand, Tasse, Ball/Kugel), die vom Sensor leicht erkannt werden (mit glatter harter Oberfläche).
  • Bestimme anschließend die Abstände von Objekten mit weicherer Oberfläche (Stofftier, zerknautschter Stoff). Zeigt der Sensor auch hier Abstände an?
  • Stelle den Sensor senkrecht zu einer Wand und bestimme den Abstand.
  • Verändere den Winkel des Sensors zur Wand und bestimme jedes mal den Abstand. Wie stark darf der Sensor vom 90° Winkel zur Wand abweichen, bis eine Abstandsberechnung nicht mehr möglich ist? Teste es aus.

Das Programm Ping_Abstand.c

Terminalausgabe zum Programm Ping_Abstand.c

Abbildung 3 - Terminalausgabe zur Abstandsbestimmung mit einem PING))) Sensor

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. 

Abbildung 4 - Startimpuls und Echolaufzeit bei einem PING)))-Sensor (Courtesy of Parallax Inc.)

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.

4 - Den Raum erfassen mit Ultraschall

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.

(Courtesy of Parallax Inc.)

5 - Die Empfindlichkeit überprüfen, Stopp, Drehmanöver

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
  • Übertrage das Programm PING_Hindernisse.c in den Editor und speichere es anschließend ab.
  • Löse das USB-Kabel vom Prop-Activity Board.
  • Schiebe den PWR-Schalter in Position 2.
  • Halte den Reset-Knopf gedrückt und setze den Roboter so auf den Boden, dass er in Richtung einer Wand, eines Hindernisses steht. Lasse den Reset-Knopf los.
  • Überprüfe, ob der Roboter mit voller Geschwindigkeit startet und abbremst bzw. stoppt und sich auf der Stelle dreht, sobald er einem Hindernis näher als 20cm kommt.
  • Führe mehrere Versuche durch und überprüfe, ob er seine Drehbewegung zufällig ausführt.

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:

  1. simpletools (pause),
    
    
  2. abdrive (jeder Befehl, der mit drive_ beginnt)
    
    
  3. ping (ping_cm) und
    
    
  4. 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
  • Lade das Programm Ping_Hindernisse.c in den Editor und speichere es über Project - Save Project As ... unter dem neuen Namen Ping_Hindernisse2.c ab.
  • Ändere das Programm so ab, wie in Abb. 3 gezeigt.
  • Um die Lesbarkeit des Programms zu verbessern, rücke die nachfolgenden Programmzeilen um zwei Stellen ein.
  • Starte das Programm über das Hauptmenü mit Program  - Load EEPROM & Run.
  • Stelle den PWR-Schalter in Position 2 und halte den Reset-Button gedrückt.
  • Stelle den Roboter auf eine ebene Unterlage in einen Raum mit mehreren Hindernissen. Beobachte, wie der ActivityBot sich den Hindernissen nähert, sich von ihnen wegdreht und seinen Weg fortsetzt, bis er auf das nächste Hindernis trifft.

 Das Programm Ping_Hindernisse2.c

Jetzt kommst du!

Wenn du mehr machen möchtest, hier sind ein paar Herausforderungen für dich.

  • Ändere den Programmcode so ab, dass der ActivityBot anhält, wenn er vier Hindernisse erfasst hat. Tipp: Definiere eine Variable, die die Hindernisse mit Drehung zählt und initialisiere sie mit 0, bevor es in die Endlosschleife while(1) geht. Inkrementiere die Variable bei jedem Schleifendurchlauf von while(1). Es gibt noch  andere Möglichkeiten, dieses Problem zu lösen. Hast du eine Idee?
  • Die einfachste Methode ein Labyrinth zu durchlaufen ist, an jeder Wand eine Rechtsdrehung auszuführen. Das ist sicherlich nicht die beste Methode, aber ganz sicher die einfachste. Ändere den Programmcode so ab, dass jedesmal, wenn eine Hindernis erkannt wird, eine Rechtsdrehung ausgeführt wird.
Druckversion | Sitemap
© Reinhard Rahner - Gettorf