Aus Raspberry Pi Geek 04/2019

Fischertechnik-Roboter mit dem Ftduino steuern (Seite 2)

Listing 1

ftduino.input_set_mode(Ftduino::I3,Ftduino::SWITCH);
ftduino.motor_set(Ftduino::M3,Ftduino::RIGHT,Ftduino::MAX);
while (!ftduino.input_get(Ftduino::I3)){}
ftduino.motor_set(Ftduino::M3,Ftduino::BRAKE,Ftduino::MAX);

Diese Schritte wiederholen Sie jetzt für alle drei Achsen und den Greifer. Bewegen Sie die Achsen so, dass sie nach Möglichkeit keine Kollisionen verursachen – erst hoch-, dann einfahren und zum Schluss drehen. Würden Sie den Arm im ausgefahrenen Zustand drehen, wäre die Wahrscheinlichkeit hoch, dass Sie irgendeinen Gegenstand umwerfen. Wollen Sie auf Nummer sicher gehen, aktivieren Sie die jeweiligen Achsen einzeln.

Die Funktion init_robot() ruft das Programm direkt aus der Funktion setup() nach dem Initialisieren der Bibliothek auf. Die vier Kommandos motor_counter() fahren jede Achse wieder ein kleines Stück nach links, damit der Roboter bei einem weiteren Testlauf nicht sofort in der Anfangsposition steht.

Bei genauerem Hinsehen fällt auf, dass der Roboter alle Motoren gleichzeitig bewegt: Das Bewegen eines Motors geschieht nicht blockierend, und das Programm läuft weiter. Das ist eigentlich ein Vorteil, führt aber in manchen Fällen zu Problemen, wie ein weiteres Testprogramm verdeutlicht (Listing 2). Die Funktion loop() brauchen wir in diesem Test nicht, daher bleibt sie leer. Man kann sie aber nicht komplett löschen, da sonst der Compiler einen Fehler wirft.

Listing 2

#include <Ftduino.h>
void init_robot() {
  ftduino.input_set_mode(Ftduino::I3,Ftduino::SWITCH);
  ftduino.motor_set(Ftduino::M3,Ftduino::RIGHT,Ftduino::MAX);
  while (!ftduino.input_get(Ftduino::I3)){}
  ftduino.motor_set(Ftduino::M3,Ftduino::BRAKE,Ftduino::MAX);
  ftduino.input_set_mode(Ftduino::I2,Ftduino::SWITCH);
  ftduino.motor_set(Ftduino::M2,Ftduino::RIGHT,Ftduino::MAX);
  while (!ftduino.input_get(Ftduino::I2)){}
  ftduino.motor_set(Ftduino::M2,Ftduino::BRAKE,Ftduino::MAX);
  ftduino.input_set_mode(Ftduino::I1,Ftduino::SWITCH);
  ftduino.motor_set(Ftduino::M1,Ftduino::RIGHT,Ftduino::MAX);
  while (!ftduino.input_get(Ftduino::I1)){}
  ftduino.motor_set(Ftduino::M1,Ftduino::BRAKE,Ftduino::MAX);
  ftduino.input_set_mode(Ftduino::I4,Ftduino::SWITCH);
  ftduino.motor_set(Ftduino::M4,Ftduino::RIGHT,Ftduino::MAX);
  while (!ftduino.input_get(Ftduino::I4)){}
  ftduino.motor_set(Ftduino::M4,Ftduino::BRAKE,Ftduino::MAX);
}
void setup() {
  ftduino.init();
  init_robot();
  ftduino.motor_counter(Ftduino::M1,Ftduino::LEFT,Ftduino::MAX, 400);
  ftduino.motor_counter(Ftduino::M2,Ftduino::LEFT,Ftduino::MAX, 10);
  ftduino.motor_counter(Ftduino::M3,Ftduino::LEFT,Ftduino::MAX, 400);
  ftduino.motor_counter(Ftduino::M4,Ftduino::LEFT,Ftduino::MAX, 10);
}
void loop() {
}

LC-Display

Um das LC-Display anzusteuern, benötigen Sie zwei zusätzliche Bibliotheken. Um sie einzubinden, navigieren Sie in der Arduino IDE zu Sketch | Bibliothek einbinden | Bibliotheken verwalten. In der Maske suchen Sie zuerst nach der Bibliothek Adafruit_SSD1306 und installieren sie. Anschließend suchen Sie nach Adafruit_GFX und fügen diese Library ebenfalls hinzu. Das LC-Display schließen Sie an den I2C-Port des Ftduino an. Eine ausführliche Anleitung dazu finden Sie im Kapitel 6.13.3 des Handbuchs [6]. Auch für das Display benötigen Sie wieder einige Bibliotheken.

Die Header-Datei Wire.h stellt die Unterstützung zur Kommunikation über den I2C-Bus bereit, Adafruit_SSD1306.h enthält die Daten für die Grundfunktionen des Displays. In Adafruit_GFX.h lagern alle Funktionen, um Grafik und Text darzustellen. Alle Operationen finden immer erst im Pufferspeicher des Ftduino statt, erst die Methode display.display() überträgt die Daten ins Display.

Beim Testprogramm (Listing 3) für das Display handelt es sich um einen einfachen Zähler, der seinen aktuellen Stand sowohl auf dem Bildschirm als auch auf den seriellen Monitor ausgibt. Das Programm beginnt mit der Definition einiger Werte und der Initialisierung eines Objekts namens display, mit dem die Software alle weiteren Operationen ausführt.

Listing 3

#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define SCREEN_WIDTH 96
#define SCREEN_HEIGHT 32
#define OLED_RESET 4
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
int i=0;
void setup() {
  Serial.begin(9600);
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
}
void loop() {
  display.clearDisplay();
  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(32,0);
  display.print("#:");
  Serial.print("#:");
  display.print(i);
  Serial.println(i);
  i++;
  display.display();
  delay(400);
}

In der Funktion setup() baut das Programm die Verbindung zum Display auf (I2C-Adresse 0x3c) und aktiviert die Schnittstelle für den seriellen Monitor. Die Funktion loop() enthält die zur Anzeige von Text nötigen Kommandos. Die Methode display.print() zeigt die Ausgabe an der zuvor mit display.setCursor() definierten Position an. Hier gilt es zu beachten, dass die Funktion die Parameter in Pixeln erwartet, nicht in Zeichen.

Müll entsorgen

Im eigentlichen Programm besteht die Aufgabe des Roboters aber darin, den Abfall auf dem Schreibtisch zu greifen und ihn fachgerecht zu entsorgen. Der Ablauf startet, sobald Sie den Taster I8 drücken. Da sich der Roboter direkt nach dem Einschalten initialisiert hat, kann er direkt die Position anfahren, an der sich der Müllcontainer befindet.

Drücken Sie den Taster I7, initialisiert sich der Roboter neu. Da das Programm mit relativen Koordinaten arbeitet, ist es wichtig, dass der Roboter beim Start des Programms immer an derselben Position steht. Er hat keine Sensoren, um seine Umgebung wahrzunehmen. Aus diesem Grund funktioniert die Software nur, wenn alle beteiligten Gegenstände immer an demselben Platz stehen. Das erreichen Sie etwa durch aufgeklebte Markierungen an den entsprechenden Stellen. Alternativ verschrauben Sie den gesamten Aufbau auf einer großen Platte aus Holz und passen anschließend die Koordinaten im Programm an diesen Aufbau an.

Fast alle Teile des Programms (Listing 4) kennen Sie schon aus den ersten zwei Programmen. Die Funktion display_message() kommt neu hinzu: Mit ihr zeigen Sie einfache Statusmeldungen des Roboters auf dem Display an.

Listing 4

#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET 4
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
void init_robot() {
  display_message("Init");
  ftduino.input_set_mode(Ftduino::I3,Ftduino::SWITCH);
  ftduino.motor_set(Ftduino::M3,Ftduino::RIGHT,Ftduino::MAX);
  while (!ftduino.input_get(Ftduino::I3)){}
  ftduino.motor_set(Ftduino::M3,Ftduino::BRAKE,Ftduino::MAX);
  ftduino.input_set_mode(Ftduino::I2,Ftduino::SWITCH);
  ftduino.motor_set(Ftduino::M2,Ftduino::RIGHT,Ftduino::MAX);
  while (!ftduino.input_get(Ftduino::I2)){}
  ftduino.motor_set(Ftduino::M2,Ftduino::BRAKE,Ftduino::MAX);
  ftduino.input_set_mode(Ftduino::I1,Ftduino::SWITCH);
  ftduino.motor_set(Ftduino::M1,Ftduino::RIGHT,Ftduino::MAX);
  while (!ftduino.input_get(Ftduino::I1)){}
  ftduino.motor_set(Ftduino::M1,Ftduino::BRAKE,Ftduino::MAX);
  ftduino.input_set_mode(Ftduino::I4,Ftduino::SWITCH);
  ftduino.motor_set(Ftduino::M4,Ftduino::RIGHT,Ftduino::MAX);
  while (!ftduino.input_get(Ftduino::I4)){}
  ftduino.motor_set(Ftduino::M4,Ftduino::BRAKE,Ftduino::MAX);
}
void display_message(String s){
  display.clearDisplay();
  display.setTextSize(3);
  display.setTextColor(WHITE);
  display.setCursor(0,0);
  display.print(s);
  display.display();
}
void setup() {
  while(!Serial){};
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
  ftduino.init();
  init_robot();
  ftduino.input_set_mode(Ftduino::I5,Ftduino::SWITCH);
  ftduino.input_set_mode(Ftduino::I6,Ftduino::SWITCH);
  ftduino.input_set_mode(Ftduino::I7,Ftduino::SWITCH);
  ftduino.input_set_mode(Ftduino::I8,Ftduino::SWITCH);
  display_message("Ready");
}
void loop() {
  if(ftduino.input_get(Ftduino::I8)){
    display_message("Start");
    ftduino.motor_counter(Ftduino::M3,Ftduino::LEFT,Ftduino::MAX, 2000);
    ftduino.motor_counter(Ftduino::M1,Ftduino::LEFT,Ftduino::MAX, 320);
    ftduino.motor_counter(Ftduino::M2,Ftduino::LEFT,Ftduino::MAX, 48);
    while(ftduino.motor_counter_active(Ftduino::M1)||
          ftduino.motor_counter_active(Ftduino::M3)||
          ftduino.motor_counter_active(Ftduino::M2));
    display_message("Grab");
    ftduino.motor_counter(Ftduino::M4,Ftduino::LEFT,Ftduino::MAX, 15);
    delay(1000);
    display_message("Move");
    ftduino.motor_counter(Ftduino::M3,Ftduino::RIGHT,Ftduino::MAX, 2000);
    while(ftduino.motor_counter_active(Ftduino::M3));
    ftduino.motor_counter(Ftduino::M1,Ftduino::LEFT,Ftduino::MAX, 900);
    while(ftduino.motor_counter_active(Ftduino::M1));
    display_message("Drop");
    ftduino.motor_counter(Ftduino::M4,Ftduino::RIGHT,Ftduino::MAX, 15);
    delay(600);
    display_message("End");
  }
  if(ftduino.input_get(Ftduino::I7)){
      init_robot();
  }
}
DIESEN ARTIKEL ALS PDF KAUFEN
EXPRESS-KAUF ALS PDFUmfang: 6 HeftseitenPreis €0,99
(inkl. 19% MwSt.)
RASPBERRY PI GEEK KAUFEN
EINZELNE AUSGABE Print-Ausgaben Digitale Ausgaben
ABONNEMENTS Print-Abos Digitales Abo
TABLET & SMARTPHONE APPS Raspberry Pi Geek bei Google Play Readly Logo
Nach oben