Ein RasPi eignet sich bestens zum Steuern eines Fischertechnik-Roboters. Damit dabei kein Chaos entsteht, gilt es, die Steuerung genau zu programmieren.
In der letzten Ausgabe entstand im Rahmen dieses Workshops ein Modul, über das sich die GPIO des RasPi mit der Welt von Fischertechnik verbinden lässt [1]. Diesmal geht es darum, den Raspberry Pi so zu programmieren, dass er den Fischertechnik-Roboter zum Leben erweckt.
Die Aufgabe des Roboters besteht darin, Gegenstände zu sortieren. Diese gelangen über Förderbänder in seine Reichweite, die ein Controllino-Modul steuert (siehe Artikel in der Rubrik “Hacks” dieser Ausgabe).
Als Basis kommt ein Dreiachsroboter aus dem Fischertechnik-Baukasten 511933 “ROBOTICS TXT Automation Robots” [2] zum Einsatz. Als Erstes bauen Sie das Modell anhand der beiliegenden Anleitung komplett auf. Das Verdrahten der Schalter und Motoren erfolgt wie in Abbildung 1 (siehe dazu auch Kasten “Errata zu Teil 1”).
Dabei hilft es, die einzelnen Komponenten vorher zu beschriften. Die Tabelle “Motoren, Schalter und Pulsgeber” liefert eine Übersicht über die Bezeichnungen aller Komponenten und deren Funktion. Die Taster S1 und S2 dienen Testzwecken, später ersetzen Sie sie durch Relaisausgänge des Controllino. Über diese zwei Eingänge teilt er dem Roboter mit, auf welches Förderband er den Gegenstand abzustellen hat. Abbildung 2 zeigt den komplett aufgebauten Roboter.

Abbildung 2: Der komplett aufgebaute und verdrahtete Fischertechnik-Roboter aus dem Baukasten 511933.
Motoren, Schalter und Pulsgeber
|
Beschriftung |
Anschluss Elektronik |
GPIO-Port |
Funktion |
|---|---|---|---|
|
M1 |
DO0 |
GPIO21 |
Roboter drehen |
|
|
DO1 |
GPIO22 |
|
|
M2 |
DO6 |
GPIO27 |
Arm ein-/ausfahren |
|
|
DO7 |
GPIO28 |
|
|
M3 |
DO2 |
GPIO23 |
Arm heben/senken |
|
|
DO3 |
GPIO24 |
|
|
M4 |
DO4 |
GPIO25 |
Greifer öffnen/schließen |
|
|
DO5 |
GPIO26 |
|
|
I1 |
DI7 |
GPIO7 |
Nullpunkt drehen |
|
I2 |
DI0 |
GPIO0 |
Nullpunkt ausfahren |
|
I3 |
DI6 |
GPIO6 |
Nullpunkt heben |
|
I4 |
DI4 |
GPIO4 |
Nullpunkt greifen |
|
C1 |
Counter 0 |
GPIO10 |
Pulsgeber drehen |
|
C2 |
DI3 |
GPIO3 |
Pulsgeber ausfahren |
|
C3 |
Counter 1 |
GPIO11 |
Pulsgeber heben |
|
C4 |
DI2 |
GPIO2 |
Pulsgeber greifen |
|
S1 |
DI5 |
GPIO5 |
Taster Förderband 1 |
|
S2 |
DI1 |
GPIO1 |
Taster Förderband 2 |
Errata zu Teil 1
In der vorigen Ausgabe im ersten Teil dieser Reihe hat sich in zwei Schaltplänen ein Fehler eingeschlichen: Im Output-Schaltplan (S. 56, Abb. 7) sind die Anschlüsse 10 und 11 des unteren L293 vertauscht. Im Input-Schaltplan (S. 57, Abb. 8) wurden die von den Counter-Eingängen kommenden Widerstände (rechts auf dem Schaltplan) fälschlicherweise nach GND statt korrekt auf +9V gezeichnet. In den Downloads zu diesem Artikel finden Sie neben einem PDF des ersten Artikels außerdem korrigierte Fassungen beider Schaltpläne.
TIPP
Alle Schaltpläne finden Sie in den Downloads zu diesem Artikel sowohl als Abbildung im Encapsulated-Postscript-Format (EPS) sowie als SCH-Datei (circuit schematic). Letztere laden Sie direkt in einer EDA-Software wie gEDA (vom Autor genutzt), KiCAD oder Autodesk EAGLE.
Initialisieren
Um die Positionen der einzelnen Achsen festzustellen, verwendet der Roboter unterschiedliche Impulsgeber. Dabei entspricht eine bestimmte Anzahl von Impulsen immer derselben Anzahl an Umdrehungen. Bei den Motoren mit integriertem Pulsgeber entstehen 75 Impulse pro Umdrehung, die diskret aufgebauten Pulsgeber liefern 4 Impulse pro Umdrehung.
Mit einem Impulsgeber ermitteln Sie die Positionen von Roboter-Komponenten sehr genau. Optische Impulsgeber, wie sie in den Motoren verbaut sind, haben eine sehr hohe Lebensspanne und Betriebssicherheit. Allerdings benötigen sie beim Einsatz immer einen definierten Nullpunkt, von dem aus der Geber die Impulse zählt.
Im Modell haben die Schalter I0 bis I3 die Funktion, die Nullpunkte der verschiedenen Achsen festzulegen. Um alle Achsen zu initialisieren, fahren Sie nacheinander die Komponenten des Roboters in den Nullpositionen an. Nach Erreichen dieser Positionen setzen Sie die entsprechenden Zähler der Achsen auf null. Achten Sie darauf, dass dabei keine Hindernisse im Weg sind.
Nun gilt es, noch eine Vereinbarung zu treffen: Wenn der Motor sich rechts herum dreht, bewegt sich die Komponente auf den Schalter für die Nullposition zu. Falls Sie bei den ersten Tests merken, dass das nicht der Fall ist, vertauschen Sie einfach die Polarität am Motor.
Das klingt möglicherweise erst einmal gar nicht so kompliziert. Wenn Sie jedoch mit dem Programmieren beginnen, zeigt sich schnell, dass ein ziemlich komplexes Programm entsteht. So ist es durchaus sinnvoll, eine eigene Bibliothek für den Roboter zu erstellen. Sie trägt in diesem Workshop den Namen Libfiropi (Library für Fischertechnik-Roboter mit Raspberry Pi).
Wir implementieren sie als statische Bibliothek, da wir nie mehr als einen Roboter an einen RasPi anschließen und der Aufwand so niedriger liegt. Was eine statische Bibliothek von ihrem dynamischen Gegenstück unterscheidet, lesen Sie im Kasten “C-Bibliotheken erstellen”.
C-Bibliotheken erstellen
Bibliotheken enthalten wiederverwendbaren, immer wieder benötigten Quellcode, der sich aus anderen Programmen heraus aufrufen lässt. Das erhöht deren Lesbarkeit und spart Tipparbeit.
Grundsätzlich gibt es zwei Typen von Bibliotheken: statische und dynamische. Statische Bibliotheken sind immer vollständig mit in den kompilierten Programmcode eingebunden. Dadurch laufen die Programme zwar schnell und unabhängig von anderen Komponenten, fallen aber auch größer aus. Unter Umständen passiert es sogar, dass sich eine Bibliothek mehrfach im Hauptspeicher befindet, wenn mehrere Programme sie verwenden.
Hier bieten dynamische Bibliotheken einen Ausweg: Sie sind nicht fest mit dem Programm verbunden, das dadurch kleiner ausfällt. Der Rechner lädt eine solche Bibliothek einmal in den Hauptspeicher, wo sie für alle Programme bereitsteht. Der Nachteil liegt darin, dass das Laden dynamischer Bibliotheken einige Zeit benötigt und einen gewissen Verwaltungsaufwand verursacht.
Um eine statische Bibliothek zu erstellen, brauchen Sie eine Headerdatei, in der Sie globale Variablen, Funktionsaufrufe und Konstanten definieren. Passend dazu benötigen Sie zusätzlich noch mindestens eine Datei mit dem Quellcode, in der sich die im Header definierten Funktionen befinden.







