Inhalt | 2. Software zur Fernsteuerung über Bluetooth | 4. Sensoren

Steuerung der Motoren

  1. Grundlage: Die Klasse Motor
  2. ServoNavigator

Grundlage: Die Klasse Motor

Motoren bewegen

Die Klasse Motor bildet die Grundlage zum Ansteuern der Servomotoren. Sie stellt Methoden zum Vor- und Zurückfahren, Auslesen und Zurücksetzen des Tachometers, Setzen der Geschwindigkeit und Einstellen des Betriebsmodus eines Motors bereit. Anstelle eines Konstruktors besitzt Motor 3 statische Instanzen ihrer selbst: Motor.A, Motor.B und Motor.C, die zum Ansteuern des jeweiligen Motorports dienen. Zum Vorwärtsbewegen eines Motors gibt es drei Möglichkeiten:
Motor.A.forward();           // Unbegrenztes Vorwärtsfahren, sofortige Rückkehr zum Programm
Motor.A.forward(300);        // Begrenztes Vorwärtsfahren, Rückkehr zum Programm nach Beenden der Fahrt
Motor.A.forward(300true);  // Begrenztes Vorwärtsfahren, sofortige Rückkehr zum Programm
Analoges gilt für das Rückwärtsfahren. Die übergebenen Zahlenwerte sind hier die Anzahl der "Ticks": 360 Ticks entsprechen ungefähr einer 360°-Drehung des Motors.

Geschwindigkeit

Die Geschwindigkeit regulieren kann man mit der Methode setSpeed(int), wobei die Geschwindigkeit als Zahlenwert zwischen 0 und 100 übergeben wird. Durch einige sehr einfache Versuche mit der Stoppuhr konnten folgende Werte ermittelt werden:
Übergebener ZahlenwertGemessene Zeit auf 1mGeschwindigkeit in m/s
250:13.48 s0,07418 m/s
500:05.71 s0,17513 m/s
750:03.65 s0,27397 m/s
1000:02.84 s0,35211 m/s
Diese Werte sind natürlich keineswegs exakt und nur als Richtwerte zu sehen.

Vorwärts- und Rückwärtsfahren

Um den Legoroboter Vorwärtsfahren zu lassen, muss man i.d.R. zwei Motoren gleichzeitig fahren lassen. Wenn man dies mit dem offensichtlichsten Ansatz
Motor.B.forward();
Motor.C.forward();
probiert, führt dies zu Problemen: Die Motoren springen unterschiedlich schnell an, der Mindstorm dreht sich, bevor er geradeaus losfährt. Um zwei Motoren gleichzeitig starten zu können, muss man die beiden synchronisieren:
Motor.C.setRegulationMode(icommand.nxtcomm.NXTProtocol.REGULATION_MODE_MOTOR_SYNC);
Motor.B.setRegulationMode(icommand.nxtcomm.NXTProtocol.REGULATION_MODE_MOTOR_SYNC);
Motor.C.forward(1080true);
Motor.B.forward(1080false);
und anschließend z.B. mit REGULATION_MODE_MOTOR_SPEED wieder die Synchronisation entfernen:
Motor.B.setRegulationMode(icommand.nxtcomm.NXTProtocol.REGULATION_MODE_MOTOR_SPEED);
Motor.C.setRegulationMode(icommand.nxtcomm.NXTProtocol.REGULATION_MODE_MOTOR_SPEED);
Würde man die Synchronisation nicht wieder herausnehmen, würde ein Befehl an einen einzelnen Motor wie z.B.
Motor.C.forward(300);
den NXT verwirren und er beginnt entweder planlos den Motor zu bewegen oder tut nichts mehr.

SyncMotors

Um nicht ständig mit den Regulation Modes der Motoren jonglieren zu müssen gibt es die Klasse SyncMotors, die neben den bereits oben genannten Fähigkeiten von Motor auch noch zwei Motoren synchronisieren kann. Selbstverständlich sollte man es vermeiden, mit SyncMotors verbundene Motoren über Motor anzusteuern. Denn ist der Motor im Moment im Synchronisationsmodus sind die Reaktionen des NXT nicht vorhersehbar. An dieser Stelle bin ich in der iCommand API auf einen Bug gestoßen: Die Methoden left(...) und right(...) haben die Synchronisation nicht aufgehoben, weshalb ich eine Methode setSync(boolean) eingefügt habe, die die Synchronisation setzen und wieder aufheben kann.

Um also zwei Motoren mit SyncMotors zu verbinden muss einfach ein Objekt der Klasse erstellt werden:

SyncMotors sm = new SyncMotors(Motor.C, Motor.B);
Der erste Parameter ist hier der linke Motor und der zweite der rechte. Vorwärts- und Rückwärtsfahren und Setzen der Geschwindigkeit funktioniert hier genau wie bei Motor.

Rotation

Lediglich die Möglichkeit der Rotation ist hinzugekommen. Mit den beiden Methoden left(...) und right(...) kann man die Motoren einzeln ansteuern und so den Roboter nach links bzw. rechts rotieren lassen. Hierbei dreht er sich um das jeweils ruhende Rad. Für diese beiden Methoden muss der NXT allerdings erst zum stehen kommen.

Um den NXT während der Fahrt die Richtung ändern zu lassen, muss man ein bisschen tricksen. Erst lassen wir den Roboter vorwärts fahren

SyncMotors sm = new SyncMotors(Motor.C, Motor.B);
sm.setSpeed(24);
sm.forward();
und warten erstmal 3 Sekunden.
wait(3000);
Nun deaktivieren wir die Synchronisation,
Motor.B.setRegulationMode(icommand.nxtcomm.NXTProtocol.REGULATION_MODE_MOTOR_SPEED);
Motor.C.setRegulationMode(icommand.nxtcomm.NXTProtocol.REGULATION_MODE_MOTOR_SPEED)
setzen die Geschwindigkeit vom linken Rad hoch,
sm.left.setSpeed(48);
sm.right.setSpeed(24);
geben dem linken Rad das Geschwindigkeitsupdate durch
sm.left.forward();
und warten wieder erstmal 7 Sekunden.
wait(7000);
Nun synchronisieren wir die Motoren wieder
Motor.B.setRegulationMode(icommand.nxtcomm.NXTProtocol.REGULATION_MODE_MOTOR_SYNC);
Motor.C.setRegulationMode(icommand.nxtcomm.NXTProtocol.REGULATION_MODE_MOTOR_SYNC);
und halten an
sm.stop();
Die zweimal auftauchende Funktion wait ist wie folgt implementiert:
public static void wait(int ms) {
  long start_time = System.currentTimeMillis();
  while(System.currentTimeMillis() - start_time < ms) {}
}
Wartet also einfach die in Millisekunden übergebene Zeit ab.


1: http://mindstorms.lego.com/Overview/Interactive_Servo_Motors.aspx
2: http://lejos.sourceforge.net/p_technologies/nxt/icommand/api/icommand/platform/nxt/Motor.html <Lokale Kopie>
3: http://lejos.sourceforge.net/p_technologies/nxt/icommand/api/icommand/platform/nxt/SyncMotors.html <Lokale Kopie>

ServoNavigator

Um den Roboter zu bewegen reicht im Prinzip die Klasse SyncMotors aus. Allerdings gibt es noch die Klasse ServoNavigator, mit der man etwas einfacher navigieren kann. So gibt es in dieser Klasse Methoden, mit denen man den Roboter eine gewisse Strecke (angegeben in Abständen in metrischen Einheiten) lassen kann oder ihn um eine bestimmte Gradzahl drehen lassen kann. Außerdem speichert diese Klasse die aktuelle Position in einer x und y Koordinate. Hierfür muss man dem Konstruktor einige physikalische Parameter übergeben:

SyncMotors sm = new SyncMotors(Motor.C, Motor.B);
ServoNavigator sn = new ServoNavigator(56.011.5360.0, sm);
Der erste Parameter ist hier der Durchmesser eines Reifens (in mm). Der zweite gibt an, wie weit die Reifen voneinander entfernt sind (in cm) und der Dritte wieviele Ticks für eine volle Umdrehung des Reifens benötigt werden. Ist der Reifen direkt am Motor befestigt, kann dieser Parameter auch weggelassen werden, er ist dann standardmäßig 360.0.

Genauigkeit

Beim Vorwärtsfahren
Hierzu das Testprogramm Forward.java
import icommand.platform.nxt.*;
import icommand.nxtcomm.*;
import icommand.robotics.*;

public class Forward {

  public static void usage() {
    System.out.println("Usage:");
    System.out.println("  java Forward <speed> <distance>");
    System.out.println("");
    System.out.println("     speed:     Integeger between 1 and 255");
    System.out.println("     distance:  Distance in cm");
  }

  public static void main(String[] args) {
    if(args.length < 2) {
      usage();
      return;
    }

    int speed = Integer.parseInt(args[0]);
    int distance = Integer.parseInt(args[1]);

    SyncMotors sm = new SyncMotors(Motor.C, Motor.B);
    sm.setSpeed(speed);
    ServoNavigator sn = new ServoNavigator(56.011.5360.0, sm);
    sn.travel(distance);

          NXTCommand.close();
  }
}
und dieser Versuchsaufbau
Versuchsaufbau
liefert die Werte
zu fahrende Entfernunggefahrene Entfernung bei Geschwindigkeit
255075100
2018202325
5048505254
1009699100105
Beim Rotieren
Mit einem simplen Versuch mit der Testunterlage von Lego und dem Programm Rotate.java kann man die Genauigkeit der Rotation messen. Allerdings geht es auch hier rein um das Abfahren von vorher definierten Strecken, die Genauigkeit verhält sich bei der Rotation also genauso wie beim Geradeausfahren.


1: http://lejos.sourceforge.net/p_technologies/nxt/icommand/api/icommand/robotics/ServoNavigator.html <Lokale Kopie>

Nach oben | Inhalt | 2. Software zur Fernsteuerung über Bluetooth | 4. Sensoren