Last Updated on 10. Oktober 2026 by sfambachLink-Status: OK
Ansteuerung eines Servos mit dem Raspberry PI 3.
Hierbei geht es nur um die grundlegende Technik, der Einsatz könnte beispielsweise ein mobiler Roboter sein.
Der Servo soll hierbei über den Software PWM angesteuert werden, um die Hardware PWMs für andere Funktionen frei zu halten.
Zusätzlich soll der Servo nicht wie üblich über Integer Werte gesteuert werden, sondern über eine Gradzahl im Bezug zur Mittelstellung des Servos.
Das unten stehende Bild zeigt, was hiermit gemeint ist.

Auf die eigentliche Funktionsweise eines Servos gehe ich hier nicht ein, dies kann bei Bedarf bei http://rn-wissen.de/wiki/index.php/Servos oder anderen Websites nachgelesen werden.
Benötigte Hardware
- PI3 (oder älter, bitte auf die richtigen Pins achten)
- Standard-Servo
- Diverse Kabel ( Vorgefertigte Pin-Header Kabel)
Aufbau der Schaltung
Die Ansteuerung des Servos geschieht in meinem Fall über GPIO 27. Die Spannungsversorgung liefert der PI. Für größere Servos müsste evtl. auf eine externe Spannungsversorgung zurückgegriffen werden.
(Die GPIOs gelten nur in Verbindung mit pi4j und wirePi)

Software
Als Entwicklungsumgebung verwende ich BlueJ auf dem PI selbst. Hiermit habe ich die folgenden Klassen erstellt.

Code
Ein erster Test
Ein guter Anfang ist immer, den im Internet gefundenen Code in eine Main Funktion zu packen, um zu schauen, ob überhaupt was klappt. Dies habe ich in Form der FirstTest Klasse getan. Sie fährt alle Positionen des Servos ab. Die Funktionalität ist hier nicht gekapselt.
Hinweis: Der ursprüngliche Code (WP-Gistpen) ist verloren gegangen. Der folgende Code wurde im Oktober 2026 neu erstellt (kompiliert, aber nicht auf der Hardware getestet).
Quellcode FirstTest.java
import com.pi4j.wiringpi.Gpio;
import com.pi4j.wiringpi.SoftPwm;
/**
* Erster Servo-Test mit Software-PWM: fährt alle Positionen ab.
* Servo-Signal an GPIO 27 (pi4j / WiringPi-Nummerierung).
* www.fambach.net, GPLv2
*/
public class FirstTest {
private static final int PIN = 27;
public static void main(String[] args) throws InterruptedException {
Gpio.wiringPiSetup();
// Takt 100 µs, Bereich 200 -> 20 ms Periode (50 Hz)
SoftPwm.softPwmCreate(PIN, 0, 200);
// 5 = 0,5 ms (Anschlag links) bis 25 = 2,5 ms (Anschlag rechts)
for (int pos = 5; pos <= 25; pos++) {
System.out.println("Position " + pos);
SoftPwm.softPwmWrite(PIN, pos);
Thread.sleep(500);
}
for (int pos = 25; pos >= 5; pos--) {
System.out.println("Position " + pos);
SoftPwm.softPwmWrite(PIN, pos);
Thread.sleep(500);
}
SoftPwm.softPwmStop(PIN);
}
}
Gekapselter Code
Als nächsten Schritt habe ich den Code aus dem ersten Test genommen und ihn mit ein paar Änderungen in eine Klasse gepackt. Hierbei habe ich auch die Umrechnung von absoluten Werten in Grad implementiert. Für den Test der Klasse habe ich wiederum eine Main-Klasse erstellt, die alles mal aufruft.
Servo-Klasse
Klasse zur Steuerung des Servos. Die zwei wichtigsten Methoden sind:
- setPos – Setzen der Position, Wertebereich von posMin bis posMax, wobei (posMax-posMin+1) die Mittelstellung ist.
- setDeg – Diese Methode projiziert die angegebene Gradzahl auf die möglichen Positionen (aktuell sehr ungenau 🙁 )
Quellcode Servo.java
import com.pi4j.wiringpi.Gpio;
import com.pi4j.wiringpi.SoftPwm;
/**
* Steuert einen Servo über Software-PWM, wahlweise über die Position
* oder über den Winkel relativ zur Mittelstellung.
* www.fambach.net, GPLv2
*/
public class Servo {
private final int pin;
private final int posMin;
private final int posMax;
private final double degMax;
/** Servo an GPIO 27, Positionen 5 bis 25 (0,5 ms bis 2,5 ms), ±90° */
public Servo() {
this(27, 5, 25, 90.0);
}
public Servo(int pin, int posMin, int posMax, double degMax) {
this.pin = pin;
this.posMin = posMin;
this.posMax = posMax;
this.degMax = degMax;
Gpio.wiringPiSetup();
SoftPwm.softPwmCreate(pin, 0, 200);
}
public int getPosMin() {
return posMin;
}
public int getPosMax() {
return posMax;
}
/** Mittelstellung des Servos */
public int getPosCenter() {
return (posMin + posMax) / 2;
}
/** Position setzen, Werte außerhalb von posMin..posMax werden begrenzt */
public void setPos(int pos) {
int limited = Math.max(posMin, Math.min(posMax, pos));
SoftPwm.softPwmWrite(pin, limited);
}
/**
* Winkel relativ zur Mittelstellung setzen (-degMax bis +degMax).
* Wird auf die nächste mögliche Position gerundet, daher recht ungenau.
*/
public void setDeg(double deg) {
double stepsPerDeg = (posMax - posMin) / (2.0 * degMax);
setPos((int) Math.round(getPosCenter() + deg * stepsPerDeg));
}
public void stop() {
SoftPwm.softPwmStop(pin);
}
}
Test-Klasse
Klasse mit Main-Methode zum Testen der Servo-Klasse. In der Main-Methode werden alle Positionen abgefahren, wobei die Positionierung über den Winkel relativ zur 0 Position erfolgt.
Quellcode ServoTest.java
/**
* Testet die Klasse Servo: fährt alle Winkel relativ zur Mittelstellung ab.
* www.fambach.net, GPLv2
*/
public class ServoTest {
public static void main(String[] args) throws InterruptedException {
Servo servo = new Servo();
servo.setDeg(0);
Thread.sleep(1000);
for (int deg = -90; deg <= 90; deg += 10) {
System.out.println("Winkel " + deg + "°");
servo.setDeg(deg);
Thread.sleep(500);
}
servo.setDeg(0);
Thread.sleep(1000);
servo.stop();
}
}
Tipps
Das Positionieren über die PI4j Lib ist sehr ungenau. Für die 180° Bewegungsspielraum des Servos stehen gerade mal rund 20 (+-2) Positionen zur Verfügung. Das sind rund 9° pro Position. Evtl. sollte man vorher testen, welche Positionen für den aktuellen Zweck am besten geeignet sind. Sollte der genaue Winkel wichtig sein, ist es besser, diesen vorab zu messen, als ihn über die setDeg Methode berechnen zu lassen.
Es gibt noch weitere Libs (Servoblast, … ), die evtl. genauer sind, man könnte auch überlegen, die Programmiersprache zu wechseln und dann den entsprechenden Code über das Nativ-Interface anzusprechen. Als nächster Versuch klingt Servoblast erst einmal vielversprechend.
Weitere Schritte
PWM in Thread
Ich habe versucht, den Software PWM innerhalb eines Threads laufen zu lassen, jedoch ohne Erfolg. Der Servo weigert sich zu funktionieren. Über die Ursache hierfür bin ich mir noch im Unklaren. Ich nehme allerdings an, dass hierdurch der Timer zerschossen wird.
ServoBlast
Nach diversen Tests mit unterschiedlichen Frequenzen habe ich mich entschlossen, ServoBlasterLink-Status: OK od. besser die PI Variante (PiBits) zu verwenden. Die Installation gestaltet sich einfach wie folgt.
Quellcode servoblaster-install.sh
# ServoBlaster (PiBits) herunterladen, bauen und installieren
sudo apt-get update
sudo apt-get install -y git build-essential
git clone https://github.com/richardghirst/PiBits.git
cd PiBits/ServoBlaster/user
make
sudo make install
# Test: Servo 5 auf 1,5 ms (Mittelstellung) stellen, Einheit 10 µs
echo 5=150 > /dev/servoblaster
Programmierbeispiel
An dieser Stelle sollte nun eigentlich ein Code-Beispiel mit ServoBlast folgen. Da ich aktuell aber die Arbeiten am PI eingestellt habe und mit dem ESP8266 und ESP32 unterwegs bin, sei auf die folgenden Links verwiesen:
Problembehandlung
Exec funktioniert nicht
Wenn die exec Funktion von Java nix macht, ist hier ein guter Link zum Bugfixing.
http://www.javaworld.com/article/2071275/core-java/when-runtime-exec—won-t.htmlLink-Status: OK
Probleme mit println
Weiterhin könnte es helfen, nicht die println Methode zu verwenden, sondern die print, da zumindest mein PI den Abschluss der Zeile nicht richtig interpretieren konnte. print( „5=100\n“) hat jedoch funktioniert.
Verwandte Beiträge
Quellen
http://razzpisampler.oreilly.com/ch05.htmlLink-Status: Kaputt
https://github.com/Pi4J/pi4j/blob/master/pi4j-example/src/main/java/MaestroServoExample.javaLink-Status: Kaputt
https://phyks.me/2015/05/controlling-servomotors-on-a-raspberry-pi.htmlLink-Status: OK
https://github.com/richardghirst/PiBits/tree/master/ServoBlasterLink-Status: OK
http://rn-wissen.de/wiki/index.php/ServosLink-Status: Unbekannt
Anhang
Pin-Belegung

| Datum | Änderung | Autor |
|---|---|---|
| 10.10.2026 | Verlorenen Gistpen-Code durch neu erstellten Code (Code-Blöcke) ersetzt | sfambach |
| 08.10.2026 | Überschriften-Hierarchie korrigiert (H1→H2, Unterebenen eine Stufe tiefer) | sfambach |
| 04.10.2026 | Rechtschreibung korrigiert: Tippfehler, Kommas, Groß-/Kleinschreibung | sfambach |
| 03.10.2026 | Log-Liste eingefügt | sfambach |
| 11.06.2017 | Beitrag erstellt | sfambach |
Dafür, dass der Artikel über ein Jahr alt ist finde ich es recht schade, dass man an einigen Stellen weiterhin „… kommt noch“ lesen muss.
Ebenso fehlt wohl irgendwas bei den „gistpen id“-Zeilen.. – oder ich verstehs nicht.
Hallo und danke für deinen Kommentar.
Ja das mit dem Alter des Beitrags ist so eine Sache, ich habe diesen im letzten Urlaub angefangen und bin dann nicht mehr dazu gekommen, bzw. habe mich in letzter Zeit mehr mit dem ESP8266/ESP32 beschäftigt. Ich bin leider noch zu keinem dokumentierten Test mit ServoBlast gekommen vielleicht im nächsten Urlaub ;). Ich habe den Beitrag mal dementsprechend angepasst um den Leser hierüber zu informieren. Es sind nun nochmal die zwei Seiten gelinkt, welche die Verwendung von ServoBlast aus meiner Sicht ganz gut beschreiben.
Das mit der Gistpen id ist ärgerlich. Eine Version von Gistpen hatte leider nicht funktioniert, diese führte dazu, dass jede Seite mit Quellcode nicht mehr angezeigt wurden. Aus diesem Grunde hatte ich es leider deaktivieren müssen und wie immer hatte ich keine Zeit die alten Seiten zu überarbeiten. Auf neunen Seiten biete ich jetzt einen Download an. lange Rede kurzer Sinn, Ich habe Gistpen in der aktuellen Version reaktiviert und es scheint wieder zu funktionieren.
Gruß SFA