Raspberry PI: Servo

Prof. Jürgen Plate

Raspberry PI: Servo

Allgemeines

Servos ("Rudermaschinen") aus dem Modellbaubereich sind trotz der Betriebsspannung von 5 Volt besonders kräftige Antriebe. Ihr hohes Drehmoment wird durch ein Untersetzungsgetriebe erreicht. Ein Servoantrieb besteht aus einem Motor, einem auf der Achse angebrachten Positions- oder Winkelsensor (im einfachsten Fall ist das ein Potentiometer) und einer Regelelektronik mit Sollwert-Eingang. Diese vergleicht den eingegebenen Sollwert mit dem Istwert des Sensors. Stimmen beide nicht überein, so lässt die Regelung den Motor zu der Position laufen, bei der Istwert und Sollwert gleich sind. Diese elektronische Motorsteuerung ermöglicht nicht nur ein sehr feinfühliges und genaues Stellen des Antriebs in eine bestimmte Position, sie sorgt auch für ein kräftiges Gegenmoment gegen Rückstellversuche der Last und hält damit die gewünschte Position.

Je nach verwendetem Servo sind Stellzeiten bis herab auf 0,08 s über einen Stellweg von 60 Grad erreichbar. Die modernste Version, der Digitalservo, ist statt der bei analog arbeitenden Servos passiv arbeitenden Servosteuerung mit einem Mikroprozessor bestückt. Durch eine hohe Taktfrequenz kann der Antriebsmotor besonders schnell und in allen Lagen mit vollem Drehmoment arbeiten, was extrem kurze Reaktionszeiten bei gleichmäßiger Kraftentfaltung erlaubt. Die Analog-Servos dagegen verlieren oft gegen Ende des Stellwegs an Drehmoment und auch Drehgeschwindigkeit. Ein weiterer Vorteil des Digitalservos ist das aktive Gegensteuern durch den Prozessor bei Rückstellversuchen der Last. Nachteilig bei beiden Typen ist der relativ kleine Stellweg und das laute Arbeitsgeräusch. Die Stellkraft (etwa 10 Newton) ist, gemessen an der Größe, beachtlich. Sie sollten aber berücksichtigen, dass die Getriebe bei vielen Modellen aus Plastikzahnrädern bestehen, die bei Überlast sehr schnell verschleißen (gegebenenfalls auf die etwas teureren Modelle mit Metallgetriebe ausweichen). Die Ansteuerung ist bei beiden Typen gleich; die Sollwert-Vorgabe erfolgt über einen längenmodulierten Impuls.

Der Servo wird alle 20 ms mit kurzen Impulsen von ein bis zwei Millisekunden Dauer angesteuert und damit die Position seines Antriebs bestimmt. Die Impulse müssen im 20-ms-Abstand wiederholt werden, damit ein Servo seine Position beibehält. Praktisch alle Servos erwarten übrigens einen positiven Impuls.

Alle genannten Eigenschaften prädestinieren den Modellbau-Servo als Antrieb für andere Verwendungen. Sie lassen sich für beliebige Betätigungsfunktionen verwenden, \zb das Betätigen eines Riegels, das Aktivieren einer Fütterungsautomatik für Fische, das Öffnen und Schließen von Lüftungsklappen, die computerisierte Einzelbild-Steuerung für Langzeitaufnahmen einer 16-mm-Kamera oder das Schwenken einer Überwachungskamera. Modellbau-Servos werden heutzutage auch gerne bei experimentellen Robotern eingesetzt. Häufig findet man in einem Roboter eine größere Anzahl davon. Ein "Käfer" mit sechs Beinen benötigt in der Regel mindestens drei Servos pro Bein, und ein einfacher Arm hat mitunter sechs bis sieben.

Es gibt leider mehrere unterschiedliche Servo-Anschlusskabel-Systeme, jeder Hersteller hat eine eigene Norm. Die verbreitetsten Steckerformen sind heute die Futaba- und die Graupner-Norm. Die diversen Steckerformen sind im folgenden Bild zu sehen.

Die äußere Form des Steckers, die man bei der Kombination des Servos mit einem Fernsteuerempfänger strikt beachten muss, tangiert beim Anschluss an das PC-Interface nicht, wohl aber die Anschlussbelegung. Denn der Stecker ist unbedingt richtig herum auf die Stiftleiste der Steuerung aufzustecken, sonst kann es zu Schäden kommen. Dabei kann man sich nach den Kabelfarben richten. Diese sind zwar auch nicht einheitlich, folgen aber zumindest einem Grundschema. So ist der Plusanschluss bei allen rot, der Minusanschluss entweder braun, schwarz oder blau. Der Signalanschluss ist entweder gelb, orange, weiß oder violett. Einziger Ausreißer aus diesem Schema ist Simprop. Hier ist der Minusanschluss blau und das Signalkabel schwarz.

Servo am Raspberry Pi

Ein Pin des RasPi kann als Ausgang mit Pulsweitenmodulation verwendet werden, GPIO 18. Hier können Frequenz und Tastverhältnis am Pin per Software festgelegt werden, ohne dass man den Port per Programm ständig ein- und ausschalten muss. Die GPIO-Bibliothek von Python enthält bereits Funktionen für die Servosteuerung, was das Programmieren von Anwendungen recht leicht macht. Der Anschluß des Servos ist recht einfach:

Wer sicher gehen will, dass dem RasPi nichts geschieht, kann zwischen den Signaleingang des Servos und Pin 12 einen Widerstand von 1 kΩ schalten.

Es ist jedoch auch Vorsicht geboten. Ein kleines Micro-Servo kann problemlos auf diese Weise betrieben werden. Bei größeren Servos ist es jedoch ratsam, das Servo mit einer eigenen Stromversorgung zu versehen. Dabei werden dann die beiden GND-Anschlüsse von RasPi und Servo-Netzteil miteinander verbunden, um einen Bezugspegel für das Servo-Steuersignal zu haben.

Bei der Software werden folgende Methoden benötigt:

Wie kommt man auf die o. a. Werte? Wenn man einen Impuls mit einer bestimmten Länge will, kann man das Tastverhältnis nach der Formels DC = Länge/Periodendauer berechnen. Nachdem das Servo eine Periodendauer von 20 ms verwendet, kann man das Tastverhältnis (in %) folgendermaßen berechnen:
     0 Grad (0.5 ms): DC = 0.5/20*100 =  2.5%
    90 Grad (1.5 ms): DC = 1.5/20*100 =  7.5%
   180 Grad (2.5 ms): DC = 2.5/20*100 = 12.5%

Das folgende Testprogramm zeigt das Zusammenspiel der Methoden. Das Servo wird initialisiert und auf die Position 0 Grad gefahren. Danach wird der Zyklus 90 Grad, 0 Grad, 180 Grad in einer Endlosschleife durchlaufen. Mit Hilfe von try - except sorgt das Programm dafür, dass beim Abbruch der Schleife das Servo auf 0 Grad fährt und das PWM-Signal abgeschaltet wird.

import RPi.GPIO as gpio
import time

# Servo-GPIO (PWM-GPIO 18, Pin 12)
servopin = 18

# GPIO initialisieren
gpio.setmode(gpio.BCM)
gpio.setup(servopin, gpio.OUT)

# PWM-Frequenz auf 50 Hz setzen
servo = gpio.PWM(servopin, 50)

# PWM starten, Servo auf 0 Grad
servo.start(2.5)

try:
  # Endlosschleife Servoansteuerung
  while True:
    # 90 Grad
    servo.ChangeDutyCycle(7.5)
    time.sleep(1)
    # 180 Grad
    servo.ChangeDutyCycle(12.5)
    time.sleep(1)
    # 0 Grad
    servo.ChangeDutyCycle(2.5)
    time.sleep(1)

except KeyboardInterrupt:
  # Abbruch mit [Strg][C],
  # Servo auf 0 Grad, PWM beenden
  servo.ChangeDutyCycle(2.5)
  servo.stop()
  gpio.cleanup()
Wenn einem die Prozentwerte nicht geheuer sind, kann man auch eine Funktion schreiben, welche die Angabe in Grad erlaubt. Dzu wurde das obige Programm etwas erweitert.
import RPi.GPIO as gpio
import time

# Servo-GPIO (PWM-GPIO 18, Pin 12)
servopin = 18

# GPIO initialisieren
gpio.setmode(gpio.BCM)
gpio.setup(servopin, gpio.OUT)

# PWM-Frequenz auf 50 Hz setzen
servo = gpio.PWM(servopin, 50)

# PWM starten, Servo auf 0 Grad
servo.start(2.5)

# Umrechnung Grad in Tastverhaeltnis
def setservo(winkel):
  if winkel < 0:
    winkel = 0
  if winkel > 180:
    winkel = 180
  pwm = winkel/18 + 2.5
  servo.ChangeDutyCycle(pwm)

try:
  # Endlosschleife Servoansteuerung
  while True:
    # 90 Grad
    setservo(90)
    time.sleep(1)
    # 180 Grad
    setservo(180)
    time.sleep(1)
    # 0 Grad
    setservo(0)
    time.sleep(1)

except KeyboardInterrupt:
  # Abbruch mit [Strg][C],
  # Servo auf 0 Grad, PWM beenden
  servo.ChangeDutyCycle(2.5)
  servo.stop()
  gpio.cleanup()
Das letzte Beispiel erlaubt die interaktive Eingabe des Winkels und verwendet die oben definierte Funktion setservo():
import RPi.GPIO as gpio
import time

# Servo-GPIO (PWM-GPIO 18, Pin 12)
servopin = 18

# GPIO initialisieren
gpio.setmode(gpio.BCM)
gpio.setup(servopin, gpio.OUT)

# PWM-Frequenz auf 50 Hz setzen
servo = gpio.PWM(servopin, 50)

# PWM starten, Servo auf 0 Grad
servo.start(2.5)

# Umrechnung Grad in Tastverhaeltnis
def setservo(winkel):
  if winkel < 0:
    winkel = 0
  elif winkel > 180:
    winkel = 180
  pwm = winkel/18 + 2.5
  servo.ChangeDutyCycle(pwm)

try:
  # Endlosschleife Servoansteuerung
  while True:
    winkel = raw_input("Winkel eingeben (0 - 180): ")
    winkel = float(winkel)
    setservo(winkel)

except KeyboardInterrupt:
  # Abbruch mit [Strg][C],
  # Servo auf 0 Grad, PWM beenden
  servo.ChangeDutyCycle(2.5)
  servo.stop()
  gpio.cleanup()

Links


Copyright © Hochschule München, FK 04, Prof. Jürgen Plate
Letzte Aktualisierung: